]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.74 1.3.74
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:40 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:40 +0000 (15:10 -0500)
82 files changed:
CREDITS
Documentation/Configure.help
Makefile
arch/i386/mm/init.c
arch/sparc/mm/srmmu.c
drivers/block/floppy.c
drivers/block/ide.c
drivers/char/ftape/Makefile
drivers/char/ftape/RELEASE-NOTES
drivers/char/ftape/calibr.c
drivers/char/ftape/ecc.c
drivers/char/ftape/fc-10.c
drivers/char/ftape/fdc-io.c
drivers/char/ftape/fdc-isr.c
drivers/char/ftape/ftape-bsm.c
drivers/char/ftape/ftape-ctl.c
drivers/char/ftape/ftape-eof.c
drivers/char/ftape/ftape-io.c
drivers/char/ftape/ftape-read.c
drivers/char/ftape/ftape-rw.c
drivers/char/ftape/ftape-write.c
drivers/char/ftape/kernel-interface.c
drivers/char/ftape/tracing.c
drivers/char/lp.c
drivers/isdn/teles/buffers.c
drivers/net/Config.in
drivers/net/Makefile
drivers/net/Space.c
drivers/net/eexpress.c
drivers/net/fmv18x.c [new file with mode: 0644]
drivers/scsi/Config.in
drivers/scsi/Makefile
drivers/scsi/README.ppa [new file with mode: 0644]
drivers/scsi/hosts.c
drivers/scsi/ppa.c [new file with mode: 0644]
drivers/scsi/ppa.h [new file with mode: 0644]
drivers/scsi/st.c
drivers/sound/.blurb
drivers/sound/.version
drivers/sound/CHANGELOG
drivers/sound/Makefile
drivers/sound/Readme
drivers/sound/Readme.cards
drivers/sound/Readme.linux
drivers/sound/ad1848.c
drivers/sound/configure.c
drivers/sound/dev_table.h
drivers/sound/dmabuf.c
drivers/sound/gus_card.c
drivers/sound/gus_wave.c
drivers/sound/os.h
drivers/sound/pas2_card.c
drivers/sound/pss.c
drivers/sound/sb16_dsp.c
drivers/sound/sb16_midi.c
drivers/sound/sb_dsp.c
drivers/sound/sound_config.h
drivers/sound/soundcard.c
drivers/sound/soundvers.h
fs/buffer.c
include/asm-alpha/pgtable.h
include/asm-i386/pgtable.h
include/asm-mips/dma.h
include/linux/fs.h
include/linux/mm.h
include/linux/proc_fs.h
include/linux/soundcard.h
include/linux/swap.h
init/main.c
ipc/shm.c
kernel/sys.c
mm/filemap.c
mm/kmalloc.c
mm/memory.c
mm/page_alloc.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
net/unix/af_unix.c
scripts/Menuconfig
scripts/header.tk
scripts/lxdialog/util.c

diff --git a/CREDITS b/CREDITS
index 0d0563b0b3d09c366d4fd9294928166584860343..a46010d1e3f69a0ee70d751403429a1de10725cf 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -394,6 +394,13 @@ N: Philip Gladstone
 E: philipg@onsett.com
 D: Kernel / timekeeping stuff
 
+N: Grant Guenther
+E: grant@torque.net
+D: Iomega PPA / ZIP driver
+S: 906-1001 Bay St.
+S: Toronto, Ontario, M5S 3A6 
+S: Canada
+
 N: Miquel van Smoorenburg
 E: miquels@cistron.nl
 D: Kernel and net hacker. Sysvinit, minicom. doing Debian stuff.
index 6aab81e29e0e8f95934acfa6dee816728cdaf8cb..6c1dc4ef4f0c376290fbb20430ac9f483a73cb66 100644 (file)
@@ -815,9 +815,9 @@ CONFIG_IP_MROUTE
 PC/TCP compatibility mode
 CONFIG_INET_PCTCP
   If you have been having difficulties telneting to your Linux machine
-  from a DOS system that uses (broken) PC/TCP networking software, try
-  enabling this option.  Everyone else says N. As of later 1.3.x kernels
-  nobody should need this option. Please report if it solves problems.
+  from a DOS system that uses (broken) PC/TCP networking software (all
+  versions up to OnNet 2.0), try enabling this option.  Everyone else
+  says N.
 
 Reverse ARP
 CONFIG_INET_RARP
@@ -1054,16 +1054,16 @@ CONFIG_BLK_DEV_SR
 SCSI generic support
 CONFIG_CHR_DEV_SG
   If you want to use SCSI scanners, synthesizers or CD-writers or just
-  about anything having "SCSI" in its name, say Y here. Those won't be
-  supported by the kernel directly, so you need some additional
-  software which knows how to talk to these things using the SCSI
-  protocol. Chances are that you'll have to write that software
-  yourself, so have a look at the SCSI-HOWTO and at the
-  SCSI-Programming-HOWTO, both available via ftp (user: anonymous) in
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to compile this
-  as a module ( = code which can be inserted in and removed from the
-  running kernel whenever you want), say M here and read
-  Documentation/modules.txt and Documentation/scsi.txt.
+  about anything having "SCSI" in its name other than disks, CDROMs or
+  tapes, say Y here. Those won't be supported by the kernel directly,
+  so you need some additional software which knows how to talk to
+  these things using the SCSI protocol. Chances are that you'll have
+  to write that software yourself, so have a look at the SCSI-HOWTO
+  and at the SCSI-Programming-HOWTO, both available via ftp (user:
+  anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you want to
+  compile this as a module ( = code which can be inserted in and
+  removed from the running kernel whenever you want), say M here and
+  read Documentation/modules.txt and Documentation/scsi.txt.
 
 Probe all LUNs on each SCSI device
 CONFIG_SCSI_MULTI_LUN
@@ -1341,6 +1341,18 @@ CONFIG_SCSI_AM53C974
   available via ftp (user: anonymous) at
   sunsite.unc.edu:/pub/Linux/docs/HOWTO, is for you.
 
+IOMEGA Parallel Port ZIP drive SCSI support
+CONFIG_SCSI_PPA
+  This driver supports the parallel port version of IOMEGA's ZIP
+  drive (a 100Mb removable media device).  For more infomation 
+  about this driver and how to use it you should read the file
+  drivers/scsi/README.ppa.  You should also read the SCSI-HOWTO,
+  which is available via anonymous ftp from sunsite.unc.edu in
+  the directory /pub/Linux/docs/HOWTO.  This driver is also available
+  as a module which can be inserted in and removed from the
+  running kernel whenever you want. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
 Network device support?
 CONFIG_NETDEVICES
   You can say N here in case you don't intend to connect to any other
@@ -1583,9 +1595,10 @@ CONFIG_ULTRA
 
 SMC 9194 Support
 CONFIG_SMC9194
-  This has support for the SMC9xxx based Ethernet cards.  Choose this option
-  if you have a DELL laptop with the docking station, or another SMC9192/9194
-  based chipset.  Say Y if you want it compiled into the kernel, and read  
+  This is support for the SMC9xxx based Ethernet cards.  Choose this
+  option if you have a DELL laptop with the docking station, or
+  another SMC9192/9194 based chipset.  Say Y if you want it compiled
+  into the kernel, and read the the file drivers/net/README.smc9 and
   the Ethernet-HOWTO, available via ftp (user: anonymous) in
   sunsite.unc.edu:/pub/Linux/docs/HOWTO.  This driver is also
   available as a module ( = code which can be inserted in and removed
@@ -1682,9 +1695,9 @@ CONFIG_EL3
   Documentation/networking/net-modules.txt. If you plan to use more
   than one network card under linux, read the
   Multiple-Ethernet-mini-HOWTO, available from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If your card is not working
-  you may need to use the DOS setup disk to disable Plug & Play mode, and
-  to select the default media type.
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If your card is not
+  working you may need to use the DOS setup disk to disable Plug &
+  Play mode, and to select the default media type.
 
 3c590 series (592/595/597) "Vortex" support
 CONFIG_VORTEX
@@ -2006,7 +2019,9 @@ CONFIG_APRICOT
 
 DE425, DE434, DE435 support
 CONFIG_DE4X5
-  If you have a network (ethernet) card of this type, say Y and read
+  This is support for the DIGITAL series of PCI/EISA ethernet
+  cards. These include the DE425, DE434, DE435, DE450 and DE500
+  models. If you have a network card of this type, say Y and read
   the Ethernet-HOWTO, available via ftp (user: anonymous) in
   sunsite.unc.edu:/pub/Linux/docs/HOWTO.  More specific information is
   contained in drivers/net/README.de4x5. This driver is also available
@@ -2383,7 +2398,8 @@ CONFIG_VFAT_FS
   partitions. It does not support Windows'95 compressed filesystems.
   You cannot use the VFAT filesystem for your root partition; use
   UMSDOS instead. This option enlarges your kernel by about 10 kB and
-  it only works if you enabled the "fat fs support" above. 
+  it only works if you enabled the "fat fs support" above. Please read
+  the file Documentation/filesystems/vfat.txt for details.
   If unsure, say N. If you want to compile this as a module ( = code 
   which can be inserted in and removed from the running kernel whenever 
   you want), say M here and read Documentation/modules.txt.
@@ -2699,7 +2715,9 @@ CONFIG_FTAPE
   (and their companion controller) is also supported. If you have a
   special controller (such as the CMS FC-10, FC-20, Iomega Mach-II, or
   Ditto Dash), you must configure it by editing the file
-  drivers/char/ftape/Makefile.  This driver is also available as a
+  drivers/char/ftape/Makefile. If you want to use such a tape drive on
+  a PCI-bus based system, please read the file
+  drivers/char/ftape/README.PCI. This driver is also available as a
   runtime loadable module ( = code which can be inserted in and
   removed from the running kernel whenever you want). If you want to
   compile it as a module, say M here and read
@@ -2962,3 +2980,5 @@ CONFIG_ISDN_DRV_TELES
 # LocalWords:  NOWAYOUT behaviour dialin isdn callback BTX Teles ICN EDSS Cisco
 # LocalWords:  ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr
 # LocalWords:  ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD
+# LocalWords:  initrd tue util DES funet des OnNet BIOSP smc Travan Iomega CMS
+# LocalWords:  FC
index e8ebce75f01fc876b9134fae115782bd2c881778..383523f6210269cc6061aa32280c564b9e682031 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 73
+SUBLEVEL = 74
 
 ARCH = i386
 
index 5c4c6860d8c62fe6d34beb1ea1680f6a4b97ca92..883d8dcf01faf8705b942c5b255842c53c1d32b0 100644 (file)
@@ -236,6 +236,8 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
                start_mem += PAGE_SIZE;
        }
        for (tmp = 0 ; tmp < high_memory ; tmp += PAGE_SIZE) {
+               if (tmp >= 16*1024*1024)
+                       mem_map[MAP_NR(tmp)].dma = 0;
                if (mem_map[MAP_NR(tmp)].reserved) {
                        if (tmp >= 0xA0000 && tmp < 0x100000)
                                reservedpages++;
index 0bd67118e60c8085dd2136976e69c3c726730c7d..b5385e5b8d7ac901723837f31a6157018d876bf5 100644 (file)
@@ -902,7 +902,7 @@ unsigned long srmmu_alloc_kernel_stack(struct task_struct *tsk)
 {
        unsigned long pages;
 
-       pages = __get_free_pages(GFP_KERNEL, 1, ~0UL);
+       pages = __get_free_pages(GFP_KERNEL, 1, 0);
        if(!pages)
                return 0;
        memset((void *) pages, 0, (PAGE_SIZE << 1));
index 15c07e19d0d0e17c7e0cf8e925689a2e1fdbe063..2aab361ca9cad2fdd354beba8a33d023dbfa8b39 100644 (file)
@@ -171,28 +171,23 @@ struct old_floppy_raw_cmd {
 /* Dma Memory related stuff */
 
 /* Pure 2^n version of get_order */
-static inline int __get_order (int size)
+static inline int __get_order(unsigned long size)
 {
        int order;
 
-#ifdef  _ASM_IO_H2
-       __asm__ __volatile__("bsr %1,%0"
-                            : "=r" (order)
-                            : "r" (size / PAGE_SIZE));
-#else
-       for (order = 0; order < NR_MEM_LISTS; ++order)
-               if (size <= (PAGE_SIZE << order))
-                       return order;
-#endif
-       return NR_MEM_LISTS;
+       size >>= (PAGE_SHIFT-1);
+       order = -1;
+       do {
+               size >>= 1;
+               order++;
+       } while (size);
+       return order;
 }
 
 static unsigned long dma_mem_alloc(int size)
 {
        int order = __get_order(size);
 
-       if (order >= NR_MEM_LISTS)
-               return(0);
        return __get_dma_pages(GFP_KERNEL,order);
 }
 
index c324a16fc419963c692eb2e06f70ec675dd806f9..7d9cfdfb796714b808026ffd3f9d696f9a798e75 100644 (file)
@@ -524,7 +524,7 @@ static void ide_geninit (struct gendisk *gd)
  */
 static void init_gendisk (ide_hwif_t *hwif)
 {
-       struct gendisk *gd, **gdp;
+       struct gendisk *gd;
        unsigned int unit, units, minors;
        int *bs;
 
@@ -556,9 +556,8 @@ static void init_gendisk (ide_hwif_t *hwif)
        gd->init        = ide_geninit;          /* initialization function */
        gd->real_devices= hwif;                 /* ptr to internal data */
 
-       for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) ;
-       gd->next = NULL;                        /* link to tail of list */
-       hwif->gd = *gdp = gd;
+       gd->next = gendisk_head;                /* link new major into list */
+       hwif->gd = gendisk_head = gd;
 }
 
 static void do_reset1 (ide_drive_t *, int);            /* needed below */
@@ -2900,11 +2899,11 @@ static int init_irq (ide_hwif_t *hwif)
                }
        }
        /*
-        * Check for serialization with ide1.
-        * This code depends on us having already taken care of ide1.
+        * Check for serialization with ide0.
+        * This code depends on us having already taken care of ide0.
         */
-       if (hwif->serialized && hwif->index == 0 && ide_hwifs[1].present)
-               hwgroup = ide_hwifs[1].hwgroup;
+       if (hwif->index == 1 && ide_hwifs[0].serialized && ide_hwifs[0].present)
+               hwgroup = ide_hwifs[0].hwgroup;
        /*
         * If this is the first interface in a group,
         * then we need to create the hwgroup structure
index 638b6c914e152e0387e3f2819644765b922d2fba..899fe200717d545bfe0a6a9c41444de3987af482 100644 (file)
@@ -54,7 +54,7 @@ FTAPE_OPT       = -DVERIFY_HEADERS -DNR_BUFFERS=3 -DCLK_48MHZ=1 \
 # This enables some (most?) 2Mbps controllers:
 #FDC_OPT         = -DFDC_BASE=0x3E0 -DFDC_IRQ=6 -DFDC_DMA=2
 
-EXTRA_CFLAGS := $(FTAPE_OPT) $(FDC_OPT) -D__NO_VERSION__
+EXTRA_CFLAGS := $(FTAPE_OPT) $(FDC_OPT)
 
 O_TARGET := ftape.o
 O_OBJS   = kernel-interface.o tracing.o fdc-io.o fdc-isr.o \
index a1fabc9ac5b5b3419b325d47d8fcb6e28e4c8c49..3848dc31e24c34434b20026c2c6e11b65bf12278 100644 (file)
@@ -1,3 +1,11 @@
+===== Release notes for ftape-2.07a, 14/03/96 =====
+
+Bugfixes by Marcin Dalecki <dalecki@namu03.gwdg.de>:
+- In the last release it just compiled against 1.3.70;
+  now the params to request_irq() and free_irq are() are fixed, so it also 
+  works in 1.3.73 :-)
+- Support for modules is now correct for newer kernels.
+
 ===== Release notes for ftape-2.07, 04/03/96 =====
 
 
index a725944d3d00097ce5749a1dedf14f04ecae5037..bd41bddb8436a620dec1cb2c482b81bbfa79e3d0 100644 (file)
@@ -20,7 +20,6 @@
  *      functions.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/ftape.h>
index 7f94f11229c2fb819814f2dc52e5763e10e75ace..5c7d86bd606a14bf5dd1cbae69221f786549f676 100644 (file)
@@ -32,7 +32,6 @@
  *      for the QIC-40/80 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 #include <stdio.h>
 #include <sys/errno.h>
index aa8619638dacedc66369c3c94a2aa167c16a7607..c079aa92fb6151fb2ebcc99e5939cea47a75447f 100644 (file)
@@ -41,7 +41,6 @@
  *      This file contains code for the CMS FC-10/FC-20 card.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 #include <asm/io.h>
 
index 2194cd3e44dc5d56751154ae022933160328ba20..0159f8786781ba37c7e36ecfed3337e8e424f88c 100644 (file)
@@ -21,7 +21,6 @@
  *      for the QIC-40/80 tape streamer device driver.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
@@ -69,6 +68,8 @@ static byte fdc_precomp = 0;  /* sets fdc to default precomp. value */
 static byte fdc_drv_spec[4];   /* drive specification bytes for i82078 */
 static int perpend_mode;       /* true if fdc is in perpendicular mode */
 
+static char ftape_id[] = "ftape"; /* used by request irq and free irq */
+
 void fdc_catch_stray_interrupts(unsigned count)
 {
        unsigned long flags;
@@ -1179,7 +1180,6 @@ int fdc_grab_irq_and_dma(void)
 {
        TRACE_FUN(8, "fdc_grab_irq_and_dma");
        int result = 0;
-       static char ftape_id[] = "ftape";
 
        if (fdc.hook == &do_ftape) {
                /*  Get fast interrupt handler.
@@ -1193,7 +1193,7 @@ int fdc_grab_irq_and_dma(void)
                        result = request_dma(fdc.dma, ftape_id);
                        if (result) {
                                TRACEx1(-1, "Unable to grab DMA%d for ftape driver", fdc.dma);
-                               free_irq(fdc.irq, NULL);
+                               free_irq(fdc.irq, ftape_id);
                                result = -EIO;
                        } else {
                                enable_irq(fdc.irq);
@@ -1224,7 +1224,7 @@ int fdc_release_irq_and_dma(void)
                disable_dma(fdc.dma);   /* just in case... */
                free_dma(fdc.dma);
                disable_irq(fdc.irq);
-               free_irq(fdc.irq, NULL);
+               free_irq(fdc.irq, ftape_id);
        }
 #ifdef FDC_DMA
        if (result == 0 && FDC_DMA == 2) {
index 4f2f02ba1b63200ce65d0ac25af5a374dfbcae65..7c9056c9b5a4999519d079fef04a065de92d48be 100644 (file)
@@ -26,7 +26,6 @@
  *      code for the QIC-40/80 tape streamer device driver.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 #include <asm/io.h>
 #include <asm/dma.h>
index 57e87d78e881f378333a08323b4fb886966d941d..6e86b065e091fd307525537bafff13abe2127568 100644 (file)
@@ -27,7 +27,6 @@
  *      QIC-40, QIC-80, QIC-3010 and QIC-3020 maps are implemented.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 #include <linux/string.h>
 
index 07fe806f8249eaab03fa0196dcf07968afdb37b0..d4e86ebf10d8630a27778e447534bd844b16bbb8 100644 (file)
@@ -20,7 +20,6 @@
  *      for the QIC-40/80 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/ftape.h>
index 5151db5f1bd4cfcc5d30f1cd7a51ced85ad070cd..75c4cbd7639c30eb32f82231300fae0dcbff84f0 100644 (file)
@@ -27,7 +27,6 @@
  *      for the QIC-40/80 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 #include <linux/string.h>
 #include <linux/errno.h>
index feea796839b7b72b2101da111d17d065ae6328e6..822a32394b2bd6fa39cd18dfb123c7140e189c62 100644 (file)
@@ -26,7 +26,6 @@
  *      for the QIC-40/80 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
index 019d52530282008bc71001c21fc1fb2c7187568b..51615264f4dc4530172a43ea519816e6bea71814 100644 (file)
@@ -26,7 +26,6 @@
  *      for the QIC-117 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
index e2d12eb2e6fe254cb7fede9848eea1df71ad6081..2a539a2500e56795407b6de4ac9297a38215ec5a 100644 (file)
@@ -26,7 +26,6 @@
  *      write routines for the QIC-117 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ftape.h>
index abf0170a1db19dc2630cd310ebc845fb8624e957..fc8f9629bd1e99eae47f5d81d756ca1573ec4397 100644 (file)
@@ -29,7 +29,6 @@
  *      for the QIC-117 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
index 6c1c2d914137831f99aa01d47d0cf31f4897e62f..7f490d67a833d45ef24ee5fb8b71424401c86afb 100644 (file)
 byte *tape_buffer[NR_BUFFERS] =
 {NULL};
 
-#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-#endif
-
 /*      Local vars.
  */
 static int busy_flag = 0;
index be69861b6c6a9cfe208706a150ca9c1275d8834b..a2d1a4268fe71082fdde31440f35ce617ebd18d7 100644 (file)
@@ -21,7 +21,6 @@
  *      for the QIC-117 floppy-tape driver for Linux.
  */
 
-#include <linux/module.h>
 #include <linux/ftape.h>
 
 #include "tracing.h"
index 77c105732023aad4a39c03834287821c9bb1554e..c34d28a3a31cd69bffa3ca431ca48c5fe9726470 100644 (file)
@@ -7,6 +7,7 @@
  * Copyright (C) 1994 by Alan Cox (Modularised it)
  * LPCAREFUL, LPABORT, LPGETSTATUS added by Chris Metcalf, metcalf@lcs.mit.edu
  * Statistics and support for slow printers by Rob Janssen, rob@knoware.nl
+ * "lp=" command line parameters added by Grant Guenther, grant@torque.net
  */
 
 #include <linux/module.h>
@@ -538,6 +539,10 @@ static int lp_probe(int offset)
        unsigned int testvalue;
 
        base = LP_B(offset);
+       if (base == 0) 
+               return -1;              /* de-configured by command line */
+       if (LP_IRQ(offset) > 15) 
+               return -1;              /* bogus interrupt value */
        size = (base == 0x3bc)? 3 : 8;
        if (check_region(base, size) < 0)
                return -1;
@@ -559,6 +564,33 @@ static int lp_probe(int offset)
                return 0;
 }
 
+/* Command line parameters:
+
+   When the lp driver is built in to the kernel, you may use the
+   LILO/LOADLIN command line to set the port addresses and interrupts
+   that the driver will use.
+
+   Syntax:     lp=port0[,irq0[,port1[,irq1[,port2[,irq2]]]]]
+
+   For example:   lp=0x378,0   or   lp=0x278,5,0x378,7
+
+   Note that if this feature is used, you must specify *all* the ports
+   you want considered, there are no defaults.  You can disable a
+   built-in driver with lp=0 .
+
+*/
+
+void   lp_setup(char *str, int *ints)
+
+{      
+        LP_B(0)   = ((ints[0] > 0) ? ints[1] : 0 );
+        LP_IRQ(0) = ((ints[0] > 1) ? ints[2] : 0 );
+        LP_B(1)   = ((ints[0] > 2) ? ints[3] : 0 );
+        LP_IRQ(1) = ((ints[0] > 3) ? ints[4] : 0 );
+        LP_B(2)   = ((ints[0] > 4) ? ints[5] : 0 );
+        LP_IRQ(2) = ((ints[0] > 5) ? ints[6] : 0 );
+}
+
 #ifdef MODULE
 static int io[] = {0, 0, 0};
 static int irq[] = {0, 0, 0};
index 3d571428227e3aca821165d9a2758d36595f31ad..96a214ed64833b995b25f6118477a9af9ba12e3c 100644 (file)
@@ -39,7 +39,7 @@ BufPoolAdd(struct BufPool *bp, int priority)
        printk(KERN_DEBUG "BufPoolAdd bp %x\n", bp);
 #endif
 
-       ptr = (struct Pages *) __get_free_pages(priority,bp->pageorder,~0);
+       ptr = (struct Pages *) __get_free_pages(priority,bp->pageorder,0);
        if (!ptr) {
                printk(KERN_WARNING "BufPoolAdd couldn't get pages!\n");
                return (-1);
index afd9be8802f2eab7d3c404a7e944b4b301e4b9f5..6160448c73e363407060cfffe679c13cd9597ce7 100644 (file)
@@ -41,6 +41,7 @@ if [ "$CONFIG_NET_ISA" = "y" ]; then
   if [ "$CONFIG_NET_ALPHA" = "y" ]; then
     bool 'SEEQ8005 support' CONFIG_SEEQ8005
     tristate 'AT1700 support' CONFIG_AT1700
+    tristate 'FMV-181/182 support' CONFIG_FMV18X
     tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
     tristate 'EtherExpress support' CONFIG_EEXPRESS
     tristate 'NI5210 support' CONFIG_NI52
index 2ad25197932e68570ecca16537256f9a115b80d2..1768c3270b374ca4724c47db92f534a4c63d25ef 100644 (file)
@@ -223,6 +223,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_FMV18X),y)
+L_OBJS += fmv18x.o
+else
+  ifeq ($(CONFIG_FMV18X),m)
+  M_OBJS += fmv18x.o
+  endif
+endif
+
 ifeq ($(CONFIG_EL1),y)
 L_OBJS += 3c501.o
 else
index 8e7971e08cc5e8bb3590abdf35697f532b6430e1..f6a7c17dd91bc2a20a12796b87d0a9571049268a 100644 (file)
@@ -51,6 +51,7 @@ extern int eepro_probe(struct device *);
 extern int el3_probe(struct device *);
 extern int at1500_probe(struct device *);
 extern int at1700_probe(struct device *);
+extern int fmv18x_probe(struct device *);
 extern int eth16i_probe(struct device *);
 extern int depca_probe(struct device *);
 extern int apricot_probe(struct device *);
@@ -127,6 +128,9 @@ ethif_probe(struct device *dev)
 #ifdef CONFIG_AT1700
        && at1700_probe(dev)
 #endif
+#ifdef CONFIG_FMV18X           /* Fujitsu FMV-181/182 */
+       && fmv18x_probe(dev)
+#endif
 #ifdef CONFIG_ETH16I
        && eth16i_probe(dev)    /* ICL EtherTeam 16i/32 */
 #endif
index a50f8a79165a76fafe4c37a9a13caf888b21384d..705383dc4f51c8c548d3ec29356ff525cf554a1c 100644 (file)
@@ -1224,8 +1224,8 @@ static struct device dev_eexp[EEXP_MAX_CARDS] =
        0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe 
 };
 
-int irq[MAX_EEXP_CARDS] = {0, };
-int io[MAX_EEXP_CARDS] = {0, };
+int irq[EEXP_MAX_CARDS] = {0, };
+int io[EEXP_MAX_CARDS] = {0, };
 
 /* Ideally the user would give us io=, irq= for every card.  If any parameters
  * are specified, we verify and then use them.  If no parameters are given, we
@@ -1261,7 +1261,7 @@ void cleanup_module(void)
        for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
                struct device *dev = &dev_eexp[this_dev];
                if (dev->priv != NULL) {
-                       kfree_s(dev->priv. sizeof(struct net_local));
+                       kfree(dev->priv);
                        dev->priv = NULL;
                        release_region(dev->base_addr, EEXP_IO_EXTENT);
                        unregister_netdev(dev);
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
new file mode 100644 (file)
index 0000000..4ef82e7
--- /dev/null
@@ -0,0 +1,664 @@
+/* fmv18x.c: A network device driver for  the Fujitsu FMV-181/182.
+
+       Original: at1700.c (1993-94 by Donald Becker).
+               Copyright 1993 United States Government as represented by the
+               Director, National Security Agency.
+               The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+               Center of Excellence in Space Data and Information Sciences
+                  Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+       Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
+               Copyright 1994 Fujitsu Laboratories Ltd.
+       Special thanks to:
+               Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
+                       for testing this driver.
+               H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
+                       for sugestion of some program modification.
+               Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
+                       for sugestion of some program modification.
+               Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
+                       for testing this driver.
+
+       This software may be used and distributed according to the terms
+       of the GNU Public License, incorporated herein by reference.
+
+       This is a device driver for the Fujitsu FMV-181/182, which is a
+       straight-forward Fujitsu MB86965 implementation.
+
+  Sources:
+    at1700.c
+    The Fujitsu MB86965 datasheet.
+    The Fujitsu FMV-181/182 user's guide
+*/
+
+static const char *version =
+       "fmv18x.c:v1.3.71e 03/04/96  Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+
+static int fmv18x_probe_list[] =
+{0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 1
+#endif
+static unsigned int net_debug = NET_DEBUG;
+
+typedef unsigned char uchar;
+
+/* Information that need to be kept for each board. */
+struct net_local {
+       struct enet_statistics stats;
+       long open_time;                         /* Useless example local info. */
+       uint tx_started:1;                      /* Number of packet on the Tx queue. */
+       uchar tx_queue;                         /* Number of packet on the Tx queue. */
+       ushort tx_queue_len;            /* Current length of the Tx queue. */
+};
+
+
+/* Offsets from the base address. */
+#define STATUS                 0
+#define TX_STATUS              0
+#define RX_STATUS              1
+#define TX_INTR                        2               /* Bit-mapped interrupt enable registers. */
+#define RX_INTR                        3
+#define TX_MODE                        4
+#define RX_MODE                        5
+#define CONFIG_0               6               /* Misc. configuration settings. */
+#define CONFIG_1               7
+/* Run-time register bank 2 definitions. */
+#define DATAPORT               8               /* Word-wide DMA or programmed-I/O dataport. */
+#define TX_START               10
+#define COL16CNTL              11
+#define MODE13                 13
+/* Fujitsu FMV-18x Card Configuration */
+#define        FJ_STATUS0              0x10
+#define        FJ_STATUS1              0x11
+#define        FJ_CONFIG0              0x12
+#define        FJ_CONFIG1              0x13
+#define        FJ_MACADDR              0x14    /* 0x14 - 0x19 */
+#define        FJ_BUFCNTL              0x1A
+#define        FJ_BUFDATA              0x1C
+#define FMV18X_IO_EXTENT       32
+
+/* Index to functions, as function prototypes. */
+
+extern int fmv18x_probe(struct device *dev);
+
+static int fmv18x_probe1(struct device *dev, short ioaddr);
+static int net_open(struct device *dev);
+static int     net_send_packet(struct sk_buff *skb, struct device *dev);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void net_rx(struct device *dev);
+static int net_close(struct device *dev);
+static struct enet_statistics *net_get_stats(struct device *dev);
+static void set_multicast_list(struct device *dev);
+
+\f
+/* Check for a network adaptor of this type, and return '0' iff one exists.
+   If dev->base_addr == 0, probe all likely locations.
+   If dev->base_addr == 1, always return failure.
+   If dev->base_addr == 2, allocate space for the device and return success
+   (detachable devices only).
+   */
+#ifdef HAVE_DEVLIST
+/* Support for a alternate probe manager, which will eliminate the
+   boilerplate below. */
+struct netdev_entry fmv18x_drv =
+{"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
+#else
+int
+fmv18x_probe(struct device *dev)
+{
+       int i;
+       int base_addr = dev ? dev->base_addr : 0;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return fmv18x_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return ENXIO;
+
+       for (i = 0; fmv18x_probe_list[i]; i++) {
+               int ioaddr = fmv18x_probe_list[i];
+               if (check_region(ioaddr, FMV18X_IO_EXTENT))
+                       continue;
+               if (fmv18x_probe1(dev, ioaddr) == 0)
+                       return 0;
+       }
+
+       return ENODEV;
+}
+#endif
+
+/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
+   "signature", the default bit pattern after a reset.  This *doesn't* work --
+   there is no way to reset the bus interface without a complete power-cycle!
+
+   It turns out that ATI came to the same conclusion I did: the only thing
+   that can be done is checking a few bits and then diving right into MAC
+   address check. */
+
+int fmv18x_probe1(struct device *dev, short ioaddr)
+{
+       char irqmap[4] = {3, 7, 10, 15};
+       unsigned int i, irq;
+
+       /* Resetting the chip doesn't reset the ISA interface, so don't bother.
+          That means we have to be careful with the register values we probe for.
+          */
+
+       /* Check I/O address configuration and Fujitsu vendor code */
+       if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
+       ||  inb(ioaddr+FJ_MACADDR  ) != 0x00
+       ||  inb(ioaddr+FJ_MACADDR+1) != 0x00
+       ||  inb(ioaddr+FJ_MACADDR+2) != 0x0e)
+               return -ENODEV;
+
+       irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+
+       /* Snarf the interrupt vector now. */
+       if (request_irq(irq, &net_interrupt, 0, "fmv18x", NULL)) {
+               printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
+                               "IRQ %d.\n", ioaddr, irq);
+               return EAGAIN;
+       }
+
+       /* Allocate a new 'dev' if needed. */
+       if (dev == NULL)
+               dev = init_etherdev(0, sizeof(struct net_local));
+
+       /* Grab the region so that we can find another board if the IRQ request
+          fails. */
+       request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x");
+
+       printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
+                  ioaddr, irq);
+
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+       irq2dev_map[irq] = dev;
+
+       for(i = 0; i < 6; i++) {
+               unsigned char val = inb(ioaddr + FJ_MACADDR + i);
+               printk("%02x", val);
+               dev->dev_addr[i] = val;
+       }
+
+       /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
+          rather than 150 ohm shielded twisted pair compensation.
+          0x0000 == auto-sense the interface
+          0x0800 == use TP interface
+          0x1800 == use coax interface
+          */
+       {
+               const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
+               ushort setup_value = inb(ioaddr + FJ_STATUS0);
+
+               switch( setup_value & 0x07 ){
+               case 0x01 /* 10base5 */:
+               case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
+               case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
+               default /* auto-sense*/: dev->if_port = 0x00; break;
+               }
+               printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
+       }
+
+       /* Initialize LAN Controller and LAN Card */
+       outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
+       outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
+       outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
+       outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
+
+       /* wait for a while */
+       udelay(200);
+
+       /* Set the station address in bank zero. */
+       outb(0x00, ioaddr + CONFIG_1);
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + 8 + i);
+
+       /* Switch to bank 1 and set the multicast table to accept none. */
+       outb(0x04, ioaddr + CONFIG_1);
+       for (i = 0; i < 8; i++)
+               outb(0x00, ioaddr + 8 + i);
+
+       /* Switch to bank 2 and lock our I/O address. */
+       outb(0x08, ioaddr + CONFIG_1);
+       outb(dev->if_port, ioaddr + MODE13);
+
+       if (net_debug)
+               printk(version);
+
+       /* Initialize the device structure. */
+       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       if (dev->priv == NULL)
+               return -ENOMEM;
+       memset(dev->priv, 0, sizeof(struct net_local));
+
+       dev->open               = net_open;
+       dev->stop               = net_close;
+       dev->hard_start_xmit = net_send_packet;
+       dev->get_stats  = net_get_stats;
+       dev->set_multicast_list = &set_multicast_list;
+
+       /* Fill in the fields of 'dev' with ethernet-generic values. */
+          
+       ether_setup(dev);
+       return 0;
+}
+\f
+
+static int net_open(struct device *dev)
+{
+       struct net_local *lp = (struct net_local *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       /* Set the configuration register 0 to 32K 100ns. byte-wide memory,
+          16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
+       outb(0x5a, ioaddr + CONFIG_0);
+
+       /* Powerup and switch to register bank 2 for the run-time registers. */
+       outb(0xe8, ioaddr + CONFIG_1);
+
+       lp->tx_started = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;
+
+       /* Clear Tx and Rx Status */
+       outb(0xff, ioaddr + TX_STATUS);
+       outb(0xff, ioaddr + RX_STATUS);
+       lp->open_time = jiffies;
+
+       dev->tbusy = 0;
+       dev->interrupt = 0;
+       dev->start = 1;
+
+       /* Enable the IRQ of the LAN Card */
+       outb(0x80, ioaddr + FJ_CONFIG1);
+
+       /* Enable both Tx and Rx interrupts */
+       outw(0x8182, ioaddr+TX_INTR);
+
+       MOD_INC_USE_COUNT;
+
+       return 0;
+}
+
+static int
+net_send_packet(struct sk_buff *skb, struct device *dev)
+{
+       struct net_local *lp = (struct net_local *)dev->priv;
+       int ioaddr = dev->base_addr;
+
+       if (dev->tbusy) {
+               /* If we get here, some higher level has decided we are broken.
+                  There should really be a "kick me" function call instead. */
+               int tickssofar = jiffies - dev->trans_start;
+               if (tickssofar < 10)
+                       return 1;
+               printk("%s: transmit timed out with status %04x, %s?\n", dev->name,
+                          htons(inw(ioaddr + TX_STATUS)),
+                          inb(ioaddr + TX_STATUS) & 0x80
+                          ? "IRQ conflict" : "network cable problem");
+               printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
+                          dev->name, htons(inw(ioaddr + 0)),
+                          htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
+                          htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
+                          htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
+                          htons(inw(ioaddr +14)));
+               printk("eth card: %04x %04x\n",
+                       htons(inw(ioaddr+FJ_STATUS0)),
+                       htons(inw(ioaddr+FJ_CONFIG0)));
+               lp->stats.tx_errors++;
+               /* ToDo: We should try to restart the adaptor... */
+               cli();
+
+               /* Initialize LAN Controller and LAN Card */
+               outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
+               outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
+               outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
+               outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
+               net_open(dev);
+
+               sti();
+       }
+
+       /* If some higher layer thinks we've missed an tx-done interrupt
+          we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+          itself. */
+       if (skb == NULL) {
+               dev_tint(dev);
+               return 0;
+       }
+
+       /* Block a timer-based transmit from overlapping.  This could better be
+          done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+       if (set_bit(0, (void*)&dev->tbusy) != 0)
+               printk("%s: Transmitter access conflict.\n", dev->name);
+       else {
+               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+               unsigned char *buf = skb->data;
+
+               if (length > ETH_FRAME_LEN) {
+                       if (net_debug)
+                               printk("%s: Attempting to send a large packet (%d bytes).\n",
+                                       dev->name, length);
+                       return 1;
+               }
+
+               if (net_debug > 4)
+                       printk("%s: Transmitting a packet of length %lu.\n", dev->name,
+                                  (unsigned long)skb->len);
+
+               /* Disable both interrupts. */
+               outw(0x0000, ioaddr + TX_INTR);
+               
+               outw(length, ioaddr + DATAPORT);
+               outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+
+               lp->tx_queue++;
+               lp->tx_queue_len += length + 2;
+
+               if (lp->tx_started == 0) {
+                       /* If the Tx is idle, always trigger a transmit. */
+                       outb(0x80 | lp->tx_queue, ioaddr + TX_START);
+                       lp->tx_queue = 0;
+                       lp->tx_queue_len = 0;
+                       dev->trans_start = jiffies;
+                       lp->tx_started = 1;
+                       dev->tbusy = 0;
+               } else if (lp->tx_queue_len < 4096 - 1502)
+                       /* Yes, there is room for one more packet. */
+                       dev->tbusy = 0;
+
+               /* Re-enable interrupts */
+               outw(0x8182, ioaddr + TX_INTR);
+       }
+       dev_kfree_skb (skb, FREE_WRITE);
+
+       return 0;
+}
+\f
+/* The typical workload of the driver:
+   Handle the network interface interrupts. */
+static void
+net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct device *dev = (struct device *)(irq2dev_map[irq]);
+       struct net_local *lp;
+       int ioaddr, status;
+
+       if (dev == NULL) {
+               printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq);
+               return;
+       }
+       dev->interrupt = 1;
+
+       ioaddr = dev->base_addr;
+       lp = (struct net_local *)dev->priv;
+
+       /* Avoid multiple interrupts. */
+       outw(0x0000, ioaddr + TX_INTR);
+
+        status = inw(ioaddr + TX_STATUS);
+       outw(status, ioaddr + TX_STATUS);
+
+       if (net_debug > 4)
+               printk("%s: Interrupt with status %04x.\n", dev->name, status);
+       if (status & 0xff00
+               ||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {                      /* Got a packet(s). */
+               net_rx(dev);
+       }
+       if (status & 0x00ff) {
+               if (status & 0x80) {
+                       lp->stats.tx_packets++;
+                       if (lp->tx_queue) {
+                               outb(0x80 | lp->tx_queue, ioaddr + TX_START);
+                               lp->tx_queue = 0;
+                               lp->tx_queue_len = 0;
+                               dev->trans_start = jiffies;
+                               dev->tbusy = 0;
+                               mark_bh(NET_BH);        /* Inform upper layers. */
+                       } else {
+                               lp->tx_started = 0;
+                               dev->tbusy = 0;
+                               mark_bh(NET_BH);        /* Inform upper layers. */
+                       }
+               }
+               if (status & 0x02 ) {
+                       if (net_debug > 4)
+                               printk("%s: 16 Collision occur during Txing.\n", dev->name);
+                       /* Retry to send the packet */
+                       outb(0x02, ioaddr + COL16CNTL);
+               }
+       }
+
+       dev->interrupt = 0;
+       outw(0x8182, ioaddr + TX_INTR);
+       return;
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct device *dev)
+{
+       struct net_local *lp = (struct net_local *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int boguscount = 10;    /* 5 -> 10: by agy 19940922 */
+
+       while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
+               /* Clear PKT_RDY bit: by agy 19940922 */
+               /* outb(0x80, ioaddr + RX_STATUS); */
+               ushort status = inw(ioaddr + DATAPORT);
+
+               if (net_debug > 4)
+                       printk("%s: Rxing packet mode %02x status %04x.\n",
+                                  dev->name, inb(ioaddr + RX_MODE), status);
+#ifndef final_version
+               if (status == 0) {
+                       outb(0x05, ioaddr + 14);
+                       break;
+               }
+#endif
+
+               if ((status & 0xF0) != 0x20) {  /* There was an error. */
+                       lp->stats.rx_errors++;
+                       if (status & 0x08) lp->stats.rx_length_errors++;
+                       if (status & 0x04) lp->stats.rx_frame_errors++;
+                       if (status & 0x02) lp->stats.rx_crc_errors++;
+                       if (status & 0x01) lp->stats.rx_over_errors++;
+               } else {
+                       ushort pkt_len = inw(ioaddr + DATAPORT);
+                       /* Malloc up new buffer. */
+                       struct sk_buff *skb;
+
+                       if (pkt_len > 1550) {
+                               printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
+                                          dev->name, pkt_len);
+                               outb(0x05, ioaddr + 14);
+                               lp->stats.rx_errors++;
+                               break;
+                       }
+                       skb = dev_alloc_skb(pkt_len+3);
+                       if (skb == NULL) {
+                               printk("%s: Memory squeeze, dropping packet (len %d).\n",
+                                          dev->name, pkt_len);
+                               outb(0x05, ioaddr + 14);
+                               lp->stats.rx_dropped++;
+                               break;
+                       }
+                       skb->dev = dev;
+                       skb_reserve(skb,2);
+
+                       insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
+
+                       if (net_debug > 5) {
+                               int i;
+                               printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
+                               for (i = 0; i < 14; i++)
+                                       printk(" %02x", skb->data[i]);
+                               printk(".\n");
+                       }
+
+                       skb->protocol=eth_type_trans(skb, dev);
+                       netif_rx(skb);
+                       lp->stats.rx_packets++;
+               }
+               if (--boguscount <= 0)
+                       break;
+       }
+
+       /* If any worth-while packets have been received, dev_rint()
+          has done a mark_bh(NET_BH) for us and will work on them
+          when we get to the bottom-half routine. */
+       {
+               int i;
+               for (i = 0; i < 20; i++) {
+                       if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
+                               break;
+                       (void)inw(ioaddr + DATAPORT);                           /* dummy status read */
+                       outb(0x05, ioaddr + 14);
+               }
+
+               if (net_debug > 5 && i > 0)
+                       printk("%s: Exint Rx packet with mode %02x after %d ticks.\n", 
+                                  dev->name, inb(ioaddr + RX_MODE), i);
+       }
+
+       return;
+}
+
+/* The inverse routine to net_open(). */
+static int net_close(struct device *dev)
+{
+       int ioaddr = dev->base_addr;
+
+       ((struct net_local *)dev->priv)->open_time = 0;
+
+       dev->tbusy = 1;
+       dev->start = 0;
+
+       /* Set configuration register 0 to disable Tx and Rx. */
+       outb(0xda, ioaddr + CONFIG_0);
+
+       /* Update the statistics -- ToDo. */
+
+       /* Power-down the chip.  Green, green, green! */
+       outb(0x00, ioaddr + CONFIG_1);
+
+       MOD_DEC_USE_COUNT;
+
+       /* Set the ethernet adaptor disable IRQ */
+       outb(0x00, ioaddr + FJ_CONFIG1);
+
+       return 0;
+}
+
+/* Get the current statistics. This may be called with the card open or
+   closed. */
+static struct enet_statistics *
+net_get_stats(struct device *dev)
+{
+       struct net_local *lp = (struct net_local *)dev->priv;
+
+       cli();
+       /* ToDo: Update the statistics from the device registers. */
+       sti();
+
+       return &lp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   num_addrs == -1     Promiscuous mode, receive all packets
+   num_addrs == 0      Normal mode, clear multicast list
+   num_addrs > 0       Multicast mode, receive normal and MC packets, and do
+                       best-effort filtering.
+ */
+static void
+set_multicast_list(struct device *dev)
+{
+       short ioaddr = dev->base_addr;
+       if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) 
+       {
+               /*
+                *      We must make the kernel realise we had to move
+                *      into promisc mode or we start all out war on
+                *      the cable. - AC
+                */
+               dev->flags|=IFF_PROMISC;                
+       
+               outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
+       } 
+       else
+               outb(2, ioaddr + RX_MODE);      /* Disable promiscuous, use normal mode */
+}
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+static struct device dev_fmv18x = {
+       devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+       0, 0, 0, 0,
+       0, 0,
+       0, 0, 0, NULL, fmv18x_probe };
+
+static int io = 0x220;
+static int irq = 0;
+
+int init_module(void)
+{
+       if (io == 0)
+               printk("fmv18x: You should not use auto-probing with insmod!\n");
+       dev_fmv18x.base_addr = io;
+       dev_fmv18x.irq       = irq;
+       if (register_netdev(&dev_fmv18x) != 0) {
+               printk("fmv18x: register_netdev() returned non-zero.\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+void
+cleanup_module(void)
+{
+       unregister_netdev(&dev_fmv18x);
+       kfree(dev_fmv18x.priv);
+       dev_fmv18x.priv = NULL;
+
+       /* If we don't do this, we can't re-insmod it later. */
+       free_irq(dev_fmv18x.irq, NULL);
+       irq2dev_map[dev_fmv18x.irq] = NULL;
+       release_region(dev_fmv18x.base_addr, FMV18X_IO_EXTENT);
+}
+#endif /* MODULE */
+\f
+/*
+ * Local variables:
+ *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
+ *  version-control: t
+ *  kept-new-versions: 5
+ *  tab-width: 4
+ *  c-indent-level: 4
+ * End:
+ */
index 95b1492c42fce6b4a520fc7b19bd4306a5af2c0b..ca8ae6e13d0144bc46bd9d551585afa4cc4f76c9 100644 (file)
@@ -45,6 +45,7 @@ dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
 dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
 dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
+dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI
 bool 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974
 #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
 endmenu
index eccc0156b8c00b6c151c7beeed1f3fedefdee6eb..c7af6042fd11df078bc51bdde6793f236c215864 100644 (file)
@@ -84,6 +84,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_PPA),y)
+L_OBJS += ppa.o
+else
+  ifeq ($(CONFIG_SCSI_PPA),m)
+  M_OBJS += ppa.o
+  endif
+endif
+
 ifeq ($(CONFIG_SCSI_QLOGIC),y)
 L_OBJS += qlogic.o
 else
diff --git a/drivers/scsi/README.ppa b/drivers/scsi/README.ppa
new file mode 100644 (file)
index 0000000..728d59e
--- /dev/null
@@ -0,0 +1,123 @@
+README.ppa (c) 1996   Grant R. Guenther,  grant@torque.net
+
+
+         The IOMEGA PPA3 parallel port SCSI Host Bus Adapter
+
+                     as embedded in the ZIP drive
+
+
+This README documents the Linux support for the parallel port version of
+IOMEGA's ZIP100.  The ZIP100 is an inexpensive and popular, but relatively 
+low performance, removable medium disk device.  The drive is also available
+as a regular SCSI device, but the driver documented here is for the
+parallel port version.  IOMEGA implemented the parallel port version by
+integrating (or emulating ?) their PPA3 parallel to SCSI converter into
+the ZIP drive.
+
+I have implemented a low-level driver, ppa.c,  for this parallel port 
+host bus adapter, thereby supporting the parallel port ZIP drive as a 
+regular SCSI device under Linux.
+
+It is possible that this driver will also work with the original PPA3
+device (to access a CDrom, for instance). But, the PPA3 is hard to find 
+and costs as much as the ZIP drive itself, so no-one has actually tried
+this, to the best of my knowledge.
+
+The driver was developed without the benefit of any technical specifications 
+for the interface.  Instead, a modified version of DOSemu was used to 
+monitor the protocol used by the DOS driver, 'guest.exe', for this adapter.
+I have no idea how my programming model relates to IOMEGA's design.
+(One technical consequence of this method:  I have never observed a
+SCSI message byte in the protocol transactions between guest.exe and
+the ZIP drive, so I do not know how they are delivered.  My working 
+hypothesis is that we don't have to worry about them if we don't
+send linked commands to the drive.)
+
+I'd like to thank Byron Jeff (byron@cc.gatech.edu) for publishing his
+observation that the 'guest' driver loads under DOSemu.  His remark was
+the stimulus that began this project.
+
+The ppa driver can detect and adapt to 4- and 8-bit parallel ports, but 
+there is currently no support for EPP or ECP ports, as I have been unable 
+to make the DOS drivers work in these modes on my test rig.
+
+The driver may be built in to the kernel, or loaded as a module.  It
+may be configured on the command line in both cases, although the syntax
+is different.  It may also be configured by editing the source file.
+
+Built-in drivers accept parameters using this LILO/LOADLIN command line
+syntax (omitted parameters retain their default values):
+
+        ppa=base[,speed_high[,speed_low[,call_sched[,nybble]]]]
+
+For example:    ppa=0x378,0,3
+
+If a driver is loaded as a module the parameters may be set on the
+insmod command line, but each one must be specified by name:
+
+For example:    insmod ppa.o ppa_base=0x378 ppa_nybble=1
+
+(Notice the ppa_ prefix on each of the parameters in the insmod form.)
+
+Here are the parameters and their functions:
+
+Variable        Default    Description
+
+ppa_base        0x378   The base address of PPA's parallel port.
+ppa_speed_high  1       Microsecond i/o delay used in data transfers
+ppa_speed_low   6       Microsecond delay used in other operations
+ppa_call_sched  1       1 to give up CPU during busy waits
+ppa_nybble      0       1 to force the driver to use 4-bit mode.
+
+A word about the timing parameters:  the ppa_speed_low parameter controls 
+the widths of a large number of pulses that are sent over the parallel bus, 
+the narrower the pulses, the faster things go, but the greater the risk of 
+distortion by noise damping circuits in the parallel ports.  The 
+ppa_speed_high parameter controls the same delays, but during the data 
+transfer phase only.   In this phase, there is a lot of handshaking going 
+on and the pulse shaping should not be so much of an issue, but if you 
+see data corruption, you can increase this parameter as well.
+
+You might also want to reduce the timing values to attempt to increase
+the transfer rates on your system.  Please be careful to watch for
+SCSI timeout errors in your log files.  If you are getting timeouts, you
+have set these parameters too low.  The default values appear to be
+safe on most machines.
+
+The ppa_call_sched parameter controls the 'friendliness' of this driver
+to the rest of your system.  When it is set to zero, the driver waits for
+events on the drive by continuously reading a port until the 0x80 bit is
+asserted.  Since it is in a tight loop inside the kernel, the rest of the
+system becomes very sluggish.  If you set ppa_call_sched to one, then
+ppa will call the scheduler in such circumstances, voluntarily giving up the
+CPU to other processes.   This appears to reduce the ZIP drive's 
+responsiveness, however.
+
+If you have both the lp and ppa drivers in your kernel, you must ensure
+that they access different parallel ports.  By default, the lp driver is
+initialised early in the booting process, and it claims all parallel
+ports that it can find.  You may control this behaviour with a LILO or
+LOADLIN command line argument of the form:
+
+        lp=base0[,irq0[,base1[,irq1[,base2[,irq2]]]]]
+
+For example:    lp=0x278,7
+
+If you use this method, only the ports named will be adopted by the lp
+driver.  You can disable them all with lp=0 .
+
+So, if you have a printer on 0x3bc and a ZIP drive on 0x278 you would
+give the following options on your boot command:
+
+        lp=0x3bc ppa=0x278
+
+In this case lp would use the polling driver, since an interrupt was not 
+specified.
+
+For information about using the ZIP drive, please read the generic
+instructions in the SCSI-HOWTO and the man pages for the normal disk
+management tools,  fdisk, mkfs, mount, umount, etc.  There is a mini-HOWTO
+circulating concerning the use of the normal SCSI version of the ZIP
+drive, most of its comments will apply to disks connected through the
+ppa driver as well.
+
index 2a4eed3ecb43eafba27fa79910857c8aee571ea2..bbf340101e2c99a3a589c537ed044ebcea5f4adc 100644 (file)
 #include "AM53C974.h"
 #endif
 
+#ifdef CONFIG_SCSI_PPA
+#include "ppa.h"
+#endif
+
 #ifdef CONFIG_SCSI_DEBUG
 #include "scsi_debug.h"
 #endif
@@ -233,6 +237,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #ifdef CONFIG_SCSI_AM53C974
     AM53C974,
 #endif
+#ifdef CONFIG_SCSI_PPA
+    PPA,
+#endif
 #ifdef CONFIG_SCSI_DEBUG
     SCSI_DEBUG,
 #endif
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
new file mode 100644 (file)
index 0000000..1fb59bc
--- /dev/null
@@ -0,0 +1,479 @@
+/*      ppa.c   --  low level driver for the IOMEGA PPA3 
+                    parallel port SCSI host adapter.
+
+        (The PPA3 is the embedded controller in the ZIP drive.)
+
+        (c) 1995,1996 Grant R. Guenther, grant@torque.net,
+                      under the terms of the GNU Public License.
+
+        THIS IS BETA SOFTWARE - PLEASE TAKE ALL NECESSARY PRECAUTIONS
+
+*/
+
+/*      This driver was developed without the benefit of any technical
+        specifications for the interface.  Instead, a modified version of
+        DOSemu was used to monitor the protocol used by the DOS driver
+        for this adapter.  I have no idea how my programming model relates
+        to IOMEGA's design.
+
+        IOMEGA's driver does not generate linked commands.  I've never
+        observed a SCSI message byte in the protocol transactions, so
+        I am assuming that as long as linked commands are not used
+        we won't see any.  
+
+        So far, this driver has been tested with the embedded PPA3 in the
+        ZIP drive, only.   It can detect and adapt to 4- and 8-bit parallel
+        ports, but there is currently no support for EPP or ECP ports, as
+        I have been unable to make the DOS drivers work in these modes on
+        my test rig.
+
+        For more information, see the file drivers/scsi/README.ppa.
+
+*/
+
+#define   PPA_VERSION   "0.20"
+
+/* Change these variables here or with insmod or with a LILO or LOADLIN
+   command line argument
+*/
+
+static int      ppa_base       = 0x378;  /* parallel port address    */
+static int      ppa_speed_high = 1;      /* port delay in data phase */
+static int      ppa_speed_low  = 6;      /* port delay otherwise     */
+static int      ppa_call_sched = 1;      /* give up the CPU ?        */
+static int      ppa_nybble     = 0;      /* don't force nybble mode  */
+
+
+#define   PPA_CAN_QUEUE         1       /* use "queueing" interface */
+#define   PPA_SELECT_TMO        5000    /* how long to wait for target ? */
+#define   PPA_SPIN_TMO          5000000 /* ppa_wait loop limiter */
+#define   PPA_SECTOR_SIZE       512     /* for a performance hack only */
+
+#include  <unistd.h>
+#include  <linux/module.h>
+#include  <linux/kernel.h>
+#include  <linux/ioport.h>
+#include  <linux/delay.h>
+#include  <linux/blk.h>
+#include  <linux/proc_fs.h>
+#include  <linux/stat.h>
+#include  <asm/io.h>
+#include  "sd.h"
+#include  "hosts.h"
+#include  "ppa.h"
+
+struct proc_dir_entry proc_scsi_ppa = 
+                { PROC_SCSI_PPA, 3, "ppa", S_IFDIR|S_IRUGO|S_IXUGO, 2 };
+
+static int              ppa_abort_flag = 0;
+static int              ppa_error_code = DID_OK;
+static char             ppa_info_string[132];
+static Scsi_Cmnd        *ppa_current = 0;
+static void             (*ppa_done) (Scsi_Cmnd *);
+static int              ppa_busy = 0;
+static int              ppa_port_delay;
+
+
+void    out_p( short port, char byte)
+
+{       outb(byte,ppa_base+port);
+        udelay(ppa_port_delay);
+}
+
+char    in_p( short port)
+
+{       return inb(ppa_base+port);
+        udelay(ppa_port_delay);
+}
+
+void    ppa_d_pulse( char b )
+
+{       out_p(0,b);
+        out_p(2,0xc); out_p(2,0xe); out_p(2,0xc); out_p(2,0x4); out_p(2,0xc);
+}
+
+void    ppa_disconnect( void )
+
+{       ppa_d_pulse(0);
+        ppa_d_pulse(0x3c);
+        ppa_d_pulse(0x20);
+        ppa_d_pulse(0xf);
+}
+
+void    ppa_c_pulse( char b )
+
+{       out_p(0,b);
+        out_p(2,0x4); out_p(2,0x6); out_p(2,0x4); out_p(2,0xc);
+}
+
+void    ppa_connect( void )
+
+{       ppa_c_pulse(0);
+        ppa_c_pulse(0x3c);
+        ppa_c_pulse(0x20);
+        ppa_c_pulse(0x8f);
+}
+
+void    ppa_do_reset( void )
+
+{       out_p(2,0);             /* This is really just a guess */
+        udelay(100);
+}
+
+char    ppa_select( int  initiator, int target )
+
+{       char    r;
+        int     k;
+
+        r = in_p(1);
+        out_p(0,(1<<target)); out_p(2,0xe); out_p(2,0xc);
+        out_p(0,(1<<initiator)); out_p(2,0x8);
+
+        k = 0;
+        while ( !(r = (in_p(1) & 0xf0)) && (k++ < PPA_SELECT_TMO)) barrier();
+        return r;
+}
+
+char    ppa_wait( void ) 
+
+/*      Wait for the high bit to be set.
+
+        In principle, this could be tied to an interrupt, but the adapter
+        doesn't appear to be designed to support interrupts.  We spin on
+        the 0x80 ready bit.  If ppa_call_sched is 1, we call the scheduler 
+        to allow other processes to run while we are waiting, just like
+        the lp driver does in polling mode.  The performance hit is
+        significant, so this behaviour is configurable.
+
+*/
+
+{       int     k;
+        char    r;
+
+        ppa_error_code = DID_OK;
+        k = 0;
+        while (!((r = in_p(1)) & 0x80) 
+                && (k++ < PPA_SPIN_TMO) && !ppa_abort_flag  )
+                        if (need_resched && ppa_call_sched) schedule();
+        if (ppa_abort_flag) {
+                if (ppa_abort_flag == 1) ppa_error_code = DID_ABORT;
+                else {  ppa_do_reset();
+                        ppa_error_code = DID_RESET;
+                }
+                ppa_disconnect();
+                return 0;
+        }
+        if (k >= PPA_SPIN_TMO) { 
+                ppa_error_code = DID_TIME_OUT;
+                ppa_disconnect();
+                return 0;               /* command timed out */
+        }
+        return (r & 0xf0);
+}
+
+int     ppa_init( void )
+
+/* This is based on a trace of what the Iomega DOS 'guest' driver does.
+   I've tried several different kinds of parallel ports with guest and
+   coded this to react in the same ways that it does.
+
+   The return value from this function is just a hint about where the
+   handshaking failed.
+
+*/
+
+{       char    r, s;
+
+        out_p(0,0xaa); 
+        if (in_p(0) != (char) 0xaa) return 1; 
+        ppa_disconnect();
+        ppa_connect();
+        out_p(2,0x6); 
+        if ((in_p(1) & 0xf0) != 0xf0) return 2; 
+        out_p(2,0x4);
+        if ((in_p(1) & 0xf0) != 0x80) return 3; 
+        ppa_disconnect();
+        s = in_p(2);
+        out_p(2,0xec);
+        out_p(0,0x55); 
+        r = in_p(0);    
+        if (r != (char) 0xff) { 
+                ppa_nybble = 1;
+                if (r != (char) 0x55) return 4; 
+                out_p(0,0xaa); if (in_p(0) != (char) 0xaa) return 5; 
+        }
+        out_p(2,s);
+        ppa_connect();
+        out_p(0,0x40); out_p(2,0x8); out_p(2,0xc);
+        ppa_disconnect();
+
+        return 0;
+}
+
+int     ppa_start( Scsi_Cmnd * cmd )
+
+{       int     k;
+
+        ppa_error_code = DID_OK;
+        ppa_abort_flag = 0;
+
+        if (cmd->target == PPA_INITIATOR) {
+                ppa_error_code = DID_BAD_TARGET;
+                return 0;
+        }
+        ppa_connect();
+        if (!ppa_select(PPA_INITIATOR,cmd->target)) {
+                ppa_disconnect();
+                ppa_error_code = DID_NO_CONNECT;
+                return 0;
+        }
+        out_p(2,0xc);
+
+        for (k=0; k < cmd->cmd_len; k++) {        /* send the command */
+                if (!ppa_wait()) return 0;
+                out_p(0,cmd->cmnd[k]);
+                out_p(2,0xe);
+                out_p(2,0xc);
+        }
+
+#ifdef PPA_DEBUG
+        printk("PPA: command out: ");
+        for (k=0; k < cmd->cmd_len; k++)
+                printk("%3x",(cmd->cmnd[k]) & 0xff );
+        printk("\n");
+#endif
+
+        return 1;
+}
+
+int     ppa_completion( Scsi_Cmnd * cmd )
+
+/* The bulk flag enables some optimisations in the data transfer loops,
+   it should be true for any command that transfers data in integral
+   numbers of sectors.
+
+   The driver appears to remain stable if we speed up the parallel port
+   i/o in this function, but not elsewhere.
+*/
+
+{       char    r, l, h, v;
+        int     dir, cnt, blen, fast, bulk;
+        char    *buffer;
+
+#ifdef PPA_DEBUG
+        int     k;
+#endif
+
+        if (!(r = ppa_wait())) return 0;
+        v = cmd->cmnd[0];
+        bulk = ((v==READ_6)||(v==READ_10)||(v==WRITE_6)||(v==WRITE_10));
+        buffer = cmd->request_buffer;
+        blen = cmd->request_bufflen;
+        cnt = 0;  dir = 0;
+        if (r == (char) 0xc0) dir = 1;  /* d0 = read c0 = write f0 = status */
+
+        ppa_port_delay = ppa_speed_high;
+
+        while (r != (char) 0xf0) {
+                if (((r & 0xc0) != 0xc0 ) || (cnt >= blen)) {
+                        ppa_disconnect();
+                        ppa_error_code = DID_ERROR;
+                        return 0;
+                }
+                fast = bulk && ((blen - cnt) >= PPA_SECTOR_SIZE);
+                if (dir) do {
+                        out_p(0,buffer[cnt++]);
+                        out_p(2,0xe); out_p(2,0xc);
+                        if (!fast) break;
+                } while (cnt % PPA_SECTOR_SIZE);
+                else {  
+                        if (ppa_nybble) do {
+                                out_p(2,0x4); h = in_p(1); 
+                                out_p(2,0x6); l = in_p(1);
+                                v = ((l >> 4) & 0x0f) + (h & 0xf0);
+                                buffer[cnt++] = v;
+                                if (!fast) break;
+                        } while (cnt % PPA_SECTOR_SIZE);
+                        else do {
+                                out_p(2,0x25); v = in_p(0); out_p(2,0x27);
+                                buffer[cnt++] = v;
+                                if (!fast) break;
+                        } while (cnt % PPA_SECTOR_SIZE);
+                        if (!ppa_nybble) {
+                                out_p(2,0x5); out_p(2,0x4);
+                        }
+                        out_p(2,0xc);
+                }
+                if (!(r = ppa_wait())) return 0;
+        }
+
+        ppa_port_delay = ppa_speed_low;
+
+        out_p(2,0x4);            /* now read status byte */
+        h = in_p(1);
+        out_p(2,0x6);
+        l = in_p(1);
+        out_p(2,0xc);
+        r = ((l >> 4) & 0x0f) + (h & 0xf0);
+
+        out_p(2,0xe); out_p(2,0xc);
+        ppa_disconnect();
+
+#ifdef PPA_DEBUG
+        printk("PPA: status: %x, data[%d]: ",r & STATUS_MASK,cnt);
+        if (cnt > 12) cnt = 12;
+        for (k=0; k < cnt; k++)
+           printk("%3x",buffer[k] & 0xff );
+        printk("\n");   
+#endif
+
+        return (r & STATUS_MASK);
+}
+
+int     ppa_command( Scsi_Cmnd * cmd )
+
+{       int     s;
+
+        s = 0;
+        if (ppa_start(cmd))
+           if (ppa_wait()) 
+               s = ppa_completion(cmd);
+        return s + (ppa_error_code << 16);
+}
+
+int     ppa_queuecommand( Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
+
+/* This is not really a queued interface at all, but apparently there may
+   be some bugs in the mid-level support for the non-queued interface.
+   This function is re-entrant, but only to one level.
+*/
+
+{       int     s;
+
+        ppa_current = cmd; ppa_done = done;
+        if (ppa_busy) return 0;
+        ppa_busy = 1;
+        while (ppa_current) {
+                cmd = ppa_current;  done = ppa_done;
+                s = 0;
+                if (ppa_start(cmd))
+                    if (ppa_wait())
+                        s = ppa_completion(cmd);
+                cmd->result = s + (ppa_error_code << 16);
+                ppa_current = 0;
+                done(cmd);              /* can reenter this function */
+        }
+        ppa_busy = 0;
+        return 0;
+}
+
+int     ppa_detect( Scsi_Host_Template * host )
+
+{       struct  Scsi_Host       *hreg;
+        int     rs;
+
+        /* can we have the ports ? */
+
+        if (check_region(ppa_base,3)) {
+                printk("PPA: ports at 0x%3x are not available\n",ppa_base);
+                return 0;
+        }
+
+        /* attempt to initialise the controller */
+
+        ppa_port_delay = ppa_speed_low;
+
+        rs = ppa_init();
+        if (rs) {
+            printk("PPA: unable to initialise controller at 0x%x, error %d\n",
+                   ppa_base,rs);
+            return 0;
+        }
+
+        /* now the glue ... */
+
+        host->proc_dir = &proc_scsi_ppa;
+
+        request_region(ppa_base,3,"ppa");
+
+        host->can_queue = PPA_CAN_QUEUE;
+
+        hreg = scsi_register(host,0);
+        hreg->io_port = ppa_base;
+        hreg->n_io_port = 3;
+        hreg->dma_channel = -1;
+
+        sprintf(ppa_info_string,
+                "PPA driver version %s using %d-bit mode on port 0x%x.",
+                PPA_VERSION,8-ppa_nybble*4,ppa_base);
+        host->name = ppa_info_string;
+
+        return 1;       /* 1 host detected */
+}
+
+int     ppa_biosparam( Disk * disk, kdev_t dev, int ip[])
+
+/*  Apparently the the disk->capacity attribute is off by 1 sector 
+    for all disk drives.  We add the one here, but it should really
+    be done in sd.c.  Even if it gets fixed there, this will still
+    work.
+*/
+
+{       ip[0] = 0x40;
+        ip[1] = 0x20;
+        ip[2] = (disk->capacity +1) / (ip[0] * ip[1]);
+        if (ip[2] > 1024) {
+                ip[0] = 0xff;
+                ip[1] = 0x3f;
+                ip[2] = (disk->capacity +1) / (ip[0] * ip[1]);
+                if (ip[2] > 1023)
+                        ip[2] = 1023;
+        }
+        return 0;
+}
+
+int     ppa_abort( Scsi_Cmnd * cmd )
+
+{       ppa_abort_flag = 1;
+        return SCSI_ABORT_SNOOZE;
+}
+
+int     ppa_reset( Scsi_Cmnd * cmd )
+
+{       ppa_abort_flag = 2;
+        return SCSI_RESET_PUNT;
+}
+
+const char      *ppa_info( struct Scsi_Host * host )
+
+{       return ppa_info_string;
+}
+
+#ifndef MODULE
+
+/* Command line parameters (for built-in driver):
+
+   Syntax:  ppa=base[,speed_high[,speed_low[,call_sched[,nybble]]]]
+
+   For example:  ppa=0x378   or   ppa=0x378,0,3
+
+*/
+
+void    ppa_setup(char *str, int *ints)
+
+{       if (ints[0] > 0) ppa_base = ints[1];
+        if (ints[0] > 1) ppa_speed_high = ints[2];
+        if (ints[0] > 2) ppa_speed_low = ints[3];
+        if (ints[0] > 3) ppa_call_sched = ints[4];
+        if (ints[0] > 4) ppa_nybble = ints[5];
+}
+
+#else
+
+Scsi_Host_Template      driver_template = PPA;
+
+#include  "scsi_module.c"
+
+#endif
+
+/* end of ppa.c */
diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
new file mode 100644 (file)
index 0000000..9dbfe7e
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _PPA_H
+#define _PPA_H
+
+/*  Driver for the PPA3 parallel port SCSI HBA embedded in 
+    the Iomega ZIP drive
+
+       (c) 1996        Grant R. Guenther  grant@torque.net
+*/
+
+#define        PPA_INITIATOR   7
+
+int ppa_detect(Scsi_Host_Template * );
+const char * ppa_info(struct Scsi_Host *);
+int ppa_command(Scsi_Cmnd *);
+int ppa_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int ppa_abort(Scsi_Cmnd *);
+int ppa_reset(Scsi_Cmnd *);
+int ppa_biosparam(Disk *, kdev_t, int[]);
+
+#define PPA {                  \
+       0,                      \
+       0,                      \
+       0,                      \
+       0,                      \
+       0,                      \
+       ppa_detect,             \
+       0,                      \
+       ppa_info,               \
+       ppa_command,            \
+       ppa_queuecommand,       \
+       ppa_abort,              \
+       ppa_reset,              \
+       0,                      \
+       ppa_biosparam,          \
+       0,                      \
+       PPA_INITIATOR,          \
+       SG_NONE,                \
+       1,                      \
+       0,                      \
+       0,                      \
+       DISABLE_CLUSTERING      \
+}
+
+#endif /* _PPA_H */
index 21e6749529f802cdfe00ca41518d4d31be87fcf8..14a009dc4d11a0c26216cdb6f74c6504f37aba0f 100644 (file)
@@ -2143,7 +2143,7 @@ static int st_detect(Scsi_Device * SDp)
 {
   if(SDp->type != TYPE_TAPE) return 0;
 
-  printk(KERN_NOTICE "Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
+  printk("Detected scsi tape st%d at scsi%d, channel %d, id %d, lun %d\n", 
         st_template.dev_noticed++,
         SDp->host->host_no, SDp->channel, SDp->id, SDp->lun); 
   
index 66852d4827ae351d31b884acd1b7b10d575e2583..da9386a92a2cfaae67c6ae995fd82d28db071f71 100644 (file)
@@ -1,6 +1,8 @@
 *********************************************************
 * Readme.cards (this directory) contains some card     *
 * specific instructions.                               *
+* See http://personal.eunet.fi/pp/voxware for most up   *
+* to date info.                                         *
 *                                                      *
 * DON'T USE PROGRAMS FROM SND_UTIL PACKAGE EARLIER THAN *
 * snd-util-3.5 WITH THIS SOUND DRIVER VERSION.          *
index 5d3bc2d53b8b2ad58cd0d39e2f0561999ed8be33..8a3d0c91117f23f33b008eaaa5191e694e73bd49 100644 (file)
@@ -1,2 +1,2 @@
-3.5-beta10
-0x030505
+3.5
+0x030500
index abfc426dede1b04600e01a0d0d58b1bcc19a9066..421c2719c575f6e217f7997f9e51ae9d2e022b7f 100644 (file)
@@ -1,7 +1,13 @@
-Changelog for version 3.5-beta10
---------------------------------
+Changelog for version 3.5
+-------------------------
 
-Since 3.5-beta8
+Since 3.5
+- Improved handling of playback underrunt situations.
+
+Since 3.5-beta10
+- Bug fixing
+
+Since 3.5-beta9
 - Fixed for compatibility with Linux 1.3.70 and later.
 - Changed boot time passing of 16 bit DMA channel number to SB driver.
 
index 50d8969cf4f21f54ed320f17ce1a5398c5e2f22f..c9d1fec52f81403231c0494a053b40513d26d285 100644 (file)
@@ -70,7 +70,7 @@ sound.a: $(OBJS)
 
 clean:
        rm -f core core.* *.o *.a tmp_make *~ x y z *%
-       rm -f configure sound_stub.c objects/*.o 
+       rm -f configure sound_stub.c objects/*.o
 
 indent:
        for n in *.c;do echo indent $$n;indent $$n;done
index 807177dfc65353deda05b85df09c03cf6735610e..1c65fb427ab622b32af033f27f5a0fe7969dbbe2 100644 (file)
@@ -1,4 +1,4 @@
-Version 3.5-beta10 release notes
+Version 3.5-beta11 release notes
 --------------------------------
 
 Most up to date information about this driver is available from 
index 02217f2bde701e7556caf034c2060e81de1859d1..17f58e2f2635ec10215b0b769986f3bd6c5a2196 100644 (file)
@@ -43,8 +43,8 @@ Read this before trying to configure the driver
 -----------------------------------------------
 
 There are currently many cards that work with this driver. Some of the cards
-have native support while the others work since they emulate some other
-cards (usually SB, MSS/WSS and/or MPU401). The following cards have native
+have native support while others work since they emulate some other
+card (usually SB, MSS/WSS and/or MPU401). The following cards have native
 support in the driver. Detailed instructions for configuring these cards
 will be given later in this document.
 
@@ -65,16 +65,17 @@ Sound Blasters
        SB 1.0 to 2.0
        SB Pro
        SB 16
-       NOTE!   The ASP chip and the EMU synth of the AWE32 is not supported 
+       NOTE!   The ASP chip and the EMU synth of AWE32 are not supported 
                since their manufacturer doesn't release information about
-               the card. However both the AB16ASP and the AWE32 work with
+               the card. However, both SB16ASP and AWE32 work with
                the driver just like a SB16. Also see the comment about some
                unsupported cards at the end of this file.
+               (The OPL3 FM chip of SB32/AWE works but you cannot hear it).
        SB16 compatible cards by other manufacturers than Creative.
                You have been fooled since there are no SB16 compatible
-               cards in the market (July95). It's likely that your card
-               is compatible just with SB Pro but there is also a non SB
-               compatible 16 bit mode. Usually it's MSS/WSS but could also
+               cards on the market (Feb 96). It's likely that your card
+               is compatible just with SB Pro but there is also a non-SB-
+               compatible 16 bit mode. Usually it's MSS/WSS but it could also
                be a proprietary one like MV Jazz16 or ESS ES688.
 
 Gravis Ultrasound (GUS)
@@ -88,26 +89,26 @@ MPU-401     and compatibles
        The driver works both with the full (intelligent mode) MPU-401
        cards (such as MPU IPC-T and MQX-32M) and with the UART only
        dumb MIDI ports. MPU-401 is currently the most common MIDI
-       interface. Most soundcards are compatible with it. However
-       don't enable MPU401 mode blindly. Many cards having native support
+       interface. Most soundcards are compatible with it. However,
+       don't enable MPU401 mode blindly. Many cards with native support
        in the driver have their own MPU401 driver. Enabling the standard one
-       will cause a conflict with these cards. So look if your card is
+       will cause a conflict with these cards. So check if your card is
        in the list of supported cards before enabling MPU401.
 
 Windows Sound System (MSS/WSS)
-       Even Microsoft has discontinued their own Sound System card, they
-       managed to make a standard. MSS compatible cards are based on a 
-       codec chip which is easily available from at least two manufacturers
+       Even when Microsoft has discontinued their own Sound System card 
+       they managed to make it a standard. MSS compatible cards are based on 
+       codec chip which is easily available from at least two manufacturers
        (AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
        Currently most soundcards are based on one of the MSS compatible codec
-       chip. The CS4231 is used in the high quality cards such as GUS MAX,
+       chips. The CS4231 is used in the high quality cards such as GUS MAX,
        MediaTriX AudioTriX Pro and TB Tropez (GUS MAX is not MSS compatible). 
 
        Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
        sign. Even if the card is not MSS compatible, it could be easy to write
        support for it. Note also that most MSS compatible cards
        require special boot time initialization which may not be present
-       in in the driver. Also some MSS compatible cards have native support.
+       in the driver. Also, some MSS compatible cards have native support.
        Enabling the MSS support with these cards is likely to
        cause a conflict. So check if your card is listed in this file before
        enabling the MSS support.
@@ -121,9 +122,9 @@ Yamaha FM synthesizers (OPL2, OPL3 and OPL4)
        operator chip used in the original AdLib card. Currently it's used
        only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator 
        FM chip which provides better sound quality and/or more available 
-       voices than the OPL2. The OPL4 is a new chip which has a OPL3 and
-       a wave table synthesizer packed on the same chip. The driver supports
-       just the OPL3 mode directly. Most cards having a OPL4 (like
+       voices than the OPL2. The OPL4 is a new chip that has an OPL3 and
+       a wave table synthesizer packed onto the same chip. The driver supports
+       just the OPL3 mode directly. Most cards with an OPL4 (like
        SM Wave and AudioTriX Pro) support the OPL4 mode using MPU401
        emulation. Writing a native OPL4 support is difficult
        since Yamaha doesn't give information about their sample ROM chip.
@@ -143,7 +144,7 @@ PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC)
        The driver supports downloading DSP algorithms to these cards.
 
 MediaTriX AudioTriX Pro
-       The ATP card is built around a CS4231 codec and a OPL4 synthesizer
+       The ATP card is built around a CS4231 codec and an OPL4 synthesizer
        chips. The OPL4 mode is supported by a microcontroller running a
        General MIDI emulator. There is also a SB 1.5 compatible playback mode.
 
@@ -158,28 +159,30 @@ Ensoniq SoundScape and compatibles
 MAD16 and Mozart based cards
        The Mozart (OAK OTI-601) and MAD16 Pro (OPTi 82C929) interface
        chips are used in many different soundcards, including some
-       cards by Reveal and Turtle Beach (Tropez). Purpose of these
+       cards by Reveal and Turtle Beach (Tropez). The purpose of these
        chips is to connect other audio components to the PC bus. The
        interface chip performs address decoding for the other chips.
+       NOTE! Tropez Plus is not MAD16 but CS4232 based.
 
 Audio Excell DSP16 
-       Support for this card is made by Riccardo Faccetti
+       Support for this card was written by Riccardo Faccetti
        (riccardo@cdc8g5.cdc.polimi.it). See aedsp16.c for more info.
+       (This driver is not functional in version 3.5 of this driver).
        
-Crystal CS4232 based cards such as AcerMagic S23 and many PC motherboards
-       (Compaq, HP, Intel, ...).
+Crystal CS4232 based cards such as AcerMagic S23, TB Tropez _Plus_ and 
+       many PC motherboards (Compaq, HP, Intel, ...)
        CS4232 is a PnP multimedia chip which contains a CS3231A codec,
        SB and MPU401 emulations. There is support for OPL3 too.
        This is a temporary driver which uses the chip in non PnP mode
        (The final driver should be included in version 3.6 of the driver).
-       Unfortunately the MPU401 mode doesn't work. The chip may also stop
-       working after it has been used few times (only cold boot resets it).
+       Unfortunately the MPU401 mode doesn't work (I don't know how to
+       initialize it). 
 
 Turtle Beach Maui and Tropez
        This driver version supports sample, patch and program loading commands
        described in the Maui/Tropez User's manual. There is no initialization
-       code for Maui so it must be initialized using DOS. Audio side of Tropez
-       is based on the MAD16 chip (see above).
+       code for Maui so it must be initialized with DOS. The audio side of
+       the Tropez is based on the MAD16 chip (see above).
 
 Jumpers and software configuration
 ----------------------------------
@@ -310,6 +313,10 @@ select some options automaticly as well.
          you read the above list correctly). Don't answer 'y' if you
          have some other card made by Media Vision or Logitech since they
          are not PAS16 compatible.
+         NOTE! Since 3.5-beta10 you need to enable SB support (next question)
+         if you want to use the SB emulation of PAS16. It's also possible to
+         the emulation if you want to use a true SB card together with PAS16
+         (there is another question about this that is asked later).
   "SoundBlaster support",
        - Answer 'y' if you have an original SB card made by Creative Labs
          or a full 100% hardware compatible clone (like Thunderboard or
@@ -317,6 +324,7 @@ select some options automaticly as well.
          please look at the card specific instructions later in this file
          before answering this question. For an unknown card you may answer 
          'y' if the card claims to be SB compatible.
+        Enable this option also with PAS16 (changed since v3.5-beta9).
 
         Don't enable SB if you have a MAD16 or Mozart compatible card.
 
@@ -477,11 +485,15 @@ simultaneously. Using the MSS mode provides 16 bit recording and playback.
 ProAudioSpectrum 16 and compatibles
 -----------------------------------
 
-There are nothing special with these cards. Just don't enable any
-other cards in case you don't have them also. The PAS16 has
-a SB mode so the driver config program will prompt for the SB settings
-do. Use I/O 0x220 and DMA1 for the SB mode. Ensure that you assign different
-IRQ numbers for the SB and PAS16 modes.
+PAS16 has a SB emulation chip which can be used together with the native
+(16 bit) mode of the card. To enable this emulation you should configure 
+the driver to have SB support too (this has been changed since version
+3.5-beta9 of this driver).
+
+With current driver versions it's also possible to use PAS16 together with 
+another SB compatible card. In this case you should configure SB support
+for the other card and to disable the SB emulation of PAS16 (there is a
+separate questions about this).
 
 With PAS16 you can use two audio device files at the same time. /dev/dsp (and
 /dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
@@ -773,11 +785,15 @@ SG NX Pro. Answer 'y' to these questions if you have one of the above 8 or
 There are some new Sound Galaxies in the market. I have no experience with
 them so read the card's manual carefully.
 
-ESS ES1688 'AudioDrive' based cards
------------------------------------
+ESS ES1688 and ES688 'AudioDrive' based cards
+---------------------------------------------
 
 Configure these cards just like SB Pro. Enable the 'SB MPU401 MIDI port'
-if you want to use MIDI features of the card.
+if you want to use MIDI features of ES1688. ES688 doesn't have MPU mode
+so you don't need to enable it (the driver uses normal SB MIDI automaticly
+with ES688).
+
+NOTE! ESS cards are not compatible with MSS/WSS.
 
 Reveal cards
 ------------
index a37ab3515dd4047593982039c8ae0cd096ac78ae..c429d196c946341e46e4fd409474b7b6dad78e28 100644 (file)
@@ -164,6 +164,23 @@ fi
 mknod -m 666 /dev/dsp0 c 14 3
 ln -s /dev/dsp0 /dev/dsp
 
+#
+#      DSPW            (14, 5)
+#
+if [ -e /dev/dspW ]; then
+       rm -f /dev/dspW
+fi
+if [ -e /dev/dspW0 ]; then
+       rm -f /dev/dspW0
+fi
+mknod -m 666 /dev/dspW0 c 14 5
+ln -s /dev/dspW0 /dev/dspW
+
+if [ -e /dev/dspW1 ]; then
+       rm -f /dev/dspW1
+fi
+mknod -m 666 /dev/dspW1 c 14 37
+
 #
 #      SPARC compatible /dev/audio     (14, 4) 
 #
index 1d6009bf293bee6cb93925d07612aa1a037d2c5a..0939d8de317218ed04a0a9460ba67f4dbe2bacbc 100644 (file)
@@ -192,7 +192,7 @@ wait_for_calibration (ad1848_info * devc)
   if (!(ad_read (devc, 11) & 0x20))
     return;
 
-  timeout = 40000;
+  timeout = 80000;
   while (timeout > 0 && ad_read (devc, 11) & 0x20)
     timeout--;
   if (ad_read (devc, 11) & 0x20)
@@ -202,11 +202,33 @@ wait_for_calibration (ad1848_info * devc)
 static void
 ad_mute (ad1848_info * devc)
 {
+  int             i;
+  unsigned char   prev;
+
+  if (devc->mode != MD_1848)
+    return;
+  /*
+     * Save old register settings and mute output channels
+   */
+  for (i = 6; i < 8; i++)
+    {
+      prev = devc->saved_regs[i] = ad_read (devc, i);
+      ad_write (devc, i, prev | 0x80);
+    }
 }
 
 static void
 ad_unmute (ad1848_info * devc)
 {
+  int             i;
+
+  /*
+     * Restore back old volume registers (unmute)
+   */
+  for (i = 6; i < 8; i++)
+    {
+      ad_write (devc, i, devc->saved_regs[i] & ~0x80);
+    }
 }
 
 static void
@@ -928,7 +950,7 @@ static int
 ad1848_prepare_for_IO (int dev, int bsize, int bcount)
 {
   int             timeout;
-  unsigned char   fs, old_fs;
+  unsigned char   fs, old_fs, tmp = 0;
   unsigned long   flags;
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
 
@@ -952,15 +974,22 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
 
   old_fs = ad_read (devc, 8);
 
-  if (fs == old_fs)            /* No change */
-    {
-      restore_flags (flags);
-      devc->xfer_count = 0;
-      return 0;
-    }
+  if (devc->mode != MD_4232)
+    if (fs == old_fs)          /* No change */
+      {
+       restore_flags (flags);
+       devc->xfer_count = 0;
+       return 0;
+      }
 
   ad_enter_MCE (devc);         /* Enables changes to the format select reg */
 
+  if (devc->mode == MD_4232)
+    {
+      tmp = ad_read (devc, 16);
+      ad_write (devc, 16, tmp | 0x30);
+    }
+
   ad_write (devc, 8, fs);
   /*
    * Write to I8 starts resyncronization. Wait until it completes.
@@ -985,6 +1014,9 @@ ad1848_prepare_for_IO (int dev, int bsize, int bcount)
 
     }
 
+  if (devc->mode == MD_4232)
+    ad_write (devc, 16, tmp & ~0x30);
+
   ad_leave_MCE (devc);         /*
                                 * Starts the calibration process.
                                 */
@@ -1011,38 +1043,14 @@ static void
 ad1848_halt (int dev)
 {
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
-  unsigned long   flags;
-  int             timeout;
-
-
-  save_flags (flags);
-  cli ();
-
-  ad_mute (devc);
-  ad_enter_MCE (devc);
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
 
-  ad_write (devc, 15, 4);      /* Clear DMA counter */
-  ad_write (devc, 14, 0);      /* Clear DMA counter */
+  unsigned char   bits = ad_read (devc, 9);
 
-  if (devc->mode != MD_1848)
-    {
-      ad_write (devc, 30, 4);  /* Clear DMA counter */
-      ad_write (devc, 31, 0);  /* Clear DMA counter */
-    }
+  if (bits & 0x01)
+    ad1848_halt_output (dev);
 
-  for (timeout = 0; timeout < 10000 && !(inb (io_Status (devc)) & 0x80);
-       timeout++);             /* Wait for interrupt */
-
-  ad_write (devc, 9, ad_read (devc, 9) & ~0x03);       /* Stop DMA */
-  outb (0, io_Status (devc));  /* Clear interrupt status */
-  outb (0, io_Status (devc));  /* Clear interrupt status */
-  devc->irq_mode = 0;
-  ad_leave_MCE (devc);
-
-  /* DMAbuf_reset_dma (dev); */
-  restore_flags (flags);
+  if (bits & 0x02)
+    ad1848_halt_input (dev);
 }
 
 static void
@@ -1051,16 +1059,26 @@ ad1848_halt_input (int dev)
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
-  if (devc->mode == MD_1848)
-    {
-      ad1848_halt (dev);
-      return;
-    }
-
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
+
+  if (devc->mode == MD_4232)   /* Use applied black magic */
+    {
+      int             tmout;
+
+      disable_dma (audio_devs[dev]->dmachan1);
+
+      for (tmout = 0; tmout < 100000; tmout++)
+       if (ad_read (devc, 11) & 0x10)
+         break;
+      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);   /* Stop playback */
+
+      enable_dma (audio_devs[dev]->dmachan1);
+      restore_flags (flags);
+      return;
+    }
   ad_write (devc, 9, ad_read (devc, 9) & ~0x02);       /* Stop capture */
 
 
@@ -1078,16 +1096,25 @@ ad1848_halt_output (int dev)
   ad1848_info    *devc = (ad1848_info *) audio_devs[dev]->devc;
   unsigned long   flags;
 
-  if (devc->mode == MD_1848)
-    {
-      ad1848_halt (dev);
-      return;
-    }
-
   save_flags (flags);
   cli ();
 
   ad_mute (devc);
+  if (devc->mode == MD_4232)   /* Use applied black magic */
+    {
+      int             tmout;
+
+      disable_dma (audio_devs[dev]->dmachan1);
+
+      for (tmout = 0; tmout < 100000; tmout++)
+       if (ad_read (devc, 11) & 0x10)
+         break;
+      ad_write (devc, 9, ad_read (devc, 9) & ~0x01);   /* Stop playback */
+
+      enable_dma (audio_devs[dev]->dmachan1);
+      restore_flags (flags);
+      return;
+    }
   ad_write (devc, 9, ad_read (devc, 9) & ~0x01);       /* Stop playback */
 
 
@@ -1503,7 +1530,7 @@ ad1848_init (char *name, int io_base, int irq, int dma_playback, int dma_capture
       nr_ad1848_devs++;
 
 #ifdef CONFIG_SEQUENCER
-      if (devc->mode != MD_1848 && devc->irq_ok)
+      if (devc->mode != MD_1848 && devc->mode != MD_1845 && devc->irq_ok)
        ad1848_tmr_install (my_dev);
 #endif
 
@@ -1592,7 +1619,7 @@ ad1848_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
 
       if (irq > 15)
        {
-         printk ("ad1848.c: Bogus interrupt %d\n", irq);
+         /* printk ("ad1848.c: Bogus interrupt %d\n", irq); */
          return;
        }
 
index e10831eecd14099911780e433b9f0f46f990c64b..9c6ba0d45ecf7b21826c4530fec0d54a85cb6b8b 100644 (file)
@@ -1,38 +1,13 @@
 /*
  *      PnP soundcard support is not included in this version.
  *
- *       AEDSP16 will not work without significant changes.
- *
- *       SB Pro and SB16 drivers are always enabled together with SB.
+ *      AEDSP16 will not work without significant changes.
  */
-#define DISABLED_OPTIONS       (B(OPT_PNP)|B(OPT_AEDSP16)|B(OPT_SBPRO)|B(OPT_SB16))
+#define DISABLED_OPTIONS       (B(OPT_PNP)|B(OPT_AEDSP16)|B(OPT_UNUSED1)|B(OPT_UNUSED2))
 /*
  * sound/configure.c  - Configuration program for the Linux Sound Driver
  */
-/*
- * Copyright by Hannu Savolainen 1993-1996
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer. 2.
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
+#define COPYING2
 
 #include <stdio.h>
 #include <unistd.h>
 #define OPT_PNP                15
 
 #define OPT_HIGHLEVEL   16     /* This must be same than the next one */
-#define OPT_SBPRO      16
-#define OPT_SB16       17
+#define OPT_UNUSED1    16
+#define OPT_UNUSED2    17
 #define OPT_AEDSP16     18
 #define OPT_AUDIO      19
 #define OPT_MIDI_AUTO  20
 #define OPT_MIDI       21
 #define OPT_YM3812_AUTO        22
 #define OPT_YM3812     23
-#define OPT_SEQUENCER  24
-#define OPT_LAST       24      /* Last defined OPT number */
+#define OPT_LAST       23      /* Last defined OPT number */
 
 #define DUMMY_OPTS (B(OPT_MIDI_AUTO)|B(OPT_YM3812_AUTO))
 
-#define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_SEQUENCER)|B(OPT_GUS)| \
+#define ANY_DEVS (B(OPT_AUDIO)|B(OPT_MIDI)|B(OPT_GUS)| \
                  B(OPT_MPU401)|B(OPT_PSS)|B(OPT_GUS16)|B(OPT_GUSMAX)| \
                  B(OPT_MSS)|B(OPT_SSCAPE)|B(OPT_UART6850)|B(OPT_TRIX)| \
                  B(OPT_MAD16)|B(OPT_CS4232)|B(OPT_MAUI))
@@ -94,6 +68,7 @@
 #define AD1848_DEVS (B(OPT_GUS16)|B(OPT_MSS)|B(OPT_PSS)|B(OPT_GUSMAX)|\
                     B(OPT_SSCAPE)|B(OPT_TRIX)|B(OPT_MAD16)|B(OPT_CS4232)|\
                     B(OPT_PNP))
+#define SEQUENCER_DEVS (OPT_MIDI|OPT_YM3812|OPT_ADLIB|OPT_GUS|OPT_MAUI|MIDI_CARDS)
 /*
  * Options that have been disabled for some reason (incompletely implemented
  * and/or tested). Don't remove from this list before looking at file
@@ -150,15 +125,14 @@ hw_entry        hw_table[] =
   {0, 0, "MAUI", 1, 0, 0},
   {0, 0, "PNP", 1, 0, 0},
 
-  {B (OPT_SB), B (OPT_PAS), "SBPRO", 1, 0, 1},
-  {B (OPT_SB) | B (OPT_SBPRO), B (OPT_PAS), "SB16", 1, 0, 1},
-  {B (OPT_SBPRO) | B (OPT_MSS) | B (OPT_MPU401), 0, "AEDSP16", 1, 0, 0},
+  {B (OPT_SB), B (OPT_PAS), "UNUSED1", 1, 0, 1},
+  {B (OPT_SB) | B (OPT_UNUSED1), B (OPT_PAS), "UNUSED2", 1, 0, 1},
+  {B (OPT_UNUSED1) | B (OPT_MSS) | B (OPT_MPU401), 0, "AEDSP16", 1, 0, 0},
   {AUDIO_CARDS, 0, "AUDIO", 1, 0, 1},
   {B (OPT_MPU401) | B (OPT_MAUI), 0, "MIDI_AUTO", 0, OPT_MIDI, 0},
   {MIDI_CARDS, 0, "MIDI", 1, 0, 1},
   {B (OPT_ADLIB), 0, "YM3812_AUTO", 0, OPT_YM3812, 0},
-  {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB) | B (OPT_MSS) | B (OPT_PSS), B (OPT_YM3812_AUTO), "YM3812", 1, 0, 1},
-  {B (OPT_MIDI) | B (OPT_YM3812) | B (OPT_YM3812_AUTO) | B (OPT_GUS), 0, "SEQUENCER", 0, 0, 1}
+  {B (OPT_PSS) | B (OPT_SB) | B (OPT_PAS) | B (OPT_ADLIB) | B (OPT_MSS) | B (OPT_PSS), B (OPT_YM3812_AUTO), "YM3812", 1, 0, 1}
 };
 
 char           *questions[] =
@@ -180,15 +154,14 @@ char           *questions[] =
   "Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers",
   "Support for PnP sound cards (_EXPERIMENTAL_)",
 
-  "SoundBlaster Pro support",
-  "SoundBlaster 16 support",
+  "*** Unused option 1 ***",
+  "*** Unused option 2 ***",
   "Audio Excel DSP 16 initialization support",
   "/dev/dsp and /dev/audio support",
   "This should not be asked",
   "MIDI interface support",
   "This should not be asked",
   "FM synthesizer (YM3812/OPL-3) support",
-  "/dev/sequencer support",
   "Is the sky really falling"
 };
 
@@ -248,7 +221,7 @@ char           *help[] =
   "them. In addition the MAD16 chip is used in some cards made by known\n"
   "manufacturers such as Turtle Beach (Tropez), Reveal (some models) and\n"
   "Diamond (latest ones).\n",
-
+  
   "Enable this if you have a card based on the Crystal CS4232 chip set.\n",
 
   "Enable this option if you have a Turtle Beach Wave Front, Maui,\n"
@@ -273,15 +246,12 @@ char           *help[] =
   "This enables the dev/midixx devices and access to any MIDI ports\n"
   "using /dev/sequencer and /dev/music. This option also affects any\n"
   "MPU401 and/or General MIDI compatible devices.\n",
-
+  
   "This should not be asked",
 
   "This enables the Yamaha FM synthesizer chip used on many sound\n"
   "cards.\n",
 
-  "This enables the /dev/sequencer and /dev/music devices used for\n"
-  "playing computer music.\n",
-
   "Is the sky really falling"
 };
 
@@ -300,6 +270,10 @@ extra_options[] =
     "AD1848", AD1848_DEVS
   }
   ,
+  {
+    "SEQUENCER", SEQUENCER_DEVS
+  }
+  ,
   {
     NULL, 0
   }
@@ -323,6 +297,21 @@ int             bin2hex (char *path, char *target, char *varname);
 int
 can_select_option (int nr)
 {
+#if 0
+  switch (nr)
+    {
+    case OPT_LAST_MUTUAL + 1:
+      fprintf (stderr, "\nThe following cards should work with any other cards.\n"
+              "CAUTION! Don't enable MPU-401 if you don't have it.\n");
+      break;
+
+    case OPT_HIGHLEVEL:
+      fprintf (stderr, "\nSelect one or more of the following options\n");
+      break;
+
+
+    }
+#endif
 
   if (hw_table[nr].conditions)
     if (!(hw_table[nr].conditions & selected_options))
@@ -344,12 +333,12 @@ think_positively (char *prompt, int def_answ, char *help)
   char            answ[512];
   int             len;
 
-response:
-  fprintf (stderr, prompt);
+  response:
+  fprintf(stderr, prompt);
   if (def_answ)
-    fprintf (stderr, " [Y/n/?] ");
+    fprintf(stderr, " [Y/n/?] ");
   else
-    fprintf (stderr, " [N/y/?] ");
+    fprintf(stderr, " [N/y/?] ");
 
   if ((len = read (0, answ, sizeof (answ))) < 1)
     {
@@ -365,13 +354,12 @@ response:
                                 */
     return def_answ;
 
-  if (answ[0] == '?')
-    {                          /* display help message */
-      fprintf (stderr, "\n");
-      fprintf (stderr, help);
-      fprintf (stderr, "\n");
-      goto response;
-    }
+  if (answ[0] == '?') {                /* display help message */
+    fprintf(stderr, "\n");
+    fprintf(stderr, help);
+    fprintf(stderr, "\n");
+    goto response;
+  }
 
   answ[len - 1] = 0;
 
@@ -432,7 +420,7 @@ ask_int_choice (int mask, char *macro,
       for (i = 0; i < OPT_LAST; i++)
        if (mask == B (i))
          {
-           unsigned int    j;
+           unsigned int             j;
 
            for (j = 0; j < strlen (choices); j++)
              if (choices[j] == '\'')
@@ -453,7 +441,7 @@ ask_int_choice (int mask, char *macro,
        return;
 
       fprintf (stderr, "\n%s\n", question);
-      if (strcmp (choices, ""))
+      if (strcmp(choices, ""))
        fprintf (stderr, "Possible values are: %s\n", choices);
 
       if (format == FMT_INT)
@@ -591,18 +579,18 @@ use_old_config (char *filename)
            continue;
 
          if (strcmp (tmp, "JAZZ_DMA16") == 0)  /* Rename it (hack) */
-           {
-             printf ("#define SB_DMA2 %s\n",
-                     &buf[18]);
-             continue;
-           }
+         {
+               printf("#define SB_DMA2 %s\n",
+                       &buf[18]);
+               continue;
+         }
 
          if (strcmp (tmp, "SB16_DMA") == 0)    /* Rename it (hack) */
-           {
-             printf ("#define SB_DMA2 %s\n",
-                     &buf[16]);
-             continue;
-           }
+         {
+               printf("#define SB_DMA2 %s\n",
+                       &buf[16]);
+               continue;
+         }
 
          tmp[8] = 0;           /* Truncate the string */
          if (strcmp (tmp, "EXCLUDE_") == 0)
@@ -690,11 +678,14 @@ use_old_config (char *filename)
   printf ("#define SELECTED_SOUND_OPTIONS\t0x%08x\n", selected_options);
   fprintf (stderr, "Old configuration copied.\n");
 
+#ifdef linux
   build_defines ();
+#endif
   old_config_used = 1;
   return 1;
 }
 
+#ifdef linux
 void
 build_defines (void)
 {
@@ -712,6 +703,10 @@ build_defines (void)
     if (!hw_table[i].alias)
       if (selected_options & B (i))
        fprintf (optf, "CONFIG_%s=y\n", hw_table[i].macro);
+#if 0
+      else
+       fprintf (optf, "CONFIG_%s=n\n", hw_table[i].macro);
+#endif
 
 
   fprintf (optf, "\n");
@@ -722,16 +717,22 @@ build_defines (void)
     {
       if (selected_options & extra_options[i].mask)
        fprintf (optf, "CONFIG_%s=y\n", extra_options[i].name);
+#if 0
+      else
+       fprintf (optf, "CONFIG_%s=n\n", extra_options[i].name);
+#endif
       i++;
     }
 
   fprintf (optf, "\n");
   fclose (optf);
 }
+#endif
 
 void
 ask_parameters (void)
 {
+#ifdef linux
   int             num;
 
   build_defines ();
@@ -764,7 +765,7 @@ ask_parameters (void)
                  "0, 1 or 3");
 
   ask_int_choice (B (OPT_SB), "SB_DMA2",
-               "SoundBlaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW)",
+                 "SoundBlaster 16 bit DMA (_REQUIRED_for SB16, Jazz16, SMW)",
                  FMT_INT,
                  5,
                  "5, 6 or 7");
@@ -796,17 +797,21 @@ ask_parameters (void)
   if (selected_options & B (OPT_PAS))
     {
       if (think_positively ("Enable Joystick port on ProAudioSpectrum", 0,
-       "Enable this option if you want to use the joystick port provided\n"
-                           "on the PAS sound card.\n"));
-
-      printf ("#define PAS_JOYSTICK_ENABLE\n");
+      "Enable this option if you want to use the joystick port provided\n"
+      "on the PAS sound card.\n"))
+         printf ("#define PAS_JOYSTICK_ENABLE\n");
 
       if (think_positively ("Enable PAS16 bus clock option", 0,
-       "The PAS16 can be noisy with some motherboards. There is a command\n"
-       "line switch (:T?) in the DOS driver for PAS16 which solves this.\n"
+      "The PAS16 can be noisy with some motherboards. There is a command\n"
+      "line switch (:T?) in the DOS driver for PAS16 which solves this.\n"
       "Don't enable this feature unless you have problems and have to use\n"
-                           "this switch with DOS\n"))
+      "this switch with DOS\n"))
        printf ("#define BROKEN_BUS_CLOCK\n");
+
+      if (think_positively ("Disable SB mode of PAS16", 0,
+      "You should disable SB emulation of PAS16 if you want to use\n"
+      "Another SB compatible card in the same system\n"))
+         printf ("#define DISABLE_SB_EMULATION\n");
     }
 
   ask_int_choice (B (OPT_GUS), "GUS_BASE",
@@ -984,10 +989,10 @@ ask_parameters (void)
       int             reveal_spea;
 
       reveal_spea = think_positively (
-                 "Is your SoundScape card made/marketed by Reveal or Spea",
-                                      0,
-                "Enable if you have a SoundScape card with the Reveal or\n"
-                                      "Spea name on it.\n");
+        "Is your SoundScape card made/marketed by Reveal or Spea",
+       0,
+       "Enable if you have a SoundScape card with the Reveal or\n"
+       "Spea name on it.\n");
       if (reveal_spea)
        printf ("#define REVEAL_SPEA\n");
 
@@ -1118,6 +1123,7 @@ ask_parameters (void)
                  FMT_INT,
                  9,
                  "5, 7, 9 or 10");
+#endif
   ask_int_choice (B (OPT_AUDIO), "DSP_BUFFSIZE",
                  "Audio DMA buffer size",
                  FMT_INT,
@@ -1137,11 +1143,18 @@ dump_script (void)
          printf ("bool '%s' CONFIG_%s\n", questions[i], hw_table[i].macro);
        }
 
+/*
+ * Some "hardcoded" options
+ */
+  printf ("bool 'Support for SM Wave' CONFIG_SMWAVE\n");
+
   dump_only = 1;
   selected_options = 0;
   ask_parameters ();
 
+#if 1
   printf ("#\n$MAKE -C drivers/sound kernelconfig || exit 1\n");
+#endif
 }
 
 void
@@ -1245,12 +1258,11 @@ main (int argc, char *argv[])
 
   if (access (oldconf, R_OK) == 0)
     {
-      char            str[255];
-
-      sprintf (str, "Old configuration exists in `%s'. Use it", oldconf);
+      char str[255];
+      sprintf(str, "Old configuration exists in `%s'. Use it", oldconf);
       if (think_positively (str, 1,
-      "Enable this option to load the previously saved configuration file\n"
-                           "for all of the sound driver parameters.\n"))
+"Enable this option to load the previously saved configuration file\n"
+"for all of the sound driver parameters.\n"))
        if (use_old_config (oldconf))
          exit (0);
     }
@@ -1293,31 +1305,31 @@ main (int argc, char *argv[])
        }
   }
 
-  if (selected_options & B (OPT_SBPRO))
+  if (selected_options & B (OPT_SB))
     {
       if (think_positively (
-                            "Support for the SG NX Pro mixer", 0,
-       "Enable this if you want to support the additional mixer functions\n"
-                         "provided on Sound Galaxy NX Pro sound cards.\n"))
+        "Support for the SG NX Pro mixer", 0,
+        "Enable this if you want to support the additional mixer functions\n"
+        "provided on Sound Galaxy NX Pro sound cards.\n"))
        printf ("#define __SGNXPRO__\n");
     }
 
   if (selected_options & B (OPT_SB))
     {
       if (think_positively ("Support for the MV Jazz16 (ProSonic etc.)", 0,
-         "Enable this if you have an MV Jazz16 or ProSonic sound card.\n"))
+      "Enable this if you have an MV Jazz16 or ProSonic sound card.\n"))
        {
          if (think_positively ("Do you have SoundMan Wave", 0,
                              "Enable this option of you have the Logitech SoundMan Wave sound card.\n"))
+ "Enable this option of you have the Logitech SoundMan Wave sound card.\n"))
            {
              printf ("#define SM_WAVE\n");
 
            midi0001_again:
              if (think_positively (
-                          "Do you have access to the MIDI0001.BIN file", 1,
-                                    "The Logitech SoundMan Wave has a microcontroller which must be\n"
-                                    "initialized before MIDI emulation works. This is possible only if the\n"
-                          "microcode file is compiled into the driver.\n"))
+"Do you have access to the MIDI0001.BIN file", 1,
+"The Logitech SoundMan Wave has a microcontroller which must be\n"
+"initialized before MIDI emulation works. This is possible only if the\n"
+"microcode file is compiled into the driver.\n"))
                {
                  char            path[512];
 
@@ -1331,8 +1343,8 @@ main (int argc, char *argv[])
                      fprintf (stderr, "Couldn't open file %s\n",
                               path);
                      if (think_positively ("Try again with correct path", 1,
-                                           "The specified file could not be opened. Enter the correct path to the\n"
-                                           "file.\n"))
+"The specified file could not be opened. Enter the correct path to the\n"
+"file.\n"))
                        goto midi0001_again;
                    }
                  else
@@ -1348,31 +1360,28 @@ main (int argc, char *argv[])
   if (selected_options & B (OPT_SB))
     {
       if (think_positively ("Do you have a Logitech SoundMan Games", 0,
-        "The Logitech SoundMan Games supports 44 kHz in stereo while the\n"
-      "standard SB Pro supports just 22 kHz stereo. You have the option of\n"
-                           "enabling SM Games mode.  However, enable it only if you are sure that\n"
-      "your card is an SM Games. Enabling this feature with a plain old SB\n"
-                           "Pro will cause troubles with stereo mode.\n\n"
-                 "DANGER! Read the above once again before answering 'y'\n"
-                           "Answer 'n' if you are unsure what to do!\n"))
+"The Logitech SoundMan Games supports 44 kHz in stereo while the\n"
+"standard SB Pro supports just 22 kHz stereo. You have the option of\n"
+"enabling SM Games mode.  However, enable it only if you are sure that\n"
+"your card is an SM Games. Enabling this feature with a plain old SB\n"
+"Pro will cause troubles with stereo mode.\n\n"
+"DANGER! Read the above once again before answering 'y'\n"
+"Answer 'n' if you are unsure what to do!\n"))
        printf ("#define SM_GAMES\n");
     }
 
-  if (selected_options & B (OPT_SB16))
-    selected_options |= B (OPT_SBPRO);
-
   if (selected_options & B (OPT_AEDSP16))
     {
       int             sel1 = 0;
 
-      if (selected_options & B (OPT_SBPRO))
+      if (selected_options & B (OPT_SB))
        {
 
          if (think_positively (
-           "Do you want support for the Audio Excel SoundBlaster Pro mode",
-                                1,
-                                "Enable this option if you want the Audio Excel sound card to operate\n"
-                                "in SoundBlaster Pro mode.\n"))
+"Do you want support for the Audio Excel SoundBlaster Pro mode",
+1,
+"Enable this option if you want the Audio Excel sound card to operate\n"
+"in SoundBlaster Pro mode.\n"))
            {
              printf ("#define AEDSP16_SBPRO\n");
              sel1 = 1;
@@ -1381,12 +1390,12 @@ main (int argc, char *argv[])
 
       if ((selected_options & B (OPT_MSS)) && (sel1 == 0))
        {
-
+         
          if (think_positively (
-                                "Do you want support for the Audio Excel Microsoft Sound System mode",
-                                1,
-                                "Enable this option if you want the Audio Excel sound card to operate\n"
-                                "in Microsoft Sound System mode.\n"))
+"Do you want support for the Audio Excel Microsoft Sound System mode",
+1,
+"Enable this option if you want the Audio Excel sound card to operate\n"
+"in Microsoft Sound System mode.\n"))
            {
              printf ("#define AEDSP16_MSS\n");
              sel1 = 1;
@@ -1407,8 +1416,8 @@ main (int argc, char *argv[])
     {
     genld_again:
       if (think_positively ("Do you wish to include an LD file", 1,
-                           "If you want to emulate the SoundBlaster card and you have a DSPxxx.LD\n"
-                     "file then you must include the LD in the kernel.\n"))
+     "If you want to emulate the SoundBlaster card and you have a DSPxxx.LD\n"
+     "file then you must include the LD in the kernel.\n"))
        {
          char            path[512];
 
@@ -1419,9 +1428,9 @@ main (int argc, char *argv[])
 
          if (!bin2hex (path, "synth-ld.h", "pss_synth"))
            {
-             fprintf (stderr, "couldn't open `%s' as the LD file\n", path);
+              fprintf (stderr, "couldn't open `%s' as the LD file\n", path);
              if (think_positively ("try again with correct path", 1,
-                                   "The given LD file could not opened.\n"))
+                "The given LD file could not opened.\n"))
                goto genld_again;
            }
          else
@@ -1446,12 +1455,12 @@ main (int argc, char *argv[])
     hex2hex_again:
 
       if (think_positively ("Do you want to include TRXPRO.HEX in your kernel",
-                           1,
-       "The MediaTriX AudioTrix Pro has an onboard microcontroller which\n"
-                           "needs to be initialized by downloading the code from the file TRXPRO.HEX\n"
-                           "in the DOS driver directory. If you don't have the TRXPRO.HEX file handy\n"
-                           "you may skip this step. However, the SB and MPU-401 modes of AudioTriX\n"
-                           "Pro will not work without this file!\n"))
+      1,
+"The MediaTriX AudioTrix Pro has an onboard microcontroller which\n"
+"needs to be initialized by downloading the code from the file TRXPRO.HEX\n"
+"in the DOS driver directory. If you don't have the TRXPRO.HEX file handy\n"
+"you may skip this step. However, the SB and MPU-401 modes of AudioTriX\n"
+"Pro will not work without this file!\n"))
        {
          char            path[512];
 
@@ -1470,7 +1479,7 @@ main (int argc, char *argv[])
   if (!(selected_options & ANY_DEVS))
     {
       printf ("invalid_configuration__run_make_config_again\n");
-      fprintf (stderr, "\n*** This combination is useless. Sound driver disabled!!! ***\n*** You need to enable support for at least one device    ***\n\n");
+      fprintf (stderr,"\n*** This combination is useless. Sound driver disabled!!! ***\n*** You need to enable support for at least one device    ***\n\n");
       exit (0);
     }
 
@@ -1507,13 +1516,12 @@ main (int argc, char *argv[])
 
   if (!old_config_used)
     {
-      char            str[255];
-
-      sprintf (str, "Save copy of this configuration to `%s'", oldconf);
-      if (think_positively (str, 1,
-       "If you enable this option then the sound driver configuration is\n"
-      "saved to a file. If you later need to recompile the kernel you have\n"
-                         "the option of using the saved configuration.\n"))
+      char str[255];
+      sprintf(str, "Save copy of this configuration to `%s'", oldconf);
+      if (think_positively (str, 1, 
+"If you enable this option then the sound driver configuration is\n"
+"saved to a file. If you later need to recompile the kernel you have\n"
+"the option of using the saved configuration.\n"))
        {
          char            cmd[200];
 
index 7f65ea82c6949d04860efe0620df08f6088bf974..bb853f1085c1f097fb51b7ecc69bc3cf25b801ed 100644 (file)
@@ -334,6 +334,7 @@ struct sound_timer_operations {
 #endif
 #ifdef CONFIG_GUS
                {"GUS", 0, SNDCARD_GUS, "Gravis Ultrasound",    attach_gus_card, probe_gus, unload_gus},
+               {"GUSPNP", 1, SNDCARD_GUSPNP,   "GUS PnP",      attach_gus_card, probe_gus, unload_gus},
 #endif
 #ifdef CONFIG_SSCAPE
                {"SSCAPE", 0, SNDCARD_SSCAPE, "Ensoniq Soundscape",     attach_sscape, probe_sscape, unload_sscape},
index 6c434807cc2102893189f2e0d6223df1a0c34d79..a26eb82648549af46fa8844253a7b9455e9bbb1e 100644 (file)
@@ -234,6 +234,7 @@ close_dmap (int dev, struct dma_buffparms *dmap, int chan)
     dmap->dma_mode = DMODE_NONE;
   dmap->flags &= ~DMA_BUSY;
 
+  disable_dma (chan);
   sound_free_dmap (dev, dmap);
 }
 
@@ -1303,35 +1304,41 @@ static void
 polish_buffers (struct dma_buffparms *dmap)
 {
   int             i;
+  int             p, l;
 
-  if (dmap->cfrag < 0)
+  i = dmap->qhead;
+
+  p = dmap->fragment_size * i;
+
+  if (i == dmap->cfrag)
     {
-      memset (dmap->raw_buf,
-             dmap->neutral_byte,
-             dmap->bytes_in_use);
-      return;
+      l = dmap->fragment_size - dmap->counts[i];
     }
+  else
+    l = dmap->fragment_size;
 
-  for (i = 0; i < dmap->nbufs; i++)
+  if (l)
     {
-      int             p, l;
-
-      p = dmap->fragment_size * i;
+      memset (dmap->raw_buf + p,
+             dmap->neutral_byte,
+             l);
+    }
+}
 
-      if (i == dmap->cfrag)
-       {
-         l = dmap->fragment_size - dmap->counts[i];
-       }
-      else
-       l = dmap->fragment_size;
+static void
+force_restart (int dev, struct dma_buffparms *dmap)
+{
+  if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
+      audio_devs[dev]->halt_output)
+    audio_devs[dev]->halt_output (dev);
+  else
+    audio_devs[dev]->halt_xfer (dev);
 
-      if (l)
-       {
-         memset (dmap->raw_buf + p,
-                 dmap->neutral_byte,
-                 l);
-       }
-    }
+  dmap->flags &= ~DMA_ACTIVE;
+  if (audio_devs[dev]->flags & DMA_AUTOMODE)
+    dmap->flags |= DMA_RESTART;
+  else
+    dmap->flags &= ~DMA_RESTART;
 }
 
 void
@@ -1393,7 +1400,14 @@ DMAbuf_outputintr (int dev, int event_type)
       if (event_type == 1 && dmap->qlen < 1)
        {
          dmap->underrun_count++;
-         /* Ignore underrun. Just move the tail pointer forward and go */
+
+         if (dmap->underrun_count > 5 || dmap->flags & DMA_EMPTY)
+           {
+             dmap->qlen = 0;
+             force_restart (dev, dmap);
+           }
+         else
+           /* Ignore underrun. Just move the tail pointer forward and go */
          if (dmap->closing)
            {
              polish_buffers (dmap);
@@ -1482,7 +1496,7 @@ DMAbuf_inputintr (int dev)
 
       if (audio_devs[dev]->flags & DMA_AUTOMODE)
        {
-         /* Force restart on next write */
+         /* Force restart on next read */
          if ((audio_devs[dev]->flags & DMA_DUPLEX) &&
              audio_devs[dev]->halt_input)
            audio_devs[dev]->halt_input (dev);
index f2b621ce40b222224b257c6e5b57572e5724d748..87d0b75448851406488d5191826f0721ab258054 100644 (file)
@@ -41,6 +41,7 @@ int             gus_base, gus_irq, gus_dma;
 extern int      gus_wave_volume;
 extern int      gus_pcm_volume;
 extern int      have_gus_max;
+int             gus_pnp_flag = 0;
 
 int            *gus_osp;
 
@@ -115,6 +116,9 @@ probe_gus (struct address_info *hw_config)
 
   gus_osp = hw_config->osp;
 
+  if (hw_config->card_subtype == 1)
+    gus_pnp_flag = 1;
+
   irq = hw_config->irq;
 
   if (hw_config->card_subtype == 0)    /* GUS/MAX/ACE */
@@ -125,10 +129,12 @@ probe_gus (struct address_info *hw_config)
        return 0;
       }
 
-  if (!check_region (hw_config->io_base, 16))
-    if (!check_region (hw_config->io_base + 0x100, 16))
-      if (gus_wave_detect (hw_config->io_base))
-       return 1;
+  if (check_region (hw_config->io_base, 16))
+    printk ("GUS: I/O range conflict (1)\n");
+  else if (check_region (hw_config->io_base + 0x100, 16))
+    printk ("GUS: I/O range conflict (2)\n");
+  else if (gus_wave_detect (hw_config->io_base))
+    return 1;
 
 #ifndef EXCLUDE_GUS_IODETECT
 
index 84fbc5c3d21bf1c50283dd7f61b475ed1f163c30..06849f1c07d87e1f005d5c19ec3fe8e53fdff735 100644 (file)
@@ -80,6 +80,7 @@ static struct voice_alloc_info *voice_alloc;
 
 extern int      gus_base;
 extern int      gus_irq, gus_dma;
+extern int      gus_pnp_flag;
 static int      gus_dma2 = -1;
 static int      dual_dma_mode = 0;
 static long     gus_mem_size = 0;
@@ -2991,13 +2992,14 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
 
   int             irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
 
-  if (irq < 0 || irq > 15)
-    {
-      printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
-      return mem_start;
-    }
+  if (!gus_pnp_flag)
+    if (irq < 0 || irq > 15)
+      {
+       printk ("ERROR! Invalid IRQ#%d. GUS Disabled", irq);
+       return mem_start;
+      }
 
-  if (dma < 0 || dma > 7)
+  if (dma < 0 || dma > 7 || dma == 4)
     {
       printk ("ERROR! Invalid DMA#%d. GUS Disabled", dma);
       return mem_start;
@@ -3022,14 +3024,21 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
   val = inb (gus_base + 0x0f);
   restore_flags (flags);
 
-  if (val != 0xff && (val & 0x06))     /* Should be 0x02?? */
+#ifndef GUSPNP_NO_AUTODETECT
+  gus_pnp_flag = (val == 1);
+#endif
+
+  if (gus_pnp_flag || (val != 0xff && (val & 0x06)))   /* Should be 0x02?? */
     {
       /*
          * It has the digital ASIC so the card is at least v3.4.
          * Next try to detect the true model.
        */
 
-      val = inb (u_MixSelect);
+      if (gus_pnp_flag)                /* Hack hack hack */
+       val = 10;
+      else
+       val = inb (u_MixSelect);
 
       /*
          * Value 255 means pre-3.7 which don't have mixer.
@@ -3103,7 +3112,11 @@ gus_wave_init (long mem_start, struct address_info *hw_config)
 
   if (hw_config->name)
     {
-      strncpy (gus_info.name, hw_config->name, sizeof (gus_info.name));
+      char            tmp[20];
+
+      strncpy (tmp, hw_config->name, 20);
+      tmp[19] = 0;
+      sprintf (gus_info.name, "%s (%dk)", tmp, (int) gus_mem_size / 1024);
       gus_info.name[sizeof (gus_info.name) - 1] = 0;
     }
   else
@@ -3420,7 +3433,8 @@ guswave_dma_irq (void)
            if (pcm_qlen == 0)
              flag = 1;         /* Underrun */
            dma_active = 0;
-           DMAbuf_outputintr (gus_devnum, flag);
+           if (gus_busy)
+             DMAbuf_outputintr (gus_devnum, flag);
          }
        break;
 
index 853937f03a6f6458de274a1a5b1d82dee9cb0a4b..32e81f34543fbbfe9973a0e452da4aeeb66a86a1 100644 (file)
@@ -55,3 +55,4 @@ extern int sound_num_blocks;
 
 #undef PSEUDO_DMA_AUTOINIT
 #define ALLOW_BUFFER_MAPPING
+
index 78e1f29bd9bc8684ff35ca9803af9d7656445472..be17a73f8d6b38de484ee9e45dcbc12c77dbf1c1 100644 (file)
@@ -299,6 +299,8 @@ config_pas_hw (struct address_info *hw_config)
 
        pas_write (irq_dma, EMULATION_CONFIGURATION);
       }
+    else
+      pas_write (0x00, COMPATIBILITY_ENABLE);
   }
 #else
   pas_write (0x00, COMPATIBILITY_ENABLE);
index 721720af35ab59c9b5f3190f80d354e81488c8ff..f6c5991c62ba220db4e3663fecd8d32fc3eface4 100644 (file)
@@ -518,6 +518,87 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
       }
       break;
 
+    case SNDCTL_COPR_SENDMSG:
+      {
+       copr_msg       *buf;
+       unsigned long   flags;
+       unsigned short *data;
+       unsigned short  tmp;
+       int             i;
+
+       buf = (copr_msg *) kmalloc (sizeof (copr_msg), GFP_KERNEL);
+       if (buf == NULL)
+         return -ENOSPC;
+
+       memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
+
+       data = (unsigned short *) (buf->data);
+
+       /* printk( "SNDCTL_COPR_SENDMSG: data = %d", data ); */
+
+       save_flags (flags);
+       cli ();
+
+       for (i = 0; i < buf->len; i++)
+         {
+           tmp = *data++;
+           if (!pss_put_dspword (devc, tmp))
+             {
+               restore_flags (flags);
+               buf->len = i;   /* feed back number of WORDs sent */
+               memcpy_tofs ((&((char *) arg)[0]), &buf, sizeof (buf));
+               kfree (buf);
+               return -EIO;
+             }
+         }
+
+       restore_flags (flags);
+       kfree (buf);
+
+       return 0;
+      }
+      break;
+
+
+    case SNDCTL_COPR_RCVMSG:
+      {
+       copr_msg       *buf;
+       unsigned long   flags;
+       unsigned short *data;
+       unsigned int    i;
+       int             err = 0;
+
+       buf = (copr_msg *) kmalloc (sizeof (copr_msg), GFP_KERNEL);
+       if (buf == NULL)
+         return -ENOSPC;
+
+       memcpy_fromfs ((char *) buf, &(((char *) arg)[0]), sizeof (*buf));
+
+       data = (unsigned short *) buf->data;
+
+       save_flags (flags);
+       cli ();
+
+       for (i = 0; i < buf->len; i++)
+         {
+           if (!pss_get_dspword (devc, data++))
+             {
+               buf->len = i;   /* feed back number of WORDs read */
+               err = -EIO;
+               break;
+             }
+         }
+
+       restore_flags (flags);
+
+       memcpy_tofs ((&((char *) arg)[0]), &buf, sizeof (buf));
+       kfree (buf);
+
+       return err;
+      }
+      break;
+
+
     case SNDCTL_COPR_RDATA:
       {
        copr_debug_buf  buf;
@@ -610,14 +691,14 @@ pss_coproc_ioctl (void *dev_info, unsigned int cmd, caddr_t arg, int local)
            return -EIO;
          }
 
-       tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
+       tmp = (unsigned int) buf.parm2 & 0x00ff;
        if (!pss_put_dspword (devc, tmp))
          {
            restore_flags (flags);
            return -EIO;
          }
 
-       tmp = (unsigned int) buf.parm2 & 0x00ff;
+       tmp = ((unsigned int) buf.parm2 >> 8) & 0xffff;
        if (!pss_put_dspword (devc, tmp))
          {
            restore_flags (flags);
index d7290006788f50ae942a7b93ad5696d4444e4748..0106b40e261bb2f516ae506f5ea324aa3fd37eea 100644 (file)
@@ -246,6 +246,7 @@ sb16_dsp_close (int dev)
   DEB (printk ("sb16_dsp_close()\n"));
   sb_dsp_command01 (0xd9);
   sb_dsp_command01 (0xd5);
+  sb_reset_dsp ();
 
   save_flags (flags);
   cli ();
index 33ea1fa15628a02f2331d7db851277cb941c88cc..547ea2c6fcc7dad2d121574a45737781e41dfb72 100644 (file)
@@ -125,7 +125,6 @@ sb16midi_open (int dev, int mode,
       return -EBUSY;
     }
 
-  reset_sb16midi ();
   while (input_avail ())
     sb16midi_read ();
 
index 9113afa277df7808fc2334f21e533428d52ddca5..43b4c4c964e7c8b5b9c4c8288c1efd1591e89d44 100644 (file)
@@ -75,6 +75,7 @@ int             sb_dsp_highspeed = 0;
 int             sbc_major = 0, sbc_minor = 0;
 static int      dsp_stereo = 0;
 static int      dsp_current_speed = DSP_DEFAULT_SPEED;
+static int      dsp_requested_speed = DSP_DEFAULT_SPEED;
 static int      sb16 = 0;
 static int      irq_verified = 0;
 
@@ -334,6 +335,8 @@ dsp_speed (int speed)
   unsigned long   flags;
   int             max_speed = 44100;
 
+  dsp_requested_speed = speed;
+
   if (AudioDrive)
     return ess_speed (speed);
 
@@ -447,6 +450,7 @@ dsp_set_stereo (int mode)
     }
 
   dsp_stereo = !!mode;
+  dsp_speed (dsp_requested_speed);
   return dsp_stereo;
 }
 
@@ -473,9 +477,6 @@ actually_output_block (int dev, unsigned long buf, int nr_bytes,
   unsigned long   flags;
   int             count = nr_bytes;
 
-  if (!sb_irq_mode)
-    dsp_speaker (ON);
-
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE);
 
   sb_irq_mode = 0;
@@ -564,9 +565,6 @@ actually_start_input (int dev, unsigned long buf, int nr_bytes, int intrflag,
    * Start a DMA input to the buffer pointed by dmaqtail
    */
 
-  if (!sb_irq_mode)
-    dsp_speaker (OFF);
-
   DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ);
   sb_irq_mode = 0;
 
@@ -665,6 +663,7 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
 
   dsp_cleanup ();
   dsp_speaker (OFF);
+  dsp_speed (dsp_requested_speed);
 
   if (sbc_major == 3)          /*
                                 * SB Pro
@@ -722,7 +721,6 @@ sb_dsp_prepare_for_input (int dev, int bsize, int bcount)
          else
            sb_dsp_command (dsp_16bit ? 0xa4 : 0xa0);
 
-         dsp_speed (dsp_current_speed);
        }                       /* !AudioDrive */
     }
   trigger_bits = 0;
@@ -734,6 +732,7 @@ sb_dsp_prepare_for_output (int dev, int bsize, int bcount)
 {
   dsp_cleanup ();
   dsp_speaker (OFF);
+  dsp_speed (dsp_requested_speed);
 
   if (sbc_major == 3)          /* SB Pro (at least ) */
     {
@@ -828,6 +827,9 @@ sb_dsp_open (int dev, int mode)
       return -ENXIO;
     }
 
+  if (!sb_midi_busy)
+    sb_reset_dsp ();
+
   if (sb_no_recording && mode & OPEN_READ)
     {
       printk ("SB Warning: Recording not supported by this device\n");
index ae08a8e5a2e4069451a2906c44d0aefc0bc49e21..e49f4b002bdc25657c685da38ff5af60496f14f9 100644 (file)
@@ -27,8 +27,8 @@
  */
 
 
-#include "os.h"
 #include "local.h"
+#include "os.h"
 #include "soundvers.h"
 
 #if defined(ISC) || defined(SCO) || defined(SVR42)
index c24ce38d077f01cb1c25d86eac979d225591707a..9da8c50d04555fa6869221db698b9f73bb9fe8e0 100644 (file)
@@ -70,8 +70,8 @@ sound_read (inode_handle * inode, file_handle * file, char *buf, int count)
 {
   int             dev;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
+
   files[dev].flags = file_get_flags (file);
 
   return sound_read_sw (dev, &files[dev], buf, count);
@@ -82,8 +82,8 @@ sound_write (inode_handle * inode, file_handle * file, const char *buf, int coun
 {
   int             dev;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
+
   files[dev].flags = file_get_flags (file);
 
   return sound_write_sw (dev, &files[dev], buf, count);
@@ -107,8 +107,7 @@ sound_open (inode_handle * inode, file_handle * file)
       return -EBUSY;
     }
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
 
   if (!soundcard_configured && dev != SND_DEV_CTL && dev != SND_DEV_STATUS)
     {
@@ -142,8 +141,7 @@ sound_release (inode_handle * inode, file_handle * file)
 {
   int             dev;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
 
   files[dev].flags = file_get_flags (file);
 
@@ -159,8 +157,8 @@ sound_ioctl (inode_handle * inode, file_handle * file,
 {
   int             dev, err;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
+
   files[dev].flags = file_get_flags (file);
 
   if (_IOC_DIR (cmd) != _IOC_NONE)
@@ -196,8 +194,8 @@ sound_select (inode_handle * inode, file_handle * file, int sel_type, select_tab
 {
   int             dev;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
+
   files[dev].flags = file_get_flags (file);
 
   DEB (printk ("sound_select(dev=%d, type=0x%x)\n", dev, sel_type));
@@ -239,8 +237,8 @@ sound_mmap (inode_handle * inode, file_handle * file, vm_area_handle * vma)
   unsigned long   size;
   struct dma_buffparms *dmap = NULL;
 
-  dev = inode_get_rdev (inode);
-  dev = MINOR (dev);
+  dev = MINOR (inode_get_rdev (inode));
+
   files[dev].flags = file_get_flags (file);
 
   dev_class = dev & 0x0f;
@@ -442,32 +440,27 @@ init_module (void)
 void
 cleanup_module (void)
 {
-  if (MOD_IN_USE)
-    printk ("sound: module busy -- remove delayed\n");
-  else
-    {
-      int             i;
+  int             i;
 
-      if (chrdev_registered)
-       module_unregister_chrdev (sound_major, "sound");
+  if (chrdev_registered)
+    module_unregister_chrdev (sound_major, "sound");
 
 #ifdef CONFIG_SEQUENCER
-      sound_stop_timer ();
+  sound_stop_timer ();
 #endif
-      sound_unload_drivers ();
+  sound_unload_drivers ();
 
-      for (i = 0; i < sound_num_blocks; i++)
-       kfree (sound_mem_blocks[i]);
+  for (i = 0; i < sound_num_blocks; i++)
+    kfree (sound_mem_blocks[i]);
 
-      free_all_irqs ();                /* If something was left allocated by accident */
+  free_all_irqs ();            /* If something was left allocated by accident */
 
-      for (i = 0; i < 8; i++)
-       if (dma_alloc_map[i] != DMA_MAP_UNAVAIL)
-         {
-           printk ("Sound: Hmm, DMA%d was left allocated - fixed\n", i);
-           sound_free_dma (i);
-         }
-    }
+  for (i = 0; i < 8; i++)
+    if (dma_alloc_map[i] != DMA_MAP_UNAVAIL)
+      {
+       printk ("Sound: Hmm, DMA%d was left allocated - fixed\n", i);
+       sound_free_dma (i);
+      }
 }
 #endif
 
@@ -499,6 +492,9 @@ snd_set_irq_handler (int interrupt_level, void (*hndlr) (int, void *, struct pt_
 void
 snd_release_irq (int vect)
 {
+  if (!(irqs & (1ul << vect)))
+    return;
+
   irqs &= ~(1ul << vect);
   free_irq (vect, NULL);
 }
@@ -651,7 +647,7 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
 
       audio_devs[dev]->buffsize = PAGE_SIZE * (1 << sz);
 
-      if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, MAX_DMA_ADDRESS)) == NULL)
+      if ((start_addr = (char *) __get_free_pages (GFP_ATOMIC, sz, 1)) == NULL)
        audio_devs[dev]->buffsize /= 2;
     }
 
@@ -685,8 +681,6 @@ sound_alloc_dmap (int dev, struct dma_buffparms *dmap, int chan)
   dmap->raw_buf = start_addr;
   dmap->raw_buf_phys = virt_to_bus (start_addr);
 
-  memset (dmap->raw_buf, 0x00, audio_devs[dev]->buffsize);
-
   for (i = MAP_NR (start_addr); i <= MAP_NR (end_addr); i++)
     {
       mem_map_reserve (i);
index d6f30766b0dfc299fe39bda0e71a86ed4f980a51..67e3554faa1a3c63df00fe95476795a0d8f90d63 100644 (file)
@@ -1,2 +1,2 @@
-#define SOUND_VERSION_STRING "3.5-beta10-960301"
-#define SOUND_INTERNAL_VERSION 0x030505
+#define SOUND_VERSION_STRING "3.5-960313"
+#define SOUND_INTERNAL_VERSION 0x030500
index 4251b6eae42e6b13e6f254b31b02974510f8bcf3..1b475df21b42f16cb1285c077bddd26ae02a8cf6 100644 (file)
@@ -49,7 +49,6 @@ static int maybe_shrink_lav_buffers(int);
 
 static int nr_hash = 0;  /* Size of hash table */
 static struct buffer_head ** hash_table;
-struct buffer_head ** buffer_pages;
 static struct buffer_head * lru_list[NR_LIST] = {NULL, };
 /* next_to_age is an array of pointers into the lru lists, used to
    cycle through the buffers aging their contents when deciding which
@@ -1327,7 +1326,7 @@ static int grow_buffers(int pri, int size)
                        break;
        }
        free_list[isize] = bh;
-       buffer_pages[MAP_NR(page)] = bh;
+       mem_map[MAP_NR(page)].buffers = bh;
        tmp->b_this_page = bh;
        buffermem += PAGE_SIZE;
        return 1;
@@ -1377,7 +1376,7 @@ int try_to_free_buffer(struct buffer_head * bh, struct buffer_head ** bhp,
                put_unused_buffer_head(p);
        } while (tmp != bh);
        buffermem -= PAGE_SIZE;
-       buffer_pages[MAP_NR(page)] = NULL;
+       mem_map[MAP_NR(page)].buffers = NULL;
        free_page(page);
        return !mem_map[MAP_NR(page)].count;
 }
@@ -1728,7 +1727,7 @@ static unsigned long try_to_generate_cluster(kdev_t dev, int block, int size)
                        break;
        }
        buffermem += PAGE_SIZE;
-       buffer_pages[MAP_NR(page)] = bh;
+       mem_map[MAP_NR(page)].buffers = bh;
        bh->b_this_page = tmp;
        while (nblock-- > 0)
                brelse(arr[nblock]);
@@ -1797,11 +1796,6 @@ void buffer_init(void)
                                                     sizeof(struct buffer_head *));
 
 
-       buffer_pages = (struct buffer_head **) vmalloc(MAP_NR(high_memory) * 
-                                                    sizeof(struct buffer_head *));
-       for (i = 0 ; i < MAP_NR(high_memory) ; i++)
-               buffer_pages[i] = NULL;
-
        for (i = 0 ; i < nr_hash ; i++)
                hash_table[i] = NULL;
        lru_list[BUF_CLEAN] = 0;
index be964872bae63a10cfa8c670d2570f8bec1814c1..2903c6db1984ef0e5dfcae90de0aeed97fc901dd 100644 (file)
@@ -238,29 +238,16 @@ extern inline unsigned long pgd_page(pgd_t pgd)
 
 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_VALID; }
-extern inline int pte_inuse(pte_t *ptep)       { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
 extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
-extern inline void pte_reuse(pte_t * ptep)
-{
-       if (!mem_map[MAP_NR(ptep)].reserved)
-               mem_map[MAP_NR(ptep)].count++;
-}
 
 extern inline int pmd_none(pmd_t pmd)          { return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)           { return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE || pmd_page(pmd) > high_memory; }
 extern inline int pmd_present(pmd_t pmd)       { return pmd_val(pmd) & _PAGE_VALID; }
-extern inline int pmd_inuse(pmd_t *pmdp)       { return mem_map[MAP_NR(pmdp)].reserved || mem_map[MAP_NR(pmdp)].count != 1; }
 extern inline void pmd_clear(pmd_t * pmdp)     { pmd_val(*pmdp) = 0; }
-extern inline void pmd_reuse(pmd_t * pmdp)
-{
-       if (!mem_map[MAP_NR(pmdp)].reserved)
-               mem_map[MAP_NR(pmdp)].count++;
-}
 
 extern inline int pgd_none(pgd_t pgd)          { return !pgd_val(pgd); }
 extern inline int pgd_bad(pgd_t pgd)           { return (pgd_val(pgd) & ~_PFN_MASK) != _PAGE_TABLE || pgd_page(pgd) > high_memory; }
 extern inline int pgd_present(pgd_t pgd)       { return pgd_val(pgd) & _PAGE_VALID; }
-extern inline int pgd_inuse(pgd_t *pgdp)       { return mem_map[MAP_NR(pgdp)].reserved; }
 extern inline void pgd_clear(pgd_t * pgdp)     { pgd_val(*pgdp) = 0; }
 
 /*
@@ -328,11 +315,10 @@ extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
 /*      
  * Allocate and free page tables. The xxx_kernel() versions are
  * used to allocate a kernel page table - this turns on ASN bits
- * if any, and marks the page tables reserved.
+ * if any.
  */
 extern inline void pte_free_kernel(pte_t * pte)
 {
-       mem_map[MAP_NR(pte)].reserved = 0;
        free_page((unsigned long) pte);
 }
 
@@ -344,7 +330,6 @@ extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
                if (pmd_none(*pmd)) {
                        if (page) {
                                pmd_set(pmd, page);
-                               mem_map[MAP_NR(page)].reserved = 1;
                                return page + address;
                        }
                        pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
@@ -362,7 +347,6 @@ extern inline pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
 
 extern inline void pmd_free_kernel(pmd_t * pmd)
 {
-       mem_map[MAP_NR(pmd)].reserved = 0;
        free_page((unsigned long) pmd);
 }
 
@@ -374,7 +358,6 @@ extern inline pmd_t * pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
                if (pgd_none(*pgd)) {
                        if (page) {
                                pgd_set(pgd, page);
-                               mem_map[MAP_NR(page)].reserved = 1;
                                return page + address;
                        }
                        pgd_set(pgd, BAD_PAGETABLE);
index c09ba31aa59fb7a9dc7456df3538733cf9682ba3..158171956d6b2e3e67db3d1d1b0425312bf1800c 100644 (file)
@@ -288,24 +288,12 @@ do { \
 
 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)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
 extern inline void pte_clear(pte_t *ptep)      { pte_val(*ptep) = 0; }
-extern inline void pte_reuse(pte_t * ptep)
-{
-       if (!mem_map[MAP_NR(ptep)].reserved)
-               mem_map[MAP_NR(ptep)].count++;
-}
 
 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 USE_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)     { }
 
 /*
  * The "pgd_xxx()" functions here are trivial for a folded two-level
@@ -315,7 +303,6 @@ extern inline void pmd_reuse(pmd_t * pmdp)  { }
 extern inline int pgd_none(pgd_t pgd)          { return 0; }
 extern inline int pgd_bad(pgd_t pgd)           { return 0; }
 extern inline int pgd_present(pgd_t pgd)       { return 1; }
-extern inline int pgd_inuse(pgd_t * pgdp)      { return mem_map[MAP_NR(pgdp)].reserved; }
 extern inline void pgd_clear(pgd_t * pgdp)     { }
 
 /*
@@ -376,11 +363,10 @@ extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
  * used to allocate a kernel page table - this turns on ASN bits
- * if any, and marks the page tables reserved.
+ * if any.
  */
 extern inline void pte_free_kernel(pte_t * pte)
 {
-       mem_map[MAP_NR(pte)].reserved = 0;
        free_page((unsigned long) pte);
 }
 
@@ -392,7 +378,6 @@ extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
                if (pmd_none(*pmd)) {
                        if (page) {
                                pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) page;
-                               mem_map[MAP_NR(page)].reserved = 1;
                                return page + address;
                        }
                        pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) BAD_PAGETABLE;
index bae845dd4cda3b51da34d30b3f83806a701b2c80..826e866079516ef2f2ab5a1b9f8a9f1f98243a20 100644 (file)
@@ -279,7 +279,6 @@ extern void free_dma(unsigned int dmanr);   /* release it again */
 /*
  * DMA memory allocation - formerly in include/linux/mm.h
  */
-#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), \
-                                             0x80000000 + MAX_DMA_ADDRESS)
+#define __get_dma_pages(priority, order) __get_free_pages((priority),(order), 1)
 
 #endif /* __ASM_MIPS_DMA_H */
index 59e08e34e3e3c9478027c304dd4327ea6af7d0ae..669768503f9c74f50e884f25f28aab3fee6f97da 100644 (file)
@@ -491,7 +491,7 @@ extern struct file_operations def_chr_fops;
 extern struct inode_operations chrdev_inode_operations;
 
 extern void init_fifo(struct inode * inode);
-struct inode_operations fifo_inode_operations;
+extern struct inode_operations fifo_inode_operations;
 
 extern struct file_operations connecting_fifo_fops;
 extern struct file_operations read_fifo_fops;
@@ -515,7 +515,6 @@ extern void set_writetime(struct buffer_head * buf, int flag);
 extern void refill_freelist(int size);
 extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**, int);
 
-extern struct buffer_head ** buffer_pages;
 extern int nr_buffers;
 extern int buffermem;
 extern int nr_buffer_heads;
index cdf1aa6248dde1d704a87b71a9b0f7b7aa8654e4..6ff1e97b5d95a3c6a05bb4ae9879bc4ee605ef45 100644 (file)
@@ -123,7 +123,8 @@ typedef struct page {
                 referenced:1,
                 locked:1,
                 free_after:1,
-                unused:2,
+                dma:1,
+                unused:1,
                 reserved:1;
        struct wait_queue *wait;
        struct page *next;
@@ -135,32 +136,19 @@ typedef struct page {
 
        struct page *prev;
        struct page *prev_hash;
+       struct buffer_head * buffers;
 } mem_map_t;
 
 extern mem_map_t * mem_map;
 
-/*
- * Free area management
- */
-
-#define NR_MEM_LISTS 6
-
-struct mem_list {
-       struct mem_list * next;
-       struct mem_list * prev;
-};
-
-extern struct mem_list free_area_list[NR_MEM_LISTS];
-extern unsigned int * free_area_map[NR_MEM_LISTS];
-
 /*
  * This is timing-critical - most of the time in getting a new page
  * goes to clearing the page. If you want a page without the clearing
  * overhead, just use __get_free_page() directly..
  */
-#define __get_free_page(priority) __get_free_pages((priority),0,~0UL)
-#define __get_dma_pages(priority, order) __get_free_pages((priority),(order),MAX_DMA_ADDRESS)
-extern unsigned long __get_free_pages(int priority, unsigned long gfporder, unsigned long max_addr);
+#define __get_free_page(priority) __get_free_pages((priority),0,0)
+#define __get_dma_pages(priority, order) __get_free_pages((priority),(order),1)
+extern unsigned long __get_free_pages(int priority, unsigned long gfporder, int dma);
 
 extern inline unsigned long get_free_page(int priority)
 {
@@ -222,7 +210,7 @@ extern unsigned long get_unmapped_area(unsigned long, unsigned long);
 
 /* filemap.c */
 extern unsigned long page_unuse(unsigned long);
-extern int shrink_mmap(int, unsigned long);
+extern int shrink_mmap(int, int);
 extern void truncate_inode_pages(struct inode *, unsigned long);
 
 #define GFP_BUFFER     0x00
index 973d460bdc51d027654a0cf9fd403f7f4bce901b..c7ce8635664cf2644ece5f55eee2aa31ce88cbb6 100644 (file)
@@ -128,6 +128,7 @@ enum scsi_directory_inos {
        PROC_SCSI_AM53C974,
        PROC_SCSI_SSC,
        PROC_SCSI_NCR53C406A,
+       PROC_SCSI_PPA,
        PROC_SCSI_SCSI_DEBUG,   
        PROC_SCSI_NOT_PRESENT,
        PROC_SCSI_FILE,                        /* I'm asuming here that we */
index dfdc05aa60f5a87654cc3580aab0c0d7dab3409c..18ba26c284b6c473773352f7095d54c3d79cc6cf 100644 (file)
@@ -57,6 +57,7 @@
 #define SNDCARD_CS4232_MPU     22
 #define SNDCARD_MAUI           23
 #define SNDCARD_PSEUDO_MSS     24
+#define SNDCARD_GUSPNP         25
 
 /***********************************
  * IOCTL Commands for /dev/sequencer
@@ -614,12 +615,13 @@ typedef struct count_info {
 #define SNDCTL_DSP_GETOPTR             _IOR ('P',18, count_info)
 
 typedef struct buffmem_desc {
-               caddr_t buffer;
+               unsigned *buffer;
                int size;
        } buffmem_desc;
 #define SNDCTL_DSP_MAPINBUF            _IOR ('P', 19, buffmem_desc)
 #define SNDCTL_DSP_MAPOUTBUF           _IOR ('P', 20, buffmem_desc)
 #define SNDCTL_DSP_SETSYNCRO           _IO  ('P', 21)
+#define SNDCTL_DSP_SETDUPLEX           _IO  ('P', 22)
 
 #define SOUND_PCM_READ_RATE            _IOR ('P', 2, int)
 #define SOUND_PCM_READ_CHANNELS                _IOR ('P', 6, int)
index d58fe447ec4b4a8476d17c77d4c2ed29780ae103..41a1f14e5bfc0b67f59cd949ba43789eeefcafeb 100644 (file)
@@ -43,10 +43,10 @@ struct vm_area_struct;
 struct sysinfo;
 
 /* linux/ipc/shm.c */
-extern int shm_swap (int, unsigned long);
+extern int shm_swap (int, int);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_page(int, unsigned long, int);
+extern int try_to_free_page(int, int, int);
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, unsigned long, char *, int);
@@ -97,19 +97,19 @@ extern unsigned long swap_cache_find_total;
 extern unsigned long swap_cache_find_success;
 #endif
 
-extern inline unsigned long in_swap_cache(unsigned long addr)
+extern inline unsigned long in_swap_cache(unsigned long index)
 {
-       return swap_cache[MAP_NR(addr)]; 
+       return swap_cache[index]; 
 }
 
-extern inline long find_in_swap_cache (unsigned long addr)
+extern inline long find_in_swap_cache(unsigned long index)
 {
        unsigned long entry;
 
 #ifdef SWAP_CACHE_INFO
        swap_cache_find_total++;
 #endif
-       entry = xchg(swap_cache + MAP_NR(addr), 0);
+       entry = xchg(swap_cache + index, 0);
 #ifdef SWAP_CACHE_INFO
        if (entry)
                swap_cache_find_success++;
@@ -117,14 +117,14 @@ extern inline long find_in_swap_cache (unsigned long addr)
        return entry;
 }
 
-extern inline int delete_from_swap_cache(unsigned long addr)
+extern inline int delete_from_swap_cache(unsigned long index)
 {
        unsigned long entry;
        
 #ifdef SWAP_CACHE_INFO
        swap_cache_del_total++;
 #endif 
-       entry= xchg(swap_cache + MAP_NR(addr), 0);
+       entry = xchg(swap_cache + index, 0);
        if (entry)  {
 #ifdef SWAP_CACHE_INFO
                swap_cache_del_success++;
index bb3f98f686c735fb5ec08b68e91b75e747bb93c2..decc36c0484d7ad514dbbe510dd2594eb7e09c6b 100644 (file)
@@ -64,6 +64,7 @@ extern void swap_setup(char *str, int *ints);
 extern void buff_setup(char *str, int *ints);
 extern void panic_setup(char *str, int *ints);
 extern void bmouse_setup(char *str, int *ints);
+extern void lp_setup(char *str, int *ints);
 extern void eth_setup(char *str, int *ints);
 extern void xd_setup(char *str, int *ints);
 extern void floppy_setup(char *str, int *ints);
@@ -82,6 +83,7 @@ extern void AM53C974_setup(char *str, int *ints);
 extern void BusLogic_Setup(char *str, int *ints);
 extern void fdomain_setup(char *str, int *ints);
 extern void NCR53c406a_setup(char *str, int *ints);
+extern void ppa_setup(char *str, int *ints);
 extern void scsi_luns_setup(char *str, int *ints);
 extern void sound_setup(char *str, int *ints);
 #ifdef CONFIG_CDU31A
@@ -227,6 +229,9 @@ struct {
 #ifdef CONFIG_INET
        { "ether=", eth_setup },
 #endif
+#ifdef CONFIG_PRINTER
+        { "lp=", lp_setup },
+#endif
 #ifdef CONFIG_SCSI
        { "max_scsi_luns=", scsi_luns_setup },
 #endif
@@ -277,6 +282,9 @@ struct {
 #ifdef CONFIG_SCSI_FUTURE_DOMAIN
        { "fdomain=", fdomain_setup},
 #endif
+#ifdef CONFIG_SCSI_PPA
+        { "ppa=", ppa_setup },
+#endif
 #ifdef CONFIG_BLK_DEV_XD
        { "xd=", xd_setup },
 #endif
index ef25cb1b951a423588fdaaf3415ce01e14cbe0a8..90303641e5ce754aaa447001241a88f9d049d105 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -674,7 +674,7 @@ done:       /* pte_val(pte) == shp->shm_pages[idx] */
 static unsigned long swap_id = 0; /* currently being swapped */
 static unsigned long swap_idx = 0; /* next to swap */
 
-int shm_swap (int prio, unsigned long limit)
+int shm_swap (int prio, int dma)
 {
        pte_t page;
        struct shmid_ds *shp;
@@ -711,7 +711,7 @@ int shm_swap (int prio, unsigned long limit)
        pte_val(page) = shp->shm_pages[idx];
        if (!pte_present(page))
                goto check_table;
-       if (pte_page(page) >= limit)
+       if (dma && !mem_map[MAP_NR(pte_page(page))].dma)
                goto check_table;
        swap_attempts++;
 
index 277c268135358effec0a7d6488b5d1775caa15fd..c9bbf14551546591b52e4d770504d435e2065487 100644 (file)
@@ -290,7 +290,7 @@ int acct_process(long exitcode)
 
    if (acct_active) {
       strncpy(ac.ac_comm, current->comm, ACCT_COMM);
-      ac.ac_comm[ACCT_COMM] = '\0';
+      ac.ac_comm[ACCT_COMM-1] = '\0';
       ac.ac_utime = current->utime;
       ac.ac_stime = current->stime;
       ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
index 87129f6e2a5821c4d98472027b2ae208ae133111..2c2f665f8886384f521b7dc23c43e8252247bdee 100644 (file)
@@ -109,25 +109,23 @@ repeat:
        }
 }
 
-int shrink_mmap(int priority, unsigned long limit)
+int shrink_mmap(int priority, int dma)
 {
        static int clock = 0;
        struct page * page;
+       unsigned long limit = MAP_NR(high_memory);
        struct buffer_head *tmp, *bh;
 
-       if (limit > high_memory)
-               limit = high_memory;
-       limit = MAP_NR(limit);
-       if (clock >= limit)
-               clock = 0;
        priority = (limit<<2) >> priority;
        page = mem_map + clock;
        while (priority-- > 0) {
                if (page->locked)
-                   goto next;
+                       goto next;
+               if (dma && !page->dma)
+                       goto next;
                /* First of all, regenerate the page's referenced bit
                    from any buffers in the page */
-               bh = buffer_pages[MAP_NR(page_address(page))];
+               bh = page->buffers;
                if (bh) {
                        tmp = bh;
                        do {
@@ -505,7 +503,7 @@ static int filemap_write_page(struct vm_area_struct * vma,
        struct inode * inode;
        struct buffer_head * bh;
 
-       bh = buffer_pages[MAP_NR(page)];
+       bh = mem_map[MAP_NR(page)].buffers;
        if (bh) {
                /* whee.. just mark the buffer heads dirty */
                struct buffer_head * tmp = bh;
index 72cd486b05690a40123d31cdb24de9eb2e0fca9a..dae0dd963715905611ab0a506e5d1170e035f40a 100644 (file)
@@ -176,7 +176,7 @@ int get_order(int size)
 void *kmalloc(size_t size, int priority)
 {
        unsigned long flags;
-       unsigned long max_addr, type;
+       unsigned long type;
        int order, i, sz;
        struct block_header *p;
        struct page_descriptor *page, **pg;
@@ -187,11 +187,9 @@ void *kmalloc(size_t size, int priority)
                return (NULL);
        }
 
-       max_addr = ~0UL;
        type = MF_USED;
        pg = &sizes[order].firstfree;
        if (priority & GFP_DMA) {
-               max_addr = MAX_DMA_ADDRESS;
                type = MF_DMA;
                pg = &sizes[order].dmafree;
        }
@@ -229,7 +227,7 @@ void *kmalloc(size_t size, int priority)
        sz = BLOCKSIZE(order);
 
        page = (struct page_descriptor *) __get_free_pages(priority,
-                       sizes[order].gfporder, max_addr);
+                       sizes[order].gfporder, priority & GFP_DMA);
 
        if (!page) {
                static unsigned long last = 0;
index 51234e0f1ba813a0cbc37d62ee7d17051f8c759d..82965a7ff6bee7a33699397630d547610dae16a1 100644 (file)
 
 unsigned long high_memory = 0;
 
-/*
- * The free_area_list arrays point to the queue heads of the free areas
- * of different sizes
- */
-int nr_swap_pages = 0;
-int nr_free_pages = 0;
-struct mem_list free_area_list[NR_MEM_LISTS];
-unsigned int * free_area_map[NR_MEM_LISTS];
-
 /*
  * We special-case the C-O-W ZERO_PAGE, because it's such
  * a common occurrence (no need to read the page to know
@@ -113,6 +104,7 @@ 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))
@@ -124,11 +116,8 @@ static inline void free_one_pgd(pgd_t * dir)
        }
        pmd = pmd_offset(dir, 0);
        pgd_clear(dir);
-       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);
 }
        
@@ -170,7 +159,7 @@ void free_page_tables(struct task_struct * tsk)
        invalidate_mm(tsk->mm);
        SET_PAGE_DIR(tsk, swapper_pg_dir);
        tsk->mm->pgd = swapper_pg_dir;  /* or else... */
-       for (i = 0 ; i < PTRS_PER_PGD ; i++)
+       for (i = 0 ; i < USER_PTRS_PER_PGD ; i++)
                free_one_pgd(page_dir + i);
        pgd_free(page_dir);
 }
@@ -193,6 +182,7 @@ int new_page_tables(struct task_struct * tsk)
 static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte, int cow)
 {
        pte_t pte = *old_pte;
+       unsigned long page_nr;
 
        if (pte_none(pte))
                return;
@@ -201,17 +191,18 @@ static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte, int cow)
                set_pte(new_pte, pte);
                return;
        }
-       if (pte_page(pte) > high_memory || mem_map[MAP_NR(pte_page(pte))].reserved) {
+       page_nr = MAP_NR(pte_page(pte));
+       if (page_nr >= MAP_NR(high_memory) || mem_map[page_nr].reserved) {
                set_pte(new_pte, pte);
                return;
        }
        if (cow)
                pte = pte_wrprotect(pte);
-       if (delete_from_swap_cache(pte_page(pte)))
+       if (delete_from_swap_cache(page_nr))
                pte = pte_mkdirty(pte);
        set_pte(new_pte, pte_mkold(pte));
        set_pte(old_pte, pte);
-       mem_map[MAP_NR(pte_page(pte))].count++;
+       mem_map[page_nr].count++;
 }
 
 static inline int copy_pte_range(pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long address, unsigned long size, int cow)
index e34fd7be185bbc75179b493b7eaa0a5927e1d957..5dfe9db92afd5ee57915d596068012834cf4f4c6 100644 (file)
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
-static inline void add_mem_queue(struct mem_list * head, struct mem_list * entry)
+int nr_swap_pages = 0;
+int nr_free_pages = 0;
+
+/*
+ * Free area management
+ *
+ * The free_area_list arrays point to the queue heads of the free areas
+ * of different sizes
+ */
+
+#define NR_MEM_LISTS 6
+
+struct free_area_struct {
+       struct page list;
+       unsigned int *  map;
+};
+
+static struct free_area_struct free_area[NR_MEM_LISTS];
+
+static inline void init_mem_queue(struct page * head)
 {
+       head->next = head;
+       head->prev = head;
+}
+
+static inline void add_mem_queue(struct page * head, struct page * entry)
+{
+       struct page * next = head->next;
+
        entry->prev = head;
-       (entry->next = head->next)->prev = entry;
+       entry->next = next;
+       next->prev = entry;
        head->next = entry;
 }
 
-static inline void remove_mem_queue(struct mem_list * head, struct mem_list * entry)
+static inline void remove_mem_queue(struct page * head, struct page * entry)
 {
-       struct mem_list * next = entry->next;
-       (next->prev = entry->prev)->next = next;
+       struct page * next = entry->next;
+       struct page * prev = entry->prev;
+       next->prev = prev;
+       prev->next = next;
 }
 
 /*
@@ -55,30 +85,33 @@ static inline void remove_mem_queue(struct mem_list * head, struct mem_list * en
 /*
  * Buddy system. Hairy. You really aren't expected to understand this
  */
-static inline void free_pages_ok(unsigned long addr, unsigned long order)
+static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
 {
-       unsigned long index = MAP_NR(addr) >> (1 + order);
-       unsigned long mask = PAGE_MASK << order;
+       unsigned long index = map_nr >> (1 + order);
+       unsigned long mask = (~0UL) << order;
+
+#define list(x) (mem_map+(x))
 
-       addr &= mask;
+       map_nr &= mask;
        nr_free_pages += 1 << order;
        while (order < NR_MEM_LISTS-1) {
-               if (!change_bit(index, free_area_map[order]))
+               if (!change_bit(index, free_area[order].map))
                        break;
-               remove_mem_queue(free_area_list+order, (struct mem_list *) (addr ^ (1+~mask)));
+               remove_mem_queue(&free_area[order].list, list(map_nr ^ (1+~mask)));
+               mask <<= 1;
                order++;
                index >>= 1;
-               mask <<= 1;
-               addr &= mask;
+               map_nr &= mask;
        }
-       add_mem_queue(free_area_list+order, (struct mem_list *) addr);
+       add_mem_queue(&free_area[order].list, list(map_nr));
+#undef list
 }
 
-static inline void check_free_buffers(unsigned long addr)
+static inline void check_free_buffers(mem_map_t * map)
 {
        struct buffer_head * bh;
 
-       bh = buffer_pages[MAP_NR(addr)];
+       bh = map->buffers;
        if (bh) {
                struct buffer_head *tmp = bh;
                do {
@@ -92,21 +125,23 @@ static inline void check_free_buffers(unsigned long addr)
 
 void free_pages(unsigned long addr, unsigned long order)
 {
-       if (MAP_NR(addr) < MAP_NR(high_memory)) {
-               unsigned long flag;
-               mem_map_t * map = mem_map + MAP_NR(addr);
+       unsigned long map_nr = MAP_NR(addr);
+
+       if (map_nr < MAP_NR(high_memory)) {
+               mem_map_t * map = mem_map + map_nr;
                if (map->reserved)
                        return;
                if (map->count) {
+                       unsigned long flag;
                        save_flags(flag);
                        cli();
                        if (!--map->count) {
-                               free_pages_ok(addr, order);
-                               delete_from_swap_cache(addr);
+                               free_pages_ok(map_nr, order);
+                               delete_from_swap_cache(map_nr);
                        }
                        restore_flags(flag);
                        if (map->count == 1)
-                               check_free_buffers(addr);
+                               check_free_buffers(map);
                        return;
                }
                printk("Trying to free free memory (%08lx): memory probably corrupted\n",addr);
@@ -118,43 +153,44 @@ void free_pages(unsigned long addr, unsigned long order)
 /*
  * Some ugly macros to speed up __get_free_pages()..
  */
-#define RMQUEUE(order, limit) \
-do { struct mem_list * queue = free_area_list+order; \
+#define MARK_USED(index, order, area) \
+       change_bit((index) >> (1+(order)), (area)->map)
+#define CAN_DMA(x) ((x)->dma)
+#define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
+#define RMQUEUE(order, dma) \
+do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
-       do { struct mem_list *prev = queue, *ret; \
-               while (queue != (ret = prev->next)) { \
-                       if ((unsigned long) ret < (limit)) { \
+       do { struct page *prev = &area->list, *ret; \
+               while (&area->list != (ret = prev->next)) { \
+                       if (!dma || CAN_DMA(ret)) { \
+                               unsigned long map_nr = ret - mem_map; \
                                (prev->next = ret->next)->prev = prev; \
-                               mark_used((unsigned long) ret, new_order); \
+                               MARK_USED(map_nr, new_order, area); \
                                nr_free_pages -= 1 << order; \
+                               EXPAND(ret, map_nr, order, new_order, area); \
                                restore_flags(flags); \
-                               EXPAND(ret, order, new_order); \
-                               return (unsigned long) ret; \
+                               return ADDRESS(map_nr); \
                        } \
                        prev = ret; \
                } \
-               new_order++; queue++; \
+               new_order++; area++; \
        } while (new_order < NR_MEM_LISTS); \
 } while (0)
 
-static inline int mark_used(unsigned long addr, unsigned long order)
-{
-       return change_bit(MAP_NR(addr) >> (1+order), free_area_map[order]);
-}
-
-#define EXPAND(addr,low,high) \
-do { unsigned long size = PAGE_SIZE << high; \
+#define EXPAND(map,index,low,high,area) \
+do { unsigned long size = 1 << high; \
        while (high > low) { \
-               high--; size >>= 1; cli(); \
-               add_mem_queue(free_area_list+high, addr); \
-               mark_used((unsigned long) addr, high); \
-               restore_flags(flags); \
-               addr = (struct mem_list *) (size + (unsigned long) addr); \
-       } mem_map[MAP_NR((unsigned long) addr)].count = 1; \
-       mem_map[MAP_NR((unsigned long) addr)].age = PAGE_INITIAL_AGE; \
+               area--; high--; size >>= 1; \
+               add_mem_queue(&area->list, map); \
+               MARK_USED(index, high, area); \
+               index += size; \
+               map += size; \
+       } \
+       map->count = 1; \
+       map->age = PAGE_INITIAL_AGE; \
 } while (0)
 
-unsigned long __get_free_pages(int priority, unsigned long order, unsigned long limit)
+unsigned long __get_free_pages(int priority, unsigned long order, int dma)
 {
        unsigned long flags;
        int reserved_pages;
@@ -176,12 +212,12 @@ unsigned long __get_free_pages(int priority, unsigned long order, unsigned long
 repeat:
        cli();
        if ((priority==GFP_ATOMIC) || nr_free_pages > reserved_pages) {
-               RMQUEUE(order, limit);
+               RMQUEUE(order, dma);
                restore_flags(flags);
                return 0;
        }
        restore_flags(flags);
-       if (priority != GFP_BUFFER && try_to_free_page(priority, limit, 1))
+       if (priority != GFP_BUFFER && try_to_free_page(priority, dma, 1))
                goto repeat;
        return 0;
 }
@@ -200,9 +236,9 @@ void show_free_areas(void)
        save_flags(flags);
        cli();
        for (order=0 ; order < NR_MEM_LISTS; order++) {
-               struct mem_list * tmp;
+               struct page * tmp;
                unsigned long nr = 0;
-               for (tmp = free_area_list[order].next ; tmp != free_area_list + order ; tmp = tmp->next) {
+               for (tmp = free_area[order].list.next ; tmp != &free_area[order].list ; tmp = tmp->next) {
                        nr ++;
                }
                total += nr * ((PAGE_SIZE>>10) << order);
@@ -246,18 +282,19 @@ unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem)
        memset(mem_map, 0, start_mem - (unsigned long) mem_map);
        do {
                --p;
+               p->dma = 1;
                p->reserved = 1;
        } while (p > mem_map);
 
        for (i = 0 ; i < NR_MEM_LISTS ; i++) {
                unsigned long bitmap_size;
-               free_area_list[i].prev = free_area_list[i].next = &free_area_list[i];
+               init_mem_queue(&free_area[i].list);
                mask += mask;
                end_mem = (end_mem + ~mask) & mask;
                bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
                bitmap_size = (bitmap_size + 7) >> 3;
                bitmap_size = LONG_ALIGN(bitmap_size);
-               free_area_map[i] = (unsigned int *) start_mem;
+               free_area[i].map = (unsigned int *) start_mem;
                memset((void *) start_mem, 0, bitmap_size);
                start_mem += bitmap_size;
        }
@@ -293,7 +330,7 @@ void swap_in(struct task_struct * tsk, struct vm_area_struct * vma,
        }
        vma->vm_mm->rss++;
        tsk->maj_flt++;
-       if (!write_access && add_to_swap_cache(page, entry)) {
+       if (!write_access && add_to_swap_cache(MAP_NR(page), entry)) {
                set_pte(page_table, mk_pte(page, vma->vm_page_prot));
                return;
        }
index c4b1210c1fdf415391cc6a18874e4ff6a8c2e983..9ca40ff9a7f53d851a4d8bb349d06b7129da9b5b 100644 (file)
@@ -49,7 +49,7 @@ void show_swap_cache_info(void)
 }
 #endif
 
-int add_to_swap_cache(unsigned long addr, unsigned long entry)
+int add_to_swap_cache(unsigned long index, unsigned long entry)
 {
        struct swap_info_struct * p = &swap_info[SWP_TYPE(entry)];
 
@@ -57,7 +57,7 @@ int add_to_swap_cache(unsigned long addr, unsigned long entry)
        swap_cache_add_total++;
 #endif
        if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) {
-               entry = xchg(swap_cache + MAP_NR(addr), entry);
+               entry = xchg(swap_cache + index, entry);
                if (entry)  {
                        printk("swap_cache: replacing non-NULL entry\n");
                }
index 1e20da9ebd7b0b03f5ac74c0fa88266115746f13..1dab57ceaad17c4d1f5641819ae2c90185023d50 100644 (file)
@@ -168,14 +168,14 @@ static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address,
        if (pte_none(pte))
                return 0;
        if (pte_present(pte)) {
-               unsigned long page = pte_page(pte);
-               if (page >= high_memory)
+               unsigned long page_nr = MAP_NR(pte_page(pte));
+               if (page_nr >= MAP_NR(high_memory))
                        return 0;
-               if (!in_swap_cache(page))
+               if (!in_swap_cache(page_nr))
                        return 0;
-               if (SWP_TYPE(in_swap_cache(page)) != type)
+               if (SWP_TYPE(in_swap_cache(page_nr)) != type)
                        return 0;
-               delete_from_swap_cache(page);
+               delete_from_swap_cache(page_nr);
                set_pte(dir, pte_mkdirty(pte));
                return 0;
        }
@@ -263,18 +263,18 @@ static int unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
        return 0;
 }
 
-static int unuse_process(struct task_struct * p, unsigned int type, unsigned long page)
+static int unuse_process(struct mm_struct * mm, unsigned int type, unsigned long page)
 {
        struct vm_area_struct* vma;
 
        /*
         * Go through process' page directory.
         */
-       if (!p->mm || pgd_inuse(p->mm->pgd))
+       if (!mm)
                return 0;
-       vma = p->mm->mmap;
+       vma = mm->mmap;
        while (vma) {
-               pgd_t * pgd = pgd_offset(p->mm, vma->vm_start);
+               pgd_t * pgd = pgd_offset(mm, vma->vm_start);
                if (unuse_vma(vma, pgd, vma->vm_start, vma->vm_end, type, page))
                        return 1;
                vma = vma->vm_next;
@@ -296,8 +296,9 @@ static int try_to_unuse(unsigned int type)
                return -ENOMEM;
        nr = 0;
        while (nr < NR_TASKS) {
-               if (task[nr]) {
-                       if (unuse_process(task[nr], type, page)) {
+               struct task_struct * p = task[nr];
+               if (p) {
+                       if (unuse_process(p->mm, type, page)) {
                                page = get_free_page(GFP_KERNEL);
                                if (!page)
                                        return -ENOMEM;
index e17476e00dc3383b158976fe3d57c8afe32bb499..98d57c77cf6ee9e434771bc14a8e9095a847d0d5 100644 (file)
@@ -68,7 +68,7 @@ static void init_swap_timer(void);
  * have died while we slept).
  */
 static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struct* vma,
-       unsigned long address, pte_t * page_table, unsigned long limit, int wait)
+       unsigned long address, pte_t * page_table, int dma, int wait)
 {
        pte_t pte;
        unsigned long entry;
@@ -81,16 +81,15 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
        page = pte_page(pte);
        if (MAP_NR(page) >= MAP_NR(high_memory))
                return 0;
-       if (page >= limit)
-               return 0;
 
        page_map = mem_map + MAP_NR(page);
-       if (page_map->reserved || page_map->locked)
+       if (page_map->reserved || page_map->locked ||
+           (dma && !page_map->dma))
                return 0;
        /* Deal with page aging.  Pages age from being unused; they
         * rejuvinate on being accessed.  Only swap old pages (age==0
         * is oldest). */
-       if ((pte_dirty(pte) && delete_from_swap_cache(page)) 
+       if ((pte_dirty(pte) && delete_from_swap_cache(MAP_NR(page))) 
            || pte_young(pte))  {
                set_pte(page_table, pte_mkold(pte));
                touch_page(page_map);
@@ -119,7 +118,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
                free_page(page);
                return 1;       /* we slept: the process may not exist any more */
        }
-        if ((entry = find_in_swap_cache(page)))  {
+        if ((entry = find_in_swap_cache(MAP_NR(page))))  {
                if (page_map->count != 1) {
                        set_pte(page_table, pte_mkdirty(pte));
                        printk("Aiee.. duplicated cached swap-cache entry\n");
@@ -154,7 +153,7 @@ static inline int try_to_swap_out(struct task_struct * tsk, struct vm_area_struc
  */
 
 static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct * vma,
-       pmd_t *dir, unsigned long address, unsigned long end, unsigned long limit, int wait)
+       pmd_t *dir, unsigned long address, unsigned long end, int dma, int wait)
 {
        pte_t * pte;
        unsigned long pmd_end;
@@ -176,7 +175,7 @@ static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct *
        do {
                int result;
                tsk->swap_address = address + PAGE_SIZE;
-               result = try_to_swap_out(tsk, vma, address, pte, limit, wait);
+               result = try_to_swap_out(tsk, vma, address, pte, dma, wait);
                if (result)
                        return result;
                address += PAGE_SIZE;
@@ -186,7 +185,7 @@ static inline int swap_out_pmd(struct task_struct * tsk, struct vm_area_struct *
 }
 
 static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct * vma,
-       pgd_t *dir, unsigned long address, unsigned long end, unsigned long limit, int wait)
+       pgd_t *dir, unsigned long address, unsigned long end, int dma, int wait)
 {
        pmd_t * pmd;
        unsigned long pgd_end;
@@ -206,7 +205,7 @@ static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct *
                end = pgd_end;
        
        do {
-               int result = swap_out_pmd(tsk, vma, pmd, address, end, limit, wait);
+               int result = swap_out_pmd(tsk, vma, pmd, address, end, dma, wait);
                if (result)
                        return result;
                address = (address + PMD_SIZE) & PMD_MASK;
@@ -216,7 +215,7 @@ static inline int swap_out_pgd(struct task_struct * tsk, struct vm_area_struct *
 }
 
 static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
-       pgd_t *pgdir, unsigned long start, unsigned long limit, int wait)
+       pgd_t *pgdir, unsigned long start, int dma, int wait)
 {
        unsigned long end;
 
@@ -227,7 +226,7 @@ static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
 
        end = vma->vm_end;
        while (start < end) {
-               int result = swap_out_pgd(tsk, vma, pgdir, start, end, limit, wait);
+               int result = swap_out_pgd(tsk, vma, pgdir, start, end, dma, wait);
                if (result)
                        return result;
                start = (start + PGDIR_SIZE) & PGDIR_MASK;
@@ -236,7 +235,7 @@ static int swap_out_vma(struct task_struct * tsk, struct vm_area_struct * vma,
        return 0;
 }
 
-static int swap_out_process(struct task_struct * p, unsigned long limit, int wait)
+static int swap_out_process(struct task_struct * p, int dma, int wait)
 {
        unsigned long address;
        struct vm_area_struct* vma;
@@ -257,7 +256,7 @@ static int swap_out_process(struct task_struct * p, unsigned long limit, int wai
                address = vma->vm_start;
 
        for (;;) {
-               int result = swap_out_vma(p, vma, pgd_offset(p->mm, address), address, limit, wait);
+               int result = swap_out_vma(p, vma, pgd_offset(p->mm, address), address, dma, wait);
                if (result)
                        return result;
                vma = vma->vm_next;
@@ -269,7 +268,7 @@ static int swap_out_process(struct task_struct * p, unsigned long limit, int wai
        return 0;
 }
 
-static int swap_out(unsigned int priority, unsigned long limit, int wait)
+static int swap_out(unsigned int priority, int dma, int wait)
 {
        static int swap_task;
        int loop, counter;
@@ -308,7 +307,7 @@ static int swap_out(unsigned int priority, unsigned long limit, int wait)
                }
                if (!--p->swap_cnt)
                        swap_task++;
-               switch (swap_out_process(p, limit, wait)) {
+               switch (swap_out_process(p, dma, wait)) {
                        case 0:
                                if (p->swap_cnt)
                                        swap_task++;
@@ -327,7 +326,7 @@ static int swap_out(unsigned int priority, unsigned long limit, int wait)
  * to be.  This works out OK, because we now do proper aging on page
  * contents. 
  */
-int try_to_free_page(int priority, unsigned long limit, int wait)
+int try_to_free_page(int priority, int dma, int wait)
 {
        static int state = 0;
        int i=6;
@@ -335,15 +334,15 @@ int try_to_free_page(int priority, unsigned long limit, int wait)
        switch (state) {
                do {
                case 0:
-                       if (shrink_mmap(i, limit))
+                       if (shrink_mmap(i, dma))
                                return 1;
                        state = 1;
                case 1:
-                       if (shm_swap(i, limit))
+                       if (shm_swap(i, dma))
                                return 1;
                        state = 2;
                default:
-                       if (swap_out(i, limit, wait))
+                       if (swap_out(i, dma, wait))
                                return 1;
                        state = 0;
                } while (i--);
@@ -400,7 +399,7 @@ int kswapd(void *unused)
                swapstats.wakeups++;
                /* Do the background pageout: */
                for (i=0; i < kswapd_ctl.maxpages; i++)
-                       try_to_free_page(GFP_KERNEL, ~0UL, 0);
+                       try_to_free_page(GFP_KERNEL, 0, 0);
        }
 }
 
index ac7a6838262abaa7cf1f27b63f0c7296b7125d29..9355f21015ee6297fd4074cc0faab9c23cb46457 100644 (file)
@@ -170,6 +170,7 @@ static void unix_delayed_delete(unix_socket *sk)
 static void unix_destroy_socket(unix_socket *sk)
 {
        struct sk_buff *skb;
+
        unix_remove_socket(sk);
        
        while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
@@ -184,7 +185,7 @@ static void unix_destroy_socket(unix_socket *sk)
                }
                else
                {
-/*                     unix_kill_credentials(skb);     *//* Throw out any passed fd's */
+                       /* passed fds are erased where?? */
                        kfree_skb(skb,FREE_WRITE);
                }
        }
@@ -782,7 +783,7 @@ static void unix_fd_free(struct sock *sk, struct file **fp, int num)
  *     but how the old code did it - or like this...
  */
 
-int unix_files_free(void)
+static int unix_files_free(void)
 {
        int i;
        int n=0;
@@ -808,13 +809,16 @@ int unix_files_free(void)
 static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
 {
        int i;
+       /* count of space in parent for fds */
        int cmnum;
        struct file **fp;
        struct file **ufp;
        int *cmfptr=NULL;       /* =NULL To keep gcc happy */
+       /* number of fds actually passed */
        int fdnum;
        int ffree;
        int ufn=0;
+
        if(cmsg==NULL)
                cmnum=0;
        else
@@ -858,7 +862,9 @@ static void unix_detach_fds(struct sk_buff *skb, struct cmsghdr *cmsg)
        }
        kfree(skb->h.filp);
        skb->h.filp=NULL;
-       
+
+       /* no need to use destructor */
+       skb->destructor = NULL;
 }
 
 static void unix_destruct_fds(struct sk_buff *skb)
@@ -869,14 +875,16 @@ static void unix_destruct_fds(struct sk_buff *skb)
 /*
  *     Attach the file descriptor array to an sk_buff
  */
 static void unix_attach_fds(int fpnum,struct file **fp,struct sk_buff *skb)
 {
+
        skb->h.filp=kmalloc(sizeof(int)+fpnum*sizeof(struct file *), 
                                                        GFP_KERNEL);
+       /* number of descriptors starts block */
        memcpy(skb->h.filp,&fpnum,sizeof(int));
+       /* actual  descriptors */
        memcpy(skb->h.filp+sizeof(int),fp,fpnum*sizeof(struct file *));
-       skb->destructor=unix_destruct_fds;
+       skb->destructor = unix_destruct_fds;
 }
 
 /*
@@ -893,8 +901,10 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        int limit=0;
        int sent=0;
        struct file *fp[UNIX_MAX_FD];
+       /* number of fds waiting to be passed, 0 means either
+        * no fds to pass or they've already been passed 
+        */
        int fpnum=0;
-       int fp_attached=0;
 
        if(sk->err)
                return sock_error(sk);
@@ -935,18 +945,12 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                   cm->cmsg_level!=SOL_SOCKET ||
                   msg->msg_accrightslen!=cm->cmsg_len)
                {
-#if 0
-                       printk("Sendmsg: bad access rights\n");
-#endif
                        kfree(cm);
                        return -EINVAL;
                }
                fpnum=unix_fd_copy(sk,cm,fp);
                kfree(cm);
                if(fpnum<0) {
-#if 0
-                       printk("Sendmsg error = %d\n", fpnum);
-#endif
                        return fpnum;
                }
        }
@@ -1001,14 +1005,14 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                skb->sk=sk;
                skb->free=1;
                
-               if(fpnum && !fp_attached)
+               if(fpnum)
                {
-                       fp_attached=1;
                        unix_attach_fds(fpnum,fp,skb);
                        fpnum=0;
                }
                else
                        skb->h.filp=NULL;
+
                memcpy_fromiovec(skb_put(skb,size),msg->msg_iov, size);
 
                cli();
@@ -1090,7 +1094,6 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
 
        if(msg->msg_accrights) 
        {
-               printk("recvmsg with accrights\n");
                cm=unix_copyrights(msg->msg_accrights, 
                        msg->msg_accrightslen);
                if(msg->msg_accrightslen<sizeof(struct cmsghdr)
index 7dcad7d489afae4b2f96addd4c2978a27a457db6..061002e43bb4a4f1d0f44fa74050abdb0d2ce95e 100644 (file)
@@ -843,11 +843,11 @@ cleanup2 () {
 
 menu_instructions="\
 Arrow keys navigate the menu.  \
-Highlighted letters are hotkeys. \
-Select an item with <Space Bar> or <Enter>. \
+Highlighted letters are hotkeys.  \
+Select an item with <Space Bar> or <Enter>.  \
 When finished press <Esc><Esc> or <X>.  \
-(*) indicates an option will be compiled into the kernel.  \
-(M) indicates an option will be compiled as a module."
+A (*) marks an option to be compiled into the kernel.  \
+An (M) marks an option to be compiled as a module."
 
 radiolist_instructions="\
 Use the arrow keys to navigate this window or \
@@ -970,7 +970,7 @@ the files are correctly re-made.
 EOM
 else
        clear
-       echo -e "Your kernel configuration changes where NOT saved.\n"
+       echo -e "Your kernel configuration changes were NOT saved.\n"
 fi
 
 
index 4db037c2c053bd9462e65a68a4103b56a39564bb..575d470f443cd7b7375730b2f7d8db8e010f9b5b 100644 (file)
@@ -381,7 +381,7 @@ proc dohelp {w varname }  {
                        /^$varname\[    \]*\$/ {
                                start=1;
                                printf(\"%s:\\n\\n\",\$0);
-                               continue;
+                               next;
                        }
                        !/^\[   \]/ {
                                start=0;
index 39e661d0a24234b08d2607e024abad4b787f1496..20c7402d86181fd6287683fc5fa9e9ef69ca14df 100644 (file)
@@ -190,16 +190,16 @@ end_dialog (void)
 
 /*
  * Print a string of text in a window, automatically wrap around to the
- * next line if the string is too long to fit on one line. Note that the
- * string may contain "\n" to represent a newline character or the real
- * newline '\n', but in that case, auto wrap around will be disabled.
+ * next line if the string is too long to fit on one line. Newline
+ * characters '\n' are replaced by spaces.  We start on a new line
+ * if there is no room for at least 4 nonblanks following a double-space.
  */
 void
 print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
 {
-    int first = 1, cur_x, cur_y;
-    int i, prompt_len;
-    char tempstr[MAX_LEN + 1], *word /*,  *tempptr, *tempptr1*/;
+    int newl, cur_x, cur_y;
+    int i, prompt_len, room, wlen;
+    char tempstr[MAX_LEN + 1], *word, *sp, *sp2;
 
     strcpy (tempstr, prompt);
 
@@ -212,24 +212,41 @@ print_autowrap (WINDOW * win, const char *prompt, int width, int y, int x)
        if(tempstr[i] == '\n') tempstr[i] = ' ';
     }
 
-    if (strlen (tempstr) <= width - x * 2) {   /* If prompt is short */
-       wmove (win, y, (width - strlen (tempstr)) / 2);
+    if (prompt_len <= width - x * 2) { /* If prompt is short */
+       wmove (win, y, (width - prompt_len) / 2);
        waddstr (win, tempstr);
     } else {
        cur_x = x;
        cur_y = y;
-       /* Print prompt word by word, wrap around if necessary */
-       while ((word = strtok (first ? tempstr : NULL, " ")) != NULL) {
-           if (first)          /* First iteration */
-               first = 0;
-           if (cur_x + strlen (word) > width) {
-               cur_y++;        /* wrap to next line */
+       newl = 1;
+       word = tempstr;
+       while (word && *word) {
+           sp = index(word, ' ');
+           if (sp)
+               *sp++ = 0;
+
+           /* Wrap to next line if either the word does not fit,
+              or it is the first word of a new sentence, and it is
+              short, and the next word does not fit. */
+           room = width - cur_x;
+           wlen = strlen(word);
+           if (wlen > room ||
+              (newl && wlen < 4 && sp && wlen+1+strlen(sp) > room
+                    && (!(sp2 = index(sp, ' ')) || wlen+1+(sp2-sp) > room))) {
+               cur_y++;
                cur_x = x;
            }
            wmove (win, cur_y, cur_x);
            waddstr (win, word);
            getyx (win, cur_y, cur_x);
            cur_x++;
+           if (sp && *sp == ' ') {
+               cur_x++;        /* double space */
+               while (*++sp == ' ');
+               newl = 1;
+           } else
+               newl = 0;
+           word = sp;
        }
     }
 }