]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.3.15 2.3.15
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:27:05 +0000 (15:27 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:27:05 +0000 (15:27 -0500)
There's a rather huge patch-set out there now, taking the 2.3.x series to
2.3.15.
This has a lot of the merge code I've been sent over the last two weeks,
but I will invariably have missed some, if for no other reason than simply
that I got absolutely _flooded_ by people sending me patches.

One of the more interesting things was the SMP pipe cleanup sent by
Richard, but try as I might it was never really stable under load on x86 -
not with the plain semaphores in 2.3.14, and not with the patches Andrea
had either. I assume Richard tested it on an alpha with the much more
well-thought-out atomic operation that the alpha provides.

I ended up rewriting the x86 semaphore code (and some of Richards pipe
code too, for that matter, to get rid of some races in waking things up),
and it doesn't show the problems I saw before, but hey, maybe I just
exchanged one set of problems for another set that I can't trigger any
more. Give me feedback, please.

Other features that don't impact everybody, but are rather major:
 - ATM support merged in
 - firewalling is gone (again), replaced by an even more generic netfilter
   facility.
 - general networking merges and updates
 - Various driver updates (ISDN, ISA PnP, sound, fbcon, usb, intelliport,
   you name it)
 - make system call return type "long" even if the system call only
   returns valid data in the lower order bits - we use the high bits for
   error handling, and some 64-bit architectures care (read: the Merced
   calling conventions want this because they don't automatically extend
   the return type - I bet it will be a new portability issue for other
   programs than just the kernel)

Have fun,
                Linus

157 files changed:
Documentation/00-INDEX
Documentation/isdn/INTERFACE
Documentation/isdn/README.HiSax
arch/alpha/kernel/Makefile
arch/alpha/kernel/semaphore.c [new file with mode: 0644]
arch/i386/kernel/Makefile
arch/i386/kernel/irq.c
arch/i386/kernel/semaphore.c [new file with mode: 0644]
arch/i386/kernel/setup.c
arch/i386/lib/Makefile
arch/i386/lib/semaphore.S [deleted file]
arch/i386/mm/init.c
drivers/atm/ambassador.h
drivers/atm/horizon.c
drivers/atm/horizon.h
drivers/atm/suni.c
drivers/atm/uPD98402.c
drivers/atm/zatm.c
drivers/atm/zatm.h
drivers/char/ip2.c
drivers/char/ip2main.c
drivers/isdn/Config.in
drivers/isdn/avmb1/b1.c
drivers/isdn/avmb1/b1isa.c
drivers/isdn/avmb1/b1pcmcia.c
drivers/isdn/avmb1/t1isa.c
drivers/isdn/divert/divert_init.c
drivers/isdn/divert/isdn_divert.c
drivers/isdn/divert/isdn_divert.h
drivers/isdn/eicon/eicon.h
drivers/isdn/eicon/eicon_idi.c
drivers/isdn/eicon/eicon_idi.h
drivers/isdn/eicon/eicon_io.c
drivers/isdn/eicon/eicon_isa.c
drivers/isdn/eicon/eicon_mod.c
drivers/isdn/eicon/eicon_pci.c
drivers/isdn/hisax/arcofi.c
drivers/isdn/hisax/bkm_a4t.c
drivers/isdn/hisax/bkm_a8.c
drivers/isdn/hisax/callc.c
drivers/isdn/hisax/config.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/gazel.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hisax.h
drivers/isdn/hisax/isac.c
drivers/isdn/hisax/isar.c
drivers/isdn/hisax/isar.h
drivers/isdn/hisax/isdnl1.c
drivers/isdn/hisax/isdnl2.c
drivers/isdn/hisax/isurf.c
drivers/isdn/hisax/l3dss1.c
drivers/isdn/hisax/md5sums.asc
drivers/isdn/hisax/sedlbauer.c
drivers/isdn/icn/icn.c
drivers/isdn/isdn_audio.c
drivers/isdn/isdn_concap.c
drivers/isdn/isdn_net.c
drivers/isdn/isdn_net.h
drivers/isdn/isdn_ppp.c
drivers/isdn/isdn_ppp.h
drivers/isdn/isdn_tty.h
drivers/isdn/isdn_ttyfax.c
drivers/isdn/isdn_x25iface.c
drivers/isdn/pcbit/module.c
drivers/net/ppp_async.c
drivers/net/sb1000.c
drivers/net/sk_mca.c
drivers/pci/names.c
drivers/pci/pci.c
drivers/pci/quirks.c
drivers/scsi/megaraid.c
drivers/sound/esssolo1.c
drivers/sound/vwsnd.c
drivers/usb/Config.in
drivers/usb/Makefile
drivers/usb/acm.c
drivers/usb/audio.c
drivers/usb/cpia.c
drivers/usb/cpia.h
drivers/usb/ezusb.c
drivers/usb/ezusb.h
drivers/usb/hub.c
drivers/usb/hub.h
drivers/usb/mouse.c
drivers/usb/printer.c
drivers/usb/proc_usb.c
drivers/usb/uhci-debug.c
drivers/usb/uhci.c
drivers/usb/uhci.h
drivers/usb/usb-debug.c
drivers/usb/usb.c
drivers/usb/usb.h
drivers/usb/usb_scsi.c
drivers/usb/uss720.c
drivers/video/Config.in
drivers/video/Makefile
drivers/video/atyfb.c
drivers/video/clgenfb.c
drivers/video/fbmem.c
drivers/video/matroxfb.c
drivers/video/pm2fb.c
drivers/video/vesafb.c
drivers/video/vga.h
drivers/video/vga16fb.c
fs/fifo.c
fs/pipe.c
include/asm-i386/atomic.h
include/asm-i386/io.h
include/asm-i386/semaphore-helper.h [deleted file]
include/asm-i386/semaphore.h
include/linux/concap.h
include/linux/i2c.h
include/linux/if_ether.h
include/linux/isdn.h
include/linux/isdn_compat.h
include/linux/isdnif.h
include/linux/msg.h
include/linux/netfilter.h
include/linux/netfilter_ipv4.h
include/linux/pipe_fs_i.h
include/linux/prctl.h
include/video/fbcon.h
ipc/msg.c
kernel/module.c
kernel/sched.c
kernel/sys.c
mm/memory.c
net/802/fc.c
net/802/llc_macinit.c
net/802/p8022.c
net/802/psnap.c
net/802/tr.c
net/appletalk/aarp.c
net/appletalk/ddp.c
net/atm/atm_misc.c
net/atm/ipcommon.c
net/atm/lec.c
net/ax25/af_ax25.c
net/core/dev.c
net/core/dev_mcast.c
net/core/dst.c
net/core/netfilter.c
net/core/profile.c
net/core/rtnetlink.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/ip_fragment.c
net/ipv4/route.c
net/ipv4/tcp.c
net/khttpd/datasending.c
net/khttpd/main.c
net/khttpd/sysctl.c
net/khttpd/userspace.c
net/khttpd/waitheaders.c
net/netsyms.c
net/unix/af_unix.c

index ea256f2f17473ae1f86c82d0f3247a9c3d96f18c..dc29ec22badd9081a6ba7b2c846873907c2bac88 100644 (file)
@@ -34,7 +34,7 @@ cdrom/
 cpqarray.txt
        - info on using Compaq's SMART2 Intelligent Disk Array Controllers.
 devices.tex
-       - TeX source listing of all the nodes in /dev/ with major minor #'s
+       - LaTeX source listing of all the nodes in /dev/ with major minor #'s
 devices.txt
        - plain ASCII listing of all the nodes in /dev/ with major minor #'s
 digiboard.txt
@@ -138,7 +138,7 @@ sgi-visws.txt
 smart-config.txt
        - description of the Smart Config makefile feature.
 smp.tex
-       - TeX document describing implementation of Multiprocessor Linux
+       - LaTeX document describing implementation of Multiprocessor Linux
 smp.txt
        - a few more notes on symmetric multi-processing
 sound/
index d8bf08ccc63c23b2839be332ec4b6fc1f0f02a1a..c2a5494b1f8865e900863c1f36f2aa9f99223197 100644 (file)
@@ -1,4 +1,4 @@
-$Id: INTERFACE,v 1.13 1999/08/11 20:30:26 armin Exp $
+$Id: INTERFACE,v 1.15 1999/08/25 20:02:13 werner Exp $
 
 Description of the Interface between Linklevel and Hardwarelevel
   of isdn4linux:
@@ -436,6 +436,57 @@ Description of the Interface between Linklevel and Hardwarelevel
       arg         = unused.
       parm        = unused.
 
+  ISDN_CMD_PROCEED: 
+
+    With this command, the HL-driver is told to proceed with a incoming call.
+
+    Parameter:
+      driver      = driver-Id.
+      command     = ISDN_CMD_PROCEED
+      arg         = channel-number locally to the driver. (starting with 0)
+      setup.eazmsn= empty string or string send as uus1 in DSS1 with 
+                    PROCEED message
+
+  ISDN_CMD_ALERT: 
+
+    With this command, the HL-driver is told to alert a proceeding call.
+
+    Parameter:
+      driver      = driver-Id.
+      command     = ISDN_CMD_ALERT
+      arg         = channel-number locally to the driver. (starting with 0)
+      setup.eazmsn= empty string or string send as uus1 in DSS1 with 
+                    ALERT message
+
+  ISDN_CMD_REDIR: 
+
+    With this command, the HL-driver is told to redirect a call in proceeding
+    or alerting state.  
+
+    Parameter:
+      driver      = driver-Id.
+      command     = ISDN_CMD_REDIR
+      arg         = channel-number locally to the driver. (starting with 0)
+      setup.eazmsn= empty string or string send as uus1 in DSS1 protocol
+      setup.screen= screening indicator
+      setup.phone = redirected to party number
+
+  ISDN_CMD_PROT_IO:
+
+    With this call, the LL-driver invokes protocol specific features through
+    the LL.
+    The call is not implicitely bound to a connection.
+
+    Parameter:
+      driver      = driver-Id
+      command     = ISDN_CMD_PROT_IO
+      arg         = The lower 8 Bits define the adressed protocol as defined
+                    in ISDN_PTYPE..., the upper bits are used to differenciate
+                    the protocol specific CMD.  
+      
+      para        = protocol and function specific. See isdnif.h for detail.
+
+
   ISDN_CMD_FAXCMD:
 
     With this command the HL-driver receives a fax sub-command.
@@ -471,34 +522,44 @@ Description of the Interface between Linklevel and Hardwarelevel
       parm        = unused.
 
   ISDN_STAT_ICALL:
+  ISDN_STAT_ICALLW:
 
     With this call, the HL-driver signals an incoming call to the LL.
+    If ICALLW is signalled the incoming call is a waiting call without
+    a available B-chan.
 
     Parameter:
       driver            = driver-Id
       command           = ISDN_STAT_ICALL
       arg               = channel-number, locally to the driver. (starting with 0)
-      parm.setup.phone  = Callernumber.
-      parm.setup.eazmsn = CalledNumber.
-      parm.setup.si1    = Service Indicator.
-      parm.setup.si2    = Additional Service Indicator.
-      parm.setup.plan   = octet 3 from Calling party number Information Element.
-      parm.setup.screen = octet 3a from Calling party number Information Element.
+      para.setup.phone  = Callernumber.
+      para.setup.eazmsn = CalledNumber.
+      para.setup.si1    = Service Indicator.
+      para.setup.si2    = Additional Service Indicator.
+      para.setup.plan   = octet 3 from Calling party number Information Element.
+      para.setup.screen = octet 3a from Calling party number Information Element.
 
     Return:
       0           = No device matching this call.
       1           = At least one device matching this call (RING on ttyI).
                     HL-driver may send ALERTING on the D-channel in this case.
       2           = Call will be rejected.
-      3           = Incomplete number.
-                    The CalledNumber would match, if more digits are appended.
-                    This feature is needed for Number-Blocks assigned to
-                    a line. In this case, the LL driver should assemble the
-                                       CalledNumber by handling keypad protocol and try again
-                                       later with a longer CalledNumber.
-                                       HL drivers serving ordinary lines should interpret this
-                                       return code like 0 (nothing matches).
+      3           = Incoming called party number is currently incomplete.
+                    Additional digits are required. 
+                    Used for signalling with PtP connections.
+      4                  = Call will be held in a proceeding state 
+                    (HL driver sends PROCEEDING)
+                    Used when a user space prog needs time to interpret a call
+                   para.setup.eazmsn may be filled with an uus1 message of
+                   30 octets maximum. Empty string if no uus. 
+      5           = Call will be actively deflected to another party
+                    Only available in DSS1/EURO protocol
+                   para.setup.phone must be set to destination party number
+                   para.setup.eazmsn may be filled with an uus1 message of
+                   30 octets maximum. Empty string if no uus. 
       -1          = An error happened. (Invalid parameters for example.)
+  The keypad support now is included in the dial command.              
+
 
   ISDN_STAT_RUN:
 
@@ -654,19 +715,31 @@ Description of the Interface between Linklevel and Hardwarelevel
       arg         = channel-number, locally to the driver. (starting with 0)
       parm.num    = ASCII string containing CAUSE-message.
 
-  ISDN_STAT_L1ERR:
+  ISDN_STAT_DISPLAY:
 
-    ***CHANGEI1.21 new status message.
-    A signal can be sent to the linklevel if an Layer1-error results in
-    packet-loss on receive or send. The field errcode of the cmd.parm
-    union describes the error more precisely.
+    With this call, the HL-driver delivers DISPLAY-messages to the LL.
+    Currently the LL does not use this messages. 
 
     Parameter:
       driver      = driver-Id
-      command     = ISDN_STAT_L1ERR
+      command     = ISDN_STAT_DISPLAY
       arg         = channel-number, locally to the driver. (starting with 0)
-      parm.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
-                   ISDN_STAT_L1ERR_RECV:     Packet lost while receiving.
+      para.display= string containing DISPLAY-message.
+
+  ISDN_STAT_PROT:
+
+    With this call, the HL-driver delivers protocol specific infos to the LL.
+    The call is not implicitely bound to a connection.
+
+    Parameter:
+      driver      = driver-Id
+      command     = ISDN_STAT_PROT
+      arg         = The lower 8 Bits define the adressed protocol as defined
+                    in ISDN_PTYPE..., the upper bits are used to differenciate
+                    the protocol specific STAT.  
+      
+      para        = protocol and function specific. See isdnif.h for detail.
+
   ISDN_STAT_DISCH:
 
     With this call, the HL-driver signals the LL to disable or enable the
@@ -683,7 +756,20 @@ Description of the Interface between Linklevel and Hardwarelevel
       command     = ISDN_STAT_DISCH
       arg         = channel-number, locally to the driver. (starting with 0)
       parm.num[0] = 0 if channel shall be disabled, else enabled.
-    
+
+  ISDN_STAT_L1ERR:
+
+    ***CHANGEI1.21 new status message.
+    A signal can be sent to the linklevel if an Layer1-error results in
+    packet-loss on receive or send. The field errcode of the cmd.parm
+    union describes the error more precisely.
+
+    Parameter:
+      driver      = driver-Id
+      command     = ISDN_STAT_L1ERR
+      arg         = channel-number, locally to the driver. (starting with 0)
+      parm.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
+                   ISDN_STAT_L1ERR_RECV:     Packet lost while receiving.
   ISDN_STAT_FAXIND:
 
     With this call the HL-driver signals a fax sub-command to the LL.
index a9f9851beb0894c26fa8ff9e4057a61e30b786fc..7faff4a349221622007ec219cdbea6a533ada9e5 100644 (file)
@@ -55,7 +55,8 @@ USR Sportster internal TA (compatible Stollmann tina-pp V3)
 ith Kommunikationstechnik GmbH MIC 16 ISA card
 Traverse Technologie NETjet PCI S0 card
 Dr. Neuhaus Niccy PnP/PCI
-Siemens I-Surf
+Siemens I-Surf 1.0
+Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom) 
 ACER P10
 HST Saphir
 Berkom Telekom A4T
@@ -173,7 +174,7 @@ Card types:
    27   AVM PnP (Fritz!PnP)      irq, io  (from isapnp setup)
    27   AVM PCI (Fritz!PCI)      no parameter
    28   Sedlbauer Speed Fax+     irq, io (from isapnp setup)
-   29  Siemens I-Surf           irq, io, memory (from isapnp setup)   
+   29  Siemens I-Surf 1.0       irq, io, memory (from isapnp setup)   
    30  ACER P10                 irq, io (from isapnp setup)   
    31  HST Saphir               irq, io
    32  Telekom A4T              none
@@ -276,7 +277,7 @@ type
    27   AVM PnP (Fritz!PnP)     ONLY WORKS AS A MODULE !
    27   AVM PCI (Fritz!PCI)     no parameter
    28   Sedlbauer Speed Fax+    ONLY WORKS AS A MODULE !
-   29  Siemens I-Surf          ONLY WORKS AS A MODULE !
+   29  Siemens I-Surf 1.0      ONLY WORKS AS A MODULE !
    30  ACER P10                ONLY WORKS AS A MODULE !
    31  HST Saphir              pa=irq, pb=io
    32  Telekom A4T             no parameter
index 9b1553cfe580e62954e60d6bd7d26f0500628f10..01498a66b0dba09f6b42d6f99dc15a65a3fd96c6 100644 (file)
@@ -16,7 +16,7 @@ all: kernel.o head.o
 
 O_TARGET := kernel.o
 O_OBJS   := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-           bios32.o ptrace.o time.o fpreg.o
+           bios32.o ptrace.o time.o fpreg.o semaphore.o
 OX_OBJS  := alpha_ksyms.o
 
 
diff --git a/arch/alpha/kernel/semaphore.c b/arch/alpha/kernel/semaphore.c
new file mode 100644 (file)
index 0000000..d62b355
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+       wake_one_more(sem);
+       wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR                               \
+       struct task_struct *tsk = current;      \
+       wait_queue_t wait;                      \
+       init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)                                          \
+                                                                       \
+                                                                       \
+       tsk->state = (task_state);                                      \
+       add_wait_queue(&sem->wait, &wait);                              \
+                                                                       \
+       /*                                                              \
+        * Ok, we're set up.  sem->count is known to be less than zero  \
+        * so we must wait.                                             \
+        *                                                              \
+        * We can let go the lock for purposes of waiting.              \
+        * We re-acquire it after awaking so as to protect              \
+        * all semaphore operations.                                    \
+        *                                                              \
+        * If "up()" is called before we call waking_non_zero() then    \
+        * we will catch it right away.  If it is called later then     \
+        * we will have to go through a wakeup cycle to catch it.       \
+        *                                                              \
+        * Multiple waiters contend for the semaphore lock to see       \
+        * who gets to gate through and who has to wait some more.      \
+        */                                                             \
+       for (;;) {
+
+#define DOWN_TAIL(task_state)                  \
+               tsk->state = (task_state);      \
+       }                                       \
+       tsk->state = TASK_RUNNING;              \
+       remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+       DOWN_VAR
+       DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+       if (waking_non_zero(sem))
+               break;
+       schedule();
+       DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+       int ret = 0;
+       DOWN_VAR
+       DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+       ret = waking_non_zero_interruptible(sem, tsk);
+       if (ret)
+       {
+               if (ret == 1)
+                       /* ret != 0 only if we get interrupted -arca */
+                       ret = 0;
+               break;
+       }
+       schedule();
+       DOWN_TAIL(TASK_INTERRUPTIBLE)
+       return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+       return waking_non_zero_trylock(sem);
+}
index 8ec25a3178a7cf1a5837250b3ef5e989620018a3..875f52d5a801c1d6c02db9b6b6fa3dda1e522c71 100644 (file)
@@ -13,7 +13,7 @@
 all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
-O_OBJS   := process.o signal.o entry.o traps.o irq.o vm86.o \
+O_OBJS   := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
            ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o
 OX_OBJS  := i386_ksyms.o
 MX_OBJS  :=
index 8d71ed8bcb9dc6c987d0ba559d257dfd41429234..bda71716477f5c54def9c39e3ae0ceff50753eff 100644 (file)
@@ -20,7 +20,6 @@
  * Naturally it's not a 1:1 relation, but there are similarities.
  */
 
-#include <linux/config.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
new file mode 100644 (file)
index 0000000..dc5e8f6
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to aquire the semaphore, while the "sleeping"
+ * variable is a count of such aquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is
+ * protected by the semaphore spinlock.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ *  - only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - when we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleeper" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+       wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void __down(struct semaphore * sem)
+{
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       tsk->state = TASK_UNINTERRUPTIBLE;
+       add_wait_queue(&sem->wait, &wait);
+
+       spin_lock_irq(&semaphore_lock);
+       sem->sleepers++;
+       for (;;) {
+               int sleepers = sem->sleepers;
+
+               /*
+                * Add "everybody else" into it. They aren't
+                * playing, because we own the spinlock.
+                */
+               if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+                       sem->sleepers = 0;
+                       wake_up(&sem->wait);
+                       break;
+               }
+               sem->sleepers = 1;      /* us - see -1 above */
+               spin_unlock_irq(&semaphore_lock);
+
+               schedule();
+               tsk->state = TASK_UNINTERRUPTIBLE;
+               spin_lock_irq(&semaphore_lock);
+       }
+       spin_unlock_irq(&semaphore_lock);
+       remove_wait_queue(&sem->wait, &wait);
+       tsk->state = TASK_RUNNING;
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+       int retval;
+       struct task_struct *tsk = current;
+       DECLARE_WAITQUEUE(wait, tsk);
+       tsk->state = TASK_INTERRUPTIBLE;
+       add_wait_queue(&sem->wait, &wait);
+
+       spin_lock_irq(&semaphore_lock);
+       sem->sleepers ++;
+       for (;;) {
+               int sleepers = sem->sleepers;
+
+               /*
+                * With signals pending, this turns into
+                * the trylock failure case - we won't be
+                * sleeping, and we* can't get the lock as
+                * it has contention. Just correct the count
+                * and exit.
+                */
+               retval = -EINTR;
+               if (signal_pending(current)) {
+                       sem->sleepers = 0;
+                       if (atomic_add_negative(sleepers, &sem->count))
+                               break;
+                       wake_up(&sem->wait);
+                       break;
+               }
+
+               /*
+                * Add "everybody else" into it. They aren't
+                * playing, because we own the spinlock. The
+                * "-1" is because we're still hoping to get
+                * the lock.
+                */
+               if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+                       wake_up(&sem->wait);
+                       retval = 0;
+                       sem->sleepers = 0;
+                       break;
+               }
+               sem->sleepers = 1;      /* us - see -1 above */
+               spin_unlock_irq(&semaphore_lock);
+
+               schedule();
+               tsk->state = TASK_INTERRUPTIBLE;
+               spin_lock_irq(&semaphore_lock);
+       }
+       spin_unlock_irq(&semaphore_lock);
+       tsk->state = TASK_RUNNING;
+       remove_wait_queue(&sem->wait, &wait);
+       return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ *
+ * We could have done the trylock with a
+ * single "cmpxchg" without failure cases,
+ * but then it wouldn't work on a 386.
+ */
+int __down_trylock(struct semaphore * sem)
+{
+       int retval, sleepers;
+
+       spin_lock_irq(&semaphore_lock);
+       sleepers = sem->sleepers + 1;
+       sem->sleepers = 0;
+
+       /*
+        * Add "everybody else" and us into it. They aren't
+        * playing, because we own the spinlock.
+        */
+       if (!atomic_add_negative(sleepers, &sem->count))
+               wake_up(&sem->wait);
+
+       spin_unlock_irq(&semaphore_lock);
+       return 1;
+}
+
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %ecx contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax when used as a return
+ * value..
+ */
+asm(
+".align 4\n"
+".globl __down_failed\n"
+"__down_failed:\n\t"
+       "pushl %eax\n\t"
+       "pushl %edx\n\t"
+       "pushl %ecx\n\t"
+       "call __down\n\t"
+       "popl %ecx\n\t"
+       "popl %edx\n\t"
+       "popl %eax\n\t"
+       "ret"
+);
+
+asm(
+".align 4\n"
+".globl __down_failed_interruptible\n"
+"__down_failed_interruptible:\n\t"
+       "pushl %edx\n\t"
+       "pushl %ecx\n\t"
+       "call __down_interruptible\n\t"
+       "popl %ecx\n\t"
+       "popl %edx\n\t"
+       "ret"
+);
+
+asm(
+".align 4\n"
+".globl __down_failed_trylock\n"
+"__down_failed_trylock:\n\t"
+       "pushl %edx\n\t"
+       "pushl %ecx\n\t"
+       "call __down_trylock\n\t"
+       "popl %ecx\n\t"
+       "popl %edx\n\t"
+       "ret"
+);
+
+asm(
+".align 4\n"
+".globl __up_wakeup\n"
+"__up_wakeup:\n\t"
+       "pushl %eax\n\t"
+       "pushl %edx\n\t"
+       "pushl %ecx\n\t"
+       "call __up\n\t"
+       "popl %ecx\n\t"
+       "popl %edx\n\t"
+       "popl %eax\n\t"
+       "ret"
+);
index 293877a156395b5c8ef25033fa3988719eb178b3..54645d254105ed64d564a91afb486f6620da3b63 100644 (file)
@@ -1134,11 +1134,11 @@ void cpu_init (void)
        struct tss_struct * t = &init_tss[nr];
 
        if (test_and_set_bit(nr,&cpu_initialized)) {
-               printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr);
+               printk("CPU#%d already initialized!\n", nr);
                for (;;) __sti();
        }
        cpus_initialized++;
-       printk("INITIALIZING CPU#%d\n", nr);
+       printk("Initializing CPU#%d\n", nr);
 
        if (boot_cpu_data.x86_capability & X86_FEATURE_PSE)
                clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
index c2cb3e5a6b9d97dc96d1d0f71a49440c771c3262..a6f8dff0993b2cfbe635de06a22e4514a84de1a2 100644 (file)
@@ -6,7 +6,7 @@
        $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS  = checksum.o old-checksum.o semaphore.o delay.o \
+L_OBJS  = checksum.o old-checksum.o delay.o \
        usercopy.o getuser.o putuser.o
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S
deleted file mode 100644 (file)
index 3f6e27f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  linux/arch/i386/lib/semaphore.S
- *
- *  Copyright (C) 1996  Linus Torvalds
- */
-
-#include <linux/linkage.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- */
-ENTRY(__down_failed)
-       pushl %eax      /* save %eax */
-       pushl %edx      /* save %edx */
-       pushl %ecx      /* save %ecx (and argument) */
-       call SYMBOL_NAME(__down)
-       popl %ecx       /* restore %ecx (count on __down not changing it) */
-       popl %edx       /* restore %edx */
-       popl %eax       /* restore %eax */
-       ret
-
-/* Don't save/restore %eax, because that will be our return value */
-ENTRY(__down_failed_interruptible)
-       pushl %edx      /* save %edx */
-       pushl %ecx      /* save %ecx (and argument) */
-       call SYMBOL_NAME(__down_interruptible)
-       popl %ecx       /* restore %ecx (count on __down_interruptible not changing it) */
-       popl %edx       /* restore %edx */
-       ret
-
-/* Don't save/restore %eax, because that will be our return value */
-ENTRY(__down_failed_trylock)
-       pushl %edx      /* save %edx */
-       pushl %ecx      /* save %ecx (and argument) */
-       call SYMBOL_NAME(__down_trylock)
-       popl %ecx       /* restore %ecx (count on __down_trylock not changing it) */
-       popl %edx       /* restore %edx */
-       ret
-
-ENTRY(__up_wakeup)
-       pushl %eax      /* save %eax */
-       pushl %edx      /* save %edx */
-       pushl %ecx      /* save %ecx (and argument) */
-       call SYMBOL_NAME(__up)
-       popl %ecx       /* restore %ecx (count on __up not changing it) */
-       popl %edx       /* restore %edx */
-       popl %eax       /* restore %eax */
-       ret
index f57920c55389bf484ba0c09667c754a74c19401b..752d70dce9c39bd4432662818130f7aae7ecba90 100644 (file)
@@ -389,9 +389,10 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
         * IBM messed up *AGAIN* in their thinkpad: 0xA0000 -> 0x9F000.
         * They seem to have done something stupid with the floppy
         * controller as well..
-        * The amount of available base memory is in WORD 40:13.
+        * The amount of available base memory is in WORD 40:13. Except
+        * when it isn't.
         */
-       endbase = PAGE_OFFSET + ((*(unsigned short *)__va(0x413) * 1024) & PAGE_MASK);
+       endbase = PAGE_OFFSET + 0x9f000;
        while (start_low_mem < endbase) {
                clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags);
                start_low_mem += PAGE_SIZE;
index 931f5f411b103be2ca352bbc825b6d512980b2a1..c9742a7e94594f230edf14dd4d86d89ea0884f5f 100644 (file)
@@ -28,6 +28,8 @@
 #ifndef AMBASSADOR_H
 #define AMBASSADOR_H
 
+#include <linux/config.h>
+
 #ifdef CONFIG_ATM_AMBASSADOR_DEBUG
 #define DEBUG_AMBASSADOR
 #endif
index b2d14b2431359801c4a6298348f4c0499c9d2f60..256cc08d687bc8c70d3bebf9a76000134e881a70 100644 (file)
@@ -26,7 +26,6 @@
 */
 
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
index 41c6b635af1e574b19898e143b7d3b3a17fb733a..f05f4411576f44da4f8538615e4bf5ecdf53d955 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef DRIVER_ATM_HORIZON_H
 #define DRIVER_ATM_HORIZON_H
 
+#include <linux/config.h>
+
 #ifdef CONFIG_ATM_HORIZON_DEBUG
 #define DEBUG_HORIZON
 #endif
index 7402a6ef2c91757bda6421ba268aba57c76e2c80..fa27ecbe582809e1e5334ad2e5e8557ad2841e92 100644 (file)
@@ -3,7 +3,6 @@
 /* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
index c06f120471c96c2c3ba0421729d5408a2f254856..a02dabf28ec869c430c8504522a7afef2b461c1e 100644 (file)
@@ -3,7 +3,6 @@
 /* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
  
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h> /* for jiffies */
 #include <linux/mm.h>
index 5980a75f74b0b94485f8ff78fa6dfc611f89ed23..3b4f3ab3ce59c66525d3e89f242a2bbb2e9f25e8 100644 (file)
@@ -3,6 +3,7 @@
 /* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
index e6a265bfd4288c0315e9709d3a16c9db40469e29..d9f05f5481bcecc6178e12ff30931a35e9bd26a5 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef DRIVER_ATM_ZATM_H
 #define DRIVER_ATM_ZATM_H
 
+#include <linux/config.h>
 #include <linux/skbuff.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
index 1dbd56ace861c8753b9907e085eaaf1b459d9fe4..96d7ef9067756c19daf87f13466674cb70ea7af4 100644 (file)
@@ -8,8 +8,6 @@
 
 #include <linux/module.h>
 #include <linux/version.h>
-#include <linux/config.h>
-#include <linux/module.h>
 #include <linux/init.h>
 
 #include "./ip2/ip2types.h"            
index 79ab3ab6310619c53044d993a30838fe147878bd..f1c4501a9a1f04807db5ea3163e3c93bce4e8801 100644 (file)
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 
-#include <linux/wait.h>
 #include <linux/cdk.h>
 #include <linux/comstats.h>
-#include <linux/ioport.h>
 #include <linux/delay.h>
 
 #include <asm/system.h>
index 5ad3772819c9ff1b3e5f8a57c80759bf4fb594d9..ec27982bbf8052759d36a5ccb623b2a82c49932c 100644 (file)
@@ -51,8 +51,8 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
     bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
     bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
     bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
+    bool 'HiSax Support for HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
     if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-       bool 'HiSax Support for HFC PCI-Bus cards (EXPERIMENTAL)' CONFIG_HISAX_HFC_PCI
 #      bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
        if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
                bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
index 1b7f07bc46f182a3fd58f024cd408bd19d018d3d..c4dffdacbc7484c6da9c446b936663e3d45c7f54 100644 (file)
@@ -1,11 +1,17 @@
 /*
- * $Id: b1.c,v 1.7 1999/08/04 10:10:09 calle Exp $
+ * $Id: b1.c,v 1.8 1999/08/22 20:26:22 calle Exp $
  * 
  * Common module for AVM B1 cards.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1.c,v $
+ * Revision 1.8  1999/08/22 20:26:22  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.7  1999/08/04 10:10:09  calle
  * Bugfix: corrected /proc functions, added structure for new AVM cards.
  *
@@ -62,7 +68,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.7 $";
+static char *revision = "$Revision: 1.8 $";
 
 /* ------------------------------------------------------------- */
 
index d5562fb3801e8a38b22b604d7d4043beecbbdc19..9ab1984323eea0b885aa24e5c60f5dcec94d12e7 100644 (file)
@@ -1,11 +1,17 @@
 /*
- * $Id: b1isa.c,v 1.3 1999/07/09 15:05:40 keil Exp $
+ * $Id: b1isa.c,v 1.4 1999/08/22 20:26:24 calle Exp $
  * 
  * Module for AVM B1 ISA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1isa.c,v $
+ * Revision 1.4  1999/08/22 20:26:24  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.3  1999/07/09 15:05:40  keil
  * compat.h is now isdn_compat.h
  *
@@ -49,7 +55,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.3 $";
+static char *revision = "$Revision: 1.4 $";
 
 /* ------------------------------------------------------------- */
 
index 9af06268abff0ed69731b66340844a665be19387..d6acda9d9e08e1b546c714b6036de2a98cd4621d 100644 (file)
@@ -1,11 +1,17 @@
 /*
- * $Id: b1pcmcia.c,v 1.3 1999/07/09 15:05:41 keil Exp $
+ * $Id: b1pcmcia.c,v 1.4 1999/08/22 20:26:26 calle Exp $
  * 
  * Module for AVM B1/M1/M2 PCMCIA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1pcmcia.c,v $
+ * Revision 1.4  1999/08/22 20:26:26  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.3  1999/07/09 15:05:41  keil
  * compat.h is now isdn_compat.h
  *
@@ -50,7 +56,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.3 $";
+static char *revision = "$Revision: 1.4 $";
 
 /* ------------------------------------------------------------- */
 
index 73fd8d24728c05f650b6d523ed557f7322b26330..3546e10610f3744b81e1644b7035140a3dd95a5b 100644 (file)
@@ -1,11 +1,17 @@
 /*
- * $Id: t1isa.c,v 1.4 1999/07/09 15:05:50 keil Exp $
+ * $Id: t1isa.c,v 1.5 1999/08/22 20:26:28 calle Exp $
  * 
  * Module for AVM T1 HEMA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: t1isa.c,v $
+ * Revision 1.5  1999/08/22 20:26:28  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.4  1999/07/09 15:05:50  keil
  * compat.h is now isdn_compat.h
  *
@@ -53,7 +59,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.4 $";
+static char *revision = "$Revision: 1.5 $";
 
 /* ------------------------------------------------------------- */
 
index ec58f43c000890362809d86937adb470ed9b03f3..ce44cfa19cd3b65e337d69fee34f9f67a98ad3cd 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: divert_init.c,v 1.3 1999/07/05 20:21:39 werner Exp $
+ * $Id: divert_init.c,v 1.4 1999/08/22 20:26:32 calle Exp $
  *
  * Module init for DSS1 diversion services for i4l.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: divert_init.c,v $
+ * Revision 1.4  1999/08/22 20:26:32  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.3  1999/07/05 20:21:39  werner
  * changes to use diversion sources for all kernel versions.
  * removed static device, only proc filesystem used
index 6650d47f4a12506560ea4f18ac3bbfbd8057133e..f10ea18b26f83ded6174c61ae71f41da5cf94c1f 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: isdn_divert.c,v 1.2 1999/07/04 21:37:32 werner Exp $
+ * $Id: isdn_divert.c,v 1.4 1999/08/25 20:02:21 werner Exp $
  *
  * DSS1 main diversion supplementary handling for i4l.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_divert.c,v $
+ * Revision 1.4  1999/08/25 20:02:21  werner
+ * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts
+ * with existing software definitions. (PtP incomplete called party number)
+ *
+ * Revision 1.3  1999/08/22 20:26:35  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.2  1999/07/04 21:37:32  werner
  * Ported from kernel version 2.0
  *
@@ -508,14 +518,14 @@ int isdn_divert_icall(isdn_ctrl *ic)
                    strcpy(ic->parm.setup.phone,dv->rule.to_nr);
                    cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
                    cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-                   retval = 4
+                   retval = 5
                  }
                else
                  retval = 1; /* alerting */                 
              }
            else
              { cs->deflect_dest[0] = '\0';
-              retval = 3; /* only proceed */
+              retval = 4; /* only proceed */
              }  
            sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
                    cs->akt_state,
index 336187837b559310e6cfd9770b79fdc2b8378578..1d329c0fb7491108e823c770553f2444905a7310 100644 (file)
@@ -1,5 +1,5 @@
 /* 
- * $Id: isdn_divert.h,v 1.2 1999/07/04 21:37:33 werner Exp $
+ * $Id: isdn_divert.h,v 1.3 1999/08/22 20:26:37 calle Exp $
  *
  * Header for the diversion supplementary ioctl interface.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_divert.h,v $
+ * Revision 1.3  1999/08/22 20:26:37  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.2  1999/07/04 21:37:33  werner
  * Ported from kernel version 2.0
  *
index 444732e7b6fa11a72c72fe3771bc709e77413be9..4e107e00d5efea130e95e75b09fcaa4be417754b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon.h,v 1.8 1999/07/25 15:12:01 armin Exp $
+/* $Id: eicon.h,v 1.10 1999/08/22 20:26:41 calle Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon.h,v $
+ * Revision 1.10  1999/08/22 20:26:41  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.9  1999/08/18 20:16:57  armin
+ * Added XLOG function for all cards.
+ * Bugfix of alloc_skb NULL pointer.
+ *
  * Revision 1.8  1999/07/25 15:12:01  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -73,6 +83,7 @@
 #define EICON_IOCTL_LOADPCI   7 
 #define EICON_IOCTL_LOADISA   8 
 #define EICON_IOCTL_GETVER    9 
+#define EICON_IOCTL_GETXLOG  10 
 
 #define EICON_IOCTL_MANIF    90 
 
 
 #define MAX_HEADER_LEN 10
 
+
 /* Struct for adding new cards */
 typedef struct eicon_cdef {
         int membase;
@@ -225,6 +237,92 @@ typedef struct {
 
 #endif /* KERNEL */
 
+#define DIVAS_SHARED_OFFSET    (0x1000)
+
+#define MIPS_BUFFER_SZ  128
+#define MIPS_MAINT_OFFS 0xff00
+
+#define XLOG_ERR_CARD_NUM       (13)
+#define XLOG_ERR_DONE           (14)
+#define XLOG_ERR_CMD            (15)
+#define XLOG_ERR_TIMEOUT        (16)
+#define XLOG_ERR_CARD_STATE     (17)
+#define XLOG_ERR_UNKNOWN        (18)
+#define XLOG_OK                  (0)
+
+typedef struct {
+  __u8 Id      __attribute__ ((packed));
+  __u8 uX      __attribute__ ((packed));
+  __u8 listen  __attribute__ ((packed));
+  __u8 active  __attribute__ ((packed));
+  __u8 sin[3]  __attribute__ ((packed));
+  __u8 bc[6]   __attribute__ ((packed));
+  __u8 llc[6]  __attribute__ ((packed));
+  __u8 hlc[6]  __attribute__ ((packed));
+  __u8 oad[20] __attribute__ ((packed));
+}DSigStruc;
+
+typedef struct {
+  __u32 cx_b1  __attribute__ ((packed));
+  __u32 cx_b2  __attribute__ ((packed));
+  __u32 cr_b1  __attribute__ ((packed));
+  __u32 cr_b2  __attribute__ ((packed));
+  __u32 px_b1  __attribute__ ((packed));
+  __u32 px_b2  __attribute__ ((packed));
+  __u32 pr_b1  __attribute__ ((packed));
+  __u32 pr_b2  __attribute__ ((packed));
+  __u16 er_b1  __attribute__ ((packed));
+  __u16 er_b2  __attribute__ ((packed));
+}BL1Struc;
+
+typedef struct {
+  __u32 XTotal __attribute__ ((packed));
+  __u32 RTotal __attribute__ ((packed));
+  __u16 XError __attribute__ ((packed));
+  __u16 RError __attribute__ ((packed));
+}L2Struc;
+
+typedef struct {
+  __u16 free_n;
+}OSStruc;
+
+typedef union
+{
+  DSigStruc DSigStats;
+  BL1Struc BL1Stats;
+  L2Struc L2Stats;
+  OSStruc OSStats;
+  __u8   b[MIPS_BUFFER_SZ];
+  __u16   w[MIPS_BUFFER_SZ>>1];
+  __u16   l[MIPS_BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
+  __u32  d[MIPS_BUFFER_SZ>>2];
+} MIPS_BUFFER;
+
+typedef struct
+{
+  __u8 req     __attribute__ ((packed));
+  __u8 rc      __attribute__ ((packed));
+  __u8 reserved[2]     __attribute__ ((packed));     /* R3000 alignment ... */
+  __u8 *mem    __attribute__ ((packed));
+  __u16 length __attribute__ ((packed));               /* used to be short */
+  __u16 port   __attribute__ ((packed));
+  __u8 fill[4] __attribute__ ((packed));         /* data at offset 16   */
+  MIPS_BUFFER data     __attribute__ ((packed));
+} mi_pc_maint_t;
+
+typedef struct
+{
+        __u16 command;
+        mi_pc_maint_t pcm;
+}xlogreq_t;
+
+typedef struct{
+        __u16 code     __attribute__ ((packed));       /* used to be short */
+        __u16 timeh    __attribute__ ((packed));
+        __u16 timel    __attribute__ ((packed));
+        char buffer[MIPS_BUFFER_SZ - 6];
+}xlog_entry_t;
+
 
 #define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
 #define DSP_COMBIFILE_FORMAT_VERSION_BCD    0x0100
@@ -556,6 +654,7 @@ extern void eicon_io_transmit(eicon_card *card);
 extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
 extern void eicon_io_rcv_dispatch(eicon_card *ccard);
 extern void eicon_io_ack_dispatch(eicon_card *ccard);
+extern int eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq);
 #ifdef CONFIG_MCA
 extern int eicon_mca_find_card(int, int, int, char *);
 extern int eicon_mca_probe(int, int, int, int, char *);
index c10b014cdf2661dfc39d769fbc0fc9f5b798f70b..bad6a4a35d38fb466439bd0e330a874ee9e2303f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.c,v 1.11 1999/07/25 15:12:03 armin Exp $
+/* $Id: eicon_idi.c,v 1.13 1999/08/22 20:26:44 calle Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  *        IDI interface 
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.13  1999/08/22 20:26:44  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.12  1999/08/18 20:16:59  armin
+ * Added XLOG function for all cards.
+ * Bugfix of alloc_skb NULL pointer.
+ *
  * Revision 1.11  1999/07/25 15:12:03  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -78,7 +88,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.11 $";
+char *eicon_idi_revision = "$Revision: 1.13 $";
 
 eicon_manifbuf *manbuf;
 
@@ -265,8 +275,8 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
 int
 idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
 {
-        struct sk_buff *skb = 0;
-        struct sk_buff *skb2 = 0;
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
        eicon_REQ *reqbuf;
        eicon_chan_ptr *chan2;
 
@@ -1081,7 +1091,8 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                ccard->interface.statcallb(&cmd);
                                eicon_idi_listen_req(ccard, chan);
 #ifdef CONFIG_ISDN_TTY_FAX
-                               chan->fax = 0;
+                               if (!chan->e.B2Id)
+                                       chan->fax = 0;
 #endif
                                break;
                        case INDICATE_IND:
@@ -1274,12 +1285,16 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
                                chan->queued = 0;
                                chan->waitq = 0;
                                chan->waitpq = 0;
+                               idi_do_req(ccard, chan, HANGUP, 0);
                                if (chan->fsm_state == EICON_STATE_ACTIVE) {
                                        cmd.driver = ccard->myid;
                                        cmd.command = ISDN_STAT_BHUP;
                                        cmd.arg = chan->No;
                                        ccard->interface.statcallb(&cmd);
                                }
+#ifdef CONFIG_ISDN_TTY_FAX
+                               chan->fax = 0;
+#endif
                                break; 
                        case IDI_N_DISC_ACK:
                                if (DebugVar & 16)
@@ -1328,7 +1343,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
    if (free_buff) dev_kfree_skb(skb);
 }
 
-void
+int
 idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
 {
        isdn_ctrl cmd;
@@ -1338,7 +1353,7 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
                if (DebugVar & 16)
                        printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, 
                                ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
-               return;
+               return 1;
        }
 
        /* Management Interface */      
@@ -1351,25 +1366,26 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
        /* Remove an Id */
        if (chan->e.Req == REMOVE) {
                if (ack->Reference != chan->e.ref) {
-                       if (DebugVar & 1)
+                       if (DebugVar & 16)
                                printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
                                        ack->Reference, chan->e.ref);
+                       return 0;
                }
                ccard->IdTable[ack->RcId] = NULL;
                if (DebugVar & 16)
-                       printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No,
+                       printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No,
                                ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
                if (!chan->e.ReqCh) 
                        chan->e.D3Id = 0;
                else
                        chan->e.B2Id = 0;
-               return;
+               return 1;
        }
 
        /* Signal layer */
        if (!chan->e.ReqCh) {
                if (DebugVar & 16)
-                       printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+                       printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
                                ack->RcId, ack->RcCh, ack->Reference);
        } else {
        /* Network layer */
@@ -1410,10 +1426,11 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
                                break;
                        default:
                                if (DebugVar & 16)
-                                       printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+                                       printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
                                                ack->RcId, ack->RcCh, ack->Reference);
                }
        }
+       return 1;
 }
 
 void
@@ -1448,7 +1465,8 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                                        printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh);
                                break;
                        }
-                       idi_handle_ack_ok(ccard, chan, ack);
+                       if (!idi_handle_ack_ok(ccard, chan, ack))
+                               chan = NULL;
                        break;
 
                case ASSIGN_OK:
@@ -1487,9 +1505,8 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
                case UNKNOWN_IE:
                case WRONG_IE:
                default:
-                       chan->e.busy = 0;
-                       if (DebugVar & 24)
-                               printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", dCh, 
+                       if (DebugVar & 1)
+                               printk(KERN_ERR "eicon_ack: Ch%d: Not OK !!: Rc=%d Id=%x Ch=%d\n", dCh, 
                                        ack->Rc, ack->RcId, ack->RcCh);
                        if (dCh == ccard->nchannels) { /* Management */
                                chan->fsm_state = 2;
@@ -1586,7 +1603,6 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
 }
 
 
-
 int
 eicon_idi_manage_assign(eicon_card *card)
 {
index ca989cf9d83ec050d0ea91ce1ae6ab26fee04773..e09c1954d47903805706084a57fd875135db3e5e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_idi.h,v 1.6 1999/07/25 15:12:04 armin Exp $
+/* $Id: eicon_idi.h,v 1.7 1999/08/22 20:26:46 calle Exp $
  *
  * ISDN lowlevel-module for the Eicon.Diehl active cards.
  * IDI-Interface
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.h,v $
+ * Revision 1.7  1999/08/22 20:26:46  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.6  1999/07/25 15:12:04  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
index 058afa229c0aa9c275ea31e06f08921a757de4a6..60b5b4818495e75fefc2651f0bde6feb4a5883f9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_io.c,v 1.2 1999/07/25 15:12:05 armin Exp $
+/* $Id: eicon_io.c,v 1.4 1999/08/22 20:26:47 calle Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Code for communicating with hardware.
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_io.c,v $
+ * Revision 1.4  1999/08/22 20:26:47  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.3  1999/08/18 20:17:01  armin
+ * Added XLOG function for all cards.
+ * Bugfix of alloc_skb NULL pointer.
+ *
  * Revision 1.2  1999/07/25 15:12:05  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -61,7 +71,7 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                                                /* doesn't matter if this happens */ 
                                                break;
                                        default: 
-                                               printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%d\n", ind->Ind, ind->IndId);
+                                               printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId);
                                                printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
                                                        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
                                }
@@ -89,12 +99,18 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
                                if (DebugVar & 1)
                                        printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n");
                                dev_kfree_skb(skb);
-                               dev_kfree_skb(skb2);
                                continue;       
                        }
                        ind2 = (eicon_IND *)skb2->data;
                        skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),
                                        GFP_ATOMIC);
+                       if (!skb_new) {
+                               if (DebugVar & 1)
+                                       printk(KERN_ERR "eicon_io: skb_alloc failed in rcv_dispatch()\n");
+                               dev_kfree_skb(skb);
+                               dev_kfree_skb(skb2);
+                               continue;       
+                       }
                        ind_new = (eicon_IND *)skb_put(skb_new,
                                        ((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length));
                        ind_new->Ind = ind2->Ind;
@@ -276,6 +292,92 @@ void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
         }
 }
 
+/*
+ * XLOG
+ */
+int
+eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq)
+{
+       int timeout, i;
+       int divas_shared_offset = 0;
+       int len = 0;
+       int stype = 0;
+       __u32 time = 0;
+       mi_pc_maint_t   *pcm = &xlogreq->pcm;
+        eicon_pci_card *pci_card = &card->hwif.pci;
+        eicon_isa_card *isa_card = &card->hwif.isa;
+       eicon_pr_ram  *prram = 0;
+        char *ram;
+
+       switch(card->type) {
+               case EICON_CTYPE_MAESTRAP:
+                       ram = (char *)pci_card->PCIram;
+                       prram = (eicon_pr_ram *)ram;
+                       divas_shared_offset = DIVAS_SHARED_OFFSET;
+                       len = sizeof(mi_pc_maint_t);
+                       break;
+               case EICON_CTYPE_MAESTRA:
+                       prram = 0;
+                       divas_shared_offset = 0;
+                       len = sizeof(mi_pc_maint_t);
+                       break;
+               case EICON_CTYPE_S:
+               case EICON_CTYPE_SX:
+               case EICON_CTYPE_SCOM:
+               case EICON_CTYPE_QUADRO:
+               case EICON_CTYPE_S2M:
+                       prram = (eicon_pr_ram *)isa_card->shmem;
+                       divas_shared_offset = 0xfb80;
+                       len = sizeof(mi_pc_maint_t) - 78;
+                       stype = 1;
+                       break;
+               default:
+                       return -ENODEV;
+       }
+
+        memset(&(xlogreq->pcm), 0, sizeof(mi_pc_maint_t));
+
+        xlogreq->pcm.rc = 0;
+        xlogreq->pcm.req = 1; /* DO_LOG */
+
+        ram = ((char *)prram) + MIPS_MAINT_OFFS - divas_shared_offset;
+
+       ram_outb(card, ram+1, pcm->rc); 
+       ram_outb(card, ram+0, pcm->req); 
+
+        timeout = jiffies + 50;
+        while (timeout > jiffies) {
+               pcm->rc = ram_inb(card, ram+1);
+               pcm->req = ram_inb(card, ram+0);
+                if (!pcm->req) break;
+                SLEEP(10);
+        }
+
+       if (pcm->req) {
+               return XLOG_ERR_TIMEOUT;
+       }
+
+       if (pcm->rc != OK) {
+               return XLOG_ERR_DONE;
+       }
+       
+       ram_copyfromcard(card, pcm, ram, len);
+
+       if (stype) {
+               for (i=0; i<8; i++)
+                       ((__u8 *)pcm)[11-i] = ((__u8 *)pcm)[9-i];
+               time =  (__u32)pcm->data.w[2] * 3600    * 1000 +
+                       (__u32)pcm->data.w[1]           * 1000 +
+                       (__u32)pcm->data.b[1]           * 20 +
+                       (__u32)pcm->data.b[0]           ;
+               pcm->data.w[1] = (__u16) (time >> 16);
+               pcm->data.w[2] = (__u16) (time & 0x0000ffff);
+               pcm->data.w[0] = 2;
+       }
+
+       return XLOG_OK;
+}
+
 /*
  *  Transmit-Function
  */
@@ -373,9 +475,13 @@ eicon_io_transmit(eicon_card *ccard) {
                chan = chan2->ptr;
                if (!chan->e.busy) {
                 if((skb = skb_dequeue(&chan->e.X))) { 
-                       save_flags(flags);
-                       cli();
-                       reqbuf = (eicon_REQ *)skb->data;
+                 save_flags(flags);
+                 cli();
+                 reqbuf = (eicon_REQ *)skb->data;
+                 if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) {
+                       if (DebugVar & 16)
+                               printk(KERN_WARNING "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); 
+                 } else {
                        if (scom) {
                                ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
                                ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
@@ -390,7 +496,7 @@ eicon_io_transmit(eicon_card *ccard) {
                                ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 
                        }
 
-                       if (reqbuf->ReqId &0x1f) { /* if this is no ASSIGN */
+                       if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
 
                                if (!reqbuf->Reference) { /* Signal Layer */
                                        if (scom)
@@ -439,14 +545,15 @@ eicon_io_transmit(eicon_card *ccard) {
                                ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); 
 
                        chan->e.busy = 1; 
-                       restore_flags(flags);
                        if (DebugVar & 32)
                                printk(KERN_DEBUG "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", 
                                                        reqbuf->Req, 
                                                        ram_inb(ccard, &ReqOut->ReqId),
                                                        reqbuf->ReqCh, reqbuf->XBuffer.length,
                                                        chan->e.ref); 
-                       dev_kfree_skb(skb);
+                 }
+                 restore_flags(flags);
+                 dev_kfree_skb(skb);
                 }
                 dev_kfree_skb(skb2);
                } 
@@ -636,16 +743,21 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                        }
                } else {
                        skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
-                       ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
-                       ack->Rc = tmp;
-                       ack->RcId = ram_inb(ccard, &com->RcId);
-                       ack->RcCh = ram_inb(ccard, &com->RcCh);
-                       ack->Reference = ccard->ref_in++;
-                       if (DebugVar & 64)
-                               printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
-                                       tmp,ack->RcId,ack->RcCh,ack->Reference);
-                       skb_queue_tail(&ccard->rackq, skb);
-                       eicon_schedule_ack(ccard);
+                       if (!skb) {
+                               if (DebugVar & 1)
+                                       printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                       } else {
+                               ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
+                               ack->Rc = tmp;
+                               ack->RcId = ram_inb(ccard, &com->RcId);
+                               ack->RcCh = ram_inb(ccard, &com->RcCh);
+                               ack->Reference = ccard->ref_in++;
+                               if (DebugVar & 64)
+                                       printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
+                                               tmp,ack->RcId,ack->RcCh,ack->Reference);
+                               skb_queue_tail(&ccard->rackq, skb);
+                               eicon_schedule_ack(ccard);
+                       }
                        ram_outb(ccard, &com->Req, 0);
                        ram_outb(ccard, &com->Rc, 0);
                }
@@ -657,19 +769,24 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                        eicon_IND *ind;
                        int len = ram_inw(ccard, &com->RBuffer.length);
                        skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
-                       ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
-                       ind->Ind = tmp;
-                       ind->IndId = ram_inb(ccard, &com->IndId);
-                       ind->IndCh = ram_inb(ccard, &com->IndCh);
-                       ind->MInd  = ram_inb(ccard, &com->MInd);
-                       ind->MLength = ram_inw(ccard, &com->MLength);
-                       ind->RBuffer.length = len; 
-                       if (DebugVar & 64)
-                               printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
-                               tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
-                       ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
-                       skb_queue_tail(&ccard->rcvq, skb);
-                       eicon_schedule_rx(ccard);
+                       if (!skb) {
+                               if (DebugVar & 1)
+                                       printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                       } else {
+                               ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
+                               ind->Ind = tmp;
+                               ind->IndId = ram_inb(ccard, &com->IndId);
+                               ind->IndCh = ram_inb(ccard, &com->IndCh);
+                               ind->MInd  = ram_inb(ccard, &com->MInd);
+                               ind->MLength = ram_inw(ccard, &com->MLength);
+                               ind->RBuffer.length = len; 
+                               if (DebugVar & 64)
+                                       printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
+                                       tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
+                               ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
+                               skb_queue_tail(&ccard->rcvq, skb);
+                               eicon_schedule_rx(ccard);
+                       }
                        ram_outb(ccard, &com->Ind, 0);
                }
        }
@@ -686,17 +803,22 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
 
                         if((Rc=ram_inb(ccard, &RcIn->Rc))) {
                                skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
-                               ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
-                               ack->Rc = Rc;
-                               ack->RcId = ram_inb(ccard, &RcIn->RcId);
-                               ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
-                               ack->Reference = ram_inw(ccard, &RcIn->Reference);
-                               if (DebugVar & 64)
-                                       printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
-                                               Rc,ack->RcId,ack->RcCh,ack->Reference);
-                               ram_outb(ccard, &RcIn->Rc, 0);
-                                skb_queue_tail(&ccard->rackq, skb);
-                                eicon_schedule_ack(ccard);
+                               if (!skb) {
+                                       if (DebugVar & 1)
+                                               printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                               } else {
+                                       ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
+                                       ack->Rc = Rc;
+                                       ack->RcId = ram_inb(ccard, &RcIn->RcId);
+                                       ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
+                                       ack->Reference = ram_inw(ccard, &RcIn->Reference);
+                                       if (DebugVar & 64)
+                                               printk(KERN_INFO "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n",
+                                                       Rc,ack->RcId,ack->RcCh,ack->Reference);
+                                       skb_queue_tail(&ccard->rackq, skb);
+                                       eicon_schedule_ack(ccard);
+                               }
+                                       ram_outb(ccard, &RcIn->Rc, 0);
                         }
                         /* get buffer address of next return code   */
                         RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)];
@@ -716,19 +838,24 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
                        if(Ind) {
                                int len = ram_inw(ccard, &IndIn->RBuffer.length);
                                skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
-                               ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
-                               ind->Ind = Ind;
-                               ind->IndId = ram_inb(ccard, &IndIn->IndId);
-                               ind->IndCh = ram_inb(ccard, &IndIn->IndCh);
-                               ind->MInd  = ram_inb(ccard, &IndIn->MInd);
-                               ind->MLength = ram_inw(ccard, &IndIn->MLength);
-                               ind->RBuffer.length = len;
-                               if (DebugVar & 64)
-                                       printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
-                                       Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
-                                ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
-                               skb_queue_tail(&ccard->rcvq, skb);
-                               eicon_schedule_rx(ccard);
+                               if (!skb) {
+                                       if (DebugVar & 1)
+                                               printk(KERN_ERR "eicon_io: skb_alloc failed in _irq()\n");
+                               } else {
+                                       ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
+                                       ind->Ind = Ind;
+                                       ind->IndId = ram_inb(ccard, &IndIn->IndId);
+                                       ind->IndCh = ram_inb(ccard, &IndIn->IndCh);
+                                       ind->MInd  = ram_inb(ccard, &IndIn->MInd);
+                                       ind->MLength = ram_inw(ccard, &IndIn->MLength);
+                                       ind->RBuffer.length = len;
+                                       if (DebugVar & 64)
+                                               printk(KERN_INFO "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n",
+                                               Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
+                                       ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
+                                       skb_queue_tail(&ccard->rcvq, skb);
+                                       eicon_schedule_rx(ccard);
+                               }
                                ram_outb(ccard, &IndIn->Ind, 0);
                         }
                         /* get buffer address of next indication  */
index ba2dd0f852c1cd2da3e55ea5e67511b56d0c30be..75122559ce9eabe4725dff76df5ec51d5ab143d5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_isa.c,v 1.6 1999/07/25 15:12:06 armin Exp $
+/* $Id: eicon_isa.c,v 1.7 1999/08/22 20:26:48 calle Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.c,v $
+ * Revision 1.7  1999/08/22 20:26:48  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.6  1999/07/25 15:12:06  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -58,7 +64,7 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.6 $";
+char *eicon_isa_revision = "$Revision: 1.7 $";
 
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 
index 9efb770ed1f3c2db1994e432e3fc06510d364e3b..8b5484c1d480e26201a653c18e74db691223273d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_mod.c,v 1.8 1999/07/25 15:12:08 armin Exp $
+/* $Id: eicon_mod.c,v 1.9 1999/08/18 20:17:02 armin Exp $
  *
  * ISDN lowlevel-module for Eicon.Diehl active cards.
  * 
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.9  1999/08/18 20:17:02  armin
+ * Added XLOG function for all cards.
+ * Bugfix of alloc_skb NULL pointer.
+ *
  * Revision 1.8  1999/07/25 15:12:08  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
@@ -63,6 +67,8 @@
  *
  */
 
+#define DRIVERPATCH ""
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -77,7 +83,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.8 $";
+static char *eicon_revision = "$Revision: 1.9 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -87,7 +93,7 @@ extern char *eicon_idi_revision;
 #define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
 #endif
 
-#define EICON_CTRL_VERSION 1
+#define EICON_CTRL_VERSION 
 
 ulong DebugVar;
 
@@ -355,6 +361,32 @@ eicon_transmit(struct eicon_card *card)
        }
 }
 
+static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq)
+{
+       xlogreq_t *xlr;
+       int ret_val;
+
+       if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) {
+               if (DebugVar & 1)
+                       printk(KERN_WARNING "idi_err: alloc_xlogreq_t failed\n");
+               return -ENOMEM;
+       }
+       if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) {
+               kfree(xlr);
+               return -EFAULT;
+       }
+
+       ret_val = eicon_get_xlog(card, xlr);
+
+       if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) {
+               kfree(xlr);
+               return -EFAULT;
+       }
+       kfree(xlr);
+
+       return ret_val;
+}
+
 static int
 eicon_command(eicon_card * card, isdn_ctrl * c)
 {
@@ -366,6 +398,10 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
        int ret = 0;
        unsigned long flags;
  
+       if (DebugVar & 16)
+               printk(KERN_WARNING "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n",
+                       c->command, c->arg, (ulong) *c->parm.num);
+
         switch (c->command) {
                case ISDN_CMD_IOCTL:
                        memcpy(&a, c->parm.num, sizeof(ulong));
@@ -507,6 +543,12 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                                                card, 
                                                (eicon_manifbuf *)a);
                                        return ret;
+
+                               case EICON_IOCTL_GETXLOG:
+                                       if (!card->flags & EICON_FLAGS_RUNNING)
+                                               return XLOG_ERR_CARD_STATE;
+                                       ret = eicon_xlog(card, (xlogreq_t *)a);
+                                       return ret;
 #if CONFIG_PCI 
                                case EICON_IOCTL_LOADPCI:
                                                if (card->flags & EICON_FLAGS_RUNNING)
@@ -674,6 +716,10 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                        if (!(chan = find_channel(card, c->arg & 0x1f)))
                                break;
                        chan->l3prot = (c->arg >> 8);
+#ifdef CONFIG_ISDN_TTY_FAX
+                       if (chan->l3prot == ISDN_PROTO_L3_FAX)
+                               chan->fax = c->parm.fax;
+#endif
                        return 0;
                case ISDN_CMD_GETL3:
                        if (!card->flags & EICON_FLAGS_RUNNING)
@@ -705,6 +751,17 @@ eicon_command(eicon_card * card, isdn_ctrl * c)
                case ISDN_CMD_UNLOCK:
                        MOD_DEC_USE_COUNT;
                        return 0;
+#ifdef CONFIG_ISDN_TTY_FAX
+               case ISDN_CMD_FAXCMD:
+                       if (!card->flags & EICON_FLAGS_RUNNING)
+                               return -ENODEV;
+                       if (!(chan = find_channel(card, c->arg & 0x1f)))
+                               break;
+                       if (!chan->fax)
+                               break;
+                       idi_fax_cmd(card, chan);
+                       return 0;
+#endif
                case ISDN_CMD_AUDIO:
                        if (!card->flags & EICON_FLAGS_RUNNING)
                                return -ENODEV;
@@ -752,16 +809,19 @@ if_command(isdn_ctrl * c)
 static int
 if_writecmd(const u_char * buf, int len, int user, int id, int channel)
 {
+#if 0
+       /* Not yet used */
         eicon_card *card = eicon_findcard(id);
 
         if (card) {
                 if (!card->flags & EICON_FLAGS_RUNNING)
-                        return -ENODEV;
+                        return (len);
                 return (len);
         }
         printk(KERN_ERR
                "eicon: if_writecmd called with invalid driverId!\n");
-        return -ENODEV;
+#endif
+        return (len);
 }
 
 static int
@@ -779,7 +839,7 @@ if_readstatus(u_char * buf, int len, int user, int id, int channel)
         printk(KERN_ERR
                "eicon: if_readstatus called with invalid driverId!\n");
 #endif
-        return -ENODEV;
+        return 0;
 }
 
 static int
@@ -802,6 +862,13 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
                        return -ENODEV;
                }
                if (chan->fsm_state == EICON_STATE_ACTIVE) {
+#ifdef CONFIG_ISDN_TTY_FAX
+                       if (chan->l2prot == ISDN_PROTO_L2_FAX) {
+                               if ((ret = idi_faxdata_send(card, chan, skb)) > 0)
+                                       ret = len;
+                       }
+                       else
+#endif
                                ret = idi_send_data(card, chan, ack, skb, 1);
                        return (ret);
                } else {
@@ -1231,8 +1298,8 @@ eicon_init(void))
        printk("%s\n", eicon_getrev(tmprev));
        release += getrel(tmprev);
        sprintf(tmprev,"%d", release);
-        printk(KERN_INFO "%s Release: %s.%s\n", DRIVERNAME,
-               DRIVERRELEASE, tmprev);
+        printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME,
+               DRIVERRELEASE, tmprev, DRIVERPATCH);
 
 #ifdef CONFIG_ISDN_DRV_EICON_ISA
 #ifdef CONFIG_MCA
index 6bb4c9a30904e53044e288798861e7aa89cf52ec..c1919e9f810c4f432259c3da3a1f81de14148905 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: eicon_pci.c,v 1.9 1999/08/11 21:01:11 keil Exp $
+/* $Id: eicon_pci.c,v 1.10 1999/08/22 20:26:49 calle Exp $
  *
  * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
  * Hardware-specific code for PCI cards.
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_pci.c,v $
+ * Revision 1.10  1999/08/22 20:26:49  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.9  1999/08/11 21:01:11  keil
  * new PCI codefix
  *
@@ -71,7 +77,7 @@
 #include "eicon_pci.h"
 
 
-char *eicon_pci_revision = "$Revision: 1.9 $";
+char *eicon_pci_revision = "$Revision: 1.10 $";
 
 #if CONFIG_PCI          /* intire stuff is only for PCI */
 
index 641106a19197c5871cbef1dc9aa564913240e5af..9e582641d30e8f5938133675754521e7c5597c98 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: arcofi.c,v 1.7 1999/07/01 08:11:17 keil Exp $
+/* $Id: arcofi.c,v 1.8 1999/08/25 16:50:51 keil Exp $
 
  * arcofi.c   Ansteuerung ARCOFI 2165
  *
@@ -7,6 +7,9 @@
  *
  *
  * $Log: arcofi.c,v $
+ * Revision 1.8  1999/08/25 16:50:51  keil
+ * Fix bugs which cause 2.3.14 hangs (waitqueue init)
+ *
  * Revision 1.7  1999/07/01 08:11:17  keil
  * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
@@ -151,4 +154,8 @@ init_arcofi(struct IsdnCardState *cs) {
        cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
        cs->dc.isac.arcofitimer.data = (long) cs;
        init_timer(&cs->dc.isac.arcofitimer);
+#ifdef COMPAT_HAS_NEW_WAITQ
+       init_waitqueue_head(&cs->dc.isac.arcofi_wait);
+#endif
+       test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
 }
index adf6b73b20127753c6620ece6fefc221ebfcc210..4781a822a84e24afe9c78bf84e11c8451f4f1122 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bkm_a4t.c,v 1.6 1999/08/11 21:01:22 keil Exp $
+/* $Id: bkm_a4t.c,v 1.7 1999/08/22 20:26:55 calle Exp $
  * bkm_a4t.c    low level stuff for T-Berkom A4T
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -7,6 +7,12 @@
  * Author       Roland Klabunde (R.Klabunde@Berkom.de)
  *
  * $Log: bkm_a4t.c,v $
+ * Revision 1.7  1999/08/22 20:26:55  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.6  1999/08/11 21:01:22  keil
  * new PCI codefix
  *
@@ -42,7 +48,7 @@
 
 extern const char *CardType[];
 
-const char *bkm_a4t_revision = "$Revision: 1.6 $";
+const char *bkm_a4t_revision = "$Revision: 1.7 $";
 
 
 static inline u_char
index 0defb74b59dd1b749321e496600611cfc1bac1e7..61709bfebf50b53cf74ffa2f3e11a4232a6a7ea1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: bkm_a8.c,v 1.6 1999/08/11 21:01:24 keil Exp $
+/* $Id: bkm_a8.c,v 1.7 1999/08/22 20:26:58 calle Exp $
  * bkm_a8.c     low level stuff for Scitel Quadro (4*S0, passive)
  *              derived from the original file sedlbauer.c
  *              derived from the original file niccy.c
@@ -7,6 +7,12 @@
  * Author       Roland Klabunde (R.Klabunde@Berkom.de)
  *
  * $Log: bkm_a8.c,v $
+ * Revision 1.7  1999/08/22 20:26:58  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.6  1999/08/11 21:01:24  keil
  * new PCI codefix
  *
@@ -43,7 +49,7 @@
 
 extern const char *CardType[];
 
-const char sct_quadro_revision[] = "$Revision: 1.6 $";
+const char sct_quadro_revision[] = "$Revision: 1.7 $";
 
 /* To survive the startup phase */
 typedef struct {
index 6caf0341fe717174b8d5f70dbe17b877e23f89a9..9d5ec964b62c9862f038b9ba4c4284fc7df98165 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: callc.c,v 2.31 1999/08/05 20:43:10 keil Exp $
+/* $Id: callc.c,v 2.34 1999/08/25 20:02:34 werner Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: callc.c,v $
+ * Revision 2.34  1999/08/25 20:02:34  werner
+ * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts
+ * with existing software definitions. (PtP incomplete called party number)
+ *
+ * Revision 2.33  1999/08/25 17:00:09  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
+ * Revision 2.32  1999/08/22 20:27:01  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 2.31  1999/08/05 20:43:10  keil
  * ISAR analog modem support
  *
@@ -140,7 +154,7 @@ extern long mod_use_count_;
 #endif /* COMPAT_HAS_NEW_SYMTAB */
 #endif /* MODULE */
 
-const char *lli_revision = "$Revision: 2.31 $";
+const char *lli_revision = "$Revision: 2.34 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -498,12 +512,12 @@ lli_deliver_call(struct FsmInst *fi, int event, void *arg)
                                FsmChangeState(fi, ST_IN_ALERT_SENT);
                                chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
                                break;
-                       case 4: /* direct redirect */
-                       case 3: /* Proceeding desired */
+                       case 5: /* direct redirect */
+                       case 4: /* Proceeding desired */
                                FsmDelTimer(&chanp->drel_timer, 61);
                                FsmChangeState(fi, ST_IN_PROCEED_SEND);
                                 chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
-                                if (ret == 4)
+                                if (ret == 5)
                                 { chanp->setup = ic.parm.setup;
                                   chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
                                  }   
@@ -971,6 +985,7 @@ release_b_st(struct Channel *chanp)
                        case (ISDN_PROTO_L2_HDLC):
                        case (ISDN_PROTO_L2_TRANS):
                        case (ISDN_PROTO_L2_MODEM):
+                       case (ISDN_PROTO_L2_FAX):
                                 releasestack_transl2(st);
                                 break;
                 }
@@ -1359,6 +1374,9 @@ init_b_st(struct Channel *chanp, int incoming)
                case (ISDN_PROTO_L2_MODEM):
                        st->l1.mode = L1_MODE_V32;
                        break;
+               case (ISDN_PROTO_L2_FAX):
+                       st->l1.mode = L1_MODE_FAX;
+                       break;
        }
        chanp->bcs->conmsg = NULL;
        if (chanp->bcs->BC_SetStack(st, chanp->bcs))
@@ -1388,6 +1406,7 @@ init_b_st(struct Channel *chanp, int incoming)
                case (ISDN_PROTO_L2_HDLC):
                case (ISDN_PROTO_L2_TRANS):
                case (ISDN_PROTO_L2_MODEM):
+               case (ISDN_PROTO_L2_FAX):
                        st->l1.l1l2 = lltrans_handler;
                        st->lli.userdata = chanp;
                        st->lli.l1writewakeup = ll_writewakeup;
@@ -1395,8 +1414,7 @@ init_b_st(struct Channel *chanp, int incoming)
                        setstack_l3bc(st, chanp);
                        break;
        }
-        test_and_set_bit(FLG_START_B, &chanp->Flags);
+       test_and_set_bit(FLG_START_B, &chanp->Flags);
        return (0);
 }
 
@@ -1547,29 +1565,29 @@ lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *
 /***************************************************************/
 static int 
 set_channel_limit(struct IsdnCardState *cs, int chanmax)
-{ isdn_ctrl ic;
-  int i, ii;
-  
-  if ((chanmax < 0) || (chanmax > 2))
-    return(-EINVAL);
-  cs->chanlimit = 0;
-  for (ii = 0; ii < 2; ii++) {
-    ic.driver = cs->myid;
-    ic.command = ISDN_STAT_DISCH;
-    ic.arg = ii;
-    if (ii >= chanmax)
-      ic.parm.num[0] = 0; /* disabled */
-    else
-      ic.parm.num[0] = 1; /* enabled */
-    i = cs->iif.statcallb(&ic); 
-    if (i) return(-EINVAL);
-    if (ii < chanmax) 
-      cs->chanlimit++;
-  }
-  return(0);
+{
+       isdn_ctrl ic;
+       int i, ii;
+
+       if ((chanmax < 0) || (chanmax > 2))
+               return(-EINVAL);
+       cs->chanlimit = 0;
+       for (ii = 0; ii < 2; ii++) {
+               ic.driver = cs->myid;
+               ic.command = ISDN_STAT_DISCH;
+               ic.arg = ii;
+               if (ii >= chanmax)
+                       ic.parm.num[0] = 0; /* disabled */
+               else
+                       ic.parm.num[0] = 1; /* enabled */
+               i = cs->iif.statcallb(&ic); 
+               if (i) return(-EINVAL);
+               if (ii < chanmax) 
+                       cs->chanlimit++;
+       }
+       return(0);
 } /* set_channel_limit */
 
-
 int
 HiSax_command(isdn_ctrl * ic)
 {
@@ -1578,7 +1596,6 @@ HiSax_command(isdn_ctrl * ic)
        struct Channel *chanp;
        int i;
        u_int num;
-       u_long adr;
 
        if (!csta) {
                printk(KERN_ERR
@@ -1586,12 +1603,10 @@ HiSax_command(isdn_ctrl * ic)
                       ic->command, ic->driver);
                return -ENODEV;
        }
-
        switch (ic->command) {
                case (ISDN_CMD_SETEAZ):
                        chanp = csta->channel + ic->arg;
                        break;
-
                case (ISDN_CMD_SETL2):
                        chanp = csta->channel + (ic->arg & 0xff);
                        if (chanp->debug & 1)
@@ -1767,11 +1782,6 @@ HiSax_command(isdn_ctrl * ic)
                                        chanp->d_st->lli.l4l3(chanp->d_st,
                                                DL_ESTABLISH | REQUEST, NULL);
                                        break;
-                               case (9): /* load firmware */
-                                       memcpy(&adr, ic->parm.num, sizeof(ulong));
-                                       csta->cardmsg(csta, CARD_LOAD_FIRM,
-                                               (void *) adr);
-                                       break;
 #ifdef MODULE
                                case (55):
                                        MOD_USE_COUNT = 0;
@@ -1797,23 +1807,12 @@ HiSax_command(isdn_ctrl * ic)
                                        printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
                                                csta->cardnr + 1, *(unsigned int *) ic->parm.num);
                                        break;
-                               case  (10):
-                                       i = *(unsigned int *) ic->parm.num;
-                                       if ((i < 0) || (i > 2))
-                                         return(-EINVAL); /* invalid number */
+                               case (10):
+                                       i = *(unsigned int *) ic->parm.num;
                                        return(set_channel_limit(csta, i));
-                                       break;
-                               case  (12):
-                                       i = *(unsigned int *) ic->parm.num;
-#ifdef CONFIG_HISAX_HFC_PCI
-                                       if (csta->typ != ISDN_CTYPE_HFC_PCI)
-                                         return(-EINVAL);
-                                       return(hfcpci_set_echo(csta,i));    
-#else
-                                       return(-EINVAL);    
-#endif
-                                       break;
                                default:
+                                       if (csta->auxcmd)
+                                               return(csta->auxcmd(csta, ic));
                                        printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
                                               (int) ic->arg);
                                        return (-EINVAL);
@@ -1850,9 +1849,10 @@ HiSax_command(isdn_ctrl * ic)
                        return(-EINVAL);                     
                        break;
                default:
-                       break;
+                       if (csta->auxcmd)
+                               return(csta->auxcmd(csta, ic));
+                       return(-EINVAL);
        }
-
        return (0);
 }
 
index 6e54fd1dcfeb04043fb2bdf0503527a3f22791e3..aef71936bc14a962776c4ebae05a1861c9763fe4 100644 (file)
@@ -1,10 +1,13 @@
-/* $Id: config.c,v 2.30 1999/08/05 20:43:14 keil Exp $
+/* $Id: config.c,v 2.31 1999/08/25 16:47:43 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.31  1999/08/25 16:47:43  keil
+ * Support new __setup; allow to add FEATURES after register_isdn
+ *
  * Revision 2.30  1999/08/05 20:43:14  keil
  * ISAR analog modem support
  *
 #include <linux/stddef.h>
 #include <linux/timer.h>
 #include <linux/config.h>
+#include <linux/isdn_compat.h>
+#ifdef COMPAT_HAS_NEW_SETUP
+#include <linux/init.h>
+#endif
 #include "hisax.h"
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
@@ -546,12 +553,24 @@ HiSax_mod_inc_use_count(void)
 #ifdef MODULE
 #define HiSax_init init_module
 #else
+#ifdef COMPAT_HAS_NEW_SETUP
+#define MAX_ARG        (HISAX_MAX_CARDS*5)
+__initfunc(int
+HiSax_setup(char *line))
+{
+       int i, j, argc;
+       int ints[MAX_ARG + 1];
+       char *str;
+
+       str = get_options(line, MAX_ARG, ints);
+#else
 __initfunc(void
 HiSax_setup(char *str, int *ints))
 {
        int i, j, argc;
-
+#endif        
        argc = ints[0];
+       printk(KERN_DEBUG"HiSax_setup: argc(%d) str(%s)\n", argc, str);
        i = 0;
        j = 1;
        while (argc && (i < HISAX_MAX_CARDS)) {
@@ -589,8 +608,15 @@ HiSax_setup(char *str, int *ints))
                strcpy(HiSaxID, "HiSax");
                HiSax_id = HiSaxID;
        }
+#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
 }
-#endif
+
+__setup("hisax=", HiSax_setup);
+#else
+}
+#endif /* COMPAT_HAS_NEW_SETUP */
+#endif /* MODULES */
 
 #if CARD_TELES0
 extern int setup_teles0(struct IsdnCard *card);
@@ -875,7 +901,7 @@ HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
 }
 
 int
-ll_run(struct IsdnCardState *cs)
+ll_run(struct IsdnCardState *cs, int addfeatures)
 {
        long flags;
        isdn_ctrl ic;
@@ -884,6 +910,7 @@ ll_run(struct IsdnCardState *cs)
        cli();
        ic.driver = cs->myid;
        ic.command = ISDN_STAT_RUN;
+       cs->iif.features |= addfeatures;
        cs->iif.statcallb(&ic);
        restore_flags(flags);
        return 0;
@@ -1053,7 +1080,6 @@ checkcard(int cardnr, char *id, int *busy_flag))
                cs->iif.features =
                        ISDN_FEATURE_L2_X75I |
                        ISDN_FEATURE_L2_HDLC |
-                       ISDN_FEATURE_L2_MODEM |
                        ISDN_FEATURE_L2_TRANS |
                        ISDN_FEATURE_L3_TRANS |
 #ifdef CONFIG_HISAX_1TR6
@@ -1269,7 +1295,7 @@ checkcard(int cardnr, char *id, int *busy_flag))
        CallcNewChan(cs);
        /* ISAR needs firmware download first */
        if (!test_bit(HW_ISAR, &cs->HW_Flags))
-               ll_run(cs);
+               ll_run(cs, 0);
        restore_flags(flags);
        return (1);
 }
index 8f47869ba8f78ecbe6aeb7a933c77a1a83f4da8a..c2d6cf2d385272d18518e7d67f9a90fd822444e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: elsa.c,v 2.17 1999/08/11 20:57:40 keil Exp $
+/* $Id: elsa.c,v 2.18 1999/08/25 16:50:54 keil Exp $
 
  * elsa.c     low level stuff for Elsa isdn cards
  *
@@ -14,6 +14,9 @@
  *              for ELSA PCMCIA support
  *
  * $Log: elsa.c,v $
+ * Revision 2.18  1999/08/25 16:50:54  keil
+ * Fix bugs which cause 2.3.14 hangs (waitqueue init)
+ *
  * Revision 2.17  1999/08/11 20:57:40  keil
  * bugfix IPAC version 1.1
  * new PCI codefix
@@ -96,7 +99,7 @@
 
 extern const char *CardType[];
 
-const char *Elsa_revision = "$Revision: 2.17 $";
+const char *Elsa_revision = "$Revision: 2.18 $";
 const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
  "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI", 
@@ -180,6 +183,7 @@ const char *ITACVer[] =
 #define ELSA_IPAC_LINE_LED     0x40    /* Bit 6 Gelbe LED */
 #define ELSA_IPAC_STAT_LED     0x80    /* Bit 7 Gruene LED */
 
+#if ARCOFI_USE
 static struct arcofi_msg ARCOFI_XOP_F =
        {NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */
 static struct arcofi_msg ARCOFI_XOP_1 =
@@ -203,9 +207,8 @@ static struct arcofi_msg ARCOFI_XOP_0 =
 
 static void set_arcofi(struct IsdnCardState *cs, int bc);
 
-#if ARCOFI_USE
 #include "elsa_ser.c"
-#endif
+#endif /* ARCOFI_USE */
 
 static inline u_char
 readreg(unsigned int ale, unsigned int adr, u_char off)
@@ -432,6 +435,7 @@ elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
                        cs->hw.elsa.counter++;
                }
        }
+#if ARCOFI_USE
        if (cs->hw.elsa.MFlag) {
                val = serial_inp(cs, UART_MCR);
                val ^= 0x8;
@@ -440,6 +444,7 @@ elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs)
                val ^= 0x8;
                serial_outp(cs, UART_MCR, val);
        }
+#endif
        if (cs->hw.elsa.trig)
                byteout(cs->hw.elsa.trig, 0x00);
        writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
@@ -514,7 +519,9 @@ release_io_elsa(struct IsdnCardState *cs)
        int bytecnt = 8;
 
        del_timer(&cs->hw.elsa.tl);
+#if ARCOFI_USE
        clear_arcofi(cs);
+#endif
        if (cs->hw.elsa.ctrl)
                byteout(cs->hw.elsa.ctrl, 0);   /* LEDs Out */
        if (cs->subtyp == ELSA_QS1000PCI) {
@@ -536,7 +543,9 @@ release_io_elsa(struct IsdnCardState *cs)
                (cs->subtyp == ELSA_PCF) ||
                (cs->subtyp == ELSA_QS3000PCI)) {
                bytecnt = 16;
+#if ARCOFI_USE
                release_modem(cs);
+#endif
        }
        if (cs->hw.elsa.base)
                release_region(cs->hw.elsa.base, bytecnt);
@@ -592,6 +601,8 @@ reset_elsa(struct IsdnCardState *cs)
        }
 }
 
+#if ARCOFI_USE
+
 static void
 set_arcofi(struct IsdnCardState *cs, int bc) {
        cs->dc.isac.arcofi_bc = bc;
@@ -602,7 +613,6 @@ set_arcofi(struct IsdnCardState *cs, int bc) {
 static int
 check_arcofi(struct IsdnCardState *cs)
 {
-#if ARCOFI_USE
        int arcofi_present = 0;
        char tmp[40];
        char *t;
@@ -690,9 +700,9 @@ check_arcofi(struct IsdnCardState *cs)
                interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
                return(1);
        }
-#endif
        return(0);
 }
+#endif /* ARCOFI_USE */
 
 static void
 elsa_led_handler(struct IsdnCardState *cs)
@@ -738,8 +748,7 @@ elsa_led_handler(struct IsdnCardState *cs)
 static int
 Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-       int len, ret = 0;
-       u_char *msg;
+       int ret = 0;
        long flags;
 
        switch (mt) {
@@ -828,8 +837,12 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
                                cs->hw.elsa.status &= ~0x0100;
                        }
                        break;
+#if ARCOFI_USE
                case CARD_AUX_IND:
                        if (cs->hw.elsa.MFlag) {
+                               int len;
+                               u_char *msg;
+
                                if (!arg)
                                        return(0);
                                msg = arg;
@@ -838,6 +851,7 @@ Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
                                modem_write_cmd(cs, msg, len);
                        }
                        break;
+#endif
        }
        if (cs->typ == ISDN_CTYPE_ELSA) {
                int pwr = bytein(cs->hw.elsa.ale);
@@ -1199,7 +1213,9 @@ setup_elsa(struct IsdnCard *card)
                        request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci");
                }
        }
+#if ARCOFI_USE
        init_arcofi(cs);
+#endif
        cs->hw.elsa.tl.function = (void *) elsa_led_handler;
        cs->hw.elsa.tl.data = (long) cs;
        init_timer(&cs->hw.elsa.tl);
index 199bf2b609c89ec89a4d9fc90fa68688422d086d..ce83fc8590862224b3cdbbd49e2438c007985d62 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: gazel.c,v 2.5 1999/08/11 21:01:26 keil Exp $
+/* $Id: gazel.c,v 2.6 1999/08/22 20:27:03 calle Exp $
 
  * gazel.c     low level stuff for Gazel isdn cards
  *
@@ -6,6 +6,12 @@
  *              based on source code from Karsten Keil
  *
  * $Log: gazel.c,v $
+ * Revision 2.6  1999/08/22 20:27:03  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 2.5  1999/08/11 21:01:26  keil
  * new PCI codefix
  *
@@ -36,7 +42,7 @@
 #endif
 
 extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.5 $";
+const char *gazel_revision = "$Revision: 2.6 $";
 
 #define R647      1
 #define R685      2
index 837c957bed8024bf0c1b6685aaa20ec74f5a1954..6d3f4efb7c58b4bb47b3f92c8be7809b6abbad31 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.13 1999/08/11 21:01:28 keil Exp $
+/* $Id: hfc_pci.c,v 1.16 1999/08/25 17:01:27 keil Exp $
 
  * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.c,v $
+ * Revision 1.16  1999/08/25 17:01:27  keil
+ * Use new LL->HL auxcmd call
+ *
+ * Revision 1.15  1999/08/22 20:27:05  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.14  1999/08/12 18:59:45  werner
+ * Added further manufacturer and device ids to PCI list
+ *
  * Revision 1.13  1999/08/11 21:01:28  keil
  * new PCI codefix
  *
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.13 $";
-
-static const int CCD_VENDOR_IDS[] = { 
-       0x1043,   /* Asuscom  */
-       0x1051,   /* Motorola MC145575 */
-        0x1397,   /* CCD and Billion */
-       0,
-};
-
-static const int CCD_DEVICE_IDS[] = { 
-       0x675,    /* Asuscom  */
-       0x100,    /* Motorola MC145575 */
-        0x2BD0,   /* CCD and Billion */
-       0,
+static const char *hfcpci_revision = "$Revision: 1.16 $";
+
+/* table entry in the PCI devices list */
+typedef struct {
+  int vendor_id; 
+  int device_id;
+  char *vendor_name;
+  char *card_name;
+  } PCI_ENTRY;
+
+static const PCI_ENTRY id_list[] = {
+  {0x1397,0x2BD0,"CCD/Billion/Asuscom","2BD0"},
+  {0x1397,0xB000,"Billion","B000"},
+  {0x1397,0xB006,"Billion","B006"},
+  {0x1397,0xB007,"Billion","B007"},
+  {0x1397,0xB008,"Billion","B008"},
+  {0x1397,0xB009,"Billion","B009"},
+  {0x1397,0xB00A,"Billion","B00A"},
+  {0x1397,0xB00B,"Billion","B00B"},
+  {0x1397,0xB00C,"Billion","B00C"},
+  {0x1043,0x0675,"Asuscom/Askey","675"},
+  {0x0871,0xFFA2,"German telekom","T-Concept"},
+  {0x0871,0xFFA1,"German telekom","A1T"},
+  {0x1051,0x0100,"Motorola MC145575","MC145575"},
+  {0x1397,0xB100,"Seyeon","B100"},
+  {0x15B0,0x2BD0,"Zoltrix","2BD0"},
+  {0,0,NULL,NULL},      
 };
 
 
@@ -618,9 +643,12 @@ hfcpci_fill_fifo(struct BCState *bcs)
 /***********************/
 /* set/reset echo mode */
 /***********************/ 
-int hfcpci_set_echo(struct IsdnCardState *cs, int i)
-{ int flags;
-
+static int
+hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic)
+{
+  int flags;
+  int i = *(unsigned int *) ic->parm.num;
+  
   if (cs->chanlimit > 1)
     return(-EINVAL);
 
@@ -651,7 +679,7 @@ int hfcpci_set_echo(struct IsdnCardState *cs, int i)
   Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
   restore_flags(flags);
   return(0);
-} /* hfcpci_set_echo */ 
+} /* hfcpci_auxcmd */ 
 
 /*****************************/
 /* E-channel receive routine */
@@ -1476,9 +1504,9 @@ __initfunc(int
                        return (0);
                }
                i = 0;
-                while (CCD_VENDOR_IDS[i]) {
-                 tmp_hfcpci = pci_find_device(CCD_VENDOR_IDS[i],
-                                              CCD_DEVICE_IDS[i],
+                while (id_list[i].vendor_id) {
+                 tmp_hfcpci = pci_find_device(id_list[i].vendor_id,
+                                              id_list[i].device_id,
                                               dev_hfcpci);
                  if (tmp_hfcpci) break;
                  i++;
@@ -1494,6 +1522,7 @@ __initfunc(int
                                return (0);
                        }
                        cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
+                       printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
                } else {
                        printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
                        return (0);
@@ -1503,14 +1532,14 @@ __initfunc(int
                        unsigned char irq;
 
                        i = 0;
-                        while (CCD_VENDOR_IDS[i]) {
-                         if (pcibios_find_device(CCD_VENDOR_IDS[i],
-                                                 CCD_DEVICE_IDS[i], pci_index,
+                        while (id_list[i].vendor_id) {
+                         if (pcibios_find_device(id_list[i].vendor_id,
+                                                 id_list[i].device_id, pci_index,
                                                  &cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) == 0) 
                            break;
                          i++;
                        }
-                       if (!CCD_VENDOR_IDS[i]
+                       if (!id_list[i].vendor_id
                          continue;
 
                        pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn,
@@ -1520,6 +1549,7 @@ __initfunc(int
                        pcibios_read_config_dword(cs->hw.hfcpci.pci_bus,
                                cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1,
                                (void *) &cs->hw.hfcpci.pci_io);
+                       printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n",id_list[i].vendor_name,id_list[i].card_name);
                        break;
                }
                if (pci_index == 255) {
@@ -1577,6 +1607,7 @@ __initfunc(int
 
        reset_hfcpci(cs);
        cs->cardmsg = &hfcpci_card_msg;
+       cs->auxcmd  = &hfcpci_auxcmd;
        return (1);
 #else
        printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
index 14c201386a024f97bc9845452798318d126342e9..b2859bce73f0647c6410b10a52d828b9325d4164 100644 (file)
@@ -1,8 +1,12 @@
-/* $Id: hisax.h,v 2.33 1999/08/05 20:43:16 keil Exp $
+/* $Id: hisax.h,v 2.34 1999/08/25 17:00:04 keil Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.34  1999/08/25 17:00:04  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
  * Revision 2.33  1999/08/05 20:43:16  keil
  * ISAR analog modem support
  *
 #define CARD_RELEASE   0x00F3
 #define CARD_TEST      0x00F4
 #define CARD_AUX_IND   0x00F5
-#define CARD_LOAD_FIRM 0x00F6
 
 #define PH_ACTIVATE    0x0100
 #define PH_DEACTIVATE  0x0110
@@ -458,6 +461,12 @@ struct isar_hw {
        int rcvidx;
        int txcnt;
        int mml;
+       u_char state;
+       u_char cmd;
+       u_char mod;
+       u_char newcmd;
+       u_char newmod;
+       struct timer_list ftimer;
        u_char *rcvbuf;         /* B-Channel receive Buffer */
        u_char conmsg[16];
        struct isar_reg *reg;
@@ -528,6 +537,14 @@ struct amd7930_hw {
 #define BC_FLG_HALF    5
 #define BC_FLG_EMPTY   6
 #define BC_FLG_ORIG    7
+#define BC_FLG_DLEETX  8
+#define BC_FLG_LASTDLE 9
+#define BC_FLG_FIRST   10
+#define BC_FLG_LASTDATA        11
+#define BC_FLG_NMD_DATA        12
+#define BC_FLG_FTI_RUN 13
+#define BC_FLG_LL_OK   14
+#define BC_FLG_LL_CONN 15
 
 #define L1_MODE_NULL   0
 #define L1_MODE_TRANS  1
@@ -852,6 +869,7 @@ struct hfcpci_chip {
 #define HW_IOM1                        0
 #define HW_IPAC                        1
 #define HW_ISAR                        2
+#define HW_ARCOFI              3
 #define FLG_TWO_DCHAN          4
 #define FLG_L1_DBUSY           5
 #define FLG_DBUSY_TIMER        6
@@ -910,6 +928,7 @@ struct IsdnCardState {
        void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
        void   (*DC_Close) (struct IsdnCardState *);
        void   (*irq_func) (int, void *, struct pt_regs *);
+       int    (*auxcmd) (struct IsdnCardState *, isdn_ctrl *);
        struct Channel channel[2+MAX_WAITING_CALLS];
        struct BCState bcs[2+MAX_WAITING_CALLS];
        struct PStack *stlist;
@@ -1138,7 +1157,6 @@ struct IsdnCardState {
 
 #ifdef CONFIG_HISAX_HFC_PCI
 #define  CARD_HFC_PCI 1
-extern int hfcpci_set_echo(struct IsdnCardState *, int);
 #else
 #define  CARD_HFC_PCI 0
 #endif
@@ -1327,7 +1345,7 @@ void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
 
 #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
 
-int ll_run(struct IsdnCardState *cs);
+int ll_run(struct IsdnCardState *cs, int addfeatures);
 void ll_stop(struct IsdnCardState *cs);
 void CallcNew(void);
 void CallcFree(void);
index 6a130ed010011595d6e3ef2be5ecd1d538ab9376..46d5daef0071e9e78108656702a63289ccbb6c87 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isac.c,v 1.22 1999/08/09 19:04:40 keil Exp $
+/* $Id: isac.c,v 1.23 1999/08/25 16:50:52 keil Exp $
 
  * isac.c   ISAC specific routines
  *
@@ -9,6 +9,9 @@
  *             ../../../Documentation/isdn/HiSax.cert
  *
  * $Log: isac.c,v $
+ * Revision 1.23  1999/08/25 16:50:52  keil
+ * Fix bugs which cause 2.3.14 hangs (waitqueue init)
+ *
  * Revision 1.22  1999/08/09 19:04:40  keil
  * Fix race condition - Thanks to Christer Weinigel
  *
@@ -168,10 +171,14 @@ isac_bh(struct IsdnCardState *cs)
                DChannel_proc_rcv(cs);
        if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
                DChannel_proc_xmt(cs);
+#if ARCOFI_USE
+       if (!test_bit(HW_ARCOFI, &cs->HW_Flags))
+               return;
        if (test_and_clear_bit(D_RX_MON1, &cs->event))
                arcofi_fsm(cs, ARCOFI_RX_END, NULL);
        if (test_and_clear_bit(D_TX_MON1, &cs->event))
                arcofi_fsm(cs, ARCOFI_TX_END, NULL);
+#endif
 }
 
 void
index 05fb7fe9cb951ba95c5557684a33b534fd963588..96442ff7d4ddc302d1d5f365dbc328691ea5a2e7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isar.c,v 1.4 1999/08/05 20:43:18 keil Exp $
+/* $Id: isar.c,v 1.5 1999/08/25 16:59:55 keil Exp $
 
  * isar.c   ISAR (Siemens PSB 7110) specific routines
  *
@@ -6,6 +6,10 @@
  *
  *
  * $Log: isar.c,v $
+ * Revision 1.5  1999/08/25 16:59:55  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
  * Revision 1.4  1999/08/05 20:43:18  keil
  * ISAR analog modem support
  *
@@ -309,6 +313,10 @@ isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
                printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
                        blk_head.len);
        }
+       /* 10ms delay */
+       cnt = 10;
+       while (cnt--)
+               udelay(1000);
        msg[0] = 0xff;
        msg[1] = 0xfe;
        ireg->bstat = 0;
@@ -343,20 +351,26 @@ isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
                printk(KERN_DEBUG"isar general status event %x\n",
                        ireg->bstat);
        }
+       /* 10ms delay */
+       cnt = 10;
+       while (cnt--)
+               udelay(1000);
        ireg->iis = 0;
        if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
                printk(KERN_ERR"isar sendmsg self tst failed\n");
                ret = 1;goto reterrflg;
        }
-       cnt = 1000; /* max 10 ms */
+       cnt = 10000; /* max 100 ms */
        while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
                udelay(10);
                cnt--;
        }
+       udelay(1000);
        if (!cnt) {
                printk(KERN_ERR"isar no self tst response\n");
                ret = 1;goto reterrflg;
-       } else if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
+       }
+       if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
                && (ireg->par[0] == 0)) {
                printk(KERN_DEBUG"isar selftest OK\n");
        } else {
@@ -369,11 +383,12 @@ isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
                printk(KERN_ERR"isar RQST SVN failed\n");
                ret = 1;goto reterror;
        }
-       cnt = 10000; /* max 100 ms */
+       cnt = 30000; /* max 300 ms */
        while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
                udelay(10);
                cnt--;
        }
+       udelay(1000);
        if (!cnt) {
                printk(KERN_ERR"isar no SVN response\n");
                ret = 1;goto reterrflg;
@@ -402,7 +417,18 @@ reterror:
        return(ret);
 }
 
-void
+extern void BChannel_bh(struct BCState *);
+#define B_LL_NOCARRIER 8
+#define B_LL_CONNECT   9
+#define B_LL_OK                10
+
+static void
+isar_bh(struct BCState *bcs)
+{
+       BChannel_bh(bcs);
+}
+
+static void
 isar_sched_event(struct BCState *bcs, int event)
 {
        bcs->event |= 1 << event;
@@ -464,9 +490,9 @@ isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
                                if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
                                        printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",
                                                bcs->hw.isar.rcvidx);
-                               } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2)))
+                               } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2))) {
                                        printk(KERN_WARNING "ISAR: receive out of memory\n");
-                               else {
+                               else {
                                        SET_SKB_FREE(skb);
                                        memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
                                                bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
@@ -709,7 +735,6 @@ isar_pump_status_ev(struct BCState *bcs, u_char devt) {
                case PSEV_DSR_ON:
                        if (cs->debug & L1_DEB_HSCX)
                                debugl1(cs, "pump stev DSR ON");
-//                     sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, 0xCF, 0, NULL);
                        break;
                case PSEV_DSR_OFF:
                        if (cs->debug & L1_DEB_HSCX)
@@ -734,7 +759,7 @@ isar_pump_status_ev(struct BCState *bcs, u_char devt) {
        }
 }
 
-static char debbuf[64];
+static char debbuf[128];
 
 void
 isar_int_main(struct IsdnCardState *cs)
@@ -806,6 +831,12 @@ isar_int_main(struct IsdnCardState *cs)
                                debugl1(cs, debbuf);
                        }
                        break;
+               case ISAR_IIS_INVMSG:
+                       rcv_mbox(cs, ireg, debbuf);
+                       if (cs->debug & L1_DEB_WARN)
+                               debugl1(cs, "invalid msg his:%x",
+                                       ireg->cmsb);
+                       break;
                default:
                        rcv_mbox(cs, ireg, debbuf);
                        if (cs->debug & L1_DEB_WARN)
@@ -816,7 +847,7 @@ isar_int_main(struct IsdnCardState *cs)
        restore_flags(flags);
 }
 
-void
+static void
 setup_pump(struct BCState *bcs) {
        struct IsdnCardState *cs = bcs->cs;
        u_char dps = SET_DPS(bcs->hw.isar.dpath);
@@ -840,15 +871,12 @@ setup_pump(struct BCState *bcs) {
                        } else {
                                param[5] = PV32P6_ATN;
                        }
-                       param[0] = 11; /* 11 db */
-//                     param[1] = PV32P2_V22A | PV32P2_V22B | PV32P2_V21; 
-                       param[1] = PV32P2_V22A; 
-//                     param[2] = PV32P3_AMOD | PV32P3_V32B;
-                       param[2] = PV32P3_AMOD;
-                       param[3] = PV32P4_48;
-                       param[4] = PV32P5_48;
-//                     param[3] = PV32P4_UT144;
-//                     param[4] = PV32P5_UT144;
+                       param[0] = 6; /* 6 db */
+                       param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
+                                  PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; 
+                       param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
+                       param[3] = PV32P4_UT144;
+                       param[4] = PV32P5_UT144;
                        if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 6, param)) {
                                if (cs->debug)
                                        debugl1(cs, "isar pump datamodem cfg dp%d failed",
@@ -863,7 +891,7 @@ setup_pump(struct BCState *bcs) {
                        } else {
                                param[1] = PFAXP2_ATN;
                        }
-                       param[0] = 8; /* 8 db */
+                       param[0] = 6; /* 6 db */
                        if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param)) {
                                if (cs->debug)
                                        debugl1(cs, "isar pump faxmodem cfg dp%d failed",
@@ -878,7 +906,7 @@ setup_pump(struct BCState *bcs) {
        }
 }
 
-void
+static void
 setup_sart(struct BCState *bcs) {
        struct IsdnCardState *cs = bcs->cs;
        u_char dps = SET_DPS(bcs->hw.isar.dpath);
@@ -900,7 +928,9 @@ setup_sart(struct BCState *bcs) {
                        }
                        break;
                case L1_MODE_HDLC:
-                       if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, "\0")) {
+               case L1_MODE_FAX:
+                       param[0] = 0;
+                       if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, param)) {
                                if (cs->debug)
                                        debugl1(cs, "isar sart hdlc dp%d failed",
                                                bcs->hw.isar.dpath);
@@ -924,7 +954,7 @@ setup_sart(struct BCState *bcs) {
        }
 }
 
-void
+static void
 setup_iom2(struct BCState *bcs) {
        struct IsdnCardState *cs = bcs->cs;
        u_char dps = SET_DPS(bcs->hw.isar.dpath);
@@ -967,6 +997,9 @@ modeisar(struct BCState *bcs, int mode, int bc)
                bcs->channel = bc;
                switch (mode) {
                        case L1_MODE_NULL: /* init */
+                               if (!bcs->hw.isar.dpath)
+                                       /* no init for dpath 0 */
+                                       return(0);
                                break;
                        case L1_MODE_TRANS:
                        case L1_MODE_HDLC:
@@ -983,6 +1016,7 @@ modeisar(struct BCState *bcs, int mode, int bc)
                                }
                                break;
                        case L1_MODE_V32:
+                       case L1_MODE_FAX:
                                /* only datapath 1 */
                                if (!test_and_set_bit(ISAR_DP1_USE, 
                                        &bcs->hw.isar.reg->Flags))
@@ -1032,6 +1066,7 @@ isar_setup(struct IsdnCardState *cs)
                cs->bcs[i].mode = 0;
                cs->bcs[i].hw.isar.dpath = i + 1;
                modeisar(&cs->bcs[i], 0, 0);
+               cs->bcs[i].tqueue.routine = (void *) (void *) isar_bh;
        }
 }
 
@@ -1169,6 +1204,36 @@ setstack_isar(struct PStack *st, struct BCState *bcs)
        return (0);
 }
 
+int
+isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
+       u_long adr;
+       int features;
+
+       if (cs->debug & L1_DEB_HSCX)
+               debugl1(cs, "isar_auxcmd cmd/ch %x/%d", ic->command, ic->arg);
+       switch (ic->command) {
+               case (ISDN_CMD_IOCTL):
+                       switch (ic->arg) {
+                               case (9): /* load firmware */
+                                       features = ISDN_FEATURE_L2_MODEM;
+                                       memcpy(&adr, ic->parm.num, sizeof(ulong));
+                                       if (isar_load_firmware(cs, (u_char *)adr))
+                                               return(1);
+                                       else 
+                                               ll_run(cs, features);
+                                       break;
+                               default:
+                                       printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
+                                              (int) ic->arg);
+                                       return(-EINVAL);
+                       }
+                       break;
+               default:
+                       return(-EINVAL);
+       }
+       return(0);
+}
+
 HISAX_INITFUNC(void 
 initisar(struct IsdnCardState *cs))
 {
index c17875263901c19125aab61612f4e59725dd6a36..c6ac6532b231e17ff6ec4f1f10332f152888f656 100644 (file)
@@ -1,10 +1,14 @@
-/* $Id: isar.h,v 1.4 1999/08/05 20:43:20 keil Exp $
+/* $Id: isar.h,v 1.5 1999/08/25 16:59:59 keil Exp $
  * isar.h   ISAR (Siemens PSB 7110) specific defines
  *
  * Author Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: isar.h,v $
+ * Revision 1.5  1999/08/25 16:59:59  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
  * Revision 1.4  1999/08/05 20:43:20  keil
  * ISAR analog modem support
  *
 #define ISAR_WADR      0x4a
 #define ISAR_RADR      0x48 
 
-#define ISAR_HIS_VNR   0x14
-#define ISAR_HIS_DKEY  0x02
-#define ISAR_HIS_FIRM  0x1e
-#define ISAR_HIS_STDSP  0x08
-#define ISAR_HIS_DIAG  0x05
-#define ISAR_HIS_P0CFG 0x3c
-#define ISAR_HIS_P12CFG        0x24
+#define ISAR_HIS_VNR           0x14
+#define ISAR_HIS_DKEY          0x02
+#define ISAR_HIS_FIRM          0x1e
+#define ISAR_HIS_STDSP         0x08
+#define ISAR_HIS_DIAG          0x05
+#define ISAR_HIS_P0CFG         0x3c
+#define ISAR_HIS_P12CFG                0x24
 #define ISAR_HIS_SARTCFG       0x25    
 #define ISAR_HIS_PUMPCFG       0x26    
 #define ISAR_HIS_PUMPCTRL      0x2a    
 #define ISAR_HIS_IOM2CFG       0x27
 #define ISAR_HIS_IOM2REQ       0x07
 #define ISAR_HIS_IOM2CTRL      0x2b
-#define ISAR_HIS_BSTREQ        0x0c
-#define ISAR_HIS_PSTREQ        0x0e
-#define ISAR_HIS_SDATA 0x20
-#define ISAR_HIS_DPS1  0x40
-#define ISAR_HIS_DPS2  0x80
-#define SET_DPS(x)     ((x<<6) & 0xc0)
-
-#define ISAR_IIS_MSCMSD 0x3f
-#define ISAR_IIS_VNR   0x15
-#define ISAR_IIS_DKEY  0x03
-#define ISAR_IIS_FIRM  0x1f
-#define ISAR_IIS_STDSP  0x09
-#define ISAR_IIS_DIAG  0x25
-#define ISAR_IIS_GSTEV 0x0
-#define ISAR_IIS_BSTEV 0x28
-#define ISAR_IIS_BSTRSP        0x2c
-#define ISAR_IIS_PSTRSP        0x2e
-#define ISAR_IIS_PSTEV 0x2a
+#define ISAR_HIS_BSTREQ                0x0c
+#define ISAR_HIS_PSTREQ                0x0e
+#define ISAR_HIS_SDATA         0x20
+#define ISAR_HIS_DPS1          0x40
+#define ISAR_HIS_DPS2          0x80
+#define SET_DPS(x)             ((x<<6) & 0xc0)
+
+#define ISAR_IIS_MSCMSD                0x3f
+#define ISAR_IIS_VNR           0x15
+#define ISAR_IIS_DKEY          0x03
+#define ISAR_IIS_FIRM          0x1f
+#define ISAR_IIS_STDSP         0x09
+#define ISAR_IIS_DIAG          0x25
+#define ISAR_IIS_GSTEV         0x00
+#define ISAR_IIS_BSTEV         0x28
+#define ISAR_IIS_BSTRSP                0x2c
+#define ISAR_IIS_PSTRSP                0x2e
+#define ISAR_IIS_PSTEV         0x2a
 #define ISAR_IIS_IOM2RSP       0x27
+#define ISAR_IIS_RDATA         0x20
+#define ISAR_IIS_INVMSG                0x3f
 
-#define ISAR_IIS_RDATA 0x20
 #define ISAR_CTRL_SWVER        0x10
 #define ISAR_CTRL_STST 0x40
 
 #define PV32P2_V21     0x02
 #define PV32P2_BEL     0x01
 
+// LSB MSB in ISAR doc wrong !!! Arghhh
 #define PV32P3_AMOD    0x80
 #define PV32P3_V32B    0x02
-#define PV32P4_48      0x05
-#define PV32P5_48      0x11
-#define PV32P4_UT48    0x0d
-#define PV32P5_UT48    0x11
-#define PV32P4_96      0x03
-#define PV32P5_96      0x11
-#define PV32P4_UT96    0x0f
-#define PV32P5_UT96    0x11
-#define PV32P4_B96     0x0b
-#define PV32P5_B96     0x91
-#define PV32P4_UTB96   0x0f
-#define PV32P5_UTB96   0xd1
-#define PV32P4_120     0x09
-#define PV32P5_120     0xb1
-#define PV32P4_UT120   0x0f
-#define PV32P5_UT120   0xf1
-#define PV32P4_144     0x09
-#define PV32P5_144     0x99
-#define PV32P4_UT144   0x0f
-#define PV32P5_UT144   0xf9
+#define PV32P3_V23B    0x01
+#define PV32P4_48      0x11
+#define PV32P5_48      0x05
+#define PV32P4_UT48    0x11
+#define PV32P5_UT48    0x0d
+#define PV32P4_96      0x11
+#define PV32P5_96      0x03
+#define PV32P4_UT96    0x11
+#define PV32P5_UT96    0x0f
+#define PV32P4_B96     0x91
+#define PV32P5_B96     0x0b
+#define PV32P4_UTB96   0xd1
+#define PV32P5_UTB96   0x0f
+#define PV32P4_120     0xb1
+#define PV32P5_120     0x09
+#define PV32P4_UT120   0xf1
+#define PV32P5_UT120   0x0f
+#define PV32P4_144     0x99
+#define PV32P5_144     0x09
+#define PV32P4_UT144   0xf9
+#define PV32P5_UT144   0x0f
 #define PV32P6_CTN     0x01
 #define PV32P6_ATN     0x02
+
 #define PFAXP2_CTN     0x01
 #define PFAXP2_ATN     0x04
 
 #define S_P1_CHS_6     0x01
 #define S_P1_CHS_5     0x00
 
-#define S_P2_BFT_DEF   30
+#define S_P2_BFT_DEF   0x10
 
 #define IOM_CTRL_ENA   0x80
 #define IOM_CTRL_NOPCM 0x00
 #define HDLC_FSD       0x20
 #define HDLC_FST       0x20
 #define HDLC_ERROR     0x1c
+#define SART_NMD       0x01
 
 #define BSTAT_RDM0     0x1
 #define BSTAT_RDM1     0x2
 #define BSTAT_RDM2     0x4
 #define BSTAT_RDM3     0x8
 
-
 extern int ISARVersion(struct IsdnCardState *cs, char *s);
-extern int isar_load_firmware(struct IsdnCardState *cs, u_char *buf);
 extern void isar_int_main(struct IsdnCardState *cs);
 extern void initisar(struct IsdnCardState *cs);
 extern void isar_fill_fifo(struct BCState *bcs);
+extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic);
index 9ed3106727cb7b961014a6455f577bb1e6688e12..c819c4811b5822255c4c6e74cc6e94be73bddcb8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdnl1.c,v 2.34 1999/07/09 13:50:15 keil Exp $
+/* $Id: isdnl1.c,v 2.36 1999/08/25 16:50:57 keil Exp $
 
  * isdnl1.c     common low level stuff for Siemens Chipsetbased isdn cards
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: isdnl1.c,v $
+ * Revision 2.36  1999/08/25 16:50:57  keil
+ * Fix bugs which cause 2.3.14 hangs (waitqueue init)
+ *
+ * Revision 2.35  1999/08/22 20:27:07  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 2.34  1999/07/09 13:50:15  keil
  * remove unused variable
  *
  *
  */
 
-const char *l1_revision = "$Revision: 2.34 $";
+const char *l1_revision = "$Revision: 2.36 $";
 
 #define __NO_VERSION__
 #include "hisax.h"
@@ -390,7 +399,7 @@ BChannel_proc_rcv(struct BCState *bcs)
        }
 }
 
-static void
+void
 BChannel_bh(struct BCState *bcs)
 {
        if (!bcs)
index 24d468da252803c8b377f4e1915dea930af6d565..ca721ea864b5810d87e5c0f79ca59546310b2f10 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdnl2.c,v 2.19 1999/08/05 20:40:26 keil Exp $
+/* $Id: isdnl2.c,v 2.20 1999/08/25 16:52:04 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
@@ -11,6 +11,9 @@
  *              Fritz Elfert
  *
  * $Log: isdnl2.c,v $
+ * Revision 2.20  1999/08/25 16:52:04  keil
+ * Make gcc on AXP happy
+ *
  * Revision 2.19  1999/08/05 20:40:26  keil
  * Fix interlayer communication
  *
@@ -80,7 +83,7 @@
 #include "hisax.h"
 #include "isdnl2.h"
 
-const char *l2_revision = "$Revision: 2.19 $";
+const char *l2_revision = "$Revision: 2.20 $";
 
 static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
 
@@ -1747,7 +1750,7 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
                        }
                        if(c) {
                                FreeSkb(skb);
-                               FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) c);
+                               FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
                                ret = 0;
                        }
                        if (ret)
index a81bf07605e2d799668c426d220d4d14cb9c7683..22e54fd8e92aef0abd5880f2293292d56c11bf05 100644 (file)
@@ -1,10 +1,20 @@
-/* $Id: isurf.c,v 1.3 1999/07/12 21:05:18 keil Exp $
+/* $Id: isurf.c,v 1.5 1999/08/25 17:00:02 keil Exp $
 
  * isurf.c  low level stuff for Siemens I-Surf/I-Talk cards
  *
  * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * $Log: isurf.c,v $
+ * Revision 1.5  1999/08/25 17:00:02  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
+ * Revision 1.4  1999/08/22 20:27:09  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.3  1999/07/12 21:05:18  keil
  * fix race in IRQ handling
  * added watchdog for lost IRQs
@@ -24,7 +34,7 @@
 
 extern const char *CardType[];
 
-static const char *ISurf_revision = "$Revision: 1.3 $";
+static const char *ISurf_revision = "$Revision: 1.5 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -174,18 +184,26 @@ ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
                        return(0);
                case CARD_TEST:
                        return(0);
-               case CARD_LOAD_FIRM:
-                       if (isar_load_firmware(cs, arg))
-                               return(1);
-                       ll_run(cs);
+       }
+       return(0);
+}
+
+static int
+isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) {
+       int ret;
+
+       if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) {
+               ret = isar_auxcmd(cs, ic);
+               if (!ret) {
                        reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
                                ISURF_ARCOFI_RESET);
                        initisac(cs);
                        cs->writeisac(cs, ISAC_MASK, 0);
                        cs->writeisac(cs, ISAC_CMDR, 0x41);
-                       return(0);
+               }
+               return(ret);
        }
-       return(0);
+       return(isar_auxcmd(cs, ic));
 }
 
 __initfunc(int
@@ -228,6 +246,7 @@ setup_isurf(struct IsdnCard *card))
 
        cs->cardmsg = &ISurf_card_msg;
        cs->irq_func = &isurf_interrupt;
+       cs->auxcmd = &isurf_auxcmd;
        cs->readisac = &ReadISAC;
        cs->writeisac = &WriteISAC;
        cs->readisacfifo = &ReadISACfifo;
index 1c541033f0fd6ba72fd2526cd07a806a91ec5ee1..22a5de9fa7ba783200d626a35663ee52658a0208 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.18 1999/08/11 20:54:39 keil Exp $
+/* $Id: l3dss1.c,v 2.19 1999/08/25 16:55:23 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
@@ -13,6 +13,9 @@
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.19  1999/08/25 16:55:23  keil
+ * Fix for test case TC10011
+ *
  * Revision 2.18  1999/08/11 20:54:39  keil
  * High layer compatibility is valid in SETUP
  *
@@ -87,7 +90,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.18 $";
+const char *dss1_revision = "$Revision: 2.19 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -764,11 +767,6 @@ ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
        int ret = 1;
 
        while (*checklist != -1) {
-#if 0
-               if (pc->debug & L3_DEB_CHECK)
-                       l3_debug(pc->st, "ie_in_set ie(%x) cl(%x)",
-                               ie, *checklist);
-#endif
                if ((*checklist & 0xff) == ie) {
                        if (ie & 0x80)
                                return(-ret);
@@ -1737,15 +1735,12 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
                return;
        }
        /* Now we are on none mandatory IEs */
-#if 1
-/* !!!!!! this check seems to be a problem ? info bugfix to Karsten */
        err = check_infoelements(pc, skb, ie_SETUP);
        if (ERR_IE_COMPREHENSION == err) {
                pc->para.cause = 96;
                l3dss1_msg_without_setup(pc, pr, NULL);
                return;
        }
-#endif
        p = skb->data;
        if ((p = findie(p, skb->len, 0x70, 0)))
                iecpy(pc->para.setup.eazmsn, p, 1);
@@ -1787,29 +1782,10 @@ l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
                } else if (pc->debug & L3_DEB_WARN)
                        l3_debug(pc->st, "wrong calling subaddress");
        }
-
-#if 0
-       if (bcfound) {
-               if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
-                       l3_debug(pc->st, "non-digital call: %s -> %s",
-                           pc->para.setup.phone, pc->para.setup.eazmsn);
-               }
-               if ((pc->para.setup.si1 != 7) &&
-                   test_bit(FLG_PTP, &pc->st->l2.flag)) {
-                       pc->para.cause = 88; /* incompatible destination */
-                       l3dss1_msg_without_setup(pc, pr, NULL);
-                       return;
-               }
-               newl3state(pc, 6);
-               pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
-       } else
-               dss1_release_l3_process(pc);
-#else
        newl3state(pc, 6);
        if (err) /* STATUS for none mandatory IE errors after actions are taken */
                l3dss1_std_ie_err(pc, err);
        pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
-#endif
 }
 
 static void
@@ -2106,8 +2082,6 @@ l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
 
        ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
        l3dss1_std_ie_err(pc, ret);
-// KKe 19.7.99 test eicon
-//        idev_kfree_skb(skb, FREE_READ);
        pc->para.cause = 30; /* response to STATUS_ENQUIRY */
         l3dss1_status_send(pc, pr, NULL);
 }
@@ -2862,7 +2836,8 @@ static struct stateentry datastatelist[] =
         MT_STATUS, l3dss1_status},
        {SBIT(0),
         MT_SETUP, l3dss1_setup},
-       {SBIT(6) | SBIT(7),
+       {SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) |
+        SBIT(15) | SBIT(17) | SBIT(19) | SBIT(25),
         MT_SETUP, l3dss1_dummy},
        {SBIT(1) | SBIT(2),
         MT_CALL_PROCEEDING, l3dss1_call_proc},
@@ -2885,8 +2860,6 @@ static struct stateentry datastatelist[] =
        {SBIT(19),  MT_RELEASE, l3dss1_release_ind},
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15) | SBIT(17) | SBIT(25),
         MT_DISCONNECT, l3dss1_disconnect},
-//     {SBIT(11),
-//      MT_DISCONNECT, l3dss1_release_req},
        {SBIT(19),
         MT_DISCONNECT, l3dss1_dummy},
        {SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
index 7fe2bbbae56e9faa050ce2ba5e46415b787ed619..481a7dc720ea628853dafacfd267654bea1a1dbe 100644 (file)
@@ -6,16 +6,16 @@
 # Eicon Technology Diva 2.01 PCI cards in the moment.
 # Read ../../../Documentation/isdn/HiSax.cert for more informations.
 # 
-d93f31e02c1b153ec04d16f69e5688b3  isac.c
-e2a78c07f32c8ca7c88fc9f92a87dfab  isdnl1.c
-54490c4f46a998ff4ef34287bc262185  isdnl2.c
+0cc164fadd4ec0e2983ec9735e209cbd  isac.c
+5fe8cb5526c78c91f61b0a94a423ea5d  isdnl1.c
+3b9522e8bf9e1c3e7848d729fc3dc05d  isdnl2.c
 f4184a50e35e5b568608e6cb7a693319  isdnl3.c
 ef70f4269fdc2ca15100f9b776afaa0d  tei.c
-cf3923304983e9d64cf35bc5a3533f6c  callc.c
+65be616dd9d0e06c788d4fdd0fe5fe0a  callc.c
 bf9605b36429898f7be6630034e83230  cert.c
-309261e4c36d950db6978440e8bc8342  l3dss1.c
+97c5e31c2739665b9c2976a30ce0b357  l3dss1.c
 b674eee9314a7cc413971c84003cf1d2  l3_1tr6.c
-8f86d92f43ecc42f6457773168cfc114  elsa.c
+51b2ef1efb221bb09fd08ab28bd2c565  elsa.c
 24cda374da44b57f6a1bb215424267b5  diva.c
 # end of md5sums
 
@@ -23,9 +23,9 @@ b674eee9314a7cc413971c84003cf1d2  l3_1tr6.c
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBN7HnvDpxHvX/mS9tAQFANgP+LGuG98lvCv97vN2dc6T/6hZTxFW+WirJ
-XMhU5NHoZ+8MISMOVKB7ugsGO9cJI0lUA0sOe8jtPCo5070nF1ZkNsxV/x7WK2dS
-RwXfHy6+TAH7qIiBnkP9odB2lib+VFl/nnkkTwsXfVwRCD8bLaagMPv+nAveDoNE
-uff0xxXEnJw=
-=Wu2M
+iQCVAwUBN8RgFjpxHvX/mS9tAQFzFQP/dOgnppDIm5ug1hnlWjQ/0BVurKEEJ64r
+DYDHwkcog+0gVE/EB1A7WUDqpFEnj52OZeoVinCfdVuVjP8IkrAJ8dCONsnXjBXz
+pzM+FunP1LFxuv2TVM0f642j98JxS8rObGWH8ZwY36P2QfNp47zorO2F9WvdCkuz
+sxJUtMUOlQ8=
+=8uEP
 -----END PGP SIGNATURE-----
index 25303b6e942bae1ebe3e4f5b0bd79956849a26bc..3251aa9fe51ad64d21e0a218004b3755e5e17d9e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sedlbauer.c,v 1.14 1999/08/11 20:59:22 keil Exp $
+/* $Id: sedlbauer.c,v 1.15 1999/08/25 17:00:00 keil Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
  *              includes support for the Sedlbauer speed star (speed star II),
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.15  1999/08/25 17:00:00  keil
+ * Make ISAR V32bis modem running
+ * Make LL->HL interface open for additional commands
+ *
  * Revision 1.14  1999/08/11 20:59:22  keil
  * new PCI codefix
  * fix IRQ problem while unload
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.14 $";
+const char *Sedlbauer_revision = "$Revision: 1.15 $";
 
 const char *Sedlbauer_Types[] =
        {"None", "speed card/win", "speed star", "speed fax+", 
@@ -530,19 +534,10 @@ Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg)
                        return(0);
                case CARD_TEST:
                        return(0);
-               case CARD_LOAD_FIRM:
-                       if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
-                               if (isar_load_firmware(cs, arg))
-                                       return(1);
-                               else 
-                                       ll_run(cs);
-                       }
-                       return(0);
        }
        return(0);
 }
 
-
 #ifdef SEDLBAUER_PCI
 #ifdef COMPAT_HAS_NEW_PCI
 static         struct pci_dev *dev_sedl __initdata = NULL;
@@ -743,7 +738,7 @@ setup_sedlbauer(struct IsdnCard *card))
                        cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
                        test_and_set_bit(HW_ISAR, &cs->HW_Flags);
                        cs->irq_func = &sedlbauer_interrupt_isar;
-       
+                       cs->auxcmd = &isar_auxcmd;
                        ISACVersion(cs, "Sedlbauer:");
                
                        cs->BC_Read_Reg = &ReadISAR;
index 0768ec0fce5662ba99dfbe67aeabd2ec5d254209..2d7b0413a7c768f7f247ff87f758611794b5afb2 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.57 1999/07/06 16:15:30 detabc Exp $
+/* $Id: icn.c,v 1.58 1999/08/25 16:44:17 keil Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
+ * Revision 1.58  1999/08/25 16:44:17  keil
+ * Support for new __setup function
+ *
  * Revision 1.57  1999/07/06 16:15:30  detabc
  * remove unused messages
  *
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.57 $";
+*revision = "$Revision: 1.58 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -1846,13 +1849,25 @@ icn_addcard(int port, char *id1, char *id2)
 #ifdef MODULE
 #define icn_init init_module
 #else
+#ifdef COMPAT_HAS_NEW_SETUP
+#include <linux/init.h>
+int
+icn_setup(char *line)
+{
+       char *p, *str;
+       int     ints[3];
+       static char sid[20];
+       static char sid2[20];
+
+       str = get_options(line, 2, ints);
+#else
 void
 icn_setup(char *str, int *ints)
 {
        char *p;
        static char sid[20];
        static char sid2[20];
-
+#endif
        if (ints[0])
                portbase = ints[1];
        if (ints[0] > 1)
@@ -1866,8 +1881,14 @@ icn_setup(char *str, int *ints)
                        icn_id2 = sid2;
                }
        }
+#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
+}
+__setup("icn=", icn_setup);
+#else
 }
 #endif
+#endif /* MODULES */
 
 int
 icn_init(void)
index a6f13ef7643203931ff5862cec1f96de92a1e291..3599d2ada109c412c8c6aaf9c517d6e413347eb5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_audio.c,v 1.16 1999/08/06 12:47:35 calle Exp $
+/* $Id: isdn_audio.c,v 1.17 1999/08/17 11:10:52 paul Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_audio.c,v $
+ * Revision 1.17  1999/08/17 11:10:52  paul
+ * don't try to use x86 assembler on non-x86!
+ *
  * Revision 1.16  1999/08/06 12:47:35  calle
  * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define
  *   ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
@@ -92,7 +95,7 @@
 #include "isdn_audio.h"
 #include "isdn_common.h"
 
-char *isdn_audio_revision = "$Revision: 1.16 $";
+char *isdn_audio_revision = "$Revision: 1.17 $";
 
 /*
  * Misc. lookup-tables.
@@ -294,7 +297,7 @@ static char dtmf_matrix[4][4] =
  * egcs 2.95 complain about invalid asm statement:
  * "fixed or forbidden register 2 (cx) was spilled for class CREG."
  */
-#if ((CPU == 386) || (CPU == 486) || (CPU == 586)) || defined(__GNUC__)
+#if ((CPU == 386) || (CPU == 486) || (CPU == 586)) && defined(__GNUC__)
 #if __GNUC__ == 2 && __GNUC_MINOR__ < 95
 #define ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT
 #endif
index 698fd34ff5fe9d20b3da706a9e99d5715587ed90..ca05f8bf315b45f243d8b557813e3fa1ac0cd266 100644 (file)
@@ -1,10 +1,16 @@
-/* $Id: isdn_concap.c,v 1.5 1998/10/30 18:44:48 he Exp $
+/* $Id: isdn_concap.c,v 1.6 1999/08/22 20:26:01 calle Exp $
  
  * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
  * stuff goes here. Stuff that depends only on the concap protocol goes to
  * another -- protocol specific -- source file.
  *
  * $Log: isdn_concap.c,v $
+ * Revision 1.6  1999/08/22 20:26:01  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.5  1998/10/30 18:44:48  he
  * pass return value from isdn_net_dial_req for dialmode change
  *
index 1cda52f6d9edf33bc59c724139251b0fb1a89ab5..9d54f01274e82df77965a8cdd0a5135b892f7ee5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.88 1999/07/07 10:13:31 detabc Exp $
+/* $Id: isdn_net.c,v 1.89 1999/08/22 20:26:03 calle Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.89  1999/08/22 20:26:03  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.88  1999/07/07 10:13:31  detabc
  * remove unused messages
  *
@@ -360,7 +366,7 @@ int isdn_net_force_dial_lp(isdn_net_local *);
 static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
 static int isdn_net_xmit(struct net_device *, isdn_net_local *, struct sk_buff *);
 
-char *isdn_net_revision = "$Revision: 1.88 $";
+char *isdn_net_revision = "$Revision: 1.89 $";
 
  /*
   * Code for raw-networking over ISDN
index c8ef6e0722c0b047a85cd2e70f71ae174083f979..bd48c592c41029df881950586f58d0f50ef1c4dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.h,v 1.9 1999/04/12 12:33:27 fritz Exp $
+/* $Id: isdn_net.h,v 1.10 1999/08/22 20:26:06 calle Exp $
 
  * header for Linux ISDN subsystem, network related functions (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.h,v $
+ * Revision 1.10  1999/08/22 20:26:06  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.9  1999/04/12 12:33:27  fritz
  * Changes from 2.0 tree.
  *
index e8ba71771f7f644a05e604f326291b377f446c24..78c71c7fe48814036bb954c7f823ce857304318d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.49 1999/07/06 07:47:11 calle Exp $
+/* $Id: isdn_ppp.c,v 1.52 1999/08/22 20:26:07 calle Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.52  1999/08/22 20:26:07  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
+ * Revision 1.51  1999/08/18 16:19:17  hipp
+ * applied MPPP-resize-headroom patch
+ *
+ * Revision 1.50  1999/08/16 07:11:41  hipp
+ * Additional VJ decomp-buffer-size increased from 40 to 128
+ *
  * Revision 1.49  1999/07/06 07:47:11  calle
  * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the
  *     hdrlen the driver want. So I changed dev_alloc_skb calls
@@ -269,7 +281,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.49 $";
+char *isdn_ppp_revision = "$Revision: 1.52 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 static struct isdn_ppp_compressor *ipc_head = NULL;
@@ -1352,7 +1364,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
                        {
                                struct sk_buff *skb_old = skb;
                                int pkt_len;
-                               skb = dev_alloc_skb(skb_old->len + 40);
+                               skb = dev_alloc_skb(skb_old->len + 128);
 
                                if (!skb) {
                                        printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
@@ -1361,7 +1373,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
                                        return;
                                }
                                skb->dev = dev;
-                               skb_put(skb, skb_old->len + 40);
+                               skb_put(skb, skb_old->len + 128);
                                memcpy(skb->data, skb_old->data, skb_old->len);
                                skb->mac.raw = skb->data;
                                pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
@@ -1415,9 +1427,17 @@ static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
        struct sk_buff *skb = *skb_p;
 
        if(skb_headroom(skb) < len) {
-               printk(KERN_ERR "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
+               struct sk_buff *nskb = skb_realloc_headroom(skb, len);
+
+               if (!nskb) {
+                       printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
+                       dev_kfree_skb(skb);
+                       return NULL;
+               }
+               printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
                dev_kfree_skb(skb);
-               return NULL;
+               *skb_p = nskb;
+               return skb_push(nskb, len);
        }
        return skb_push(skb,len);
 }
index a24a8ce9efb632d70381ec6453c5309789bd2635..1a1dcfcfe6e234f587a20e7681aa75e3d7211baa 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.13 1998/03/22 18:50:50 hipp Exp $
+/* $Id: isdn_ppp.h,v 1.14 1999/08/22 20:26:10 calle Exp $
 
  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.h,v $
+ * Revision 1.14  1999/08/22 20:26:10  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.13  1998/03/22 18:50:50  hipp
  * Added BSD Compression for syncPPP .. UNTESTED at the moment
  *
index 62e723eafbed13927aa01ce374dc10606a05112b..87acd7be2fd384864f81c84a257a5889391d7e26 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.15 1999/07/31 12:59:48 armin Exp $
+/* $Id: isdn_tty.h,v 1.16 1999/08/22 20:26:10 calle Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.16  1999/08/22 20:26:10  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.15  1999/07/31 12:59:48  armin
  * Added tty fax capabilities.
  *
index cc7c14fc6a6d4642531060d7e1fc5be91a1ef6bd..7665aa812c266cd6da310a1a40e0fbcd6446b648 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_ttyfax.c,v 1.2 1999/08/05 10:36:10 armin Exp $
+/* $Id: isdn_ttyfax.c,v 1.3 1999/08/22 20:26:12 calle Exp $
  * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
  *
  * Copyright 1999    by Armin Schindler (mac@melware.de)
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ttyfax.c,v $
+ * Revision 1.3  1999/08/22 20:26:12  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.2  1999/08/05 10:36:10  armin
  * Bugfix: kernel oops on getting revision.
  *
@@ -40,7 +46,7 @@
 #include "isdn_ttyfax.h"
 
 
-static char *isdn_tty_fax_revision = "$Revision: 1.2 $";
+static char *isdn_tty_fax_revision = "$Revision: 1.3 $";
 
 #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
 
index 63f7c521f119ef653b6a08a05edb9c290bf71f1f..9a50748015c5ce13eabbc6eac8896703be96578f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_x25iface.c,v 1.6 1999/01/27 22:53:19 he Exp $
+/* $Id: isdn_x25iface.c,v 1.7 1999/08/22 20:26:13 calle Exp $
  * stuff needed to support the Linux X.25 PLP code on top of devices that
  * can provide a lab_b service using the concap_proto mechanism.
  * This module supports a network interface wich provides lapb_sematics
  * goes to another -- device related -- concap_proto support source file.
  *
  * $Log: isdn_x25iface.c,v $
+ * Revision 1.7  1999/08/22 20:26:13  calle
+ * backported changes from kernel 2.3.14:
+ * - several #include "config.h" gone, others come.
+ * - "struct device" changed to "struct net_device" in 2.3.14, added a
+ *   define in isdn_compat.h for older kernel versions.
+ *
  * Revision 1.6  1999/01/27 22:53:19  he
  * minor updates (spellings, jiffies wrap around in isdn_tty)
  *
index 33aee3360eb3ca8416d0f82df59c4e860ce06e9f..ae4abb590d49181c4a4f6a47feba42615476ce58 100644 (file)
@@ -102,10 +102,21 @@ void cleanup_module(void)
 }
 
 #else
-void pcbit_setup(char *str, int *ints)
+#ifdef COMPAT_HAS_NEW_SETUP
+#define MAX_PARA       (MAX_PCBIT_CARDS * 2)
+#include <linux/init.h>
+int pcbit_setup(char *line)
 {
        int i, j, argc;
+       char *str;
+       int ints[MAX_PARA+1];
 
+       str = get_options(line, MAX_PARA, ints);
+#else
+void pcbit_setup(char *str, int *ints)
+{
+       int i, j, argc;
+#endif
        argc = ints[0];
        i = 0;
        j = 1;
@@ -124,8 +135,14 @@ void pcbit_setup(char *str, int *ints)
 
                i++;
        }
+#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
+}
+__setup("pcbit=", pcbit_setup);
+#else
 }
 #endif
+#endif
 
 
 
index eb46520e95fb129c8535d410b1d4f625709aad36..0c4cd584676a1876b759f14c8a8adf72cdc0a3c2 100644 (file)
@@ -313,7 +313,7 @@ ppp_async_ioctl(struct tty_struct *tty, struct file *file,
        switch (cmd) {
        case PPPIOCGFLAGS:
                val = ap->flags | ap->rbits;
-               if (put_user(ap->flags, (int *) arg))
+               if (put_user(val, (int *) arg))
                        break;
                err = 0;
                break;
index 26839d47cb0a65dc2bc795c5c110d079f5342b1d..346830ec65414dc34ac392698f146f1a7af02615 100644 (file)
@@ -34,7 +34,6 @@
 
 static char version[] = "sb1000.c:v1.1.2 6/01/98 (fventuri@mediaone.net)\n";
 
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/version.h>
index cdee2d6e68863216b17eb1c89718ce8021402887..c112489584a067c88e58fda1f843b4a83d440f06 100644 (file)
@@ -71,7 +71,6 @@ History:
 #include <linux/version.h>
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/errno.h>
index eb5ff58f49bba34265f03d2049b730a3301d356e..d16940e031905972178f61392da8318d17c88780 100644 (file)
@@ -57,8 +57,6 @@ void __init pci_name_device(struct pci_dev *dev)
        int i = VENDORS;
        char *name = dev->name;
 
-       name += sprintf(name, "PCI<%02x:%02x.%d>", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-
        do {
                if (vendor_p->vendor == dev->vendor)
                        goto match_vendor;
@@ -66,7 +64,7 @@ void __init pci_name_device(struct pci_dev *dev)
        } while (--i);
 
        /* Couldn't find either the vendor nor the device */
-       sprintf(name, " %04x:%04x", dev->vendor, dev->device);
+       sprintf(name, "PCI device %04x:%04x", dev->vendor, dev->device);
        return;
 
        match_vendor: {
@@ -81,7 +79,7 @@ void __init pci_name_device(struct pci_dev *dev)
                }
 
                /* Ok, found the vendor, but unknown device */
-               sprintf(name, " %04x:%04x (%s)", dev->vendor, dev->device, vendor_p->name);
+               sprintf(name, " PCI device %04x:%04x (%s)", dev->vendor, dev->device, vendor_p->name);
                return;
 
                /* Full match */
index 25b78e15f3a5bc258059410642b48d8766fb8e9e..d8ab783b42133d246f4f067098269016d9a450ea 100644 (file)
@@ -274,11 +274,7 @@ static unsigned int __init pci_do_scan_bus(struct pci_bus *bus)
                dev_cache = NULL;
                dev->vendor = l & 0xffff;
                dev->device = (l >> 16) & 0xffff;
-#ifdef CONFIG_PCI_NO_NAMES
-               sprintf(dev->name, "pci:%02x:%02x.%d", bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
-#else
                pci_name_device(dev);
-#endif
 
                /* non-destructively determine if device can be a master: */
                pci_read_config_byte(dev, PCI_COMMAND, &cmd);
index 724d431a0311e2db514e5286709fe1bc269e2943..3ff88302e9469a330c6e1a19af55bdf63d00634f 100644 (file)
@@ -12,7 +12,6 @@
  *  use the PowerTweak utility (see http://linux.powertweak.com/).
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
index 762572e45d968de3376432496b32a4a7043ab3da..e5c36cd8893def600a3084f2caef8c23480068be 100644 (file)
 
 #define MEGARAID_VERSION "v1.04 (August 16, 1999)"
 
-#include <linux/config.h>
 #include <linux/version.h>
 
 #ifdef MODULE
index 452df756cf686edb6702898403b1c547a68e4fa8..4189dc37c2fa8924b05f4f067ed7e088a526ffbd 100644 (file)
@@ -59,7 +59,6 @@
 
 /*****************************************************************************/
       
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
index 664f38bdba98758b39383bbe1d77c8c9cf418889..ef2cf7f366ea3068a6e22273f1148c02a5d0b357 100644 (file)
  *     This happens in pcm_copy_{in,out}().
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/stddef.h>
 #include <asm/fixmap.h>
index 636eda6fbc820af3b4823b910dea5053498ff729..1df6112940233766229b797486fbaf10c2a9fede 100644 (file)
@@ -24,6 +24,8 @@ if [ ! "$CONFIG_USB" = "n" ]; then
        bool '  OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB
   fi
 
+  bool 'Enable lots of ISOC debugging output' CONFIG_USB_DEBUG_ISOC
+
   dep_tristate 'USB hub support' CONFIG_USB_HUB $CONFIG_USB
   dep_tristate 'USB mouse support' CONFIG_USB_MOUSE $CONFIG_USB
   dep_tristate 'USB keyboard support' CONFIG_USB_KBD $CONFIG_USB
index c65dd06471867426cfb15060263d06c2802df59b..f2a98c3b3c79c30c4c7d0189af8f16eeb9ee9cde 100644 (file)
@@ -18,14 +18,14 @@ L_OBJS   :=
 MOD_LIST_NAME := USB_MODULES
 
 ifeq ($(CONFIG_USB),y)
-  L_OBJS +=usbcore.o
+  L_OBJS += usbcore.o
   ifeq ($(CONFIG_USB_PROC),y)
     L_OBJS += proc_usb.o
   endif
 endif
 ifeq ($(CONFIG_USB),m)
-  M_OBJS +=usbcore.o
-  MIX_OBJS +=usb.o usb-debug.o usb-core.o
+  M_OBJS += usbcore.o
+  MIX_OBJS += usb.o usb-debug.o usb-core.o
   ifeq ($(CONFIG_USB_PROC),y)
     MIX_OBJS += proc_usb.o
   endif
@@ -60,16 +60,16 @@ ifeq ($(CONFIG_USB_MOUSE),y)
   L_OBJS += mouse.o
 endif
 ifeq ($(CONFIG_USB_MOUSE),m)
-  M_OBJS  +=mouse.o    
-  MIX_OBJS +=mouse.o
+  M_OBJS += mouse.o    
+  MIX_OBJS += mouse.o
 endif
 
 ifeq ($(CONFIG_USB_HUB),y)
   L_OBJS += hub.o
 endif
 ifeq ($(CONFIG_USB_HUB),m)
-  M_OBJS  +=hub.o
-  MIX_OBJS +=hub.o     
+  M_OBJS += hub.o
+  MIX_OBJS += hub.o    
 endif
 
 ifeq ($(CONFIG_USB_ACM),y)
@@ -77,7 +77,7 @@ ifeq ($(CONFIG_USB_ACM),y)
 endif
 ifeq ($(CONFIG_USB_ACM),m)
   M_OBJS += acm.o
-  MIX_OBJS +=acm.o
+  MIX_OBJS += acm.o
 endif
 
 ifeq ($(CONFIG_USB_PRINTER),y)
@@ -89,15 +89,6 @@ ifeq ($(CONFIG_USB_PRINTER),m)
   MIX_OBJS += printer.o  
 endif
 
-ifeq ($(CONFIG_USB_CPIA),y)
-  L_OBJS += cpia.o
-endif
-
-ifeq ($(CONFIG_USB_CPIA),m)
-  M_OBJS += cpia.o
-  MIX_OBJS += cpia.o  
-endif
-
 ifeq ($(CONFIG_USB_KBD),y)
   L_OBJS += keyboard.o keymap.o
 endif
index db61c2ea801c5a96f4f4767a4f444b724aa63de8..fb18b5cf95217050b98711ff5ede73a092cfbb03 100644 (file)
@@ -468,15 +468,15 @@ static void rs_unthrottle(struct tty_struct * tty)
                Set_Control_Line_Status (acm->ctrlstate | CTRL_STAT_RTS, acm);
 }
 
-static int get_free_acm()
+static int get_free_acm(void)
 {
- int i;
      int i;
  
- for (i=0;i<NR_PORTS;i++) {
-        if (!acm_state_table[i].present)
-                return i;
- }
- return -1;
      for (i=0;i<NR_PORTS;i++) {
+               if (!acm_state_table[i].present)
+                       return i;
      }
      return -1;
 }
 
 static int acm_probe(struct usb_device *dev)
@@ -500,10 +500,10 @@ static int acm_probe(struct usb_device *dev)
             dev->descriptor.bDeviceProtocol != 0)
                return -1;
 
-       /*Now scan all configs for a ACM configuration*/
+       /* Now scan all configs for a ACM configuration */
        for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
                /* The first one should be Communications interface? */
-               interface = &dev->config[cfgnum].altsetting[0].interface[0];
+               interface = &dev->config[cfgnum].interface[0].altsetting[0];
                if (interface->bInterfaceClass != 2 ||
                    interface->bInterfaceSubClass != 2 ||
                    interface->bInterfaceProtocol != 1 ||
@@ -517,7 +517,7 @@ static int acm_probe(struct usb_device *dev)
                        continue;
                        
                /* The second one should be a Data interface? */
-               interface = &dev->config[cfgnum].altsetting[0].interface[1];
+               interface = &dev->config[cfgnum].interface[1].altsetting[0];
                if (interface->bInterfaceClass != 10 ||
                    interface->bInterfaceSubClass != 0 ||
                    interface->bInterfaceProtocol != 0 ||
@@ -542,18 +542,18 @@ static int acm_probe(struct usb_device *dev)
                acm->dev=dev;
                dev->private=acm;
 
-               acm->readendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].bEndpointAddress;
+               acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0].bEndpointAddress;
                acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
-               acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[0].wMaxPacketSize,GFP_KERNEL);
+               acm->readbuffer=kmalloc(acm->readsize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0].wMaxPacketSize,GFP_KERNEL);
                acm->reading=0;
                if (!acm->readbuffer) {
                        printk("ACM: Couldn't allocate readbuffer\n");
                        return -1;
                }
                
-               acm->writeendp=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].bEndpointAddress;
+               acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1].bEndpointAddress;
                acm->writepipe=usb_sndbulkpipe(dev,acm->writeendp);
-               acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].altsetting[0].interface[1].endpoint[1].wMaxPacketSize, GFP_KERNEL);
+               acm->writebuffer=kmalloc(acm->writesize=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1].wMaxPacketSize, GFP_KERNEL);
                acm->writing=0;
                if (!acm->writebuffer) {
                        printk("ACM: Couldn't allocate writebuffer\n");
@@ -561,11 +561,11 @@ static int acm_probe(struct usb_device *dev)
                        return -1;
                }
                
-               acm->ctrlendp=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bEndpointAddress;
+               acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress;
                acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
-               acm->ctrlinterval=dev->config[cfgnum].altsetting[0].interface[0].endpoint[0].bInterval;
+               acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval;
 
-               acm->present=1;                         
+               acm->present=1;
                MOD_INC_USE_COUNT;
                return 0;
        }
@@ -699,4 +699,4 @@ void cleanup_module(void)
 {
        usb_acm_cleanup();
 }
-#endif
\ No newline at end of file
+#endif
index 704ec051f503c880134ac4e7186baa229a4c8a84..cba0e774fc44a405c2f46253273575ec8dfb5503 100644 (file)
@@ -15,6 +15,8 @@ static LIST_HEAD(usb_audio_list);
 struct usb_audio {
        struct usb_device *dev;
        struct list_head list;
+
+       void *irq_handle;
 };
 
 static struct usb_driver usb_audio_driver = {
@@ -25,42 +27,43 @@ static struct usb_driver usb_audio_driver = {
 };
 
 
+#if 0
 static int usb_audio_irq(int state, void *buffer, int len, void *dev_id)
 {
+#if 0
        struct usb_audio *aud = (struct usb_audio *)dev_id;
 
        printk("irq on %p\n", aud);
+#endif
 
        return 1;
 }
+#endif
 
 static int usb_audio_probe(struct usb_device *dev)
 {
-       struct usb_interface_descriptor *intf_desc;
-       struct usb_endpoint_descriptor *endpoint;
+       struct usb_interface_descriptor *interface;
        struct usb_audio *aud;
-       int bEndpointAddress = 0;
        int i;
        int na=0;
        
-
        for (i=0; i<dev->config[0].bNumInterfaces; i++) {
-               intf_desc = &dev->config->interface[i].altsetting[0];
+               interface = &dev->config->interface[i].altsetting[0];
 
-               if(intf_desc->bInterfaceClass != 1) 
+               if (interface->bInterfaceClass != 1) 
                        continue;
 
                printk(KERN_INFO "USB audio device detected.\n");
        
-               switch(intf_desc->bInterfaceSubClass) {
+               switch(interface->bInterfaceSubClass) {
                        case 0x01:
-                               printk(KERN_INFO "audio: Control device.\n");
+                               printk(KERN_INFO "audio: control device\n");
                                break;
                        case 0x02:
-                               printk(KERN_INFO "audio: streaming.\n");
+                               printk(KERN_INFO "audio: streaming\n");
                                break;
                        case 0x03:
-                               printk(KERN_INFO "audio: nonstreaming.\n");
+                               printk(KERN_INFO "audio: nonstreaming\n");
                                break;
                }
                na++;
@@ -70,44 +73,49 @@ static int usb_audio_probe(struct usb_device *dev)
                return -1;
 
        aud = kmalloc(sizeof(struct usb_audio), GFP_KERNEL);
-       if (aud) {
-               memset(aud, 0, sizeof(*aud));
-               aud->dev = dev;
-               dev->private = aud;
-
-//             if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-//                     printk (KERN_INFO " Failed usb_set_configuration: Audio\n");
-//                     break;
-//             }
-//             usb_set_protocol(dev, 0);
-//             usb_set_idle(dev, 0, 0);
-        
-//             usb_request_irq(dev,
-//                        usb_rcvctrlpipe(dev, bEndpointAddress),
-//                        usb_audio_irq,
-//                        endpoint->bInterval,
-//                        aud);
+       if (!aud)
+               return -1;
 
-               list_add(&aud->list, &usb_audio_list);
-               
-               return 0;
+               memset(aud, 0, sizeof(*aud));
+               aud->dev = dev;
+               dev->private = aud;
+
+/*
+       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+               printk (KERN_INFO "Failed usb_set_configuration: Audio\n");
+               break;
        }
-       
-       if (aud)
-               kfree (aud);
-       return -1;
+       usb_set_protocol(dev, 0);
+       usb_set_idle(dev, 0, 0);
+*/
+        
+/*
+       aud->irq_handle = usb_request_irq(dev,
+               usb_rcvctrlpipe(dev, endpoint->bEndpointAddress),
+               usb_audio_irq,
+               endpoint->bInterval,
+               aud);
+*/
+
+       list_add(&aud->list, &usb_audio_list);
+               
+       return 0;
 }
 
 static void usb_audio_disconnect(struct usb_device *dev)
 {
        struct usb_audio *aud = (struct usb_audio*) dev->private;
 
-       if (aud) {
-               dev->private = NULL;
-               list_del(&aud->list);
-               kfree(aud);
-       }
-       printk(KERN_INFO "USB audio driver removed.\n");
+       if (!aud)
+               return;
+
+               list_del(&aud->list);
+
+       usb_release_irq(aud->dev, aud->irq_handle);
+       aud->irq_handle = NULL;
+
+               kfree(aud);
+               dev->private = NULL;
 }
 
 int usb_audio_init(void)
index 9e7f0acd8c8d1b79917d01a5576b9e683df425a9..6c2ed4db94cdf67ab369f2fc8da6c3a8561fc46e 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * USB CPiA Video Camera driver
  *
- * Supports CPiA based Video Camera's. Many manufacturers use this chipset.
+ * Supports CPiA based Video Cameras. Many manufacturers use this chipset.
  * There's a good chance, if you have a USB video camera, it's a CPiA based
- * one
+ * one.
  *
  * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
  */
 
 #include <linux/kernel.h>
@@ -453,6 +454,31 @@ static void cpia_parse_data(struct usb_cpia *cpia)
        cpia->scratchlen = l;
 }
 
+/*
+ * For the moment there is no actual data compression (making blocks
+ * of data contiguous).  This just checks the "frames" array for errors.
+ */
+static int cpia_compress_isochronous(struct usb_isoc_desc *isodesc)
+{
+       char *data = isodesc->data;
+       int i, totlen = 0;
+
+       for (i = 0; i < isodesc->frame_count; i++) {
+               int n = isodesc->frames [i].frame_length;
+               int st = isodesc->frames [i].frame_status;
+
+#ifdef CPIA_DEBUG
+               /* Debugging */
+               if (st)
+                       printk(KERN_DEBUG "cpia data error: [%d] len=%d, status=%X\n",
+                               i, n, st);
+#endif
+
+       }
+
+       return totlen;
+}
+
 static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id)
 {
        struct usb_cpia *cpia = dev_id;
@@ -489,10 +515,10 @@ static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id)
 
        sbuf = &cpia->sbuf[cpia->receivesbuf];
 
-       usb_unschedule_isochronous(dev, sbuf->isodesc);
+       usb_kill_isoc(sbuf->isodesc);
 
        /* Do something to it now */
-       sbuf->len = usb_compress_isochronous(dev, sbuf->isodesc);
+       sbuf->len = cpia_compress_isochronous(sbuf->isodesc);
 
 #ifdef CPIA_DEBUG
        if (sbuf->len)
@@ -511,7 +537,12 @@ static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id)
        }
 
        /* Reschedule this block of Isochronous desc */
+       /*
+       usb_run_isoc(sbuf->isodesc, NULL);
+       */
+/*
        usb_schedule_isochronous(dev, sbuf->isodesc, cpia->sbuf[(cpia->receivesbuf + 2) % 3].isodesc);
+*/
 
        /* Move to the next one */
        cpia->receivesbuf = (cpia->receivesbuf + 1) % 3;
@@ -522,6 +553,8 @@ static int cpia_isoc_irq(int status, void *__buffer, int len, void *dev_id)
 int cpia_init_isoc(struct usb_cpia *cpia)
 {
        struct usb_device *dev = cpia->dev;
+       struct usb_isoc_desc *id;
+       int fx, err;
 
        cpia->receivesbuf = 0;
 
@@ -529,21 +562,66 @@ int cpia_init_isoc(struct usb_cpia *cpia)
        cpia->curline = 0;
        cpia->state = STATE_SCANNING;
 
-       /* Allocate all of the memory necessary */
+       /* ALT_ISOC is only doing double-buffering, not triple. */
+       err = usb_init_isoc (dev, usb_rcvisocpipe (dev, 1), FRAMES_PER_DESC, cpia,
+               &cpia->sbuf[0].isodesc);
+       if (err)
+               printk ("cpia_init_isoc: usb_init_isoc() ret. %d\n", err);
+       err = usb_init_isoc (dev, usb_rcvisocpipe (dev, 1), FRAMES_PER_DESC, cpia,
+               &cpia->sbuf[1].isodesc);
+       if (err)
+               printk ("cpia_init_isoc: usb_init_isoc() ret. %d\n", err);
+
+       if (!cpia->sbuf[0].isodesc || !cpia->sbuf[1].isodesc) {
+               if (cpia->sbuf[0].isodesc)
+                       usb_free_isoc (cpia->sbuf[0].isodesc);
+               if (cpia->sbuf[1].isodesc)
+                       usb_free_isoc (cpia->sbuf[1].isodesc);
+               return -ENOMEM;
+       }
+#if 0
        cpia->sbuf[0].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[0].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
        cpia->sbuf[1].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
        cpia->sbuf[2].isodesc = usb_allocate_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
+#endif
 
 #ifdef CPIA_DEBUG
        printk("isodesc[0] @ %p\n", cpia->sbuf[0].isodesc);
        printk("isodesc[1] @ %p\n", cpia->sbuf[1].isodesc);
+#if 0
        printk("isodesc[2] @ %p\n", cpia->sbuf[2].isodesc);
+#endif
 #endif
 
-       /* Schedule the queues */
+       /* Set the Isoc. desc. parameters. */
+       /* First for desc. [0] */
+       id = cpia->sbuf [0].isodesc;
+       id->start_type = START_ASAP;
+       id->callback_frames = 1;        /* on every frame */
+       id->callback_fn = cpia_isoc_irq;
+       id->data = cpia->sbuf [0].data;
+       id->buf_size = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
+       for (fx = 0; fx < FRAMES_PER_DESC; fx++)
+               id->frames [fx].frame_length = FRAME_SIZE_PER_DESC;
+
+       /* and the desc. [1] */
+       id = cpia->sbuf [1].isodesc;
+       id->start_type = 0;             /* will follow the first desc. */
+       id->callback_frames = 1;        /* on every frame */
+       id->callback_fn = cpia_isoc_irq;
+       id->data = cpia->sbuf [1].data;
+       id->buf_size = FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
+       for (fx = 0; fx < FRAMES_PER_DESC; fx++)
+               id->frames [fx].frame_length = FRAME_SIZE_PER_DESC;
+
+       usb_run_isoc (cpia->sbuf [0].isodesc, NULL);
+       usb_run_isoc (cpia->sbuf [1].isodesc, cpia->sbuf [0].isodesc);
+
+#if 0
        usb_schedule_isochronous(dev, cpia->sbuf[0].isodesc, NULL);
        usb_schedule_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc);
        usb_schedule_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc);
+#endif
 
 #ifdef CPIA_DEBUG
        printk("done scheduling\n");
@@ -582,19 +660,28 @@ void cpia_stop_isoc(struct usb_cpia *cpia)
        }
 
        /* Unschedule all of the iso td's */
+       usb_kill_isoc (cpia->sbuf[1].isodesc);
+       usb_kill_isoc (cpia->sbuf[0].isodesc);
+#if 0
        usb_unschedule_isochronous(dev, cpia->sbuf[2].isodesc);
        usb_unschedule_isochronous(dev, cpia->sbuf[1].isodesc);
        usb_unschedule_isochronous(dev, cpia->sbuf[0].isodesc);
+#endif
 
        /* Delete them all */
+       usb_free_isoc (cpia->sbuf[1].isodesc);
+       usb_free_isoc (cpia->sbuf[0].isodesc);
+#if 0
        usb_delete_isochronous(dev, cpia->sbuf[2].isodesc);
        usb_delete_isochronous(dev, cpia->sbuf[1].isodesc);
        usb_delete_isochronous(dev, cpia->sbuf[0].isodesc);
+#endif
 }
 
 /* Video 4 Linux API */
 static int cpia_open(struct video_device *dev, int flags)
 {
+       int err = -ENOMEM;
        struct usb_cpia *cpia = (struct usb_cpia *)dev;
 
 #ifdef CPIA_DEBUG
@@ -615,6 +702,15 @@ static int cpia_open(struct video_device *dev, int flags)
        printk("frame [1] @ %p\n", cpia->frame[1].data);
 #endif
 
+       cpia->sbuf[0].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+       if (!cpia->sbuf[0].data)
+               goto open_err_on0;
+
+       cpia->sbuf[1].data = kmalloc (FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+       if (!cpia->sbuf[1].data)
+               goto open_err_on1;
+
+#if 0
        cpia->sbuf[0].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
        if (!cpia->sbuf[0].data)
                goto open_err_on0;
@@ -626,11 +722,14 @@ static int cpia_open(struct video_device *dev, int flags)
        cpia->sbuf[2].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
        if (!cpia->sbuf[2].data)
                goto open_err_on2;
+#endif
 
 #ifdef CPIA_DEBUG
        printk("sbuf[0] @ %p\n", cpia->sbuf[0].data);
        printk("sbuf[1] @ %p\n", cpia->sbuf[1].data);
+#if 0
        printk("sbuf[2] @ %p\n", cpia->sbuf[2].data);
+#endif
 #endif
 
        cpia->curframe = -1;
@@ -638,7 +737,9 @@ static int cpia_open(struct video_device *dev, int flags)
 
        usb_cpia_initstreamcap(cpia->dev, 0, 60);
 
-       cpia_init_isoc(cpia);
+       err = cpia_init_isoc(cpia);
+       if (err)
+               goto open_err_on2;
 
        return 0;
 
@@ -649,7 +750,7 @@ open_err_on1:
 open_err_on0:
        rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE);
 open_err_ret:
-       return -ENOMEM;
+       return err;
 }
 
 static void cpia_close(struct video_device *dev)
index 51ff43e7940433d9e1a4527c1d2ddb753bf001c8..6fb9143098727212529431763d76b101591917ca 100644 (file)
@@ -82,6 +82,9 @@
 
 #define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
 
+#define FRAMES_PER_DESC                500
+#define FRAME_SIZE_PER_DESC    960     /* Shouldn't be hardcoded */
+
 enum {
        STATE_SCANNING,         /* Scanning for start */
        STATE_HEADER,           /* Parsing header */
@@ -93,7 +96,10 @@ struct usb_device;
 struct cpia_sbuf {
        char *data;
        int len;
+       struct usb_isoc_desc *isodesc;
+#if 0
        void *isodesc;
+#endif
 };
 
 enum {
index 4df629732a45a87ebed3fb0a03ac80c3bf52b935..e98423d09a875b0dd0abd8fe026ffeb7b2cf7b1a 100644 (file)
@@ -31,7 +31,6 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <asm/uaccess.h>
@@ -68,9 +67,9 @@ struct isodesc {
        void *hcbuf[2];
        void *hcisodesc[2];
        unsigned char *buf;
-};     
+};     
 
-#define ISOFLG_ACTIVE  (1<<0)
+#define ISOFLG_ACTIVE  (1<<0)
 
 /* --------------------------------------------------------------------- */
 
@@ -231,7 +230,7 @@ static void iso_schedrcv(struct isodesc *isodesc)
        unsigned diff;
 
        if (!(isodesc->flags & ISOFLG_ACTIVE))
-           return;
+               return;
        diff = (isodesc->buflen - 1 + isodesc->rd - isodesc->wr) % isodesc->buflen;
        if (diff < isodesc->framesperint * isodesc->pktsz)
                return;
@@ -249,9 +248,9 @@ static void iso_schedsnd(struct isodesc *isodesc)
 {
        unsigned diff, bcnt, x;
        unsigned char *p1, *p2;
-       
+
        if (!(isodesc->flags & ISOFLG_ACTIVE))
-           return;
+               return;
        for (;;) {
                diff = (isodesc->schedcnt - isodesc->unschedcnt) & 3;
                if (diff >= 2)
@@ -646,7 +645,7 @@ static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                else
                        iso_schedsnd(isodesc);
                spin_unlock_irqrestore(&isodesc->lock, flags);
-                               up(&ez->mutex);
+               up(&ez->mutex);
                return 0;
        }
        return -ENOIOCTLCMD;
index 0ba383e249ff7ad5cf62cb78cec3f6424b6c12eb..44c57ba9dcef189ece946c9dc3076297d094413a 100644 (file)
@@ -76,11 +76,12 @@ struct ezusb_isodata {
        void *data;
 };
 
-#define EZUSB_STARTISO       _IOR('E', 8, struct ezusb_isotransfer)
-#define EZUSB_STOPISO        _IOR('E', 9, unsigned int)
-#define EZUSB_ISODATA        _IOWR('E', 10, struct ezusb_isodata)
-#define EZUSB_PAUSEISO       _IOR('E', 11, unsigned int)
-#define EZUSB_RESUMEISO      _IOR('E', 12, unsigned int)
+#define EZUSB_STARTISO         _IOR('E', 8, struct ezusb_isotransfer)
+#define EZUSB_STOPISO          _IOR('E', 9, unsigned int)
+#define EZUSB_ISODATA          _IOWR('E', 10, struct ezusb_isodata)
+#define EZUSB_PAUSEISO         _IOR('E', 11, unsigned int)
+#define EZUSB_RESUMEISO                _IOR('E', 12, unsigned int)
 
 /* --------------------------------------------------------------------- */
 #endif /* _LINUX_EZUSB_H */
+
index 072d769014b9236572a25ff97f7495d9cfceada4..19f2fcfd3d6bf23f0d468eceb2cfa5859de67dcb 100644 (file)
@@ -32,72 +32,35 @@ static int khubd_running = 0;
 
 static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
 {
-       devrequest dr;
-
-       dr.requesttype = USB_DIR_IN | USB_RT_HUB;
-       dr.request = USB_REQ_GET_DESCRIPTOR;
-       dr.value = (USB_DT_HUB << 8);
-       dr.index = 0;
-       dr.length = size;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
-               data, size);
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+               USB_DT_HUB << 8, 0, data, size);
 }
 
 static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
 {
-       devrequest dr;
-
-       dr.requesttype = USB_RT_PORT;
-       dr.request = USB_REQ_CLEAR_FEATURE;
-       dr.value = feature;
-       dr.index = port;
-       dr.length = 0;
-
-       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr,
-               NULL, 0);
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0);
 }
 
 static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
 {
-       devrequest dr;
-
-       dr.requesttype = USB_RT_PORT;
-       dr.request = USB_REQ_SET_FEATURE;
-       dr.value = feature;
-       dr.index = port;
-       dr.length = 0;
-
-       return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr,
-               NULL, 0);
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0);
 }
 
 static int usb_get_hub_status(struct usb_device *dev, void *data)
 {
-       devrequest dr;
-
-       dr.requesttype = USB_DIR_IN | USB_RT_HUB;
-       dr.request = USB_REQ_GET_STATUS;
-       dr.value = 0;
-       dr.index = 0;
-       dr.length = 4;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
-               data, 4);
+       /* FIXME: Don't hardcode 4 */
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, 4);
 }
 
 static int usb_get_port_status(struct usb_device *dev, int port, void *data)
 {
-       devrequest dr;
-
-       dr.requesttype = USB_DIR_IN | USB_RT_PORT;
-       dr.request = USB_REQ_GET_STATUS;
-       dr.value = 0;
-       dr.index = port;
-       dr.length = 4;
-
-       return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
-               data, 4);
+       /* FIXME: Don't hardcode 4 */
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, 4);
 }
 
 /*
@@ -110,37 +73,58 @@ static int hub_irq(int status, void *__buffer, int len, void *dev_id)
        struct usb_hub *hub = dev_id;
        unsigned long flags;
 
-       if (waitqueue_active(&khubd_wait)) {
-               /* Add the hub to the event queue */
-               spin_lock_irqsave(&hub_event_lock, flags);
-               if (hub->event_list.next == &hub->event_list) {
-                       list_add(&hub->event_list, &hub_event_list);
-                       /* Wake up khubd */
-                       wake_up(&khubd_wait);
+       switch (status) {
+       case USB_ST_REMOVED:
+               /* Just ignore it */
+               break;
+       case USB_ST_NOERROR:
+               /* Something happened, let khubd figure it out */
+               if (waitqueue_active(&khubd_wait)) {
+                       /* Add the hub to the event queue */
+                       spin_lock_irqsave(&hub_event_lock, flags);
+                       if (hub->event_list.next == &hub->event_list) {
+                               list_add(&hub->event_list, &hub_event_list);
+                               /* Wake up khubd */
+                               wake_up(&khubd_wait);
+                       }
+                       spin_unlock_irqrestore(&hub_event_lock, flags);
                }
-               spin_unlock_irqrestore(&hub_event_lock, flags);
+               break;
        }
 
        return 1;
 }
 
-static void usb_hub_configure(struct usb_hub *hub)
+static int usb_hub_configure(struct usb_hub *hub)
 {
        struct usb_device *dev = hub->dev;
-       unsigned char hubdescriptor[8], buf[4];
-       int charac, i;
+       unsigned char buffer[4], *bitmap;
+       struct usb_hub_descriptor *descriptor;
+       struct usb_descriptor_header *header;
+       int i;
 
+       /* Set it to the first configuration */
        usb_set_configuration(dev, dev->config[0].bConfigurationValue);
 
-       if (usb_get_hub_descriptor(dev, hubdescriptor, 8))
-               return;
+       /* Get the length first */
+       if (usb_get_hub_descriptor(dev, buffer, 4))
+               return -1;
 
-       hub->nports = dev->maxchild = hubdescriptor[2];
+       header = (struct usb_descriptor_header *)buffer;
+       bitmap = kmalloc(header->bLength, GFP_KERNEL);
+       if (!bitmap)
+               return -1;
+
+       if (usb_get_hub_descriptor(dev, bitmap, header->bLength))
+               return -1;
+
+       descriptor = (struct usb_hub_descriptor *)bitmap;
+
+       hub->nports = dev->maxchild = descriptor->bNbrPorts;
        printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports,
                (hub->nports == 1) ? "" : "s");
 
-       charac = (hubdescriptor[4] << 8) + hubdescriptor[3];
-       switch (charac & HUB_CHAR_LPSM) {
+       switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
                case 0x00:
                        printk(KERN_INFO "hub: ganged power switching\n");
                        break;
@@ -153,12 +137,12 @@ static void usb_hub_configure(struct usb_hub *hub)
                        break;
        }
 
-       if (charac & HUB_CHAR_COMPOUND)
+       if (descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
                printk(KERN_INFO "hub: part of a compound device\n");
        else
                printk(KERN_INFO "hub: standalone hub\n");
 
-       switch (charac & HUB_CHAR_OCPM) {
+       switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
                case 0x00:
                        printk(KERN_INFO "hub: global over current protection\n");
                        break;
@@ -172,34 +156,38 @@ static void usb_hub_configure(struct usb_hub *hub)
        }
 
        printk(KERN_INFO "hub: power on to power good time: %dms\n",
-               hubdescriptor[5] * 2);
+               descriptor->bPwrOn2PwrGood * 2);
 
        printk(KERN_INFO "hub: hub controller current requirement: %dmA\n",
-               hubdescriptor[6]);
+               descriptor->bHubContrCurrent);
 
        for (i = 0; i < dev->maxchild; i++)
                printk(KERN_INFO "hub:  port %d is%s removable\n", i + 1,
-                       hubdescriptor[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8))
+                       bitmap[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8))
                        ? " not" : "");
 
-       if (usb_get_hub_status(dev, buf))
-               return;
+       kfree(bitmap);
+
+       if (usb_get_hub_status(dev, buffer))
+               return -1;
 
        printk(KERN_INFO "hub: local power source is %s\n",
-               (buf[0] & 1) ? "lost (inactive)" : "good");
+               (buffer[0] & 1) ? "lost (inactive)" : "good");
 
        printk(KERN_INFO "hub: %sover current condition exists\n",
-               (buf[0] & 2) ? "" : "no ");
+               (buffer[0] & 2) ? "" : "no ");
 
        /* Enable power to the ports */
        printk(KERN_INFO "hub: enabling power on all ports\n");
        for (i = 0; i < hub->nports; i++)
                usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
+
+       return 0;
 }
 
 static int hub_probe(struct usb_device *dev)
 {
-       struct usb_interface_descriptor *intf_desc;
+       struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
        struct usb_hub *hub;
        unsigned long flags;
@@ -212,20 +200,23 @@ static int hub_probe(struct usb_device *dev)
        if (dev->config[0].bNumInterfaces != 1)
                return -1;
 
-       intf_desc = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->config[0].interface[0].altsetting[0];
 
        /* Is it a hub? */
-       if (intf_desc->bInterfaceClass != 9)
+       if (interface->bInterfaceClass != USB_CLASS_HUB)
                return -1;
-       if ((intf_desc->bInterfaceSubClass != 0) &&
-           (intf_desc->bInterfaceSubClass != 1))
+
+       /* Some hubs have a subclass of 1, which AFAICT according to the */
+       /*  specs is not defined, but it works */
+       if ((interface->bInterfaceSubClass != 0) &&
+           (interface->bInterfaceSubClass != 1))
                return -1;
 
        /* Multiple endpoints? What kind of mutant ninja-hub is this? */
-       if (intf_desc->bNumEndpoints != 1)
+       if (interface->bNumEndpoints != 1)
                return -1;
 
-       endpoint = &intf_desc->endpoint[0];
+       endpoint = &interface->endpoint[0];
 
        /* Output endpoint? Curiousier and curiousier.. */
        if (!(endpoint->bEndpointAddress & USB_DIR_IN))
@@ -256,13 +247,13 @@ static int hub_probe(struct usb_device *dev)
        list_add(&hub->hub_list, &hub_list);
        spin_unlock_irqrestore(&hub_list_lock, flags);
 
-       usb_hub_configure(hub);
-
-       hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev,
-               endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
+       if (usb_hub_configure(hub) >= 0) {
+               hub->irq_handle = usb_request_irq(dev, usb_rcvctrlpipe(dev,
+                       endpoint->bEndpointAddress), hub_irq, endpoint->bInterval, hub);
 
-       /* Wake up khubd */
-       wake_up(&khubd_wait);
+               /* Wake up khubd */
+               wake_up(&khubd_wait);
+       }
 
        return 0;
 }
@@ -282,8 +273,10 @@ static void hub_disconnect(struct usb_device *dev)
 
        spin_unlock_irqrestore(&hub_event_lock, flags);
 
-       usb_release_irq(hub->dev, hub->irq_handle);
-       hub->irq_handle = NULL;
+       if (hub->irq_handle) {
+               usb_release_irq(hub->dev, hub->irq_handle);
+               hub->irq_handle = NULL;
+       }
 
        /* Free the memory */
        kfree(hub);
@@ -319,7 +312,7 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
                return;
 
        /* Allocate a new device struct for it */
-       usb = hub->bus->op->allocate(hub);
+       usb = usb_alloc_dev(hub, hub->bus);
        if (!usb) {
                printk(KERN_ERR "couldn't allocate usb_device\n");
                return;
@@ -335,36 +328,47 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
        /* Run it through the hoops (find a driver, etc) */
        if (usb_new_device(usb)) {
                /* Woops, disable the port */
-               printk(KERN_DEBUG "hub: disabling malfunctioning port %d\n",
+               printk(KERN_DEBUG "hub: disabling port %d\n",
                        port + 1);
                usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
-               usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_POWER);
        }
 }
 
 static void usb_hub_events(void)
 {
        unsigned long flags;
-       unsigned char buf[4];
-       unsigned short portstatus, portchange;
        int i;
-       struct list_head *next, *tmp, *head = &hub_event_list;
+       struct list_head *tmp;
        struct usb_device *dev;
        struct usb_hub *hub;
 
-       spin_lock_irqsave(&hub_event_lock, flags);
+       /*
+        *  We restart the list everytime to avoid a deadlock with
+        * deleting hubs downstream from this one. This should be
+        * safe since we delete the hub from the event list.
+        * Not the most efficient, but avoids deadlocks.
+        */
+       while (1) {
+               spin_lock_irqsave(&hub_event_lock, flags);
+
+               if (list_empty(&hub_event_list))
+                       goto he_unlock;
+
+               /* Grab the next entry from the beginning of the list */
+               tmp = hub_event_list.next;
 
-       tmp = head->next;
-       while (tmp != head) {
                hub = list_entry(tmp, struct usb_hub, event_list);
                dev = hub->dev;
 
-               next = tmp->next;
-
                list_del(tmp);
                INIT_LIST_HEAD(tmp);
 
+               spin_unlock_irqrestore(&hub_event_lock, flags);
+
                for (i = 0; i < hub->nports; i++) {
+                       unsigned char buf[4];
+                       unsigned short portstatus, portchange;
+
                        if (usb_get_port_status(dev, i + 1, buf)) {
                                printk(KERN_ERR "get_port_status failed\n");
                                continue;
@@ -406,9 +410,9 @@ static void usb_hub_events(void)
                        }
 
                }
-               tmp = next;
         }
 
+he_unlock:
        spin_unlock_irqrestore(&hub_event_lock, flags);
 }
 
@@ -464,7 +468,6 @@ int usb_hub_init(void)
        int pid;
 
        usb_register(&hub_driver);
-       printk(KERN_INFO "USB hub driver registered\n");
 
        pid = kernel_thread(usb_hub_thread, NULL,
                CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
@@ -482,15 +485,13 @@ int usb_hub_init(void)
 
 void usb_hub_cleanup(void)
 {
-       struct list_head *next, *tmp, *head = &hub_list;
-       struct usb_hub *hub;
-       unsigned long flags, flags2;
        int ret;
 
        /* Kill the thread */
        ret = kill_proc(khubd_pid, SIGTERM, 1);
        if (!ret) {
-               int count = 10;
+               /* Wait 10 seconds */
+               int count = 10 * 100;
 
                while (khubd_running && --count) {
                        current->state = TASK_INTERRUPTIBLE;
index 62f4c0ef93d2fa5888c412ac59c324aae9169031..a4c40769d3e43d4051558b88808ee7f59ce726c1 100644 (file)
 #define HUB_CHAR_COMPOUND      0x0004
 #define HUB_CHAR_OCPM          0x0018
 
+/* Hub descriptor */
+struct usb_hub_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bNbrPorts;
+       __u16 wHubCharacteristics;
+#if 0
+       __u8  wHubCharacteristics[2];   /* __u16 but not aligned! */
+#endif
+       __u8  bPwrOn2PwrGood;
+       __u8  bHubContrCurrent;
+       /* DeviceRemovable and PortPwrCtrlMask want to be variable-length 
+          bitmaps that hold max 256 entries, but for now they're ignored */
+#if 0
+       __u8  filler;
+#endif
+} __attribute__ ((packed));
+
 struct usb_device;
 
 typedef enum {
@@ -69,7 +87,7 @@ struct usb_hub {
        struct usb_device *dev;
 
        /* Reference to the hub's polling IRQ */
-       voidirq_handle;
+       void *irq_handle;
 
        /* List of hubs */
        struct list_head hub_list;
index 60d454048282a594b41c92720e23c9b3b55f235f..f46c3ab64c5de793c5795b080b58367f855e51fd 100644 (file)
@@ -256,7 +256,7 @@ static struct miscdevice usb_mouse = {
 
 static int mouse_probe(struct usb_device *dev)
 {
-       struct usb_interface_descriptor *intf_desc;
+       struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
        struct mouse_state *mouse = &static_mouse_state;
 
@@ -269,19 +269,19 @@ static int mouse_probe(struct usb_device *dev)
                return -1;
 
        /* Is it a mouse interface? */
-       intf_desc = &dev->config[0].interface[0].altsetting[0];
-       if (intf_desc->bInterfaceClass != 3)
+       interface = &dev->config[0].interface[0].altsetting[0];
+       if (interface->bInterfaceClass != 3)
                return -1;
-       if (intf_desc->bInterfaceSubClass != 1)
+       if (interface->bInterfaceSubClass != 1)
                return -1;
-       if (intf_desc->bInterfaceProtocol != 2)
+       if (interface->bInterfaceProtocol != 2)
                return -1;
 
        /* Multiple endpoints? What kind of mutant ninja-mouse is this? */
-       if (intf_desc->bNumEndpoints != 1)
+       if (interface->bNumEndpoints != 1)
                return -1;
 
-       endpoint = &intf_desc->endpoint[0];
+       endpoint = &interface->endpoint[0];
 
        /* Output endpoint? Curiousier and curiousier.. */
        if (!(endpoint->bEndpointAddress & 0x80))
index 6a7cc53b1997a56b66e3f10671a3470eda10b650..b82131568324885a1af78f72c37ae945037b3e0b 100644 (file)
@@ -161,7 +161,7 @@ static ssize_t write_printer(struct file * file,
        unsigned long copy_size;
        unsigned long bytes_written = 0;
        unsigned long partial;
-       int result;
+       int result = USB_ST_NOERROR;
        int maxretry;
 
        do {
index 565fb3923b7d61f97f1d8bb791f8db0489e2af25..9c406fa3ef563d560ab85d241547022f5a4acba0 100644 (file)
@@ -213,7 +213,7 @@ static int usb_dump_config (const struct usb_config_descriptor *config,
                                const int active, char *buf, int *len)
 {
        int i, j;
-       struct usb_interface *intf;
+       struct usb_interface *interface;
 
        if (!config) {          /* getting these some in 2.3.7; none in 2.3.6 */
                *len += sprintf (buf + *len, "(null Cfg. desc.)\n");
@@ -224,12 +224,12 @@ static int usb_dump_config (const struct usb_config_descriptor *config,
                return -1;
 
        for (i = 0; i < config->bNumInterfaces; i++) {
-               intf = config->interface + i;
-               if ((intf) == NULL)
+               interface = config->interface + i;
+               if (!interface)
                        break;
 
-               for (j = 0; j < intf->num_altsetting; j++)
-                       if (usb_dump_interface (intf->altsetting + j, buf, len) < 0)
+               for (j = 0; j < interface->num_altsetting; j++)
+                       if (usb_dump_interface (interface->altsetting + j, buf, len) < 0)
                                return -1;
        }
 
@@ -433,6 +433,250 @@ static int usb_driver_list_dump (char *buf, char **start, off_t offset,
        return (len);
 }
 
+/*
+ * proc entry for every device
+ * sailer@ife.ee.ethz.ch
+ */
+#include <linux/bitops.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
+#include "ezusb.h"
+
+static long long usbdev_lseek(struct file * file, long long offset, int orig)
+{
+       switch (orig) {
+       case 0:
+               file->f_pos = offset;
+               return file->f_pos;
+
+       case 1:
+               file->f_pos += offset;
+               return file->f_pos;
+
+       case 2:
+               return -EINVAL;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static ssize_t usbdev_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
+{
+        struct inode *inode = file->f_dentry->d_inode;
+       struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
+       struct usb_device *dev = (struct usb_device *)dp->data;
+       ssize_t ret = 0;
+       unsigned len;
+
+       if (*ppos < 0)
+               return -EINVAL;
+       if (*ppos < sizeof(struct usb_device_descriptor)) {
+               len = sizeof(struct usb_device_descriptor);
+               if (len > nbytes)
+                       len = nbytes;
+               copy_to_user_ret(buf, ((char *)&dev->descriptor) + *ppos, len, -EFAULT);
+               *ppos += len;
+               buf += len;
+               nbytes -= len;
+               ret += len;
+       }
+       return ret;
+}
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
+       struct usb_device *dev = (struct usb_device *)dp->data;
+       struct ezusb_ctrltransfer ctrl;
+       struct ezusb_bulktransfer bulk;
+       struct ezusb_setinterface setintf;
+       unsigned int len1, ep, pipe;
+       unsigned long len2;
+       unsigned char *tbuf;
+       int i;
+
+       switch (cmd) {
+       case EZUSB_CONTROL:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+               if (ctrl.dlen > PAGE_SIZE)
+                       return -EINVAL;
+               if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+                       return -ENOMEM;
+               if (ctrl.requesttype & 0x80) {
+                       if (ctrl.dlen && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.dlen)) {
+                               free_page((unsigned long)tbuf);
+                               return -EINVAL;
+                       }
+                       i = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&ctrl, tbuf, ctrl.dlen);
+                       if (!i && ctrl.dlen) {
+                               copy_to_user_ret(ctrl.data, tbuf, ctrl.dlen, -EFAULT);
+                       }
+               } else {
+                       if (ctrl.dlen) {
+                               copy_from_user_ret(tbuf, ctrl.data, ctrl.dlen, -EFAULT);
+                       }
+                       i = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&ctrl, tbuf, ctrl.dlen);
+               }
+               free_page((unsigned long)tbuf);
+               if (i) {
+                       printk(KERN_WARNING "procusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n", 
+                              ctrl.requesttype, ctrl.request, ctrl.length, i);
+                       return -ENXIO;
+               }
+               return 0;
+
+       case EZUSB_BULK:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+               if (bulk.ep & 0x80)
+                       pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+               else
+                       pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+               if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
+                       return -EINVAL;
+               len1 = bulk.len;
+               if (len1 > PAGE_SIZE)
+                       len1 = PAGE_SIZE;
+               if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+                       return -ENOMEM;
+               if (bulk.ep & 0x80) {
+                       if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+                               free_page((unsigned long)tbuf);
+                               return -EINVAL;
+                       }
+                       i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+                       if (!i && len2) {
+                               copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+                       }
+               } else {
+                       if (len1) {
+                               copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+                       }
+                       i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+               }
+               free_page((unsigned long)tbuf);
+               if (i) {
+                       printk(KERN_WARNING "procusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n", 
+                              bulk.ep, bulk.len, i);
+                       return -ENXIO;
+               }
+               return len2;
+
+       case EZUSB_RESETEP:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+               if ((ep & ~0x80) >= 16)
+                       return -EINVAL;
+               usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
+               return 0;
+
+       case EZUSB_SETINTERFACE:
+               if (!capable(CAP_SYS_RAWIO))
+                       return -EPERM;
+               copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
+               if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
+                       return -EINVAL;
+               return 0;
+       }
+       return -ENOIOCTLCMD;
+}
+
+static struct file_operations proc_usb_device_file_operations = {
+       usbdev_lseek,    /* lseek   */
+       usbdev_read,     /* read    */
+       NULL,            /* write   */
+       NULL,            /* readdir */
+       NULL,            /* poll    */
+       usbdev_ioctl,    /* ioctl   */
+       NULL,            /* mmap    */
+       NULL,            /* no special open code    */
+       NULL,            /* flush */
+       NULL,            /* no special release code */
+       NULL             /* can't fsync */
+};
+
+static struct inode_operations proc_usb_device_inode_operations = {
+        &proc_usb_device_file_operations,  /* file-ops */
+        NULL,                              /* create       */
+        NULL,                              /* lookup       */
+        NULL,                              /* link         */
+        NULL,                              /* unlink       */
+        NULL,                              /* symlink      */
+        NULL,                              /* mkdir        */
+        NULL,                              /* rmdir        */
+        NULL,                              /* mknod        */
+        NULL,                              /* rename       */
+        NULL,                              /* readlink     */
+        NULL,                              /* follow_link  */
+        NULL,                              /* get_block    */
+        NULL,                              /* readpage     */
+        NULL,                              /* writepage    */
+        NULL,                              /* flushpage    */
+        NULL,                              /* truncate     */
+        NULL,                              /* permission   */
+        NULL,                              /* smap         */
+        NULL                               /* revalidate   */
+};
+
+#define PROCUSB_MAXBUSSES 64
+
+static unsigned long busnumbermap[(PROCUSB_MAXBUSSES+8 * sizeof(unsigned long)-1) / (8 * sizeof(unsigned long))] = { 0, };
+
+void proc_usb_add_bus(struct usb_bus *bus)
+{
+       int bnum;
+       char buf[16];
+
+       bus->proc_busnum = -1;
+       bus->proc_entry = NULL;
+       if (!usbdir)
+               return;
+       bnum = find_first_zero_bit(busnumbermap, PROCUSB_MAXBUSSES);
+       if (bnum >= PROCUSB_MAXBUSSES)
+               return;
+       sprintf(buf, "%03d", bnum);
+       if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))
+               return;
+       set_bit(bnum, busnumbermap);
+       bus->proc_busnum = bnum;
+       bus->proc_entry->data = bus;
+}
+
+/* devices need already be removed! */
+void proc_usb_remove_bus(struct usb_bus *bus)
+{
+       if (!bus->proc_entry)
+               return;
+       remove_proc_entry(bus->proc_entry->name, usbdir);
+       clear_bit(bus->proc_busnum, busnumbermap);
+}
+
+void proc_usb_add_device(struct usb_device *dev)
+{
+       char buf[16];
+
+       dev->proc_entry = NULL;
+       if (!dev->bus->proc_entry)
+               return;
+       sprintf(buf, "%03d", dev->devnum);
+       if (!(dev->proc_entry = create_proc_entry(buf, 0, dev->bus->proc_entry)))
+               return;
+       dev->proc_entry->ops = &proc_usb_device_inode_operations;
+       dev->proc_entry->data = dev;
+}
+
+void proc_usb_remove_device(struct usb_device *dev)
+{
+       if (dev->proc_entry)
+               remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry);
+}
+
+
 void proc_usb_cleanup (void)
 {
        if (driversdir)
index b081842be3e9eb914aea0f2006b7f11aa94026ac..39c326fedf8cb807850aba97e41fe48754eeeab7 100644 (file)
@@ -2,7 +2,11 @@
  * UHCI-specific debugging code. Invaluable when something
  * goes wrong, but don't get in my face.
  *
+ * Kernel visible pointers are surrounded in []'s and bus
+ * visible pointers are surrounded in ()'s
+ *
  * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999 Johannes Erdfelt
  */
 
 #include <linux/kernel.h>
 
 #include "uhci.h"
 
-void show_td(struct uhci_td * td)
+void uhci_show_td(struct uhci_td * td)
 {
        char *spid;
 
        printk("%08x ", td->link);
-       printk("%se%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
-               ((td->status >> 29) & 1) ? "SPD " : "",
+       printk("e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
                ((td->status >> 27) & 3),
-               ((td->status >> 26) & 1) ? "LS " : "",
-               ((td->status >> 25) & 1) ? "IOS " : "",
-               ((td->status >> 24) & 1) ? "IOC " : "",
-               ((td->status >> 23) & 1) ? "Active " : "",
-               ((td->status >> 22) & 1) ? "Stalled " : "",
-               ((td->status >> 21) & 1) ? "DataBufErr " : "",
-               ((td->status >> 20) & 1) ? "Babble " : "",
-               ((td->status >> 19) & 1) ? "NAK " : "",
-               ((td->status >> 18) & 1) ? "CRC/Timeo " : "",
-               ((td->status >> 17) & 1) ? "BitStuff " : "",
+               (td->status & TD_CTRL_SPD) ?      "SPD " : "",
+               (td->status & TD_CTRL_LS) ?       "LS " : "",
+               (td->status & TD_CTRL_IOC) ?      "IOC " : "",
+               (td->status & TD_CTRL_ACTIVE) ?   "Active " : "",
+               (td->status & TD_CTRL_STALLED) ?  "Stalled " : "",
+               (td->status & TD_CTRL_DBUFERR) ?  "DataBufErr " : "",
+               (td->status & TD_CTRL_BABBLE) ?   "Babble " : "",
+               (td->status & TD_CTRL_NAK) ?      "NAK " : "",
+               (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+               (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
                td->status & 0x7ff);
+
        switch (td->info & 0xff) {
-       case 0x2d:
-               spid = "SETUP";
-               break;
-       case 0xe1:
-               spid = "OUT";
-               break;
-       case 0x69:
-               spid = "IN";
-               break;
-       default:
-               spid = "?";
-               break;
+               case USB_PID_SETUP:
+                       spid = "SETUP";
+                       break;
+               case USB_PID_OUT:
+                       spid = "OUT";
+                       break;
+               case USB_PID_IN:
+                       spid = "IN";
+                       break;
+               default:
+                       spid = "?";
+                       break;
        }
+
        printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
                td->info >> 21,
-                ((td->info >> 19) & 1),
-                (td->info >> 15) & 15,
-                (td->info >> 8) & 127,
-                (td->info & 0xff),
-                spid);
+               ((td->info >> 19) & 1),
+               (td->info >> 15) & 15,
+               (td->info >> 8) & 127,
+               (td->info & 0xff),
+               spid);
        printk("(buf=%08x)\n", td->buffer);
 }
 
-static void show_sc(int port, unsigned short status)
+static void uhci_show_sc(int port, unsigned short status)
 {
        printk("  stat%d     =     %04x   %s%s%s%s%s%s%s%s\n",
                port,
                status,
-               (status & (1 << 12)) ? " PortSuspend" : "",
-               (status & (1 << 9)) ? " PortReset" : "",
-               (status & (1 << 8)) ? " LowSpeed" : "",
-               (status & 0x40) ? " ResumeDetect" : "",
-               (status & 0x08) ? " EnableChange" : "",
-               (status & 0x04) ? " PortEnabled" : "",
-               (status & 0x02) ? " ConnectChange" : "",
-               (status & 0x01) ? " PortConnected" : "");
+               (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+               (status & USBPORTSC_PR) ?   "PortReset " : "",
+               (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+               (status & USBPORTSC_RD) ?   "ResumeDetect " : "",
+               (status & USBPORTSC_PEC) ?  "EnableChange " : "",
+               (status & USBPORTSC_PE) ?   "PortEnabled " : "",
+               (status & USBPORTSC_CSC) ?  "ConnectChange " : "",
+               (status & USBPORTSC_CCS) ?  "PortConnected " : "");
 }
 
-void show_status(struct uhci *uhci)
+void uhci_show_status(struct uhci *uhci)
 {
        unsigned int io_addr = uhci->io_addr;
        unsigned short usbcmd, usbstat, usbint, usbfrnum;
@@ -87,30 +92,31 @@ void show_status(struct uhci *uhci)
 
        printk("  usbcmd    =     %04x   %s%s%s%s%s%s%s%s\n",
                usbcmd,
-               (usbcmd & 0x80) ? " Maxp64" : " Maxp32",
-               (usbcmd & 0x40) ? " CF" : "",
-               (usbcmd & 0x20) ? " SWDBG" : "",
-               (usbcmd & 0x10) ? " FGR" : "",
-               (usbcmd & 0x08) ? " EGSM" : "",
-               (usbcmd & 0x04) ? " GRESET" : "",
-               (usbcmd & 0x02) ? " HCRESET" : "",
-               (usbcmd & 0x01) ? " RS" : "");
+               (usbcmd & USBCMD_MAXP) ?    "Maxp64 " : "Maxp32 ",
+               (usbcmd & USBCMD_CF) ?      "CF " : "",
+               (usbcmd & USBCMD_SWDBG) ?   "SWDBG " : "",
+               (usbcmd & USBCMD_FGR) ?     "FGR " : "",
+               (usbcmd & USBCMD_EGSM) ?    "EGSM " : "",
+               (usbcmd & USBCMD_GRESET) ?  "GRESET " : "",
+               (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+               (usbcmd & USBCMD_RS) ?      "RS " : "");
 
        printk("  usbstat   =     %04x   %s%s%s%s%s%s\n",
                usbstat,
-               (usbstat & 0x20) ? " HCHalted" : "",
-               (usbstat & 0x10) ? " HostControllerProcessError" : "",
-               (usbstat & 0x08) ? " HostSystemError" : "",
-               (usbstat & 0x04) ? " ResumeDetect" : "",
-               (usbstat & 0x02) ? " USBError" : "",
-               (usbstat & 0x01) ? " USBINT" : "");
+               (usbstat & USBSTS_HCH) ?    "HCHalted " : "",
+               (usbstat & USBSTS_HCPE) ?   "HostControllerProcessError " : "",
+               (usbstat & USBSTS_HSE) ?    "HostSystemError " : "",
+               (usbstat & USBSTS_RD) ?     "ResumeDetect " : "",
+               (usbstat & USBSTS_ERROR) ?  "USBError " : "",
+               (usbstat & USBSTS_USBINT) ? "USBINT " : "");
 
        printk("  usbint    =     %04x\n", usbint);
-       printk("  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1, 0xfff & (4*(unsigned int)usbfrnum));
+       printk("  usbfrnum  =   (%d)%03x\n", (usbfrnum >> 10) & 1,
+               0xfff & (4*(unsigned int)usbfrnum));
        printk("  flbaseadd = %08x\n", flbaseadd);
        printk("  sof       =       %02x\n", sof);
-       show_sc(1, portsc1);
-       show_sc(2, portsc2);
+       uhci_show_sc(1, portsc1);
+       uhci_show_sc(2, portsc2);
 }
 
 #define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x))
@@ -123,13 +129,13 @@ struct uhci_td *uhci_link_to_td(unsigned int link)
        return bus_to_virt(link & ~UHCI_PTR_BITS);
 }
 
-void show_queue(struct uhci_qh *qh)
+void uhci_show_queue(struct uhci_qh *qh)
 {
-       struct uhci_td *td;
-       int i = 0;
+       struct uhci_td *td, *first;
+       int i = 0, count = 1000;
 
        if (qh->element & UHCI_PTR_QH)
-               printk("      Element points to QH?\n");
+               printk("      Element points to QH (bug?)\n");
 
        if (qh->element & UHCI_PTR_DEPTH)
                printk("      Depth traverse\n");
@@ -138,19 +144,30 @@ void show_queue(struct uhci_qh *qh)
                printk("      Terminate\n");
 
        if (!(qh->element & ~UHCI_PTR_BITS)) {
-               printk("      td 0 = NULL\n");
+               printk("      td 0: [NULL]\n");
                return;
        }
 
-       for(td = uhci_link_to_td(qh->element); td; 
-           td = uhci_link_to_td(td->link)) {
-               printk("      td %d = %p\n", i++, td);
+       if (qh->first)
+               first = qh->first;
+       else
+               first = uhci_link_to_td(qh->element);
+
+       /* Make sure it doesn't runaway */
+       for (td = first; td && count > 0; 
+            td = uhci_link_to_td(td->link), --count) {
+               printk("      td %d: [%p]\n", i++, td);
                printk("      ");
-               show_td(td);
+               uhci_show_td(td);
+
+               if (td == uhci_link_to_td(td->link)) {
+                       printk(KERN_ERR "td links to itself!\n");
+                       break;
+               }
        }
 }
 
-int is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
+static int uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
 {
        int j;
 
@@ -166,7 +183,7 @@ static const char *qh_names[] = {"interrupt2", "interrupt4", "interrupt8",
                                 "interrupt128", "interrupt256", "control",
                                 "bulk"};
 
-void show_queues(struct uhci *uhci)
+void uhci_show_queues(struct uhci *uhci)
 {
        int i;
        struct uhci_qh *qh;
@@ -178,13 +195,13 @@ void show_queues(struct uhci *uhci)
 
                qh = uhci_link_to_qh(uhci->skelqh[i].link);
                for (; qh; qh = uhci_link_to_qh(qh->link)) {
-                       if (is_skeleton_qh(uhci, qh))
+                       if (uhci_is_skeleton_qh(uhci, qh))
                                break;
 
                        printk("    [%p] (%08X) (%08x)\n",
                                qh, qh->link, qh->element);
 
-                       show_queue(qh);
+                       uhci_show_queue(qh);
                }
        }
 }
index 86a96c47fddb6d5b568757ee8c7bf53840f26cd8..9413ce67b925cf40634555187b2384e55a63a8c1 100644 (file)
@@ -3,6 +3,7 @@
  *
  * (C) Copyright 1999 Linus Torvalds
  * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -63,32 +64,51 @@ static LIST_HEAD(uhci_list);
 #define UHCI_DEBUG
 
 /*
- * Map status to standard result codes.
+ * function prototypes
+ */
+
+static int uhci_get_current_frame_number (struct usb_device *usb_dev);
+
+static int uhci_init_isoc (struct usb_device *usb_dev,
+                               unsigned int pipe,
+                               int frame_count,
+                               void *context,
+                               struct usb_isoc_desc **isocdesc);
+
+static void uhci_free_isoc (struct usb_isoc_desc *isocdesc);
+
+static int uhci_run_isoc (struct usb_isoc_desc *isocdesc,
+                               struct usb_isoc_desc *pr_isocdesc);
+
+static int uhci_kill_isoc (struct usb_isoc_desc *isocdesc);
+
+/*
+ * Map status to standard result codes
  *
- * <status> is ((td->status >> 16) & 0xff) [a.k.a. uhci_status_bits(td->status)]
+ * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)
  * <dir_out> is True for output TDs and False for input TDs.
  */
 static int uhci_map_status(int status, int dir_out)
 {
        if (!status)
                return USB_ST_NOERROR;
-       if (status & 0x02)                              /* Bitstuff error*/
+       if (status & TD_CTRL_BITSTUFF)                  /* Bitstuff error */
                return USB_ST_BITSTUFF;
-       if (status & 0x04)      {                       /* CRC/Timeout */
+       if (status & TD_CTRL_CRCTIMEO) {                /* CRC/Timeout */
                if (dir_out)
-                       return USB_ST_NORESPONSE;
+                       return USB_ST_NORESPONSE;
                else
                        return USB_ST_CRC;
        }
-       if (status & 0x08)                              /* NAK */
+       if (status & TD_CTRL_NAK)                       /* NAK */
                return USB_ST_TIMEOUT;
-       if (status & 0x10)                              /* Babble */
+       if (status & TD_CTRL_BABBLE)                    /* Babble */
                return USB_ST_STALL;
-       if (status & 0x20)                              /* Buffer error */
+       if (status & TD_CTRL_DBUFERR)                   /* Buffer error */
                return USB_ST_BUFFERUNDERRUN;
-       if (status & 0x40)                              /* Stalled */
+       if (status & TD_CTRL_STALLED)                   /* Stalled */
                return USB_ST_STALL;
-       if (status & 0x80)                              /* Active */
+       if (status & TD_CTRL_ACTIVE)                    /* Active */
                return USB_ST_NOERROR;
 
        return USB_ST_INTERNALERROR;
@@ -96,77 +116,83 @@ static int uhci_map_status(int status, int dir_out)
 /*
  * Return the result of a TD..
  */
-static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned long *rval)
+static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned long *rval, int debug)
 {
        unsigned int status;
        struct uhci_td *tmp;
-
-       if (!td->qh)
-               tmp = td;
-       else
-               tmp = uhci_ptr_to_virt(td->qh->element);
+       int count = 1000;
 
        if (rval)
                *rval = 0;
 
-       /* locate the first failing td, if any */
+       /* Start at the TD first in the chain, if possible */
+       if (td->qh && td->qh->first)
+               tmp = td->qh->first;
+       else
+               tmp = td;
 
+       if (!tmp)
+               return USB_ST_INTERNALERROR;
+
+       /* Locate the first failing td, if any */
        do {
                status = uhci_status_bits(tmp->status);
+
                if (status) {
-                       /* must reset the toggle on first error */
-                       if (uhci_debug) {
-                               printk(KERN_DEBUG "Set toggle from %x rval %ld\n",
-                                       (unsigned int)tmp, rval ? *rval : 0);
+                       if (debug) {
+                               /* Must reset the toggle on first error */
+                               if (uhci_debug) {
+                                       printk(KERN_DEBUG "Set toggle from %x rval %ld\n",
+                                               (unsigned int)tmp, rval ? *rval : 0);
+                               }
+
+                               usb_settoggle(dev->usb, uhci_endpoint(tmp->info),
+                                       uhci_packetout(tmp->info) ^ 1,
+                                       uhci_toggle(tmp->info));
+                               break;
                        }
-                       usb_settoggle(dev->usb, uhci_endpoint(tmp->info),
-                               uhci_packetout(tmp->info), uhci_toggle(tmp->info));
-                       break;
                } else {
-                   if (rval)
-                       *rval += uhci_actual_length(tmp->status);
+                       if (rval && ((tmp->info & 0xFF) == USB_PID_IN))
+                               *rval += uhci_actual_length(tmp->status);
                }
+
                if ((tmp->link & UHCI_PTR_TERM) ||
                    (tmp->link & UHCI_PTR_QH))
                        break;
+
                tmp = uhci_ptr_to_virt(tmp->link);
-       } while (1);
+       } while (--count);
 
-       if (!status)
+       if (!count) {
+               printk(KERN_ERR "runaway td's in uhci_td_result!\n");
+               /* Force debugging on */
+               debug = 1;
+       } else if (!status)
                return USB_ST_NOERROR;
 
        /* Some debugging code */
-       if (uhci_debug) {
-               int count = 10;
-
-               if (!td->qh)
-                       tmp = td;
-               else
-                       tmp = uhci_ptr_to_virt(td->qh->element);
+       if (debug && uhci_debug) {
                printk(KERN_DEBUG "uhci_td_result() failed with status %x\n",
                        status);
-               do {
-                       show_td(tmp);
-                       if ((tmp->link & UHCI_PTR_TERM) ||
-                           (tmp->link & UHCI_PTR_QH))
-                               break;
-                       tmp = uhci_ptr_to_virt(tmp->link);
-               } while (--count);
+
+               /* Print the chain for debugging purposes */
+               if (td->qh)
+                       uhci_show_queue(td->qh);
+               else
+                       uhci_show_td(td);
        }
 
-       if (status & 0x40) {
+       if (status & TD_CTRL_STALLED) {
                /* endpoint has stalled - mark it halted */
                usb_endpoint_halt(dev->usb, uhci_endpoint(tmp->info),
                                uhci_packetout(tmp->info));
                return USB_ST_STALL;
        }
 
-       if (status == 0x80) {
-               /* still active */
-               if (!rval)
-                       return USB_ST_DATAUNDERRUN;
-       }
-       return uhci_map_status(status, uhci_packetout(tmp->info));
+       if ((status == TD_CTRL_ACTIVE) && (!rval))
+               return USB_ST_DATAUNDERRUN;
+
+       return uhci_map_status(status, usb_pipeout(tmp->info) ^ 1);
 }
 
 /*
@@ -194,6 +220,7 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, str
                        :"=q" (success), "=a" (link)
                        :"m" (qh->element), "1" (link), "r" (new)
                        :"memory");
+
                if (success) {
                        /* Was there a successor entry? Fix it's backpointer */
                        if ((link & UHCI_PTR_TERM) == 0) {
@@ -203,6 +230,10 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *first, str
                        break;
                }
        }
+
+       qh->first = first;
+       first->qh = qh;
+       last->qh = qh;
 }
 
 static inline void uhci_insert_td_in_qh(struct uhci_qh *qh, struct uhci_td *td)
@@ -279,6 +310,54 @@ static void uhci_remove_td(struct uhci_td *td)
                :
                :"r" (link), "m" (*backptr), "a" (me)
                :"memory");
+
+       /* Reset it just in case */
+       td->link = UHCI_PTR_TERM;
+}
+
+/*
+ * Only the USB core should call uhci_alloc_dev and uhci_free_dev
+ */
+static int uhci_alloc_dev(struct usb_device *usb_dev)
+{
+       struct uhci_device *dev;
+
+       /* Allocate the UHCI device private data */
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -1;
+
+       /* Initialize "dev" */
+       memset(dev, 0, sizeof(*dev));
+
+       usb_dev->hcpriv = dev;
+       dev->usb = usb_dev;
+       atomic_set(&dev->refcnt, 1);
+
+       if (usb_dev->parent)
+               dev->uhci = usb_to_uhci(usb_dev->parent)->uhci;
+
+       return 0;
+}
+
+static int uhci_free_dev(struct usb_device *usb_dev)
+{
+       struct uhci_device *dev = usb_to_uhci(usb_dev);
+
+       if (atomic_dec_and_test(&dev->refcnt))
+               kfree(dev);
+
+       return 0;
+}
+
+static void uhci_inc_dev_use(struct uhci_device *dev)
+{
+       atomic_inc(&dev->refcnt);
+}
+
+static void uhci_dec_dev_use(struct uhci_device *dev)
+{
+       uhci_free_dev(dev->usb);
 }
 
 static struct uhci_td *uhci_td_alloc(struct uhci_device *dev)
@@ -305,13 +384,19 @@ static struct uhci_td *uhci_td_alloc(struct uhci_device *dev)
        INIT_LIST_HEAD(&td->irq_list);
        atomic_set(&td->refcnt, 1);
 
+       uhci_inc_dev_use(dev);
+
        return td;
 }
 
 static void uhci_td_free(struct uhci_td *td)
 {
-       if (atomic_dec_and_test(&td->refcnt))
+       if (atomic_dec_and_test(&td->refcnt)) {
                kmem_cache_free(uhci_td_cachep, td);
+
+               if (td->dev)
+                       uhci_dec_dev_use(td->dev);
+       }
 }
 
 static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev)
@@ -332,16 +417,23 @@ static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev)
 
        qh->dev = dev;
        qh->skel = NULL;
+       qh->first = NULL;
        init_waitqueue_head(&qh->wakeup);
        atomic_set(&qh->refcnt, 1);
 
+       uhci_inc_dev_use(dev);
+
        return qh;
 }
 
 static void uhci_qh_free(struct uhci_qh *qh)
 {
-       if (atomic_dec_and_test(&qh->refcnt))
+       if (atomic_dec_and_test(&qh->refcnt)) {
                kmem_cache_free(uhci_qh_cachep, qh);
+
+               if (qh->dev)
+                       uhci_dec_dev_use(qh->dev);
+       }
 }
 
 /*
@@ -371,9 +463,9 @@ static void uhci_remove_irq_list(struct uhci_td *td)
 }
 
 /*
- * This function removes and disallcoates all structures set up for an transfer.
+ * This function removes and disallocates all structures set up for a transfer.
  * It takes the qh out of the skeleton, removes the tq and the td's.
- * It only removes the associated interrupt handler if removeirq ist set.
+ * It only removes the associated interrupt handler if removeirq is set.
  * The *td argument is any td in the list of td's.
  */
 static void uhci_remove_transfer(struct uhci_td *td, char removeirq)
@@ -382,10 +474,10 @@ static void uhci_remove_transfer(struct uhci_td *td, char removeirq)
        struct uhci_td *curtd;
        unsigned int nextlink;
 
-       if (!td->qh)
-               curtd = td;
+       if (td->qh && td->qh->first)
+               curtd = td->qh->first;
        else
-               curtd = uhci_ptr_to_virt(td->qh->element);
+               curtd = td;
 
        /* Remove it from the skeleton */
        uhci_remove_qh(td->qh->skel, td->qh);
@@ -436,7 +528,8 @@ static void *uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb
        td->link = UHCI_PTR_TERM;               /* Terminate */
        td->status = status;                    /* In */
        td->info = destination | ((usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe)) - 1) << 21) |
-               (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
+               (usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
+
        td->buffer = virt_to_bus(dev->data);
        td->qh = qh;
        td->dev = dev;
@@ -471,10 +564,6 @@ int uhci_release_irq(struct usb_device *usb, void *handle)
        struct uhci_td *td;
        struct uhci_qh *qh;
 
-#ifdef UHCI_DEBUG
-       printk(KERN_DEBUG "usb-uhci: releasing irq handle %p\n", handle);
-#endif
-
        td = (struct uhci_td *)handle;
        if (!td)
                return USB_ST_INTERNALERROR;
@@ -498,190 +587,327 @@ int uhci_release_irq(struct usb_device *usb, void *handle)
 } /* uhci_release_irq() */
 
 /*
- * Isochronous operations
+ * uhci_get_current_frame_number()
+ *
+ * returns the current frame number for a USB bus/controller.
  */
-static int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
+static int uhci_get_current_frame_number(struct usb_device *usb_dev)
 {
-       struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
-       char *data = isodesc->data;
-       int i, totlen = 0;
+       return inw (usb_to_uhci(usb_dev)->uhci->io_addr + USBFRNUM) & 0x3ff;
+}
 
-       for (i = 0; i < isodesc->num; i++) {
-               struct uhci_td *td = &isodesc->td[i];
-               char *cdata = uhci_ptr_to_virt(td->buffer);
-               int n = uhci_actual_length(td->status);
 
-               if ((cdata != data) && (n))
-                       memmove(data, cdata, n);
+/*
+ * uhci_init_isoc()
+ *
+ * Checks bus bandwidth allocation for this USB bus.
+ * Allocates some data structures.
+ * Initializes parts of them from the function parameters.
+ *
+ * It does not associate any data/buffer pointers or
+ * driver (caller) callback functions with the allocated
+ * data structures.  Such associations are left until
+ * uhci_run_isoc().
+ *
+ * Returns 0 for success or negative value for error.
+ * Sets isocdesc before successful return.
+ */
+static int uhci_init_isoc (struct usb_device *usb_dev,
+                               unsigned int pipe,
+                               int frame_count,        /* bandwidth % = 100 * this / 1000 */
+                               void *context,
+                               struct usb_isoc_desc **isocdesc)
+{
+       struct usb_isoc_desc *id;
 
-#ifdef UHCI_DEBUG
-               /* Debugging */
-               if (uhci_status_bits(td->status))
-                       printk(KERN_DEBUG "error: %d %X\n", i,
-                               (td->status >> 16));
+#ifdef BANDWIDTH_ALLOCATION
+       /* TBD: add bandwidth allocation/checking/management HERE. */
+       /* TBD: some way to factor in frame_spacing ??? */
 #endif
 
-               data += n;
-               totlen += n;
-       }
+       *isocdesc = NULL;
 
-       return totlen;
-}
-
-static int uhci_unschedule_isochronous(struct usb_device *usb_dev, void *_isodesc)
-{
-       struct uhci_device *dev = usb_to_uhci(usb_dev);
-       struct uhci *uhci = dev->uhci;
-       struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
-       int i;
-
-       if ((isodesc->frame < 0) || (isodesc->frame > 1023)) {
-               printk(KERN_ERR "illegal frame number %d\n", isodesc->frame);
-               return 1;
+       /* Check some parameters. */
+       if ((frame_count < 0) || (frame_count > UHCI_NUMFRAMES)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_init_isoc: invalid frame_count (%d)\n",
+                       frame_count);
+#endif
+               return -EINVAL;
        }
 
-       /* FIXME: Use uhci_remove_td */
+       if (!usb_pipeisoc (pipe)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_init_isoc: NOT an Isoc. pipe\n");
+#endif
+               return -EINVAL;
+       }
 
-       /* Remove from previous frames */
-       for (i = 0; i < isodesc->num; i++) {
-               struct uhci_td *td = &isodesc->td[i];
+       id = kmalloc (sizeof (*id) +
+               (sizeof (struct isoc_frame_desc) * frame_count), GFP_KERNEL);
+       if (!id)
+               return -ENOMEM;
 
-               /* Turn off Active and IOC bits */
-               td->status &= ~(3 << 23);
-               td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC);
-               
-               uhci->fl->frame[(isodesc->frame + i) % 1024] = td->link;
+       id->td = kmalloc (sizeof (struct uhci_td) * frame_count, GFP_KERNEL);
+       if (!id->td) {
+               kfree (id);
+               return -ENOMEM;
        }
 
-       isodesc->frame = -1;
-
+       memset (id, 0, sizeof (*id) +
+               (sizeof (struct isoc_frame_desc) * frame_count));
+       memset (id->td, 0, sizeof (struct uhci_td) * frame_count);
+
+       id->frame_count = frame_count;
+       id->frame_size  = usb_maxpacket (usb_dev, pipe, usb_pipeout(pipe));
+               /* TBD: or make this a parameter to allow for frame_size
+               that is less than maxpacketsize */
+       id->start_frame = -1;
+       id->end_frame   = -1;
+       id->usb_dev     = usb_dev;
+       id->pipe        = pipe;
+       id->context     = context;
+
+       *isocdesc = id;
        return 0;
-}
-       
-/* td points to the one td we allocated for isochronous transfers */
-static int uhci_schedule_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc)
+} /* end uhci_init_isoc */
+
+/*
+ * uhci_run_isoc()
+ *
+ * Associates data/buffer pointers/lengths and
+ * driver (caller) callback functions with the
+ * allocated Isoc. data structures and TDs.
+ *
+ * Then inserts the TDs into the USB controller frame list
+ * for its processing.
+ * And inserts the callback function into its TD.
+ *
+ * pr_isocdesc (previous Isoc. desc.) may be NULL.
+ * It is used only for chaining one list of TDs onto the
+ * end of the previous list of TDs.
+ *
+ * Returns 0 (success) or error code (negative value).
+ */
+static int uhci_run_isoc (struct usb_isoc_desc *isocdesc,
+                               struct usb_isoc_desc *pr_isocdesc)
 {
-       struct uhci_device *dev = usb_to_uhci(usb_dev);
+       struct uhci_device *dev = usb_to_uhci (isocdesc->usb_dev);
        struct uhci *uhci = dev->uhci;
-       struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
-       struct uhci_iso_td *pisodesc = (struct uhci_iso_td *)_pisodesc;
-       int frame, i;
-
-       if (isodesc->frame != -1) {
-               printk(KERN_ERR "isoc queue not removed\n");
-               uhci_unschedule_isochronous(usb_dev, isodesc);
+       unsigned long   destination, status;
+       struct uhci_td  *td;
+       int             ix, cur_frame, pipeinput, frlen;
+       int             cb_frames = 0;
+       struct isoc_frame_desc *fd;
+       unsigned char   *bufptr;
+
+       if (!isocdesc->callback_fn) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_run_isoc: caller must have a callback function\n");
+#endif
+               return -EINVAL;
        }
 
-       /* Insert TD into list */
-       if (!pisodesc) {
-               /* It's not guaranteed to be 1-1024 */
-               frame = inw(uhci->io_addr + USBFRNUM) % 1024;
-
-               /* HACK: Start 2 frames from now */
-               frame = (frame + 2) % 1024;
-       } else
-               frame = (pisodesc->endframe + 1) % 1024;
-
-       for (i = 0; i < isodesc->num; i++) {
-               struct uhci_td *td = &isodesc->td[i];
-
-               /* Active */
-               td->status |= TD_CTRL_ACTIVE;
-               td->backptr = &uhci->fl->frame[(frame + i) % 1024];
-               td->link = uhci->fl->frame[(frame + i) % 1024];
-               uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(td);
+       /* Check buffer size large enough for maxpacketsize * frame_count. */
+       if (isocdesc->buf_size < (isocdesc->frame_count * isocdesc->frame_size)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_init_isoc: buf_size too small (%d < %d)\n",
+                       isocdesc->buf_size, isocdesc->frame_count * isocdesc->frame_size);
+#endif
+               return -EINVAL;
        }
 
-       /* IOC on the last TD */
-       isodesc->td[i - 1].status |= TD_CTRL_IOC;
+       /* Check buffer ptr for Null. */
+       if (!isocdesc->data) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_init_isoc: data ptr is null\n");
+#endif
+               return -EINVAL;
+       }
 
-       isodesc->frame = frame;
-       isodesc->endframe = (frame + isodesc->num - 1) % 1024;
+#ifdef NEED_ALIGNMENT
+       /* Check data page alignment. */
+       if (((int)(isocdesc->data) & (PAGE_SIZE - 1)) != 0) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_init_isoc: buffer must be page-aligned (%p)\n",
+                       isocdesc->data);
+#endif
+               return -EINVAL;
+       }
+#endif /* NEED_ALIGNMENT */
 
-       return 0;
-}
+       /*
+        * Check start_type unless pr_isocdesc is used.
+        */
+       if (!pr_isocdesc && (isocdesc->start_type > START_TYPE_MAX)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_run_isoc: invalid start_type (%d)\n",
+                       isocdesc->start_type);
+#endif
+               return -EINVAL;
+       }
 
-/*
- * Initialize isochronous queue
- */
-static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
-{
-       struct uhci_device *dev = usb_to_uhci(usb_dev);
-       unsigned long destination, status;
-       struct uhci_td *td;
-       struct uhci_iso_td *isodesc;
-       int i;
+       /* if not START_ASAP (i.e., RELATIVE or ABSOLUTE): */
+       if (!pr_isocdesc && (isocdesc->start_type != START_ASAP))
+               if ((isocdesc->start_frame < 0) || (isocdesc->start_frame > 1000)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+                       printk (KERN_DEBUG "uhci_init_isoc: bad start_frame value (%d)\n",
+                               isocdesc->start_frame);
+#endif
+                       return -EINVAL;
+               }
 
-       isodesc = kmalloc(sizeof(*isodesc), GFP_KERNEL);
-       if (!isodesc) {
-               printk(KERN_ERR "Couldn't allocate isodesc!\n");
-               return NULL;
+       /*
+        * Set the start/end frame numbers.
+        */
+       if (!pr_isocdesc)
+               cur_frame = uhci_get_current_frame_number (isocdesc->usb_dev);
+
+       if (pr_isocdesc) {
+               isocdesc->start_frame = pr_isocdesc->end_frame + 1;
+       } else if (isocdesc->start_type == START_ABSOLUTE) {
+               /* Use start_frame as is. */
+       } else if (isocdesc->start_type == START_RELATIVE) {
+               if (isocdesc->start_frame < START_FRAME_FUDGE)
+                       isocdesc->start_frame = START_FRAME_FUDGE;
+               isocdesc->start_frame += cur_frame;
+       } else if (isocdesc->start_type == START_ASAP) {
+               isocdesc->start_frame = cur_frame + START_FRAME_FUDGE;
        }
 
-       memset(isodesc, 0, sizeof(*isodesc));
+       /* and see if start_frame needs any correction */
+       if (isocdesc->start_frame >= 1000)
+               isocdesc->start_frame -= 1000;
 
-       /* Carefully work around the non contiguous pages */
-       isodesc->num = len / maxsze;
-       isodesc->td = kmalloc(sizeof(struct uhci_td) * isodesc->num, GFP_KERNEL);
-       isodesc->frame = isodesc->endframe = -1;
-       isodesc->data = data;
-       isodesc->maxsze = maxsze;
-       
-       if (!isodesc->td) {
-               printk(KERN_ERR "couldn't allocate td's\n");
-               kfree(isodesc);
-               return NULL;
-       }
+       /* and fix the end_frame value */
+       isocdesc->end_frame = isocdesc->start_frame + isocdesc->frame_count - 1;
+       if (isocdesc->end_frame >= 1000)
+       isocdesc->end_frame -= 1000;
 
-       isodesc->frame = isodesc->endframe = -1;
+       isocdesc->prev_completed_frame = -1;
+       isocdesc->cur_completed_frame  = -1;
+
+       destination = (isocdesc->pipe & PIPE_DEVEP_MASK) |
+               usb_packetid (isocdesc->pipe);
+       status = TD_CTRL_ACTIVE | TD_CTRL_IOS;  /* mark Isoc.; can't be low speed */
+       pipeinput = usb_pipein (isocdesc->pipe);
+       cur_frame = isocdesc->start_frame;
+       bufptr = isocdesc->data;
 
        /*
-        * Build the DATA TD's
+        * Build the Data TDs.
+        * TBD: Not using frame_spacing (Yet).  Defaults to 1 (every frame).
+        * (frame_spacing is a way to request less bandwidth.)
+        * This can also be done by using frame_length = 0 in the
+        * frame_desc array, but this way won't take less bandwidth
+        * allocation into account.
         */
-       i = 0;
-       do {
-               /* Build the TD for control status */
-               td = &isodesc->td[i];
 
-               /* The "pipe" thing contains the destination in bits 8--18 */
-               destination = (pipe & PIPE_DEVEP_MASK)
-                       | usb_packetid (pipe);  /* add IN or OUT */
+       if (isocdesc->frame_spacing <= 0)
+               isocdesc->frame_spacing = 1;
+
+       for (ix = 0, td = isocdesc->td, fd = isocdesc->frames;
+            ix < isocdesc->frame_count; ix++, td++, fd++, cur_frame++) {
+               frlen = fd->frame_length;
+               if (frlen > isocdesc->frame_size)
+                       frlen = isocdesc->frame_size;
 
-               status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOS;
+#ifdef NOTDEF
+               td->info = destination |  /* use Actual len on OUT; max. on IN */
+                       (pipeinput ? ((isocdesc->frame_size - 1) << 21)
+                       : ((frlen - 1) << 21));
+#endif
+
+               td->dev_id = isocdesc;  /* can get dev_id or context from isocdesc */
+               td->status = status;
+               td->info   = destination | ((frlen - 1) << 21);
+               td->buffer = virt_to_bus (bufptr);
+               td->dev    = dev;
+               td->isoc_td_number = ix;        /* 0-based; does not wrap 999 -> 0 */
+
+               if (isocdesc->callback_frames &&
+                   (++cb_frames >= isocdesc->callback_frames)) {
+                       td->status |= TD_CTRL_IOC;
+                       td->completed = isocdesc->callback_fn;
+                       cb_frames = 0;
+               }
+
+               bufptr += fd->frame_length;  /* or isocdesc->frame_size; */
 
                /*
-                * Build the TD for the control request
+                * Insert the TD in the frame list.
                 */
-               td->status = status;
-               td->info = destination | ((maxsze - 1) << 21);
-               td->buffer = virt_to_bus(data);
-               td->backptr = NULL;
+               td->backptr = &uhci->fl->frame [cur_frame];
+               td->link    = uhci->fl->frame [cur_frame];
+               uhci->fl->frame [cur_frame] = virt_to_bus (td);
 
-               i++;
+               if (cur_frame >= 999)
+                       cur_frame = -1;
+       } /* end for ix */
 
-               data += maxsze;
-               len -= maxsze;
-       } while (i < isodesc->num);
+       /*
+        * Add IOC on the last TD.
+        */
+       td--;
+       td->status |= TD_CTRL_IOC;
+       uhci_add_irq_list (dev->uhci, td, isocdesc->callback_fn, isocdesc->context); /* TBD: D.K. ??? */
 
-       uhci_add_irq_list(dev->uhci, td, completed, dev_id);
+       return 0;
+} /* end uhci_run_isoc */
 
-       return isodesc;
-}
+/*
+ * uhci_kill_isoc()
+ *
+ * Marks a TD list as Inactive and removes it from the Isoc.
+ * TD frame list.
+ *
+ * Does not free any memory resources.
+ *
+ * Returns 0 for success or negative value for error.
+ */
+static int uhci_kill_isoc (struct usb_isoc_desc *isocdesc)
+{
+       struct uhci_device *dev = usb_to_uhci (isocdesc->usb_dev);
+       struct uhci     *uhci = dev->uhci;
+       struct uhci_td  *td;
+       int             ix, cur_frame;
+
+       if ((isocdesc->start_frame < 0) || (isocdesc->start_frame >= 1000)) {
+#ifdef CONFIG_USB_DEBUG_ISOC
+               printk (KERN_DEBUG "uhci_kill_isoc: invalid start_frame (%d)\n",
+                       isocdesc->start_frame);
+#endif
+               return -EINVAL;
+       }
+
+       for (ix = 0, td = isocdesc->td, cur_frame = isocdesc->start_frame;
+            ix < isocdesc->frame_count; ix++, td++) {
+               td->status &= ~(TD_CTRL_ACTIVE | TD_CTRL_IOC);
+               uhci->fl->frame [cur_frame] = td->link;
 
-static void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc)
+               if (++cur_frame >= 1000)
+                       cur_frame = 0;
+       } /* end for ix */
+
+       isocdesc->start_frame = -1;
+       return 0;
+} /* end uhci_kill_isoc */
+
+static void uhci_free_isoc (struct usb_isoc_desc *isocdesc)
 {
-       struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
+       /* If still Active, kill it. */
+       if (isocdesc->start_frame >= 0)
+               uhci_kill_isoc (isocdesc);
 
-       /* If it's still scheduled, unschedule them */
-       if (isodesc->frame)
-               uhci_unschedule_isochronous(usb_dev, isodesc);
+       /* Remove it from the IRQ list. */
+       uhci_remove_irq_list ((struct uhci_td *)&(isocdesc->td [isocdesc->frame_count - 1]));
 
-       /* Remove it from the IRQ list */
-       uhci_remove_irq_list(&isodesc->td[isodesc->num - 1]);
+       /* Free the associate memory. */
+       if (isocdesc->td)
+               kfree (isocdesc->td);
 
-       kfree(isodesc->td);
-       kfree(isodesc);
-}
+       kfree (isocdesc);
+} /* end uhci_free_isoc */
 
 /*
  * Control thread operations: we just mark the last TD
@@ -718,26 +944,6 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru
 
        uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup);
        
-#if 0
-       /* FIXME: This is kinda kludged */
-       /* Walk the TD list and update the QH pointer */
-       {
-       struct uhci_td *curtd;
-       int count = 100;
-
-       curtd = first;
-       do {
-               curtd->qh = ctrl_qh;
-               if (curtd->link & TD_CTRL_TERM)
-                       break;
-
-               curtd = uhci_ptr_to_virt(curtd->link);
-       } while (--count);
-       if (!count)
-               printk(KERN_DEBUG "runaway tds!\n");
-       }
-#endif
-
        uhci_insert_tds_in_qh(qh, first, last);
 
        /* Add it into the skeleton */
@@ -755,7 +961,7 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru
 
        uhci_qh_free(qh);
 
-       return uhci_td_result(dev, last, NULL);
+       return uhci_td_result(dev, last, NULL, 1);
 }
 
 /*
@@ -778,6 +984,11 @@ static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, stru
  * 29 TD's is a minimum of 232 bytes worth of control
  * information, that's just ridiculously high. Most
  * control messages have just a few bytes of data.
+ *
+ * 232 is not ridiculously high with many of the
+ * configurations on audio devices, etc. anyway,
+ * there is no restriction on length of transfers
+ * anymore
  */
 static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd, void *data, int len)
 {
@@ -787,12 +998,14 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        int ret, count;
        int maxsze = usb_maxpacket(usb_dev, pipe, usb_pipeout(pipe));
        __u32 nextlink;
+       unsigned long bytesrequested = len;
+       unsigned long bytesread = 0;
 
        first = td = uhci_td_alloc(dev);
        if (!td)
                return -ENOMEM;
 
-       /* The "pipe" thing contains the destination in bits 8--18. */
+       /* The "pipe" thing contains the destination in bits 8--18 */
        destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
 
        /* 3 errors */
@@ -811,7 +1024,7 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
         */
        destination ^= (USB_PID_SETUP ^ USB_PID_IN);            /* SETUP -> IN */
        if (usb_pipeout(pipe))
-               destination ^= (USB_PID_OUT ^ USB_PID_IN);      /* IN -> OUT */
+               destination ^= (USB_PID_IN ^ USB_PID_OUT);      /* IN -> OUT */
 
        prevtd = td;
        td = uhci_td_alloc(dev);
@@ -851,7 +1064,13 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        /*
         * Build the final TD for control status 
         */
-       destination ^= (USB_PID_OUT ^ USB_PID_IN);      /* OUT -> IN */
+       /* It's only IN if the pipe is out AND we aren't expecting data */
+       destination &= ~0xFF;
+       if (usb_pipeout(pipe) | (bytesrequested == 0))
+               destination |= USB_PID_IN;
+       else
+               destination |= USB_PID_OUT;
+
        destination |= 1 << TD_TOKEN_TOGGLE;            /* End in Data1 */
 
        td->status = status | TD_CTRL_IOC;                      /* no limit on errors on final packet */
@@ -863,9 +1082,13 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        /* Start it up.. */
        ret = uhci_run_control(dev, first, td);
 
-       count = 100;
+       count = 1000;
        td = first;
        do {
+               if (!uhci_status_bits(td->status) && ((td->info & 0xFF) ==
+                   USB_PID_IN))
+                       bytesread += uhci_actual_length(td->status);
+
                nextlink = td->link;
                uhci_remove_td(td);
                uhci_td_free(td);
@@ -879,6 +1102,12 @@ static int uhci_control_msg(struct usb_device *usb_dev, unsigned int pipe, devre
        if (!count)
                printk(KERN_ERR "runaway td's!?\n");
 
+       if (ret && (bytesread >= bytesrequested)) {
+               printk(KERN_DEBUG "Recovered sufficient data (asked for %ld, got %ld) from failed cmd\n",
+                       bytesrequested, bytesread);
+               ret = 0;
+       }
+
        if (uhci_debug && ret) {
                __u8 *p = (__u8 *)cmd;
 
@@ -911,32 +1140,12 @@ static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct
 
        uhci_add_irq_list(dev->uhci, last, uhci_generic_completed, &qh->wakeup);
        
-#if 0
-       /* FIXME: This is kinda kludged */
-       /* Walk the TD list and update the QH pointer */
-       {
-       struct uhci_td *curtd;
-       int count = 100;
-
-       curtd = first;
-       do {
-               curtd->qh = bulk_qh;
-               if (curtd->link & UHCI_PTR_TERM)
-                       break;
-
-               curtd = uhci_ptr_to_virt(curtd->link);
-       } while (--count);
-       if (!count)
-               printk(KERN_ERR "runaway tds!\n");
-       }
-#endif
-
        uhci_insert_tds_in_qh(qh, first, last);
 
        /* Add it into the skeleton */
        uhci_insert_qh(&dev->uhci->skel_bulk_qh, qh);
 
-       schedule_timeout(HZ*5);         /* 5 seconds */
+       schedule_timeout(HZ * 5);       /* 5 seconds */
 
        remove_wait_queue(&qh->wakeup, &wait);
 
@@ -947,7 +1156,7 @@ static int uhci_run_bulk(struct uhci_device *dev, struct uhci_td *first, struct
 
        uhci_qh_free(qh);
 
-       return uhci_td_result(dev, last, rval);
+       return uhci_td_result(dev, last, rval, 1);
 }
 
 /*
@@ -1107,82 +1316,36 @@ static void * uhci_request_bulk(struct usb_device *usb_dev, unsigned int pipe, u
 }
 
 /*
- *Remove a handler from a pipe. This terminates the transfer.
- *We have some assumptions here:
+ * Remove a handler from a pipe. This terminates the transfer.
+ * We have some assumptions here:
  * There is only one queue using this pipe. (the one we remove)
  * Any data that is in the queue is useless for us, we throw it away.
  */
-static int uhci_terminate_bulk(struct usb_device *dev, void * first)
+static int uhci_terminate_bulk(struct usb_device *dev, void *first)
 {
        /* none found? there is nothing to remove! */
        if (!first)
                return 0;
 
-       uhci_remove_transfer(first,1);
+       uhci_remove_transfer(first, 1);
 
        return 1;
 }
 
-static struct usb_device *uhci_usb_alloc(struct usb_device *parent)
-{
-       struct usb_device *usb_dev;
-       struct uhci_device *dev;
-
-       /* Allocate the USB device */
-       usb_dev = kmalloc(sizeof(*usb_dev), GFP_KERNEL);
-       if (!usb_dev)
-               return NULL;
-
-       memset(usb_dev, 0, sizeof(*usb_dev));
-
-       /* Allocate the UHCI device private data */
-       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev) {
-               kfree(usb_dev);
-               return NULL;
-       }
-
-       /* Initialize "dev" */
-       memset(dev, 0, sizeof(*dev));
-
-       usb_dev->hcpriv = dev;
-       dev->usb = usb_dev;
-
-       usb_dev->parent = parent;
-
-       if (parent) {
-               usb_dev->bus = parent->bus;
-               dev->uhci = usb_to_uhci(parent)->uhci;
-       }
-
-       return usb_dev;
-}
-
-static int uhci_usb_free(struct usb_device *usb_dev)
-{
-       struct uhci_device *dev = usb_to_uhci(usb_dev);
-
-       kfree(dev);
-       usb_destroy_configuration(usb_dev);
-       kfree(usb_dev);
-
-       return 0;
-}
-
 struct usb_operations uhci_device_operations = {
-       uhci_usb_alloc,
-       uhci_usb_free,
+       uhci_alloc_dev,
+       uhci_free_dev,
        uhci_control_msg,
        uhci_bulk_msg,
        uhci_request_irq,
        uhci_release_irq,
        uhci_request_bulk,
        uhci_terminate_bulk,
-       uhci_allocate_isochronous,
-       uhci_delete_isochronous,
-       uhci_schedule_isochronous,
-       uhci_unschedule_isochronous,
-       uhci_compress_isochronous
+       uhci_get_current_frame_number,
+       uhci_init_isoc,
+       uhci_free_isoc,
+       uhci_run_isoc,
+       uhci_kill_isoc
 };
 
 /*
@@ -1207,7 +1370,7 @@ static void uhci_reset_port(unsigned int port)
        wait_ms(10);
 
        status = inw(port);
-       if(!(status & USBPORTSC_PE)) {
+       if (!(status & USBPORTSC_PE)) {
                outw(status | USBPORTSC_PE, port);      /* one more try at enabling port */
                wait_ms(50);
        }
@@ -1251,7 +1414,7 @@ static void uhci_connect_change(struct uhci *uhci, unsigned int port, unsigned i
         * Ok, we got a new connection. Allocate a device to it,
         * and find out what it wants to do..
         */
-       usb_dev = uhci_usb_alloc(root_hub->usb);
+       usb_dev = usb_alloc_dev(root_hub->usb, root_hub->usb->bus);
        if (!usb_dev)
                return;
        
@@ -1303,6 +1466,58 @@ static void uhci_check_configuration(struct uhci *uhci)
        } while (nr < maxchild);
 }
 
+static int fixup_isoc_desc (struct uhci_td *td)
+{
+       struct usb_isoc_desc    *isocdesc = td->dev_id;
+       struct uhci_td          *prtd;
+       struct isoc_frame_desc  *frm;
+       int                     first_comp = isocdesc->cur_completed_frame + 1; /* 0-based */
+       int                     cur_comp = td->isoc_td_number;  /* 0-based */
+       int                     ix, fx;
+       int                     num_comp;
+
+       if (first_comp >= isocdesc->frame_count)
+               first_comp = 0;
+       num_comp = cur_comp - first_comp + 1;
+
+#ifdef CONFIG_USB_DEBUG_ISOC
+       printk ("fixup_isoc_desc.1: td = %p, id = %p, first_comp = %d, cur_comp = %d, num_comp = %d\n",
+                       td, isocdesc, first_comp, cur_comp, num_comp);
+#endif
+
+       for (ix = 0, fx = first_comp, prtd = &isocdesc->td [first_comp], frm = &isocdesc->frames [first_comp];
+           ix < num_comp; ix++) {
+               frm->frame_length = uhci_actual_length (prtd->status);
+               isocdesc->total_length += frm->frame_length;
+
+               if ((frm->frame_status = uhci_map_status (uhci_status_bits (prtd->status),
+                   uhci_packetout (prtd->info))))
+                       isocdesc->error_count++;
+             
+               prtd++;
+               frm++;
+               if (++fx >= isocdesc->frame_count) {    /* wrap fx, prtd, and frm */
+                       fx = 0;
+                       prtd = isocdesc->td;
+                       frm  = isocdesc->frames;
+               } /* end wrap */
+       } /* end for */
+
+       /*
+        * Update some other fields for drivers.
+        */
+       isocdesc->prev_completed_frame = isocdesc->cur_completed_frame;
+       isocdesc->cur_completed_frame  = cur_comp;
+       isocdesc->total_completed_frames += num_comp;   /* 1-based */
+
+#ifdef CONFIG_USB_DEBUG_ISOC
+       printk ("fixup_isoc_desc.2: total_comp_frames = %d, total_length = %d, error_count = %d\n",
+               isocdesc->total_completed_frames, isocdesc->total_length, isocdesc->error_count);
+#endif /* CONFIG_USB_DEBUG_ISOC */
+
+       return 0;
+}
+
 static void uhci_interrupt_notify(struct uhci *uhci)
 {
        struct list_head *tmp, *head = &uhci->interrupt_list;
@@ -1311,57 +1526,43 @@ static void uhci_interrupt_notify(struct uhci *uhci)
        spin_lock(&irqlist_lock);
        tmp = head->next;
        while (tmp != head) {
-               struct uhci_td *first, *td = list_entry(tmp,
-                                       struct uhci_td, irq_list);
+               struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list);
+               unsigned long rval;
 
                tmp = tmp->next;
 
-               /* We check the TD which had the IOC bit as well as the */
-               /*  first TD */
-               /* XXX: Shouldn't we check all of the TD's in the chain? */
-               if ((td->qh) && (td->qh->element & ~UHCI_PTR_BITS))
-                       first = uhci_link_to_td(td->qh->element);
-               else
-                       first = NULL;
-
-               /* If any of the error bits are set OR the active is NOT set */
-               /*  then we're interested in this TD */
-               status = td->status & 0xF60000;
-
-               if ((!(status ^ TD_CTRL_ACTIVE)) && (first) &&
-                   (!(first->status & TD_CTRL_ACTIVE)))
-                       status = first->status & 0xF60000;
+               /* We're interested if there was an error or if the chain of */
+               /*  TD's completed successfully */
+               status = uhci_td_result(td->dev, td, &rval, 0);
 
-               if (!(status ^ TD_CTRL_ACTIVE))
+               if ((status == USB_ST_NOERROR) && (td->status & TD_CTRL_ACTIVE))
                        continue;
 
-
                /* remove from IRQ list */
                list_del(&td->irq_list);
                INIT_LIST_HEAD(&td->irq_list);
 
-               if (td->completed(uhci_map_status(uhci_status_bits(status), uhci_packetout(td->info)),
-                   bus_to_virt(td->buffer), -1, td->dev_id)) {
+               if (td->completed(status, bus_to_virt(td->buffer), rval,
+                   td->dev_id)) {
+                       struct usb_device *usb_dev = td->dev->usb;
+
                        list_add(&td->irq_list, &uhci->interrupt_list);
 
-                       /* Isochronous TD's don't need this */
-                       if (!(td->status & TD_CTRL_IOS)) {
-                               struct usb_device *usb_dev = td->dev->usb;
-
-                               usb_dotoggle(usb_dev, uhci_endpoint(td->info), uhci_packetout(td->info));
-                               td->info &= ~(1 << TD_TOKEN_TOGGLE); /* clear data toggle */
-                               td->info |= usb_gettoggle(usb_dev, uhci_endpoint(td->info),
-                                       uhci_packetout(td->info)) << TD_TOKEN_TOGGLE; /* toggle between data0 and data1 */
-                               td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
-                               /* The HC removes it, so re-add it */
-                               uhci_insert_td_in_qh(td->qh, td);
-                       }
+                       usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1);
+                       td->info &= ~(1 << 19); /* clear data toggle */
+                       td->info |= usb_gettoggle(usb_dev, usb_pipeendpoint(td->info),
+                               usb_pipeout(td->info) ^ 1) << 19; /* toggle between data0 and data1 */
+                       td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+                       /* The HC only removes it when it completed */
+                       /* successfully, so force remove and readd it */
+                       uhci_remove_td(td);
+                       uhci_insert_td_in_qh(td->qh, td);
                } else if (td->flags & UHCI_TD_REMOVE) {
                        struct usb_device *usb_dev = td->dev->usb;
 
                        /* marked for removal */
                        td->flags &= ~UHCI_TD_REMOVE;
-                       usb_dotoggle(usb_dev, uhci_endpoint(td->info), uhci_packetout(td->info));
+                       usb_dotoggle(usb_dev, usb_pipeendpoint(td->info), usb_pipeout(td->info) ^ 1);
                        uhci_remove_qh(td->qh->skel, td->qh);
                        uhci_qh_free(td->qh);
                        uhci_td_free(td);
@@ -1406,7 +1607,8 @@ static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
        unsigned short status;
 
        /*
-        * Read the interrupt status, and write it back to clear the interrupt cause
+        * Read the interrupt status, and write it back to clear the
+        * interrupt cause
         */
        status = inw(io_addr + USBSTS);
        outw(status, io_addr + USBSTS);
@@ -1511,9 +1713,9 @@ static void start_hc(struct uhci *uhci)
  * Queues are dynamically allocated for devices now,
  * this code only sets up the skeleton queue
  */
-static struct uhci *alloc_uhci(unsigned int io_addr)
+static struct uhci *alloc_uhci(unsigned int io_addr, unsigned int io_size)
 {
-       int i;
+       int i, port;
        struct uhci *uhci;
        struct usb_bus *bus;
        struct uhci_device *dev;
@@ -1527,6 +1729,7 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
 
        uhci->irq = -1;
        uhci->io_addr = io_addr;
+       uhci->io_size = io_size;
        INIT_LIST_HEAD(&uhci->interrupt_list);
 
        /* We need exactly one page (per UHCI specs), how convenient */
@@ -1544,7 +1747,7 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
        /*
         * Allocate the root_hub
         */
-       usb = uhci_usb_alloc(NULL);
+       usb = usb_alloc_dev(NULL, bus);
        if (!usb)
                goto au_free_bus;
 
@@ -1556,10 +1759,29 @@ static struct uhci *alloc_uhci(unsigned int io_addr)
        uhci->bus->root_hub = uhci_to_usb(dev);
 
        /* Initialize the root hub */
+
        /* UHCI specs says devices must have 2 ports, but goes on to say */
        /* they may have more but give no way to determine how many they */
        /* have, so default to 2 */
-       usb->maxchild = 2;
+       /* According to the UHCI spec, Bit 7 is always set to 1. So we try */
+       /* to use this to our advantage */
+       for (port = 0; port < (io_size - 0x10) / 2; port++) {
+               unsigned int portstatus;
+
+               portstatus = inw(io_addr + 0x10 + (port * 2));
+               if (!(portstatus & 0x0080))
+                       break;
+       }
+       printk(KERN_DEBUG "Detected %d ports\n", port);
+
+       /* This is experimental so anything less than 2 or greater than 8 is */
+       /*  something weird and we'll ignore it */
+       if (port < 2 || port > 8) {
+               printk(KERN_DEBUG "Port count misdetected, forcing to 2 ports\n");
+               port = 2;
+       }
+
+       usb->maxchild = port;
        usb_init_root_hub(usb);
 
        /* 8 Interrupt queues */
@@ -1650,7 +1872,7 @@ static void release_uhci(struct uhci *uhci)
        kfree(uhci);
 }
 
-static int uhci_control_thread(void * __uhci)
+static int uhci_control_thread(void *__uhci)
 {
        struct uhci *uhci = (struct uhci *)__uhci;
 
@@ -1693,7 +1915,7 @@ static int uhci_control_thread(void * __uhci)
 
                        if (signr == SIGUSR1) {
                                printk(KERN_DEBUG "UHCI queue dump:\n");
-                               show_queues(uhci);
+                               uhci_show_queues(uhci);
                        } else if (signr == SIGUSR2) {
                                uhci_debug = !uhci_debug;
                                printk(KERN_DEBUG "UHCI debug toggle = %x\n",
@@ -1716,19 +1938,19 @@ static int uhci_control_thread(void * __uhci)
  * If we've successfully found a UHCI, now is the time to increment the
  * module usage count, start the control thread, and return success..
  */
-static int found_uhci(int irq, unsigned int io_addr)
+static int found_uhci(int irq, unsigned int io_addr, unsigned int io_size)
 {
        int retval;
        struct uhci *uhci;
 
-       uhci = alloc_uhci(io_addr);
+       uhci = alloc_uhci(io_addr, io_size);
        if (!uhci)
                return -ENOMEM;
 
        INIT_LIST_HEAD(&uhci->uhci_list);
        list_add(&uhci->uhci_list, &uhci_list);
 
-       request_region(uhci->io_addr, 32, "usb-uhci");
+       request_region(uhci->io_addr, io_size, "usb-uhci");
 
        reset_hc(uhci);
 
@@ -1754,7 +1976,7 @@ static int found_uhci(int irq, unsigned int io_addr)
        }
 
        reset_hc(uhci);
-       release_region(uhci->io_addr, 32);
+       release_region(uhci->io_addr, uhci->io_size);
 
        release_uhci(uhci);
        return retval;
@@ -1767,18 +1989,18 @@ static int start_uhci(struct pci_dev *dev)
        /* Search for the IO base address.. */
        for (i = 0; i < 6; i++) {
                unsigned int io_addr = dev->resource[i].start;
+               unsigned int io_size =
+                       dev->resource[i].end - dev->resource[i].start;
 
                /* IO address? */
                if (!(dev->resource[i].flags & 1))
                        continue;
 
-#if 0
                /* Is it already in use? */
-               if (check_region(io_addr, 32))
+               if (check_region(io_addr, io_size))
                        break;
-#endif
 
-               return found_uhci(dev->irq, io_addr);
+               return found_uhci(dev->irq, io_addr, io_size);
        }
        return -1;
 }
@@ -1819,30 +2041,15 @@ int uhci_init(void)
        int retval;
        struct pci_dev *dev = NULL;
        u8 type;
-       char *name;
 
-       /* FIXME: This is lame, but I guess it's better to leak memory than */
-       /* crash */
-       name = kmalloc(10, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
-
-       strcpy(name, "uhci_td");
-
-       uhci_td_cachep = kmem_cache_create(name,
+       uhci_td_cachep = kmem_cache_create("uhci_td",
                sizeof(struct uhci_td), 0,
                SLAB_HWCACHE_ALIGN, NULL, NULL);
 
        if (!uhci_td_cachep)
                return -ENOMEM;
 
-       name = kmalloc(10, GFP_KERNEL);
-       if (!name)
-               return -ENOMEM;
-
-       strcpy(name, "uhci_qh");
-
-       uhci_qh_cachep = kmem_cache_create(name,
+       uhci_qh_cachep = kmem_cache_create("uhci_qh",
                sizeof(struct uhci_qh), 0,
                SLAB_HWCACHE_ALIGN, NULL, NULL);
 
@@ -1854,10 +2061,12 @@ int uhci_init(void)
                dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev);
                if (!dev)
                        break;
+
                /* Is it UHCI */
                pci_read_config_byte(dev, PCI_CLASS_PROG, &type);
-               if(type != 0)
+               if (type != 0)
                        continue;
+
                /* Ok set it up */
                retval = start_uhci(dev);
                if (retval < 0)
@@ -1889,7 +2098,8 @@ void uhci_cleanup(void)
                /* Check if the process is still running */
                ret = kill_proc(uhci->control_pid, 0, 1);
                if (!ret) {
-                       int count = 10;
+                       /* Try a maximum of 10 seconds */
+                       int count = 10 * 100;
 
                        uhci->control_continue = 0;
                        wake_up(&uhci_configure);
@@ -1910,7 +2120,7 @@ void uhci_cleanup(void)
                usb_deregister_bus(uhci->bus);
 
                reset_hc(uhci);
-               release_region(uhci->io_addr, 32);
+               release_region(uhci->io_addr, uhci->io_size);
 
                release_uhci(uhci);
 
index 1432b6909fe6c15debc8769b33eaf807dfb858db..f1a2d35c023c0e709da60410017d239b58a2690e 100644 (file)
 #define UHCI_PTR_QH            0x0002
 #define UHCI_PTR_DEPTH         0x0004
 
+#define UHCI_NUMFRAMES         1024
+
+struct uhci_td;
+
 struct uhci_qh {
        /* Hardware fields */
        __u32 link;                             /* Next queue */
@@ -70,6 +74,8 @@ struct uhci_qh {
        struct uhci_device *dev;                /* The owning device */
        struct uhci_qh *skel;                   /* Skeleton head */
 
+       struct uhci_td *first;                  /* First TD in the chain */
+
        wait_queue_head_t wakeup;
 } __attribute__((aligned(16)));
 
@@ -81,6 +87,7 @@ struct uhci_framelist {
  * for TD <status>:
  */
 #define TD_CTRL_SPD            (1 << 29)       /* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK     (3 << 27)       /* Error Counter bits */
 #define TD_CTRL_LS             (1 << 26)       /* Low Speed Device */
 #define TD_CTRL_IOS            (1 << 25)       /* Isochronous Select */
 #define TD_CTRL_IOC            (1 << 24)       /* Interrupt on Complete */
@@ -89,14 +96,14 @@ struct uhci_framelist {
 #define TD_CTRL_DBUFERR                (1 << 21)       /* Data Buffer Error */
 #define TD_CTRL_BABBLE         (1 << 20)       /* Babble Detected */
 #define TD_CTRL_NAK            (1 << 19)       /* NAK Received */
-#define TD_CTRL_CRCTIME                (1 << 18)       /* CTC/Time Out Error */
+#define TD_CTRL_CRCTIMEO       (1 << 18)       /* CRC/Time Out Error */
 #define TD_CTRL_BITSTUFF       (1 << 17)       /* Bit Stuff Error */
 #define TD_CTRL_ACTLEN_MASK    0x7ff           /* actual length, encoded as n - 1 */
 
 #define TD_CTRL_ANY_ERROR      (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
                                 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
 
-#define uhci_status_bits(ctrl_sts)     ((ctrl_sts >> 16) & 0xff)
+#define uhci_status_bits(ctrl_sts)     (ctrl_sts & 0xFE0000)
 #define uhci_actual_length(ctrl_sts)   ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
 
 #define uhci_ptr_to_virt(x)    bus_to_virt(x & ~UHCI_PTR_BITS)
@@ -120,6 +127,20 @@ struct uhci_framelist {
 #define uhci_packetout(token)  (uhci_packetid(token) != USB_PID_IN)
 #define uhci_packetin(token)   (uhci_packetid(token) == USB_PID_IN)
 
+/*
+ * for TD <info>: (a.k.a. Token)
+ */
+#define TD_TOKEN_TOGGLE                19
+
+#define uhci_maxlen(token)     ((token) >> 21)
+#define uhci_toggle(token)     (((token) >> TD_TOKEN_TOGGLE) & 1)
+#define uhci_endpoint(token)   (((token) >> 15) & 0xf)
+#define uhci_devaddr(token)    (((token) >> 8) & 0x7f)
+#define uhci_devep(token)      (((token) >> 8) & 0x7ff)
+#define uhci_packetid(token)   ((token) & 0xff)
+#define uhci_packetout(token)  (uhci_packetid(token) != USB_PID_IN)
+#define uhci_packetin(token)   (uhci_packetid(token) == USB_PID_IN)
+
 
 /*
  * The documentation says "4 words for hardware, 4 words for software".
@@ -152,6 +173,7 @@ struct uhci_td {
        struct uhci_device *dev;        /* The owning device */
        struct uhci_qh *qh;             /* QH this TD is a part of (ignored for Isochronous) */
        int flags;                      /* Remove, etc */
+       int isoc_td_number;             /* 0-relative number within a usb_isoc_desc. */
 } __attribute__((aligned(16)));
 
 struct uhci_iso_td {
@@ -180,10 +202,12 @@ struct uhci;
 #define UHCI_MAXQH     16
 #endif
 
-/* The usb device part must be first! */
+/* The usb device part must be first! Not anymore -jerdfelt */
 struct uhci_device {
        struct usb_device       *usb;
 
+       atomic_t                refcnt;
+
        struct uhci             *uhci;
 #if 0
        struct uhci_qh          qh[UHCI_MAXQH];         /* These are the "common" qh's for each device */
@@ -260,6 +284,7 @@ struct uhci_device {
 struct uhci {
        int irq;
        unsigned int io_addr;
+       unsigned int io_size;
 
        int control_pid;
        int control_running;
@@ -281,9 +306,10 @@ struct uhci {
 struct uhci_td *uhci_link_to_td(unsigned int element);
 
 /* Debugging code */
-void show_td(struct uhci_td * td);
-void show_status(struct uhci *uhci);
-void show_queues(struct uhci *uhci);
+void uhci_show_td(struct uhci_td *td);
+void uhci_show_status(struct uhci *uhci);
+void uhci_show_queue(struct uhci_qh *qh);
+void uhci_show_queues(struct uhci *uhci);
 
 #endif
 
index 36010f24c6a17f2c2bf89f55318768192dc598db..501a726da7138fa3bffbe1a07174878f9eb374b0 100644 (file)
@@ -18,24 +18,27 @@ static void usb_show_interface(struct usb_interface_descriptor *altsetting)
        int i;
 
        usb_show_interface_descriptor(altsetting);
-       for (i = 0 ; i < altsetting->bNumEndpoints; i++)
+
+       for (i = 0; i < altsetting->bNumEndpoints; i++)
                usb_show_endpoint(altsetting->endpoint + i);
 }
 
 static void usb_show_config(struct usb_config_descriptor *config)
 {
-  int i, j;
-  struct usb_interface *intf;
-
-  usb_show_config_descriptor(config);
-  for (i = 0; i < config->bNumInterfaces; i++) {
-    intf = config->interface + i;
-    if ((intf) == NULL)
-      break;
-    printk("\n  Interface: %d\n", i);
-    for (j = 0 ; j < intf->num_altsetting; j++)
-      usb_show_interface(intf->altsetting + j);
-  }
+       int i, j;
+       struct usb_interface *ifp;
+
+       usb_show_config_descriptor(config);
+       for (i = 0; i < config->bNumInterfaces; i++) {
+               ifp = config->interface + i;
+
+               if (!ifp)
+                       break;
+
+               printk("\n  Interface: %d\n", i);
+               for (j = 0; j < ifp->num_altsetting; j++)
+                       usb_show_interface(ifp->altsetting + j);
+       }
 }
 
 void usb_show_device(struct usb_device *dev)
@@ -47,7 +50,6 @@ void usb_show_device(struct usb_device *dev)
                usb_show_config(dev->config + i);
 }
 
-
 /*
  * Parse and show the different USB descriptors.
  */
@@ -72,10 +74,25 @@ void usb_show_device_descriptor(struct usb_device_descriptor *desc)
        case 0:
                printk("    Per-interface classes\n");
                break;
-       case 9:
+       case USB_CLASS_AUDIO:
+               printk("    Audio device class\n");
+               break;
+       case USB_CLASS_COMM:
+               printk("    Communications class\n");
+               break;
+       case USB_CLASS_HID:
+               printk("    Human Interface Devices class\n");
+               break;
+       case USB_CLASS_PRINTER:
+               printk("    Printer device class\n");
+               break;
+       case USB_CLASS_MASS_STORAGE:
+               printk("    Mass Storage device class\n");
+               break;
+       case USB_CLASS_HUB:
                printk("    Hub device class\n");
                break;
-       case 0xff:
+       case USB_CLASS_VENDOR_SPEC:
                printk("    Vendor class\n");
                break;
        default:
@@ -83,7 +100,7 @@ void usb_show_device_descriptor(struct usb_device_descriptor *desc)
        }
 }
 
-void usb_show_config_descriptor(struct usb_config_descriptor * desc)
+void usb_show_config_descriptor(struct usb_config_descriptor *desc)
 {
        printk("Configuration:\n");
        printk("  bLength             = %4d%s\n", desc->bLength,
@@ -97,7 +114,7 @@ void usb_show_config_descriptor(struct usb_config_descriptor * desc)
        printk("  MaxPower            = %4dmA\n", desc->MaxPower * 2);
 }
 
-void usb_show_interface_descriptor(struct usb_interface_descriptor * desc)
+void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
 {
        printk("  Alternate Setting: %2d\n", desc->bAlternateSetting);
        printk("    bLength             = %4d%s\n", desc->bLength,
@@ -111,15 +128,33 @@ void usb_show_interface_descriptor(struct usb_interface_descriptor * desc)
        printk("    iInterface          =   %02x\n", desc->iInterface);
 }
 
-void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor * desc)
+void usb_show_hid_descriptor(struct usb_hid_descriptor * desc)
 {
-       char *bLengthCommentString = (USB_DT_AUCLSTEP_SIZE == desc->bLength) ?
-                 " (!Audio)" : " (!!!)";
+       int i;
+    
+       printk("    HID:\n");
+       printk("      HID version %x.%02x\n", desc->bcdHID >> 8, desc->bcdHID & 0xff);
+       printk("      bLength             = %4d\n", desc->bLength);
+       printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
+       printk("      bCountryCode        =   %02x\n", desc->bCountryCode);
+       printk("      bNumDescriptors     =   %02x\n", desc->bNumDescriptors);
+
+       for (i=0; i<desc->bNumDescriptors; i++) {
+               printk("        %d:\n", i);
+               printk("            bDescriptorType      =   %02x\n", desc->desc[i].bDescriptorType);
+               printk("            wDescriptorLength    =   %04x\n", desc->desc[i].wDescriptorLength);
+       }
+}
 
+void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
+{
+       char *LengthCommentString = (desc->bLength ==
+               USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
+               USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
        char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
        printk("    Endpoint:\n");
        printk("      bLength             = %4d%s\n", desc->bLength,
-               desc->bLength == USB_DT_ENDPOINT_SIZE ? "" : bLengthCommentString);
+               LengthCommentString);
        printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
        printk("      bEndpointAddress    =   %02x (%s)\n", desc->bEndpointAddress,
                (desc->bEndpointAddress & 0x80) ? "in" : "out");
@@ -127,29 +162,19 @@ void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor * desc)
                EndpointType[3 & desc->bmAttributes]);
        printk("      wMaxPacketSize      = %04x\n", desc->wMaxPacketSize);
        printk("      bInterval           =   %02x\n", desc->bInterval);
-       if (USB_DT_AUCLSTEP_SIZE == desc->bLength) {
-               printk("      bRefresh            = %04x\n", desc->bRefresh);
-               printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
-       }
-}
-
-void usb_show_hub_descriptor(struct usb_hub_descriptor * desc)
-{
-       int len = 7;
-       unsigned char *ptr = (unsigned char *) desc;
 
-       printk("Interface:");
-       while (len) {
-               printk(" %02x", *ptr);
-               ptr++; len--;
+       /* Audio extensions to the endpoint descriptor */
+       if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
+               printk("      bRefresh            =   %02x\n", desc->bRefresh);
+               printk("      bSynchAddress       =   %02x\n", desc->bSynchAddress);
        }
-       printk("\n");
 }
 
-void usb_show_string(struct usb_devicedev, char *id, int index)
+void usb_show_string(struct usb_device *dev, char *id, int index)
 {
        char *p = usb_string(dev, index);
 
        if (p != 0)
                printk(KERN_INFO "%s: %s\n", id, p);
 }
+
index a6ba923b2e3dd96f5b7f97b2288cb14437260887..b028f4bf1e0ac54e9079d73c3aac523e74766ef1 100644 (file)
@@ -2,6 +2,7 @@
  * drivers/usb/usb.c
  *
  * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
  * are evil.
  */
 
-/*
- * Table 9-2
- *
- * Offset      Field           Size    Value           Desc
- * 0           bmRequestType   1       Bitmap          D7:     Direction
- *                                                     0 = Host-to-device
- *                                                     1 = Device-to-host
- *                                                     D6..5:  Type
- *                                                     0 = Standard
- *                                                     1 = Class
- *                                                     2 = Vendor
- *                                                     3 = Reserved
- *                                                     D4..0:  Recipient
- *                                                     0 = Device
- *                                                     1 = Interface
- *                                                     2 = Endpoint
- *                                                     3 = Other
- *                                                     4..31 = Reserved
- * 1           bRequest        1       Value           Specific request (9-3)
- * 2           wValue          2       Value           Varies
- * 4           wIndex          2       Index/Offset    Varies
- * 6           wLength         2       Count           Bytes for data
- */
-
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
@@ -67,7 +44,7 @@ int usb_register(struct usb_driver *new_driver)
         */
        tmp = usb_bus_list.next;
        while (tmp != &usb_bus_list) {
-               struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
+               struct usb_bus *bus = list_entry(tmp,struct usb_bus, bus_list);
 
                tmp = tmp->next;
                usb_check_support(bus->root_hub);
@@ -96,12 +73,13 @@ void usb_deregister(struct usb_driver *driver)
        }
 }
 
-/* This function is part of a depth-first search down the device tree,
+/*
+ * This function is part of a depth-first search down the device tree,
  * removing any instances of a device driver.
  */
-void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev)
+static void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev)
 {
-       int i;
+       int i;
 
        if (!dev) {
                printk(KERN_ERR "usbcore: null device being purged!!!\n");
@@ -158,16 +136,16 @@ void usb_free_bus(struct usb_bus *bus)
        if (!bus)
                return;
 
-       if (bus->bus_list.next != &bus->bus_list)
-               printk(KERN_ERR "usbcore: freeing non-empty bus\n");
-
        kfree(bus);
 }
 
-void usb_register_bus(struct usb_bus *new_bus)
+void usb_register_bus(struct usb_bus *bus)
 {
+       proc_usb_add_bus(bus);
+
        /* Add it to the list of buses */
-       list_add(&new_bus->bus_list, &usb_bus_list);
+       list_add(&bus->bus_list, &usb_bus_list);
+
        printk("New USB bus registered\n");
 }
 
@@ -179,13 +157,15 @@ void usb_deregister_bus(struct usb_bus *bus)
         * itself up
         */
        list_del(&bus->bus_list);
+
+       proc_usb_remove_bus(bus);
 }
 
 /*
  * This function is for doing a depth-first search for devices which
  * have support, for dynamic loading of driver modules.
  */
-void usb_check_support(struct usb_device *dev)
+static void usb_check_support(struct usb_device *dev)
 {
        int i;
 
@@ -209,7 +189,7 @@ void usb_check_support(struct usb_device *dev)
  * looking for one that will accept this device as
  * his..
  */
-int usb_find_driver(struct usb_device *dev)
+static int usb_find_driver(struct usb_device *dev)
 {
        struct list_head *tmp = usb_driver_list.next;
 
@@ -231,283 +211,311 @@ int usb_find_driver(struct usb_device *dev)
 }
 
 /*
- * Parse the fairly incomprehensible output of
- * the USB configuration data, and build up the
- * USB device database.
+ * Only HC's should call usb_alloc_dev and usb_free_dev directly
+ * Anybody may use usb_inc_dev_use or usb_dec_dev_use
  */
-static int usb_expect_descriptor(unsigned char *ptr, int len, unsigned char desctype, unsigned char descindex)
+struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
 {
-       int parsed = 0;
-       int n_len;
-       unsigned short n_desc;
+       struct usb_device *dev;
 
-       for (;;) {
-               int i;
+       dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
 
-               if (len < descindex)
-                       return -1;
-               n_desc = le16_to_cpup((unsigned short *)ptr);
-               n_len = ptr[0];
+       memset(dev, 0, sizeof(*dev));
 
-               if (n_desc == ((desctype << 8) + descindex))
-                       break;
+       dev->bus = bus;
+       dev->parent = parent;
+       atomic_set(&dev->refcnt, 1);
 
-               if (((n_desc >> 8)&0xFF) == desctype &&
-                       n_len > descindex)
-               {
-                       printk("bug: oversized descriptor.\n");
-                       break;
-               }
-                       
-               if (n_len < 2 || n_len > len)
-               {
-                       printk("Short descriptor\n");
-                       return -1;
-               }
-               printk(
-               "Expected descriptor %02X/%02X, got %02X/%02X - skipping\n",
-                       desctype, descindex,
-                       (n_desc >> 8) & 0xFF, n_desc & 0xFF);
-               for (i = 0 ; i < n_len; i++)
-                       printk("   %d %02x\n", i, ptr[i]);
-               len -= n_len;
-               ptr += n_len;
-               parsed += n_len;
+       dev->bus->op->allocate(dev);
+
+       return dev;
+}
+
+void usb_free_dev(struct usb_device *dev)
+{
+       if (atomic_dec_and_test(&dev->refcnt)) {
+               usb_destroy_configuration(dev);
+               kfree(dev);
+
+               dev->bus->op->deallocate(dev);
        }
-       
-       printk("Found %02X:%02X\n",
-               desctype, descindex);
-       return parsed;
 }
 
-/*
- * Parse the even more incomprehensible mess made of the USB spec
- * by USB audio having private magic to go with it.
- */
-static int usb_check_descriptor(unsigned char *ptr, int len, unsigned char desctype)
+void usb_inc_dev_use(struct usb_device *dev)
 {
-       int n_len = ptr[0];
+       atomic_inc(&dev->refcnt);
+}
 
-       if (len <= 0)
-               return -1;
+static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
+{
+       struct usb_descriptor_header *header;
+       int parsed = 0;
+
+       header = (struct usb_descriptor_header *)buffer;
 
-       if (n_len < 2 || n_len > len) {
-               int i;
-               printk("Short descriptor. (%d, %d):\n", len, n_len);
-               for (i = 0; i < len; ++i)
-                       printk(" %d: %x\n", i, ptr[i]);
+       /* Everything should be fine being passed into here, but we sanity */
+       /*  check JIC */
+       if (header->bLength > size) {
+               printk(KERN_ERR "usb: ran out of descriptors parsing\n");
                return -1;
        }
-
-       if (ptr[1] == desctype)
-               return 0;
                
-       return -1;
-}
+       if (header->bDescriptorType != USB_DT_ENDPOINT) {
+               printk(KERN_INFO "usb: unexpected descriptor 0x%X\n",
+                       endpoint->bDescriptorType);
+               return parsed;
+       }
 
+       memcpy(endpoint, buffer, USB_DT_ENDPOINT_SIZE);
+        le16_to_cpus(&endpoint->wMaxPacketSize);
 
-static int usb_parse_endpoint(struct usb_device *dev, struct usb_endpoint_descriptor *endpoint, unsigned char *ptr, int len)
-{
-       int parsed = usb_expect_descriptor(ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE);
-       int i;
+       buffer += header->bLength;
+       size -= header->bLength;
+       parsed += header->bLength;
 
-       if (parsed < 0)
-               return parsed;
-       memcpy(endpoint, ptr + parsed, ptr[parsed]);
-       le16_to_cpus(&endpoint->wMaxPacketSize);
+       /* Skip over the rest of the Class Specific or Vendor Specific */
+       /*  descriptors */
+       while (size >= sizeof(struct usb_descriptor_header)) {
+               header = (struct usb_descriptor_header *)buffer;
 
-       parsed += ptr[parsed];
-       len -= parsed;
+               if (header->bLength < 2) {
+                       printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength);
+                       return -1;
+               }
+
+               /* If we find another descriptor which is at or below us */
+               /*  in the descriptor heirarchy then return */
+               if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
+                   (header->bDescriptorType == USB_DT_INTERFACE) ||
+                   (header->bDescriptorType == USB_DT_CONFIG) ||
+                   (header->bDescriptorType == USB_DT_DEVICE))
+                       return parsed;
 
-       while((i = usb_check_descriptor(ptr+parsed, len, 0x25)) >= 0) {
-               usb_audio_endpoint(endpoint, ptr+parsed+i);
-               len -= ptr[parsed+i];
-               parsed += ptr[parsed+i];
+               printk(KERN_INFO "usb: skipping descriptor 0x%X\n",
+                       header->bDescriptorType);
+
+               buffer += header->bLength;
+               size -= header->bLength;
+               parsed += header->bLength;
        }
-       
-       return parsed;// + ptr[parsed];
+
+       return parsed;
 }
 
-static int usb_parse_altsetting(struct usb_device *dev, struct usb_interface_descriptor *altsetting, unsigned char *ptr, int len)
+#if 0
+static int usb_parse_hid(struct usb_device *dev, struct usb_hid_descriptor *hid, unsigned char *ptr, int len)
 {
+       int parsed = usb_expect_descriptor(ptr, len, USB_DT_HID, ptr[0]);
        int i;
-       int parsed = usb_expect_descriptor(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE);
-       int retval;
 
        if (parsed < 0)
                return parsed;
 
-       memcpy(altsetting, ptr + parsed, *ptr);
-       len -= ptr[parsed];
-       parsed += ptr[parsed];
+       memcpy(hid, ptr + parsed, ptr[parsed]);
+       le16_to_cpus(&hid->bcdHID);
 
-       while((i=usb_check_descriptor(ptr+parsed, len, 0x24)) >= 0) {
-               usb_audio_interface(altsetting, ptr+parsed+i);
-               len -= ptr[parsed+i];
-               parsed += ptr[parsed+i];
-       }
-       
-       if (altsetting->bNumEndpoints > USB_MAXENDPOINTS) {
-               printk(KERN_WARNING "usb: too many endpoints.\n");
-               return -1;
-       }
+       for (i=0; i<hid->bNumDescriptors; i++)
+               le16_to_cpus(&(hid->desc[i].wDescriptorLength));
 
-       altsetting->endpoint = (struct usb_endpoint_descriptor *)
-               kmalloc(altsetting->bNumEndpoints * sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
-       if (!altsetting->endpoint) {
-               printk(KERN_WARNING "usb: out of memory.\n");
-               return -1;      
-       }
-       memset(altsetting->endpoint, 0, altsetting->bNumEndpoints*sizeof(struct usb_endpoint_descriptor));
-       
-       for (i = 0; i < altsetting->bNumEndpoints; i++) {
-//             if(((USB_DT_HID << 8) | 9) == *(unsigned short*)(ptr + parsed)) {
-//                     parsed += 9;    /* skip over the HID descriptor for now */
-//                     len -= 9;
-//             }
-               retval = usb_parse_endpoint(dev, altsetting->endpoint + i, ptr + parsed, len);
-               if (retval < 0)
-                       return retval;
-               parsed += retval;
-               len -= retval;
-       }
-       return parsed;
+       return parsed + ptr[parsed];
 }
+#endif
 
-static int usb_parse_config(struct usb_device *dev, struct usb_config_descriptor *config, unsigned char *ptr, int len)
+static int usb_parse_interface(struct usb_device *dev, struct usb_interface *interface, unsigned char *buffer, int size)
 {
        int i;
-       int retval;
-       struct usb_interface *intf;
-       struct usb_interface_descriptor as;     /* This is needing for copying. */
-       int parsed = usb_expect_descriptor(ptr, len, USB_DT_CONFIG, 9);
-       unsigned short bNumInterfaces;
-       unsigned short bIntfaceNum = 0, bAltSetting = 0;
+       int retval, parsed = 0;
+       struct usb_descriptor_header *header;
+       struct usb_interface_descriptor *ifp;
 
-       if (parsed < 0)
-               return parsed;
-
-       memcpy(config, ptr + parsed, *ptr);
-       len -= *ptr;
-       parsed += *ptr;
-       le16_to_cpus(&config->wTotalLength);
-       bNumInterfaces = config->bNumInterfaces;
+       interface->act_altsetting = 0;
+       interface->num_altsetting = 0;
 
-       if (bNumInterfaces > USB_MAXINTERFACES) {
-               printk(KERN_WARNING "usb: too many interfaces.\n");
+       interface->altsetting = kmalloc(sizeof(struct usb_interface_descriptor) * USB_MAXALTSETTING, GFP_KERNEL);
+       if (!interface->altsetting) {
+               printk("couldn't kmalloc interface->altsetting\n");
                return -1;
        }
 
-       config->interface = (struct usb_interface *)
-               kmalloc(bNumInterfaces * sizeof(struct usb_interface), GFP_KERNEL);
-       if (!config->interface) {
-               printk(KERN_WARNING "usb: out of memory.\n");
-               return -1;
-       }
-       memset(config->interface, 
-                  0, (bNumInterfaces) * sizeof(struct usb_interface));
-
-       for (i = 0; i < bNumInterfaces; i++) {
-               intf = (config->interface) +i;
-               /* We have at least one interface */
-               intf->num_altsetting = 1;
-               intf->altsetting = (struct usb_interface_descriptor*)
-                       kmalloc((USB_MAXALTSETTING +1) * sizeof(struct usb_interface_descriptor), GFP_KERNEL);
-               if (!config->interface[i].altsetting) {
-                       printk(KERN_WARNING "usb: out of memory.\n");
-                       return -1;      
-               }
-               memset(intf->altsetting, 
-                          0, (USB_MAXALTSETTING+1) * sizeof(struct usb_interface_descriptor));
-       }
-               
-       /* Ok, we now have allocated the necessary structures, now decide
-     * where to put the parsed interface descriptors - sort by
-        * bAltSetting and bInterfaceNumber.
-        */
-       while (len > 0) {
-               retval = usb_parse_altsetting(dev, &as, ptr + parsed, len);
-               if (retval < 0)
-                       return parsed; // HACK
-       //              return retval;
-               parsed += retval;
-               len -= retval;
-               bIntfaceNum = as.bInterfaceNumber;
-               if (bIntfaceNum > config->bNumInterfaces) {
-                       printk(KERN_WARNING "usb: bInterfaceNumber %2u exceeding config->bNumINterfaces.\n", bIntfaceNum);
+       while (size > 0) {
+               ifp = interface->altsetting + interface->num_altsetting;
+               interface->num_altsetting++;
+
+               if (interface->num_altsetting >= USB_MAXALTSETTING) {
+                       printk(KERN_WARNING "usb: too many alternate settings\n");
                        return -1;
                }
-               bAltSetting = as.bAlternateSetting;
-               if (bAltSetting > USB_MAXALTSETTING) {
-                       printk(KERN_WARNING "usb: illegal bAlternateSetting %2u.\n", bAltSetting);
+               memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE);
+
+               /* Skip over the interface */
+               buffer += ifp->bLength;
+               parsed += ifp->bLength;
+               size -= ifp->bLength;
+
+               /* Skip over at Interface class or vendor descriptors */
+               while (size >= sizeof(struct usb_descriptor_header)) {
+                       header = (struct usb_descriptor_header *)buffer;
+
+                       if (header->bLength < 2) {
+                               printk(KERN_ERR "usb: invalid descriptor length of %d\n", header->bLength);
+                               return -1;
+                       }
+
+                       /* If we find another descriptor which is at or below us */
+                       /*  in the descriptor heirarchy then return */
+                       if ((header->bDescriptorType == USB_DT_INTERFACE) ||
+                           (header->bDescriptorType == USB_DT_ENDPOINT))
+                               break;
+
+                       if ((header->bDescriptorType == USB_DT_CONFIG) ||
+                           (header->bDescriptorType == USB_DT_DEVICE))
+                               return parsed;
+
+                       if (header->bDescriptorType == USB_DT_HID)
+                               printk(KERN_INFO "usb: skipping HID descriptor\n");
+                       else
+                               printk(KERN_INFO "usb: unexpected descriptor 0x%X\n",
+                                       header->bDescriptorType);
+
+                       buffer += header->bLength;
+                       parsed += header->bLength;
+                       size -= header->bLength;
+               }
+
+               if (ifp->bNumEndpoints > USB_MAXENDPOINTS) {
+                       printk(KERN_WARNING "usb: too many endpoints\n");
                        return -1;
                }
-               if (bAltSetting > config->interface[bIntfaceNum].num_altsetting) {
-                       config->interface[bIntfaceNum].num_altsetting = bAltSetting +1;
+
+               ifp->endpoint = (struct usb_endpoint_descriptor *)
+                       kmalloc(ifp->bNumEndpoints *
+                       sizeof(struct usb_endpoint_descriptor), GFP_KERNEL);
+               if (!ifp->endpoint) {
+                       printk(KERN_WARNING "usb: out of memory\n");
+                       return -1;      
                }
-               memcpy( &(config->interface[bIntfaceNum].altsetting[bAltSetting]),
-                               &as, sizeof(struct usb_interface_descriptor));
+
+               memset(ifp->endpoint, 0, ifp->bNumEndpoints *
+                       sizeof(struct usb_endpoint_descriptor));
+       
+               for (i = 0; i < ifp->bNumEndpoints; i++) {
+                       header = (struct usb_descriptor_header *)buffer;
+
+                       if (header->bLength > size) {
+                               printk(KERN_ERR "usb: ran out of descriptors parsing\n");
+                               return -1;
+                       }
+               
+                       retval = usb_parse_endpoint(dev, ifp->endpoint + i, buffer, size);
+                       if (retval < 0)
+                               return retval;
+
+                       buffer += retval;
+                       parsed += retval;
+                       size -= retval;
+               }
+
+               /* We check to see if it's an alternate to this one */
+               ifp = (struct usb_interface_descriptor *)buffer;
+               if (size < USB_DT_INTERFACE_SIZE ||
+                   ifp->bDescriptorType != USB_DT_INTERFACE ||
+                   !ifp->bAlternateSetting)
+                       return parsed;
        }
 
-       printk("parsed = %d len = %d\n", parsed, len);
        return parsed;
 }
 
-int usb_parse_configuration(struct usb_device *dev, void *__buf, int bytes)
+static int usb_parse_configuration(struct usb_device *dev, struct usb_config_descriptor *config, char *buffer)
 {
        int i;
-       unsigned char *ptr = __buf;
+       int retval;
+       int size;
+       struct usb_descriptor_header *header;
 
-       if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
-               printk(KERN_WARNING "usb: too many configurations.\n");
+       memcpy(config, buffer, USB_DT_INTERFACE_SIZE);
+
+       le16_to_cpus(&config->wTotalLength);
+       size = config->wTotalLength;
+
+       if (config->bNumInterfaces > USB_MAXINTERFACES) {
+               printk(KERN_WARNING "usb: too many interfaces\n");
                return -1;
        }
 
-       dev->config = (struct usb_config_descriptor *)
-               kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL);
-       if (!dev->config) {
-               printk(KERN_WARNING "usb: out of memory.\n");
+       config->interface = (struct usb_interface *)
+               kmalloc(config->bNumInterfaces *
+               sizeof(struct usb_interface), GFP_KERNEL);
+       if (!config->interface) {
+               printk(KERN_WARNING "usb: out of memory\n");
                return -1;      
        }
-       memset(dev->config, 0, dev->descriptor.bNumConfigurations*sizeof(struct usb_config_descriptor));
-       for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-               int retval = usb_parse_config(dev, dev->config + i, ptr, bytes);
+
+       memset(config->interface, 0,
+              config->bNumInterfaces*sizeof(struct usb_interface_descriptor));
+
+       buffer += config->bLength;
+       size -= config->bLength;
+       
+       for (i = 0; i < config->bNumInterfaces; i++) {
+               header = (struct usb_descriptor_header *)buffer;
+               if (header->bLength > size) {
+                       printk(KERN_ERR "usb: ran out of descriptors parsing\n");
+                       return -1;
+               }
+               
+               if (header->bDescriptorType != USB_DT_INTERFACE) {
+                       printk(KERN_INFO "usb: unexpected descriptor 0x%X\n",
+                               header->bDescriptorType);
+
+                       buffer += header->bLength;
+                       size -= header->bLength;
+                       continue;
+               }
+
+               retval = usb_parse_interface(dev, config->interface + i, buffer, size);
                if (retval < 0)
                        return retval;
-               ptr += retval;
-               bytes -= retval;
+
+               buffer += retval;
+               size -= retval;
        }
-       if (bytes)
-               printk(KERN_WARNING "usb: %d bytes of extra configuration data left\n", bytes);
-       return 0;
+
+       return size;
 }
 
 void usb_destroy_configuration(struct usb_device *dev)
 {
-       int c, a, i;
-       struct usb_config_descriptor *cf;
-       struct usb_interface *intf;
-       struct usb_interface_descriptor *as;
+       int c, i, j;
        
        if (!dev->config)
                return;
 
        for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
-               cf = &dev->config[c];
+               struct usb_config_descriptor *cf = &dev->config[c];
+
                if (!cf->interface)
                        break;
-               for (a = 0; a < cf->bNumInterfaces; a++) {
-                       intf = &cf->interface[a];
-                       if (intf->altsetting == NULL)
+
+               for (i = 0; i < cf->bNumInterfaces; i++) {
+                       struct usb_interface *ifp =
+                               &cf->interface[i];
+
+                       if (!ifp->altsetting)
                                break;
-                       for(i=0; i <= USB_MAXALTSETTING ;i++) {
-                               as = &intf->altsetting[i];
-                               if(as->endpoint==NULL)
-                                      break;
+
+                       for (j = 0; j < ifp->num_altsetting; j++) {
+                               struct usb_interface_descriptor *as =
+                                       &ifp->altsetting[j];
+
+                               if (!as->endpoint)
+                                       break;
+
                                kfree(as->endpoint);
                        }
-                       kfree(intf->altsetting);
+                       kfree(ifp->altsetting);
                }
                kfree(cf->interface);
        }
@@ -531,29 +539,33 @@ void usb_init_root_hub(struct usb_device *dev)
 void usb_disconnect(struct usb_device **pdev)
 {
        struct usb_device * dev = *pdev;
+       int i;
 
-       if (dev) {
-               int i;
-
-               *pdev = NULL;
+       if (!dev)
+               return;
 
-               printk("USB disconnect on device %d\n", dev->devnum);
+       *pdev = NULL;
 
-               if(dev->driver) dev->driver->disconnect(dev);
+       printk("USB disconnect on device %d\n", dev->devnum);
 
-               /* Free up all the children.. */
-               for (i = 0; i < USB_MAXCHILDREN; i++) {
-                       struct usb_device **child = dev->children + i;
-                       usb_disconnect(child);
-               }
+       if (dev->driver)
+               dev->driver->disconnect(dev);
 
-               /* Free up the device itself, including its device number */
-               if (dev->devnum > 0)
-                       clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
-               dev->bus->op->deallocate(dev);
+       /* Free up all the children.. */
+       for (i = 0; i < USB_MAXCHILDREN; i++) {
+               struct usb_device **child = dev->children + i;
+               usb_disconnect(child);
        }
-}
 
+       /* remove /proc/bus/usb entry */
+       proc_usb_remove_device(dev);
+
+       /* Free up the device itself, including its device number */
+       if (dev->devnum > 0)
+               clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
+
+       usb_free_dev(dev);
+}
 
 /*
  * Connect a new USB device. This basically just initializes
@@ -704,12 +716,13 @@ int usb_set_idle(struct usb_device *dev,  int duration, int report_id)
 static void usb_set_maxpacket(struct usb_device *dev)
 {
        int i, j;
-       struct usb_interface *intf;
+       struct usb_interface *ifp;
 
        for (i=0; i<dev->actconfig->bNumInterfaces; i++) {
-               intf = (dev->actconfig->interface) +i;
-               for (j = 0; j < intf->num_altsetting; j++) {
-                       struct usb_interface_descriptor *as = intf->altsetting +j;
+               ifp = dev->actconfig->interface + i;
+
+               for (j = 0; j < ifp->num_altsetting; j++) {
+                       struct usb_interface_descriptor *as = ifp->altsetting + j;
                        struct usb_endpoint_descriptor *ep = as->endpoint;
                        int e;
 
@@ -718,7 +731,7 @@ static void usb_set_maxpacket(struct usb_device *dev)
                                        dev->epmaxpacketout[ep[e].bEndpointAddress & 0x0f] =
                                                ep[e].wMaxPacketSize;
                                else
-                                       dev->epmaxpacketin[ep[e].bEndpointAddress & 0x0f] =
+                                       dev->epmaxpacketin [ep[e].bEndpointAddress & 0x0f] =
                                                ep[e].wMaxPacketSize;
                        }
                }
@@ -823,60 +836,78 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        return 0;
 }
 
-int usb_get_report(struct usb_device *dev)
+int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
 {
-       unsigned char buf[8];
        devrequest dr;
 
        dr.requesttype = USB_RT_HIDD | 0x80;
        dr.request = USB_REQ_GET_REPORT;
-       dr.value = 0x100;
-       dr.index = 1;
-       dr.length = 3;
+       dr.value = (type << 8) + id;
+       dr.index = index;
+       dr.length = size;
 
-       if (dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, 3))
+       if (dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), &dr, buf, size))
                return -1;
 
-       return buf[0];
+       return 0;
 }
 
 int usb_get_configuration(struct usb_device *dev)
 {
        unsigned int cfgno;
-       unsigned char * bufptr;
-       unsigned char * buffer;
-       int parse;
+       unsigned char buffer[8];
+       unsigned char *bigbuffer;
+       struct usb_config_descriptor *desc =
+               (struct usb_config_descriptor *)buffer;
 
-       buffer = (unsigned char *) __get_free_page (GFP_KERNEL);
-       if (!buffer)
+       if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
+               printk(KERN_WARNING "usb: too many configurations\n");
                return -1;
+       }
 
-       bufptr = buffer;
-       for (cfgno = 0 ; cfgno < dev->descriptor.bNumConfigurations ; cfgno++) {
-               unsigned int size;
-               /* Get the first 8 bytes - guaranteed */
-               if (usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bufptr, 8)) {
-                       __free_page ((struct page *) buffer);
+       dev->config = (struct usb_config_descriptor *)
+               kmalloc(dev->descriptor.bNumConfigurations *
+               sizeof(struct usb_config_descriptor), GFP_KERNEL);
+       if (!dev->config) {
+               printk(KERN_WARNING "usb: out of memory.\n");
+               return -1;      
+       }
+       memset(dev->config, 0, dev->descriptor.bNumConfigurations *
+               sizeof(struct usb_config_descriptor));
+
+       for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) {
+               int result;
+
+               /* We grab the first 8 bytes so we know how long the whole */
+               /*  configuration is */
+               result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
+               if (result)
                        return -1;
-               }
 
                /* Get the full buffer */
-               size = le16_to_cpup((unsigned short *)(bufptr+2));
-               if (bufptr+size > buffer+PAGE_SIZE) {
-                       printk(KERN_INFO "usb: truncated DT_CONFIG (want %d).\n", size);
-                       size = buffer+PAGE_SIZE-bufptr;
-               }
-               if (usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bufptr, size)) {
-                       __free_page ((struct page *) buffer);
+               le16_to_cpus(&desc->wTotalLength);
+
+               bigbuffer = kmalloc(desc->wTotalLength, GFP_KERNEL);
+               if (!bigbuffer)
+                       return -1;
+
+               /* Now that we know the length, get the whole thing */
+               result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength);
+               if (result) {
+                       kfree(bigbuffer);
                        return -1;
                }
                        
-               /* Prepare for next configuration */
-               bufptr += size;
+               result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer);
+               kfree(bigbuffer);
+
+               if (result > 0)
+                       printk(KERN_INFO "usb: descriptor data left\n");
+               else if (result < 0)
+                       return -1;
        }
-       parse = usb_parse_configuration(dev, buffer, bufptr - buffer);
-       __free_page ((struct page *) buffer);
-       return parse;
+
+       return 0;
 }
 
 
@@ -903,14 +934,15 @@ char *usb_string(struct usb_device *dev, int index)
                dev->string_langid |= 0x10000;  /* so it's non-zero */
        }
 
-       if (usb_get_string(dev, dev->string_langid, index, u.buffer, 2)
-           || usb_get_string(dev, dev->string_langid, index, u.buffer,
+       if (usb_get_string(dev, dev->string_langid, index, u.buffer, 2) ||
+           usb_get_string(dev, dev->string_langid, index, u.buffer,
                              u.desc.bLength))
                return 0;
 
        len = u.desc.bLength / 2;       /* includes terminating null */
+
        ptr = kmalloc(len, GFP_KERNEL);
-       if (ptr == 0)
+       if (!ptr)
                return 0;
 
        for (i = 0; i < len - 1; ++i)
@@ -943,7 +975,7 @@ int usb_new_device(struct usb_device *dev)
 
        /* Slow devices */
        if (usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8)) {
-               printk(KERN_ERR "USB device not responding, giving up\n");
+               printk(KERN_ERR "usbcore: USB device not responding, giving up\n");
                dev->devnum = -1;
                return 1;
        }
@@ -960,7 +992,7 @@ int usb_new_device(struct usb_device *dev)
        dev->devnum = addr;
 
        if (usb_set_address(dev)) {
-               printk(KERN_ERR "USB device not accepting new address\n");
+               printk(KERN_ERR "usbcore: USB device not accepting new address\n");
                dev->devnum = -1;
                return 1;
        }
@@ -968,13 +1000,13 @@ int usb_new_device(struct usb_device *dev)
        wait_ms(10);    /* Let the SET_ADDRESS settle */
 
        if (usb_get_device_descriptor(dev)) {
-               printk(KERN_ERR "Unable to get device descriptor\n");
+               printk(KERN_ERR "usbcore: unable to get device descriptor\n");
                dev->devnum = -1;
                return 1;
        }
 
        if (usb_get_configuration(dev)) {
-               printk(KERN_ERR "Unable to get configuration\n");
+               printk(KERN_ERR "usbcore: unable to get configuration\n");
                dev->devnum = -1;
                return 1;
        }
@@ -987,6 +1019,9 @@ int usb_new_device(struct usb_device *dev)
        usb_show_string(dev, "Product", dev->descriptor.iProduct);
        usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 
+       /* now that the basic setup is over, add a /proc/bus/usb entry */
+       proc_usb_add_device(dev);
+
        if (!usb_find_driver(dev)) {
                /*
                 * Ok, no driver accepted the device, so show the info for
@@ -999,7 +1034,21 @@ int usb_new_device(struct usb_device *dev)
        return 0;
 }
 
-void* usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
+int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size)
+{
+        devrequest dr;
+
+        dr.requesttype = requesttype;
+        dr.request = request;
+        dr.value = cpu_to_le16p(&value);
+        dr.index = cpu_to_le16p(&index);
+        dr.length = cpu_to_le16p(&size);
+
+        return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr,
+                data, size);
+}
+
+void *usb_request_irq(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, int period, void *dev_id)
 {
        return dev->bus->op->request_irq(dev, pipe, handler, period, dev_id);
 }
@@ -1014,44 +1063,56 @@ int usb_terminate_bulk(struct usb_device *dev, void *first)
        return dev->bus->op->terminate_bulk(dev, first);
 }
 
-void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
+int usb_release_irq(struct usb_device *dev, void *handle)
 {
-       return usb_dev->bus->op->alloc_isoc (usb_dev, pipe, data, len, maxsze, completed, dev_id);
+       return dev->bus->op->release_irq(dev, handle);
 }
 
-void usb_delete_isochronous (struct usb_device *dev, void *_isodesc)
+/*
+ * usb_get_current_frame_number()
+ *
+ * returns the current frame number for the parent USB bus/controller
+ * of the given USB device.
+ */
+int usb_get_current_frame_number (struct usb_device *usb_dev)
 {
-       return dev->bus->op->delete_isoc (dev, _isodesc);
+       return usb_dev->bus->op->get_frame_number (usb_dev);
 }
 
-int usb_schedule_isochronous (struct usb_device *usb_dev, void *_isodesc, void *_pisodesc)
+int usb_init_isoc (struct usb_device *usb_dev,
+                       unsigned int pipe,
+                       int frame_count,
+                       void *context,
+                       struct usb_isoc_desc **isocdesc)
 {
-       return usb_dev->bus->op->sched_isoc (usb_dev, _isodesc, _pisodesc);
+       return usb_dev->bus->op->init_isoc (usb_dev, pipe, frame_count, context, isocdesc);
 }
 
-int usb_unschedule_isochronous (struct usb_device *usb_dev, void *_isodesc)
+void usb_free_isoc (struct usb_isoc_desc *isocdesc)
 {
-       return usb_dev->bus->op->unsched_isoc (usb_dev, _isodesc);
+       isocdesc->usb_dev->bus->op->free_isoc (isocdesc);
 }
 
-int usb_compress_isochronous (struct usb_device *usb_dev, void *_isodesc)
+int usb_run_isoc (struct usb_isoc_desc *isocdesc,
+                       struct usb_isoc_desc *pr_isocdesc)
 {
-       return usb_dev->bus->op->compress_isoc (usb_dev, _isodesc);
+       return isocdesc->usb_dev->bus->op->run_isoc (isocdesc, pr_isocdesc);
 }
 
-int usb_release_irq(struct usb_device *dev, void* handle)
+int usb_kill_isoc (struct usb_isoc_desc *isocdesc)
 {
-       return dev->bus->op->release_irq(dev, handle);
+       return isocdesc->usb_dev->bus->op->kill_isoc (isocdesc);
 }
 
 #ifdef CONFIG_PROC_FS
-struct list_head * usb_driver_get_list (void)
+struct list_head *usb_driver_get_list(void)
 {
        return &usb_driver_list;
 }
 
-struct list_head * usb_bus_get_list (void)
+struct list_head *usb_bus_get_list(void)
 {
        return &usb_bus_list;
 }
 #endif
+
index fda4d7fcd79a50360b91957ee425b1a6225acb95..cf0e40e61df7eebeeda87cf614a8b8b0663115ba 100644 (file)
@@ -12,7 +12,7 @@ extern int usb_cpia_init(void);
 extern int usb_mouse_init(void);
 extern int usb_printer_init(void);
 
-extern void hub_cleanup(void);
+extern void usb_hub_cleanup(void);
 extern void usb_mouse_cleanup(void);
 
 static __inline__ void wait_ms(unsigned int ms)
@@ -21,14 +21,13 @@ static __inline__ void wait_ms(unsigned int ms)
         schedule_timeout(1 + ms * HZ / 1000);
 }
 
-
 typedef struct {
-  unsigned char requesttype;
-  unsigned char request;
-  unsigned short value;
-  unsigned short index;
-  unsigned short length;
-} devrequest;
+       __u8 requesttype;
+       __u8 request;
+       __u16 value;
+       __u16 index;
+       __u16 length;
+} devrequest __attribute__ ((packed));
 
 /*
  * Device and/or Interface Class codes
@@ -40,6 +39,7 @@ typedef struct {
 #define USB_CLASS_PRINTER              7
 #define USB_CLASS_MASS_STORAGE         8
 #define USB_CLASS_HUB                  9
+#define USB_CLASS_DATA                 10
 #define USB_CLASS_VENDOR_SPEC          0xff
 
 /*
@@ -53,6 +53,8 @@ typedef struct {
 
 #define USB_DT_HUB                     0x29
 #define USB_DT_HID                     0x21
+#define USB_DT_REPORT                  0x22
+#define USB_DT_PHYSICAL                        0x23
 
 /*
  * Descriptor sizes per descriptor type
@@ -61,7 +63,7 @@ typedef struct {
 #define USB_DT_CONFIG_SIZE             9
 #define USB_DT_INTERFACE_SIZE          9
 #define USB_DT_ENDPOINT_SIZE           7
-#define USB_DT_AUCLSTEP_SIZE           9       /* Audio Classes are special */
+#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
 #define USB_DT_HUB_NONVAR_SIZE         7
 
 /*
@@ -114,6 +116,10 @@ typedef struct {
 #define USB_RECIP_ENDPOINT             0x02
 #define USB_RECIP_OTHER                        0x03
 
+#define USB_HID_RPT_INPUT              0x01
+#define USB_HID_RPT_OUTPUT             0x02
+#define USB_HID_RPT_FEATURE            0x03
+
 /*
  * Request target types.
  */
@@ -127,7 +133,7 @@ typedef struct {
 #define USB_RT_HIDD                    (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
 
 /* 
- * Status codes (these follow an OHCI controllers condition codes)
+ * Status codes (these follow OHCI controllers condition codes)
  */
 #define USB_ST_NOERROR         0x0
 #define USB_ST_CRC             0x1
@@ -151,6 +157,7 @@ typedef struct {
 #define USB_ST_TIMEOUT         0x110
 #define USB_ST_INTERNALERROR   -1
 #define USB_ST_NOTSUPPORTED    -2
+#define USB_ST_BANDWIDTH_ERROR -3
 
 /*
  * USB device number allocation bitmap. There's one bitmap
@@ -164,14 +171,21 @@ struct usb_devmap {
  * This is a USB device descriptor.
  *
  * USB device information
- *
  */
 
+/* Everything but the endpoint maximums are aribtrary */
 #define USB_MAXCONFIG          8
-#define USB_MAXALTSETTING   6   
+#define USB_MAXALTSETTING      16
 #define USB_MAXINTERFACES      32
 #define USB_MAXENDPOINTS       32
 
+/* All standard descriptors have these 2 fields in common */
+struct usb_descriptor_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+} __attribute__ ((packed));
+
+/* Device descriptor */
 struct usb_device_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
@@ -187,7 +201,7 @@ struct usb_device_descriptor {
        __u8  iProduct;
        __u8  iSerialNumber;
        __u8  bNumConfigurations;
-};
+} __attribute__ ((packed));
 
 /* Endpoint descriptor */
 struct usb_endpoint_descriptor {
@@ -199,8 +213,23 @@ struct usb_endpoint_descriptor {
        __u8  bInterval;
        __u8  bRefresh;
        __u8  bSynchAddress;
-       void  *audio;
-};
+} __attribute__ ((packed));
+
+/* HID descriptor */
+struct usb_hid_class_descriptor {
+       __u8  bDescriptorType;
+       __u16 wDescriptorLength;
+} __attribute__ ((packed));
+
+struct usb_hid_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u16 bcdHID;
+       __u8  bCountryCode;
+       __u8  bNumDescriptors;
+
+       struct usb_hid_class_descriptor desc[1];
+} __attribute__ ((packed));
 
 /* Interface descriptor */
 struct usb_interface_descriptor {
@@ -214,14 +243,15 @@ struct usb_interface_descriptor {
        __u8  bInterfaceProtocol;
        __u8  iInterface;
 
+       struct usb_hid_descriptor *hid;
        struct usb_endpoint_descriptor *endpoint;
-       void  *audio;
-};
+} __attribute__ ((packed));
 
 struct usb_interface {
-        struct usb_interface_descriptor *altsetting;
-        int act_altsetting;                /* active alternate setting */
-        int num_altsetting;                /* number of alternate settings */
+       struct usb_interface_descriptor *altsetting;
+
+       int act_altsetting;             /* active alternate setting */
+       int num_altsetting;             /* number of alternate settings */
 };
 
 /* Configuration descriptor information.. */
@@ -234,35 +264,25 @@ struct usb_config_descriptor {
        __u8  iConfiguration;
        __u8  bmAttributes;
        __u8  MaxPower;
+
        struct usb_interface *interface;
-};
+} __attribute__ ((packed));
 
 /* String descriptor */
 struct usb_string_descriptor {
        __u8  bLength;
        __u8  bDescriptorType;
        __u16 wData[1];
-};
-
-/* Hub descriptor */
-struct usb_hub_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bNbrPorts;
-       __u8  wHubCharacteristics[2];   /* __u16 but not aligned! */
-       __u8  bPwrOn2PwrGood;
-       __u8  bHubContrCurrent;
-       /* DeviceRemovable and PortPwrCtrlMask want to be variable-length 
-          bitmaps that hold max 256 entries, but for now they're ignored */
-       __u8  filler;
-};
+} __attribute__ ((packed));
 
 struct usb_device;
 
 struct usb_driver {
-       const char * name;
+       const char *name;
+
        int (*probe)(struct usb_device *);
        void (*disconnect)(struct usb_device *);
+
        struct list_head driver_list;
 };
 
@@ -284,21 +304,97 @@ struct usb_driver {
  */
 typedef int (*usb_device_irq)(int, void *, int, void *);
 
+/*
+ * Isoc. support additions
+ */
+#define START_FRAME_FUDGE      3
+
+/* for start_type: */
+enum {
+       START_ASAP = 0,
+       START_ABSOLUTE,
+       START_RELATIVE
+};
+#define START_TYPE_MAX     START_RELATIVE
+
+/*
+ * Completion/Callback routine returns an enum,
+ * which tells the interrupt handler what to do
+ * with the completed frames (TDs).
+ */
+enum {
+       CB_CONTINUE = 0,        /* OK, remove all TDs;
+                                  needs to be 0 to be consistent with
+                                  current callback function ret. values */
+       CB_REUSE,               /* leave descriptors as NULL, not active */
+       CB_RESTART,             /* leave descriptors as they are, alive */
+       CB_ABORT                /* kill this USB transfer request */
+};
+
+struct isoc_frame_desc {
+       int             frame_length;   /* may be 0 (i.e., allowed) */
+                       /* set by driver for OUTs to devices;
+                        * set by USBD for INs from devices,
+                        * after I/O complete */
+       unsigned int    frame_status;
+                       /* set by USBD after I/O complete */
+};
+
+struct usb_isoc_desc {
+       /*
+        * The following fields are set by the usb_init_isoc() call.
+        */
+       struct usb_device *usb_dev;
+       unsigned int    pipe;
+       int             frame_count;
+       void            *context;       /* driver context (private) ptr */
+       int             frame_size;
+       /*
+        * The following fields are set by the driver between the
+        * usb_init_isoc() and usb_run_isoc() calls
+        * (along with the "frames" array for OUTput).
+        */
+       int             start_type;
+       int             start_frame;    /* optional, depending on start_type */
+       int             frame_spacing;  /* not using (yet?) */
+       int             callback_frames; /* every # frames + last one */
+                               /* 0 means no callbacks until IOC on last frame */
+       usb_device_irq  callback_fn;
+       void            *data;
+       int             buf_size;
+       /*
+        * The following fields are set by the usb_run_isoc() call.
+        */
+       int             end_frame;
+       void            *td;            /* UHCI or OHCI TD ptr */
+       /*
+        * The following fields are set by the USB HCD interrupt handler
+        * before calling the driver's callback function.
+        */
+       int             total_completed_frames;
+       int             prev_completed_frame;   /* from the previous callback */
+       int             cur_completed_frame;    /* from this callback */
+       int             total_length;           /* accumulated */
+       int             error_count;            /* accumulated */
+       struct isoc_frame_desc frames [0];      /* variable size: [frame_count] */
+};
+
 struct usb_operations {
-       struct usb_device *(*allocate)(struct usb_device *);
+       int (*allocate)(struct usb_device *);
        int (*deallocate)(struct usb_device *);
        int (*control_msg)(struct usb_device *, unsigned int, devrequest *, void *, int);
        int (*bulk_msg)(struct usb_device *, unsigned int, void *, int,unsigned long *);
-       void(*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *);
-       int (*release_irq)(struct usb_device *, void* handle);
+       void *(*request_irq)(struct usb_device *, unsigned int, usb_device_irq, int, void *);
+       int (*release_irq)(struct usb_device *, void *);
        void *(*request_bulk)(struct usb_device *, unsigned int, usb_device_irq,
  void *, int, void *);
        int (*terminate_bulk)(struct usb_device *, void *);
-       void *(*alloc_isoc)(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id);
-       void (*delete_isoc)(struct usb_device *dev, void *_isodesc);
-       int (*sched_isoc)(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc);
-       int (*unsched_isoc)(struct usb_device *usb_dev, void *_isodesc);
-       int (*compress_isoc)(struct usb_device *usb_dev, void *_isodesc);
+       int (*get_frame_number) (struct usb_device *usb_dev);
+       int (*init_isoc) (struct usb_device *usb_dev, unsigned int pipe,
+                               int frame_count, void *context, struct usb_isoc_desc **isocdesc);
+       void (*free_isoc) (struct usb_isoc_desc *isocdesc);
+       int (*run_isoc) (struct usb_isoc_desc *isocdesc, struct usb_isoc_desc *pr_isocdesc);
+       int (*kill_isoc) (struct usb_isoc_desc *isocdesc);
 };
 
 /*
@@ -310,14 +406,20 @@ struct usb_bus {
        struct usb_device *root_hub;    /* Root hub */
        struct list_head bus_list;
        void *hcpriv;                   /* Host Controller private data */
-};
 
+       /* procfs entry */
+       int proc_busnum;
+       struct proc_dir_entry *proc_entry;
+};
 
-#define USB_MAXCHILDREN (8)
+#define USB_MAXCHILDREN (8)    /* This is arbitrary */
 
 struct usb_device {
        int devnum;                     /* Device number on USB bus */
        int slow;                       /* Slow device? */
+
+       atomic_t refcnt;                /* Reference count */
+
        int maxpacketsize;              /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
        unsigned int toggle[2];         /* one bit for each endpoint ([0] = IN, [1] = OUT) */
        unsigned int halted[2];         /* endpoint halts; one bit per endpoint # & direction; */
@@ -326,14 +428,23 @@ struct usb_device {
        int epmaxpacketin[16];          /* INput endpoint specific maximums */
        int epmaxpacketout[16];         /* OUTput endpoint specific maximums */
        int ifnum;                      /* active interface number */
+
+       struct usb_device *parent;
        struct usb_bus *bus;            /* Bus we're part of */
        struct usb_driver *driver;      /* Driver */
+
        struct usb_device_descriptor descriptor;/* Descriptor */
        struct usb_config_descriptor *config;   /* All of the configs */
-       struct usb_device *parent;
+
        char *string;                   /* pointer to the last string read from the device */
        int string_langid;              /* language ID for strings */
   
+       void *hcpriv;                   /* Host Controller private data */
+       void *private;                  /* Upper layer private data */
+
+       /* procfs entry */
+       struct proc_dir_entry *proc_entry;
+
        /*
         * Child devices - these can be either new devices
         * (if this is a hub device), or different instances
@@ -344,20 +455,28 @@ struct usb_device {
 
        int maxchild;                   /* Number of ports if hub */
        struct usb_device *children[USB_MAXCHILDREN];
-
-       void *hcpriv;                   /* Host Controller private data */
-       void *private;                  /* Upper layer private data */
 };
 
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
 
+int usb_find_driver(struct usb_device *);
+void usb_check_support(struct usb_device *);
+void usb_driver_purge(struct usb_driver *, struct usb_device *);
+
 extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
 extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
 extern void usb_deregister_bus(struct usb_bus *);
 
-extern void* usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *);
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+extern void usb_inc_dev_use(struct usb_device *);
+#define usb_dec_dev_use usb_free_dev
+
+extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size);
+
+extern void *usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *);
 extern int usb_release_irq(struct usb_device *dev, void *handle);
 
 extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
@@ -367,10 +486,6 @@ extern void usb_init_root_hub(struct usb_device *dev);
 extern void usb_connect(struct usb_device *dev);
 extern void usb_disconnect(struct usb_device **);
 
-extern int usb_find_driver(struct usb_device *dev);
-void usb_check_support(struct usb_device *);
-void usb_driver_purge(struct usb_driver *,struct usb_device *);
-extern int  usb_parse_configuration(struct usb_device *dev, void *buf, int len);
 extern void usb_destroy_configuration(struct usb_device *dev);
 
 extern void *usb_allocate_isochronous (struct usb_device *usb_dev, unsigned int pipe, void *data, int len,
@@ -380,6 +495,21 @@ extern int usb_schedule_isochronous (struct usb_device *usb_dev, void *_isodesc,
 extern int usb_unschedule_isochronous (struct usb_device *usb_dev, void *_isodesc);
 extern int usb_compress_isochronous (struct usb_device *usb_dev, void *_isodesc);
 
+int usb_get_current_frame_number (struct usb_device *usb_dev);
+
+int usb_init_isoc (struct usb_device *usb_dev,
+                       unsigned int pipe,
+                       int frame_count,
+                       void *context,
+                       struct usb_isoc_desc **isocdesc);
+
+void usb_free_isoc (struct usb_isoc_desc *isocdesc);
+
+int usb_run_isoc (struct usb_isoc_desc *isocdesc,
+                       struct usb_isoc_desc *pr_isocdesc);
+
+int usb_kill_isoc (struct usb_isoc_desc *isocdesc);
+
 /*
  * Calling this entity a "pipe" is glorifying it. A USB pipe
  * is something embarrassingly simple: it basically consists
@@ -479,7 +609,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate);
 int usb_set_idle(struct usb_device *dev, int duration, int report_id);
 int usb_set_interface(struct usb_device *dev, int interface, int alternate);
 int usb_set_configuration(struct usb_device *dev, int configuration);
-int usb_get_report(struct usb_device *dev);
+int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size);
 char *usb_string(struct usb_device *dev, int index);
 int usb_clear_halt(struct usb_device *dev, int endp);
 
@@ -489,21 +619,25 @@ int usb_clear_halt(struct usb_device *dev, int endp);
 void usb_show_device_descriptor(struct usb_device_descriptor *);
 void usb_show_config_descriptor(struct usb_config_descriptor *);
 void usb_show_interface_descriptor(struct usb_interface_descriptor *);
+void usb_show_hid_descriptor(struct usb_hid_descriptor * desc);
 void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *);
-void usb_show_hub_descriptor(struct usb_hub_descriptor *);
 void usb_show_device(struct usb_device *);
-void usb_show_string(struct usb_devicedev, char *id, int index);
+void usb_show_string(struct usb_device *dev, char *id, int index);
 
 /*
- * Audio parsing helpers
+ * procfs stuff
  */
 
-#ifdef CONFIG_USB_AUDIO
-void usb_audio_interface(struct usb_interface_descriptor *, u8 *);
-void usb_audio_endpoint(struct usb_endpoint_descriptor *, u8 *);
+#ifdef CONFIG_USB_PROC
+void proc_usb_add_bus(struct usb_bus *bus);
+void proc_usb_remove_bus(struct usb_bus *bus);
+void proc_usb_add_device(struct usb_device *dev);
+void proc_usb_remove_device(struct usb_device *dev);
 #else
-extern inline void usb_audio_interface(struct usb_interface_descriptor *interface, u8 *data) {}
-extern inline void usb_audio_endpoint(struct usb_endpoint_descriptor *interface, u8 *data) {}
+extern inline void proc_usb_add_bus(struct usb_bus *bus) {}
+extern inline void proc_usb_remove_bus(struct usb_bus *bus) {}
+extern inline void proc_usb_add_device(struct usb_device *dev) {}
+extern inline void proc_usb_remove_device(struct usb_device *dev) {}
 #endif
 
 #endif
index fcd5f5da5ea3448135f606c09d4f377d8a159329..7752d5bd41f3fe0acd3b8353b04903ddbb8e3e0f 100644 (file)
@@ -1108,9 +1108,9 @@ static int scsi_probe(struct usb_device *dev)
            protocol = US_PR_CB;
            subclass = US_SC_8070;      /* an assumption */
        } else if (dev->descriptor.bDeviceClass != 0 ||
-           dev->config->interface->altsetting->bInterfaceClass != 8 ||
-           dev->config->interface->altsetting->bInterfaceSubClass < US_SC_MIN ||
-           dev->config->interface->altsetting->bInterfaceSubClass > US_SC_MAX) {
+           dev->config[0].interface[0].altsetting[0].bInterfaceClass != 8 ||
+           dev->config[0].interface[0].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
+           dev->config[0].interface[0].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
            return -1;
        }
 
@@ -1143,7 +1143,7 @@ static int scsi_probe(struct usb_device *dev)
        memset(ss, 0, sizeof(struct us_data));
     }
 
-    interface = dev->config->interface->altsetting;
+    interface = &dev->config[0].interface[0].altsetting[0];
     ss->filter = filter;
     ss->fdata = fdata;
     ss->flags = flags;
index 3454cf6b943d0cc08a1eb376a80fa712c8cc5bc9..5d74216941091b5d5230f38a5074f4fa5a6f5a67 100644 (file)
@@ -36,7 +36,6 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/socket.h>
 #include <linux/parport.h>
@@ -561,8 +560,8 @@ static int uss720_probe(struct usb_device *usbdev)
                usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
 
         if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) &&
-            (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001) &&
-            (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284))
+           (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001) &&
+           (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284))
                 return -1;
 
         /* We don't handle multiple configurations */
index 13c1af45d1145f23945bcddbc9aaa2e7b79f3fb3..339dc6d9f0e6731a6cac43cde670328366811b5c 100644 (file)
@@ -7,7 +7,7 @@ if [ "$CONFIG_FB" = "y" ]; then
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_PCI" = "y" ]; then
       tristate 'Cirrus Logic suport (experimental)' CONFIG_FB_CLGEN
-      bool 'Permedia2 support (experimental)' CONFIG_FB_PM2
+      tristate 'Permedia2 support (experimental)' CONFIG_FB_PM2
       if [ "$CONFIG_FB_PM2" = "y" ]; then
         if [ "$CONFIG_PCI" = "y" ]; then
           bool '  enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
index 923ca5238f454d3c1c437cf2d4b0ef04308d15ec..8a7c9853f317d22fb88ba48fda771f94634e12ee 100644 (file)
@@ -82,6 +82,11 @@ endif
 ifeq ($(CONFIG_FB_PM2),y)
 L_OBJS += pm2fb.o
 CONFIG_FBGEN_BUILTIN = y
+else
+  ifeq ($(CONFIG_FB_PM2),m)
+  M_OBJS += pm2fb.o
+  CONFIG_FBGEN_MODULE = y
+  endif
 endif
 
 ifeq ($(CONFIG_FB_APOLLO),y)
index 68dab49ff42a85d1ee8977a34b45b1fcf349aff0..425199739c5466cb2a37d89f99f1c57428c97188 100644 (file)
@@ -390,7 +390,9 @@ int atyfb_init(void);
 #ifdef CONFIG_FB_OF
 void atyfb_of_init(struct device_node *dp);
 #endif
+#ifndef MODULE
 int atyfb_setup(char*);
+#endif
 
 static int currcon = 0;
 
@@ -411,7 +413,10 @@ static char noaccel __initdata = 0;
 static u32 default_vram __initdata = 0;
 static int default_pll __initdata = 0;
 static int default_mclk __initdata = 0;
+
+#ifndef MODULE
 static const char *mode_option __initdata = NULL;
+#endif
 
 #if defined(CONFIG_PPC)
 static int default_vmode __initdata = VMODE_NVRAM;
@@ -2869,7 +2874,7 @@ int __init atyfb_init(void)
            memset(info, 0, sizeof(struct fb_info_aty));
 
            rp = &pdev->resource[0];
-           if (rp->flags & IORESOURCE_IOPORT)
+           if (rp->flags & IORESOURCE_IO)
                    rp = &pdev->resource[1];
            addr = rp->start;
            if (!addr)
@@ -2912,7 +2917,7 @@ int __init atyfb_init(void)
 
                base = rp->start;
 
-               io = (rp->flags & IORESOURCE_IOPORT);
+               io = (rp->flags & IORESOURCE_IO);
 
                size = rp->end - base + 1;
                
@@ -3261,6 +3266,7 @@ void __init atyfb_of_init(struct device_node *dp)
 #endif /* CONFIG_FB_OF */
 
 
+#ifndef MODULE
 int __init atyfb_setup(char *options)
 {
     char *this_opt;
@@ -3328,9 +3334,12 @@ int __init atyfb_setup(char *options)
            }
        }
 #endif
+       else
+           mode_option = this_opt;
     }
     return 0;
 }
+#endif /* !MODULE */
 
 #ifdef CONFIG_ATARI
 static int __init store_video_par(char *video_str, unsigned char m64_num)
index c6d650463977e6af42f69a99e000ee4dc754910a..3009529aa416cd61a59ee864b2d3f5a3b6d53a5c 100644 (file)
@@ -31,8 +31,9 @@
  *
  */
 
-#define CLGEN_VERSION "1.9.4.2"
+#define CLGEN_VERSION "1.9.4.3"
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -324,6 +325,8 @@ struct clgenfb_info {
 #ifdef CONFIG_ZORRO
        int keyRAM;             /* RAM, REG zorro board keys */
        int keyREG;
+       unsigned long board_addr,
+                     board_size;
 #endif
 
 #ifdef CONFIG_PCI
@@ -338,7 +341,9 @@ static struct display disp;
 
 static struct clgenfb_info boards[MAX_NUM_BOARDS];     /* the boards */
 
-static unsigned clgen_def_mode = 0;
+static unsigned clgen_def_mode = 1;
+
+static int release_io_ports = 0;
 
 
 
@@ -1787,12 +1792,16 @@ static void __init init_vgachip (struct clgenfb_info *fb_info)
                break;
        }
 
+#ifdef CLGEN_USE_HARDCODED_RAM_SETTINGS
        /* "pre-set" a RAMsize; if the test succeeds, double it */
        if (fb_info->btype == BT_SD64 ||
            fb_info->btype == BT_PICASSO4)
                fb_info->size = 0x400000;
        else
                fb_info->size = 0x200000;
+#else
+       assert (fb_info->size > 0); /* make sure RAM size set by this point */
+#endif
 
        /* assume it's a "large memory" board (2/4 MB) */
        fb_info->smallboard = FALSE;
@@ -2362,7 +2371,7 @@ static void __init get_pci_addrs (const struct pci_dev *pdev,
 
 #else
 
-       if (pdev->resource[0].flags & IORESOURCE_IOPORT) {
+       if (pdev->resource[0].flags & IORESOURCE_IO) {
                *display = pdev->resource[1].start;
                *registers = pdev->resource[0].start;
        } else {
@@ -2380,6 +2389,21 @@ static void __init get_pci_addrs (const struct pci_dev *pdev,
 
 
 
+/* clgen_pci_unmap only used in modules */
+#ifdef MODULE
+static void clgen_pci_unmap (struct clgenfb_info *info)
+{
+       iounmap (info->fbmem);
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
+       __release_region (&iomem_resource, info->fbmem_phys, info->size);
+       __release_region (&iomem_resource, 0xA0000, 65535);
+       if (release_io_ports)
+               __release_region (&ioport_resource, 0x3C0, 32);
+#endif
+}
+#endif /* MODULE */
+
+
 static int __init clgen_pci_setup (struct clgenfb_info *info,
                                   clgen_board_t *btype)
 {
@@ -2411,8 +2435,8 @@ static int __init clgen_pci_setup (struct clgenfb_info *info,
 
        pci_read_config_word (pdev, PCI_COMMAND, &tmp16);
        if (!(tmp16 & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO))) {
-               tmp16 |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
-               pci_write_config_word (pdev, PCI_COMMAND, tmp16);
+               u16 tmp16_o = tmp16 | PCI_COMMAND_MEMORY | PCI_COMMAND_IO;
+               pci_write_config_word (pdev, PCI_COMMAND, tmp16_o);
        }
 
 #ifdef CONFIG_FB_OF
@@ -2453,10 +2477,33 @@ static int __init clgen_pci_setup (struct clgenfb_info *info,
        } else {
                board_size = clgen_get_memsize (info->regs);
        }
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
+
+       if (!__request_region (&iomem_resource, board_addr,
+                              board_size, "clgenfb")) {
+               pci_write_config_word (pdev, PCI_COMMAND, tmp16);
+               printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
+                      board_addr);
+               return -1;
+       }
+       if (!__request_region (&iomem_resource, 0xA0000, 65535, "clgenfb")) {
+               pci_write_config_word (pdev, PCI_COMMAND, tmp16);
+               printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
+                      0xA0000L);
+               __release_region(&iomem_resource, board_addr, board_size);
+               return -1;
+       }
+       if (__request_region(&ioport_resource, 0x3C0, 32, "clgenfb"))
+               release_io_ports = 1;
+
+#endif /* kernel > 2.3.13 */
+
        info->fbmem = ioremap (board_addr, board_size);
        info->fbmem_phys = board_addr;
+       info->size = board_size;
 
-       printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
+       printk (" RAM (%lu MB) at 0x%lx, ", info->size / MB_, board_addr);
 
        printk (KERN_INFO "Cirrus Logic chipset on PCI bus\n");
 
@@ -2499,6 +2546,25 @@ static int __init clgen_zorro_find (int *key_o, int *key2_o, clgen_board_t *btyp
 
 
 
+/* clgen_zorro_unmap only used in modules */
+#ifdef MODULE
+static void clgen_zorro_unmap (struct clgenfb_info *info)
+{
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
+       __release_region(&iomem_resource, info->board_addr, info->board_size);
+#endif
+       if (info->btype == BT_PICASSO4) {
+               iounmap (info->board_addr);
+               iounmap (info->fbmem_phys);
+       } else {
+               if (info->board_addr > 0x01000000)
+                       iounmap (info->board_addr);
+       }
+}
+#endif /* MODULE */
+
+
+
 static int __init clgen_zorro_setup (struct clgenfb_info *info,
                                     clgen_board_t *btype)
 {
@@ -2520,9 +2586,17 @@ static int __init clgen_zorro_setup (struct clgenfb_info *info,
        info->keyRAM = key;
        info->keyREG = key2;
        cd = zorro_get_board (key);
-       board_addr = (unsigned long) cd->cd_BoardAddr;
-       board_size = (unsigned long) cd->cd_BoardSize;
-       printk (" RAM (%lu MB) at $%lx, ", board_size / 0x100000, board_addr);
+       info->board_addr = board_addr = (unsigned long) cd->cd_BoardAddr;
+       info->board_size = board_size = (unsigned long) cd->cd_BoardSize;
+
+       if (!__request_region(&iomem_resource, board_addr,
+                             board_size, "clgenfb")) {
+               printk(KERN_ERR "clgen: cannot reserve region 0x%lu, abort\n",
+                      board_addr);
+               return -1;
+       }
+
+       printk (" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr);
 
        if (*btype == BT_PICASSO4) {
                printk (" REG at $%lx\n", board_addr + 0x600000);
@@ -2683,9 +2757,13 @@ static void clgenfb_cleanup (struct clgenfb_info *info)
 #ifdef CONFIG_ZORRO
        switch_monitor (info, 0);
 
+       clgen_zorro_unmap (info);
+
        zorro_unconfig_board (info->keyRAM, 0);
        if (info->btype != BT_PICASSO4)
                zorro_unconfig_board (info->keyREG, 0);
+#else
+       clgen_pci_unmap (info);
 #endif                         /* CONFIG_ZORRO */
 
        unregister_framebuffer ((struct fb_info *) info);
index e333730c188ea3238a90129444cf4fff4897d92a..0767c3b87c3292df97166c2cfad0320a983d125d 100644 (file)
@@ -470,6 +470,14 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
                return -ENODEV;
        if (fb->fb_mmap)
                return fb->fb_mmap(info, file, vma);
+
+#if defined(__sparc__)
+       /* Should never get here, all fb drivers should have their own
+          mmap routines */
+       return -EINVAL;
+#else
+       /* non-SPARC... */
+
        fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);
 
        /* frame buffer memory */
@@ -505,9 +513,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
        pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
 #elif defined(__alpha__)
        /* Caching is off in the I/O space quadrant by design.  */
-#elif defined(__sparc__)
-       /* Should never get here, all fb drivers should have their own
-          mmap routines */
 #elif defined(__i386__)
        if (boot_cpu_data.x86 > 3)
                pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
@@ -528,6 +533,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
                             vma->vm_end - vma->vm_start, vma->vm_page_prot))
                return -EAGAIN;
        return 0;
+
+#endif /* defined(__sparc__) */
 }
 
 static int
index 1c27a49e91b0cafc2f203ad9b9ed71c30637e8b4..999dbac302822c346b94e5f16b553a389de0f34a 100644 (file)
@@ -5152,7 +5152,10 @@ static unsigned int fv = 0;              /* "matrox:fv:xxxxx" */
 static unsigned int fh = 0;            /* "matrox:fh:xxxxxk" */
 static unsigned int maxclk = 0;                /* "matrox:maxclk:xxxxM" */
 static char fontname[64];              /* "matrox:font:xxxxx" */
+
+#ifndef MODULE
 static char videomode[64];             /* "matrox:mode:xxxxx" or "matrox:xxxxx" */
+#endif
 
 #ifndef MODULE
 int __init matroxfb_setup(char *options) {
@@ -5295,7 +5298,7 @@ int __init matroxfb_setup(char *options) {
        }
        return 0;
 }
-#endif
+#endif /* !MODULE */
 
 static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize){
        vaddr_t vm;
@@ -5884,7 +5887,7 @@ static int __init initMatrox2(WPMINFO struct display* d, struct board* b){
                fb_find_mode(&vesafb_defined, &ACCESS_FBINFO(fbcon), videomode[0]?videomode:NULL,
                NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
        }
-#endif
+#endif /* !MODULE */
 
        /* mode modifiers */
        if (hslen)
index 518d4e895b7bdbd4e20054c6f8e37586f10ec47a..343ad3f5228bbf09cb74159a220cf2faf69725bf 100644 (file)
@@ -192,12 +192,12 @@ static struct pm2fb_info {
        int board;                      /* Permedia2 board index (see
                                           board_table[] below) */
        struct {
-               unsigned char* fb_base; /* framebuffer memory base */
+               unsigned long  fb_base; /* physical framebuffer memory base */
                u32 fb_size;            /* framebuffer memory size */
-               unsigned char* rg_base; /* register memory base */
-               unsigned char* p_fb;    /* physical address of frame buffer */
+               unsigned long  rg_base; /* physical register memory base */
+               unsigned long  p_fb;    /* physical address of frame buffer */
                unsigned char* v_fb;    /* virtual address of frame buffer */
-               unsigned char* p_regs;  /* physical address of registers
+               unsigned long  p_regs;  /* physical address of registers
                                           region, must be rg_base or
                                           rg_base+PM2_REGS_SIZE depending on
                                           the host endianness */
@@ -750,13 +750,26 @@ static int __init pm2fb_conf(struct pm2fb_info* p){
                return 0;
        }
        DPRINTK("found board: %s\n", board_table[p->board].name);
+
        p->regions.p_fb=p->regions.fb_base;
+       if (!__request_region(&iomem_resource, p->regions.p_fb,
+                             p->regions.fb_size, "pm2fb")) {
+               printk (KERN_ERR "pm2fb: cannot reserve fb memory, abort\n");
+               return 0;
+       }
        p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);
+
 #ifdef __LITTLE_ENDIAN
        p->regions.p_regs=p->regions.rg_base;
 #else
        p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
 #endif
+       if (!__request_region(&iomem_resource, p->regions.p_regs,
+                             PM2_REGS_SIZE, "pm2fb")) {
+               printk (KERN_ERR "pm2fb: cannot reserve mmio memory, abort\n");
+               UNMAP(p->regions.v_fb, p->regions.fb_size);
+               return 0;
+       }
        p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE);
        return 1;
 }
@@ -809,9 +822,9 @@ static int cvppc_detect(struct pm2fb_info* p) {
 
        if (!cvppc_PCI_init(&p->board_par.cvppc))
                return 0;
-       p->regions.fb_base=(unsigned char* )CVPPC_FB_APERTURE_ONE;
+       p->regions.fb_base=CVPPC_FB_APERTURE_ONE;
        p->regions.fb_size=CVPPC_FB_SIZE;
-       p->regions.rg_base=(unsigned char* )CVPPC_REGS_REGION;
+       p->regions.rg_base=CVPPC_REGS_REGION;
        p->memclock=CVPPC_MEMCLOCK;
        return 1;
 }
@@ -855,24 +868,18 @@ static int pm2pci_detect(struct pm2fb_info* p) {
                        pci->dev->resource[0].start,
                        pci->dev->resource[1].start,
                        pci->dev->resource[2].start,
-                       pci->dev->rom_address);
+                       pci->dev->resource[PCI_ROM_RESOURCE].start);
 #ifdef __sparc__
-       p->regions.rg_base=(unsigned char* )
-               __pa(pci->dev->resource[0].start);
-       p->regions.fb_base=(unsigned char* )
-               __pa(pci->dev->resource[1].start);
+       p->regions.rg_base= __pa(pci->dev->resource[0].start);
+       p->regions.fb_base= __pa(pci->dev->resource[1].start);
 #else
        if (pm2fb_options.flags & OPTF_VIRTUAL) {
-               p->regions.rg_base=(unsigned char* )
-                       __pa(pci->dev->resource[0].start);
-               p->regions.fb_base=(unsigned char* )
-                       __pa(pci->dev->resource[1].start);
+               p->regions.rg_base= __pa(pci->dev->resource[0].start);
+               p->regions.fb_base= __pa(pci->dev->resource[1].start);
        }
        else {
-               p->regions.rg_base=(unsigned char* )
-                       (pci->dev->resource[0].start);
-               p->regions.fb_base=(unsigned char* )
-                       (pci->dev->resource[0].start);
+               p->regions.rg_base= (pci->dev->resource[0].start);
+               p->regions.fb_base= (pci->dev->resource[0].start);
        }
 #endif
 #ifdef __BIG_ENDIAN
@@ -1581,15 +1588,23 @@ static int pm2fb_release(struct fb_info* info, int user) {
  * Begin of public functions
  ***************************************************************************/
 
-void pm2fb_cleanup(struct fb_info* info) {
-       struct pm2fb_info* i=(struct pm2fb_info* )info;
+#ifdef MODULE
+static void pm2fb_cleanup(void) {
+       struct pm2fb_info* i = &fb_info;
 
-       unregister_framebuffer(info);
+       unregister_framebuffer((struct fb_info *)i);
        pm2fb_reset(i);
-       /* FIXME UNMAP()??? */
+
+       UNMAP(i->regions.v_fb, i->regions.fb_size);
+       __release_region(&iomem_resource, i->regions.p_fb, i->regions.fb_size);
+
+       UNMAP(i->regions.v_regs, PM2_REGS_SIZE);
+       __release_region(&iomem_resource, i->regions.p_regs, PM2_REGS_SIZE);
+
        if (board_table[i->board].cleanup)
                board_table[i->board].cleanup(i);
 }
+#endif /* MODULE */
 
 int __init pm2fb_init(void){
 
index b808fd0a6b0b8835d35071a9158288a321cc8f84..bb98bd8c730b44b43c2337db1fe9ff801d4ee6b5 100644 (file)
@@ -41,7 +41,7 @@
  */
 
 /* card */
-char *video_base;
+unsigned long video_base; /* physical addr */
 int   video_size;
 char *video_vbase;        /* mapped */
 
@@ -530,7 +530,7 @@ int __init vesafb_init(void)
        if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
                return -ENXIO;
 
-       video_base          = (char*)screen_info.lfb_base;
+       video_base          = screen_info.lfb_base;
        video_bpp           = screen_info.lfb_depth;
        video_width         = screen_info.lfb_width;
        video_height        = screen_info.lfb_height;
@@ -538,9 +538,18 @@ int __init vesafb_init(void)
        video_size          = screen_info.lfb_size * 65536;
        video_visual = (video_bpp == 8) ?
                FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-        video_vbase = ioremap((unsigned long)video_base, video_size);
 
-       printk(KERN_INFO "vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+       if (!__request_region(&iomem_resource, video_base, video_size,
+                             "vesafb")) {
+               printk(KERN_ERR
+                      "vesafb: abort, cannot reserve video memory at 0x%lu\n",
+                       video_base);
+               return -1;
+       }
+
+        video_vbase = ioremap(video_base, video_size);
+
+       printk(KERN_INFO "vesafb: framebuffer at 0x%lu, mapped to 0x%p, size %dk\n",
               video_base, video_vbase, video_size/1024);
        printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
               video_width, video_height, video_bpp, video_linelength, screen_info.pages);
@@ -633,9 +642,13 @@ int __init vesafb_init(void)
                }
                video_cmap_len = 256;
        }
-       request_region(0x3c0, 32, "vga+");
+
+       /* request failure does not faze us, as vgacon probably has this
+        * region already (FIXME) */
+       __request_region(&ioport_resource, 0x3c0, 32, "vesafb");
+
        if (mtrr)
-               mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
+               mtrr_add(video_base, video_size, MTRR_TYPE_WRCOMB, 1);
        
        strcpy(fb_info.modename, "VESA VGA");
        fb_info.changevar = NULL;
index 8aaa1a5c11526bad4bb56317855cce6678985535..7c05ba331ee9d7fb6f6801df444c9362e835e13c 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef __linux_video_vga_h__
 #define __linux_video_vga_h__
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #ifndef CONFIG_AMIGA
index 723bef47657faa94e84cf72a853e50c64b5c9ee1..9b014c45e6759a333367e1b2207ea233c51f5464 100644 (file)
@@ -32,6 +32,9 @@
 #define dac_reg        (0x3c8)
 #define dac_val        (0x3c9)
 
+#define VGA_FB_PHYS 0xA0000
+#define VGA_FB_PHYS_LEN 65535
+
 /* --------------------------------------------------------------------- */
 
 /*
@@ -101,6 +104,8 @@ static struct { u_short blue, green, red, pad; } palette[256];
 
 static int             currcon   = 0;
 
+static int release_io_ports = 0;
+
 /* --------------------------------------------------------------------- */
 
        /*
@@ -158,8 +163,8 @@ static int vga16fb_get_fix(struct fb_fix_screeninfo *fix, int con,
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
        strcpy(fix->id,"VGA16 VGA");
 
-       fix->smem_start = 0xa0000;
-       fix->smem_len = 65536;
+       fix->smem_start = VGA_FB_PHYS;
+       fix->smem_len = VGA_FB_PHYS_LEN;
        fix->type = FB_TYPE_VGA_PLANES;
        fix->visual = FB_VISUAL_PSEUDOCOLOR;
        fix->xpanstep  = 8;
@@ -919,7 +924,13 @@ int __init vga16_init(void)
 
        printk(KERN_DEBUG "vga16fb: initializing\n");
 
-        vga16fb.video_vbase = ioremap((unsigned long)0xa0000, 65536);
+       if (!__request_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN,
+                             "vga16fb")) {
+               printk (KERN_ERR "vga16fb: unable to reserve VGA memory, exiting\n");
+               return -1;
+       }
+
+        vga16fb.video_vbase = ioremap(VGA_FB_PHYS, VGA_FB_PHYS_LEN);
        printk(KERN_INFO "vga16fb: mapped to 0x%p\n", vga16fb.video_vbase);
 
        vga16fb.isVGA = ORIG_VIDEO_ISVGA;
@@ -937,10 +948,11 @@ int __init vga16_init(void)
                palette[i].green = default_grn[j];
                palette[i].blue  = default_blu[j];
        }
-       if (vga16fb.isVGA)
-               request_region(0x3c0, 32, "vga+");
-       else
-               request_region(0x3C0, 32, "ega");
+
+       /* note - does not cause failure, b/c vgacon probably still owns this 
+        * region (FIXME) */
+       if (__request_region(&ioport_resource, 0x3C0, 32, "vga16fb"))
+               release_io_ports = 1;
 
        disp.var = vga16fb_defined;
 
@@ -981,8 +993,10 @@ int init_module(void)
 void cleanup_module(void)
 {
     unregister_framebuffer(&vga16fb.fb_info);
-    release_region(0x3c0, 32);
     iounmap(vga16fb.video_vbase);
+    __release_region(&iomem_resource, VGA_FB_PHYS, VGA_FB_PHYS_LEN);
+    if (release_io_ports)
+       __release_region(&ioport_resource, 0x3c0, 32);
 }
 
 #endif
index 3e641a6fe891696f820ecb8f7175709aafce42c5..757b2c4f444fd4570b58931712c724e8a9d663c1 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
 #include <linux/mm.h>
 #include <linux/malloc.h>
 
-static int fifo_open(struct inode * inode,struct file * filp)
+static int fifo_open(struct inode *inode, struct file *filp)
 {
-       int retval = 0;
-       unsigned long page = 0;
-       struct pipe_inode_info *info, *tmp = NULL;
-
-       if (inode->i_pipe)
-               goto got_it;
-       tmp = kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL);
-       if (inode->i_pipe)
-               goto got_it;
-       if (!tmp)
-               goto oom;
-       page = __get_free_page(GFP_KERNEL);
-       if (inode->i_pipe)
-               goto got_it;
-       if (!page)
-               goto oom;
-       inode->i_pipe = tmp;
-       PIPE_LOCK(*inode) = 0;
-       PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
-       PIPE_BASE(*inode) = (char *) page;
-       PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
-       PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
-       init_waitqueue_head(&PIPE_WAIT(*inode));
-       tmp = NULL;     /* no need to free it */
-       page = 0;
-
-got_it:
-
-       switch( filp->f_mode ) {
+       int ret;
 
+       ret = -ERESTARTSYS;
+       if (down_interruptible(PIPE_SEM(*inode)))
+               goto err_nolock_nocleanup;
+
+       if (! inode->i_pipe) {
+               unsigned long page;
+               struct pipe_inode_info *info;
+
+               info = kmalloc(sizeof(struct pipe_inode_info),GFP_KERNEL);
+
+               ret = -ENOMEM;
+               if (!info)
+                       goto err_nocleanup;
+               page = __get_free_page(GFP_KERNEL);
+               if (!page) {
+                       kfree(info);
+                       goto err_nocleanup;
+               }
+
+               inode->i_pipe = info;
+
+               init_waitqueue_head(PIPE_WAIT(*inode));
+               PIPE_BASE(*inode) = (char *) page;
+               PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
+               PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
+       }
+
+       switch (filp->f_mode) {
        case 1:
        /*
         *  O_RDONLY
@@ -51,26 +51,26 @@ got_it:
         *  opened, even when there is no process writing the FIFO.
         */
                filp->f_op = &connecting_fifo_fops;
-               if (!PIPE_READERS(*inode)++)
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
-               if (!(filp->f_flags & O_NONBLOCK) && !PIPE_WRITERS(*inode)) {
-                       PIPE_RD_OPENERS(*inode)++;
+               if (PIPE_READERS(*inode)++ == 0)
+                       wake_up_interruptible(PIPE_WAIT(*inode));
+
+               if (!(filp->f_flags & O_NONBLOCK)) {
                        while (!PIPE_WRITERS(*inode)) {
-                               if (signal_pending(current)) {
-                                       retval = -ERESTARTSYS;
-                                       break;
-                               }
-                               interruptible_sleep_on(&PIPE_WAIT(*inode));
+                               if (signal_pending(current))
+                                       goto err_rd;
+                               up(PIPE_SEM(*inode));
+                               interruptible_sleep_on(PIPE_WAIT(*inode));
+
+                               /* Note that using down_interruptible here
+                                  and similar places below is pointless,
+                                  since we have to acquire the lock to clean
+                                  up properly.  */
+                               down(PIPE_SEM(*inode));
                        }
-                       if (!--PIPE_RD_OPENERS(*inode))
-                               wake_up_interruptible(&PIPE_WAIT(*inode));
                }
-               while (PIPE_WR_OPENERS(*inode))
-                       interruptible_sleep_on(&PIPE_WAIT(*inode));
+
                if (PIPE_WRITERS(*inode))
                        filp->f_op = &read_fifo_fops;
-               if (retval && !--PIPE_READERS(*inode))
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
                break;
        
        case 2:
@@ -79,29 +79,21 @@ got_it:
         *  POSIX.1 says that O_NONBLOCK means return -1 with
         *  errno=ENXIO when there is no process reading the FIFO.
         */
-               if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode)) {
-                       retval = -ENXIO;
-                       break;
-               }
+               ret = -ENXIO;
+               if ((filp->f_flags & O_NONBLOCK) && !PIPE_READERS(*inode))
+                       goto err;
+
                filp->f_op = &write_fifo_fops;
                if (!PIPE_WRITERS(*inode)++)
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
-               if (!PIPE_READERS(*inode)) {
-                       PIPE_WR_OPENERS(*inode)++;
-                       while (!PIPE_READERS(*inode)) {
-                               if (signal_pending(current)) {
-                                       retval = -ERESTARTSYS;
-                                       break;
-                               }
-                               interruptible_sleep_on(&PIPE_WAIT(*inode));
-                       }
-                       if (!--PIPE_WR_OPENERS(*inode))
-                               wake_up_interruptible(&PIPE_WAIT(*inode));
+                       wake_up_interruptible(PIPE_WAIT(*inode));
+
+               while (!PIPE_READERS(*inode)) {
+                       if (signal_pending(current))
+                               goto err_wr;
+                       up(PIPE_SEM(*inode));
+                       interruptible_sleep_on(PIPE_WAIT(*inode));
+                       down(PIPE_SEM(*inode));
                }
-               while (PIPE_RD_OPENERS(*inode))
-                       interruptible_sleep_on(&PIPE_WAIT(*inode));
-               if (retval && !--PIPE_WRITERS(*inode))
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
                break;
        
        case 3:
@@ -112,39 +104,47 @@ got_it:
         *  the process can at least talk to itself.
         */
                filp->f_op = &rdwr_fifo_fops;
-               if (!PIPE_READERS(*inode)++)
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
-               while (PIPE_WR_OPENERS(*inode))
-                       interruptible_sleep_on(&PIPE_WAIT(*inode));
-               if (!PIPE_WRITERS(*inode)++)
-                       wake_up_interruptible(&PIPE_WAIT(*inode));
-               while (PIPE_RD_OPENERS(*inode))
-                       interruptible_sleep_on(&PIPE_WAIT(*inode));
+
+               PIPE_READERS(*inode)++;
+               PIPE_WRITERS(*inode)++;
+               if (PIPE_READERS(*inode) == 1 || PIPE_WRITERS(*inode) == 1)
+                       wake_up_interruptible(PIPE_WAIT(*inode));
                break;
 
        default:
-               retval = -EINVAL;
+               ret = -EINVAL;
+               goto err;
        }
-       if (retval) 
-               goto cleanup;
-out:
-       if (tmp)
-               kfree(tmp);
-       if (page)
-               free_page(page);
-       return retval;
-
-cleanup:
+
+       /* Ok! */
+       up(PIPE_SEM(*inode));
+       return 0;
+
+err_rd:
+       if (!--PIPE_READERS(*inode))
+               wake_up_interruptible(PIPE_WAIT(*inode));
+       ret = -ERESTARTSYS;
+       goto err;
+
+err_wr:
+       if (!--PIPE_WRITERS(*inode))
+               wake_up_interruptible(PIPE_WAIT(*inode));
+       ret = -ERESTARTSYS;
+       goto err;
+
+err:
        if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
-               info = inode->i_pipe;
+               struct pipe_inode_info *info = inode->i_pipe;
                inode->i_pipe = NULL;
                free_page((unsigned long)info->base);
                kfree(info);
        }
-       goto out;
-oom:
-       retval = -ENOMEM;
-       goto out;
+
+err_nocleanup:
+       up(PIPE_SEM(*inode));
+
+err_nolock_nocleanup:
+       return ret;
 }
 
 /*
index 2303ca32849897cd7fcdcf0f0266e5d1788195a2..89fdc96d76e20847c21ec4147258ee3a96b45730 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/pipe.c
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1991, 1992, 1999  Linus Torvalds
  */
 
 #include <linux/mm.h>
 #undef FIFO_SUNOS_BRAINDAMAGE
 #endif
 
-/* We don't use the head/tail construction any more. Now we use the start/len*/
-/* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
-/* Florian Coosmann (FGC)                                ^ current = 1       */
-/* Additionally, we now use locking technique. This prevents race condition  */
-/* in case of paging and multiple read/write on the same pipe. (FGC)         */
-/* Reads with count = 0 should always return 0. Julian Bradfield 1999-06-07. */
+/*
+ * We use a start+len construction, which provides full use of the 
+ * allocated memory.
+ * -- Florian Coosmann (FGC)
+ * 
+ * Reads with count = 0 should always return 0.
+ * -- Julian Bradfield 1999-06-07.
+ */
+
+/* Drop the inode semaphore and wait for a pipe event, atomically */
+static void pipe_wait(struct inode * inode)
+{
+       DECLARE_WAITQUEUE(wait, current);
+       current->state = TASK_INTERRUPTIBLE;
+       add_wait_queue(PIPE_WAIT(*inode), &wait);
+       up(PIPE_SEM(*inode));
+       schedule();
+       remove_wait_queue(PIPE_WAIT(*inode), &wait);
+       current->state = TASK_RUNNING;
+}
 
-static ssize_t do_pipe_read(struct file * filp, char * buf, size_t count)
+static ssize_t
+pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
 {
-       struct inode * inode = filp->f_dentry->d_inode;
-       ssize_t chars = 0, size = 0, read = 0;
-        char *pipebuf;
+       struct inode *inode = filp->f_dentry->d_inode;
+       ssize_t size, read, ret;
 
+       /* Seeks are not allowed on pipes.  */
+       ret = -ESPIPE;
+       if (ppos != &filp->f_pos)
+               goto out_nolock;
+
+       /* Always return 0 on null read.  */
+       ret = 0;
+       if (count == 0)
+               goto out_nolock;
+
+       /* Grab, or try to grab, the pipe's semaphore with data present.  */
        if (filp->f_flags & O_NONBLOCK) {
-               if (PIPE_LOCK(*inode))
-                       return -EAGAIN;
-               if (PIPE_EMPTY(*inode)) {
-                       if (PIPE_WRITERS(*inode))
-                               return -EAGAIN;
-                       else
-                               return 0;
-               }
-       } else while (PIPE_EMPTY(*inode) || PIPE_LOCK(*inode)) {
+               ret = -EAGAIN;
+               if (down_trylock(PIPE_SEM(*inode)))
+                       goto out_nolock;
+               ret = PIPE_WRITERS(*inode) ? -EAGAIN : 0;
+               if (PIPE_EMPTY(*inode))
+                       goto out;
+       } else {
+               ret = -ERESTARTSYS;
+               if (down_interruptible(PIPE_SEM(*inode)))
+                       goto out_nolock;
+
                if (PIPE_EMPTY(*inode)) {
-                       if (!PIPE_WRITERS(*inode) || !count)
-                               return 0;
+                       ret = 0;
+                       if (!PIPE_WRITERS(*inode))
+                               goto out;
+
+                       for (;;) {
+                               pipe_wait(inode);
+                               ret = -ERESTARTSYS;
+                               if (signal_pending(current))
+                                       goto out_nolock;
+                               if (down_interruptible(PIPE_SEM(*inode)))
+                                       goto out_nolock;
+                               ret = 0;
+                               if (!PIPE_EMPTY(*inode))
+                                       break;
+                               if (!PIPE_WRITERS(*inode))
+                                       goto out;
+                       }
                }
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-               interruptible_sleep_on(&PIPE_WAIT(*inode));
        }
-       PIPE_LOCK(*inode)++;
-       while (count>0 && (size = PIPE_SIZE(*inode))) {
-               chars = PIPE_MAX_RCHUNK(*inode);
+
+       /* Read what data is available.  */
+       ret = -EFAULT;
+       read = 0;
+       while (count > 0 && (size = PIPE_LEN(*inode))) {
+               char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
+               ssize_t chars = PIPE_MAX_RCHUNK(*inode);
+
                if (chars > count)
                        chars = count;
                if (chars > size)
                        chars = size;
+
+               if (copy_to_user(buf, pipebuf, chars))
+                       goto out;
+
                read += chars;
-                pipebuf = PIPE_BASE(*inode)+PIPE_START(*inode);
                PIPE_START(*inode) += chars;
-               PIPE_START(*inode) &= (PIPE_BUF-1);
+               PIPE_START(*inode) &= (PIPE_SIZE - 1);
                PIPE_LEN(*inode) -= chars;
                count -= chars;
-               copy_to_user(buf, pipebuf, chars );
                buf += chars;
        }
-       PIPE_LOCK(*inode)--;
-       wake_up_interruptible(&PIPE_WAIT(*inode));
-       if (read) {
+
+       /* Cache behaviour optimization */
+       if (!PIPE_LEN(*inode))
+               PIPE_START(*inode) = 0;
+
+       /* Signal writers there is more room.  */
+       wake_up_interruptible(PIPE_WAIT(*inode));
+
+       if (read)
                UPDATE_ATIME(inode);
-               return read;
-       }
-       if (PIPE_WRITERS(*inode))
-               return -EAGAIN;
-       return 0;
+       ret = read;
+
+out:
+       up(PIPE_SEM(*inode));
+out_nolock:
+       return ret;
 }
 
-static ssize_t do_pipe_write(struct file * filp, const char * buf, size_t count)
+static ssize_t
+pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
 {
-       struct inode * inode = filp->f_dentry->d_inode;
-       ssize_t chars = 0, free = 0, written = 0, err=0;
-       char *pipebuf;
+       struct inode *inode = filp->f_dentry->d_inode;
+       ssize_t free, written, ret;
 
-       if (!PIPE_READERS(*inode)) { /* no readers */
-               send_sig(SIGPIPE,current,0);
-               return -EPIPE;
-       }
-       /* if count <= PIPE_BUF, we have to make it atomic */
-       if (count <= PIPE_BUF)
-               free = count;
-       else
-               free = 1; /* can't do it atomically, wait for any free space */
-       if (down_interruptible(&inode->i_sem)) {
-               return -ERESTARTSYS;
-       }
-       while (count>0) {
-               while ((PIPE_FREE(*inode) < free) || PIPE_LOCK(*inode)) {
-                       if (!PIPE_READERS(*inode)) { /* no readers */
-                               send_sig(SIGPIPE,current,0);
-                               err = -EPIPE;
-                               goto errout;
-                       }
-                       if (signal_pending(current)) {
-                               err = -ERESTARTSYS;
-                               goto errout;
-                       }
-                       if (filp->f_flags & O_NONBLOCK) {
-                               err = -EAGAIN;
-                               goto errout;
-                       }
-                       interruptible_sleep_on(&PIPE_WAIT(*inode));
+       /* Seeks are not allowed on pipes.  */
+       ret = -ESPIPE;
+       if (ppos != &filp->f_pos)
+               goto out_nolock;
+
+       /* Null write succeeds.  */
+       ret = 0;
+       if (count == 0)
+               goto out_nolock;
+
+       ret = -ERESTARTSYS;
+       if (down_interruptible(PIPE_SEM(*inode)))
+               goto out_nolock;
+
+       /* No readers yields SIGPIPE.  */
+       if (!PIPE_READERS(*inode))
+               goto sigpipe;
+
+       /* If count <= PIPE_BUF, we have to make it atomic.  */
+       free = (count <= PIPE_BUF ? count : 1);
+       written = 0;
+
+       /* Wait, or check for, available space.  */
+       if (filp->f_flags & O_NONBLOCK) {
+               ret = -EAGAIN;
+               if (PIPE_FREE(*inode) < free)
+                       goto out;
+       } else {
+               while (PIPE_FREE(*inode) < free) {
+                       pipe_wait(inode);
+                       ret = -ERESTARTSYS;
+                       if (signal_pending(current))
+                               goto out_nolock;
+                       if (down_interruptible(PIPE_SEM(*inode)))
+                               goto out_nolock;
+
+                       if (!PIPE_READERS(*inode))
+                               goto sigpipe;
                }
-               PIPE_LOCK(*inode)++;
-               while (count>0 && (free = PIPE_FREE(*inode))) {
-                       chars = PIPE_MAX_WCHUNK(*inode);
+       }
+
+       /* Copy into available space.  */
+       ret = -EFAULT;
+       while (count > 0) {
+               int space;
+               char *pipebuf = PIPE_BASE(*inode) + PIPE_END(*inode);
+               ssize_t chars = PIPE_MAX_WCHUNK(*inode);
+
+               if ((space = PIPE_FREE(*inode)) != 0) {
                        if (chars > count)
                                chars = count;
-                       if (chars > free)
-                               chars = free;
-                        pipebuf = PIPE_BASE(*inode)+PIPE_END(*inode);
+                       if (chars > space)
+                               chars = space;
+
+                       if (copy_from_user(pipebuf, buf, chars))
+                               goto out;
+
                        written += chars;
                        PIPE_LEN(*inode) += chars;
                        count -= chars;
-                       copy_from_user(pipebuf, buf, chars );
                        buf += chars;
+                       space = PIPE_FREE(*inode);
+                       continue;
                }
-               PIPE_LOCK(*inode)--;
-               wake_up_interruptible(&PIPE_WAIT(*inode));
-               free = 1;
-       }
-       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-       mark_inode_dirty(inode);
-errout:
-       up(&inode->i_sem);
-       return written ? written : err;
-}
-
-static ssize_t pipe_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
-{
-       ssize_t retval;
-
 
-       if (ppos != &filp->f_pos)
-               return -ESPIPE;
-
-       if ( !count ) return 0;
+               ret = written;
+               if (filp->f_flags & O_NONBLOCK)
+                       break;
+
+               do {
+                       /* This should be a synchronous wake-up: don't do idle reschedules! */
+                       wake_up_interruptible(PIPE_WAIT(*inode));
+                       pipe_wait(inode);
+                       if (signal_pending(current))
+                               goto out;
+                       if (down_interruptible(PIPE_SEM(*inode)))
+                               goto out_nolock;
+                       if (!PIPE_READERS(*inode))
+                               goto sigpipe;
+               } while (!PIPE_FREE(*inode));
+               ret = -EFAULT;
+       }
 
-       lock_kernel();
-       retval = do_pipe_read(filp, buf, count);
-       unlock_kernel();
-       return retval;
-}
+       /* Signal readers there is more data.  */
+       wake_up_interruptible(PIPE_WAIT(*inode));
 
-static ssize_t pipe_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
-{
-       ssize_t retval;
+       ret = (written ? written : -EAGAIN);
+       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+       mark_inode_dirty(inode);
 
-       if (ppos != &filp->f_pos)
-               return -ESPIPE;
+out:
+       up(PIPE_SEM(*inode));
+out_nolock:
+       return ret;
 
-       lock_kernel();
-       retval = do_pipe_write(filp, buf, count);
-       unlock_kernel();
-       return retval;
+sigpipe:
+       up(PIPE_SEM(*inode));
+       send_sig(SIGPIPE, current, 0);
+       return -EPIPE;
 }
 
-static long long pipe_lseek(struct file * file, long long offset, int orig)
+static loff_t
+pipe_lseek(struct file *file, loff_t offset, int orig)
 {
        return -ESPIPE;
 }
 
-static ssize_t bad_pipe_r(struct file * filp, char * buf,
-                         size_t count, loff_t *ppos)
+static ssize_t
+bad_pipe_r(struct file *filp, char *buf, size_t count, loff_t *ppos)
 {
        return -EBADF;
 }
 
-static ssize_t bad_pipe_w(struct file * filp, const char * buf,
-                         size_t count, loff_t *ppos)
+static ssize_t
+bad_pipe_w(struct file *filp, const char *buf, size_t count, loff_t *ppos)
 {
        return -EBADF;
 }
 
-static int pipe_ioctl(struct inode *pino, struct file * filp,
-                     unsigned int cmd, unsigned long arg)
+static int
+pipe_ioctl(struct inode *pino, struct file *filp,
+          unsigned int cmd, unsigned long arg)
 {
        switch (cmd) {
                case FIONREAD:
-                       return put_user(PIPE_SIZE(*pino),(int *) arg);
+                       return put_user(PIPE_LEN(*pino), (int *)arg);
                default:
                        return -EINVAL;
        }
 }
 
-static unsigned int pipe_poll(struct file * filp, poll_table * wait)
+static unsigned int
+pipe_poll(struct file *filp, poll_table *wait)
 {
        unsigned int mask;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_dentry->d_inode;
 
-       poll_wait(filp, &PIPE_WAIT(*inode), wait);
+       poll_wait(filp, PIPE_WAIT(*inode), wait);
+
+       /* Reading only -- no need for aquiring the semaphore.  */
        mask = POLLIN | POLLRDNORM;
        if (PIPE_EMPTY(*inode))
                mask = POLLOUT | POLLWRNORM;
@@ -210,6 +286,7 @@ static unsigned int pipe_poll(struct file * filp, poll_table * wait)
                mask |= POLLHUP;
        if (!PIPE_READERS(*inode))
                mask |= POLLERR;
+
        return mask;
 }
 
@@ -218,17 +295,21 @@ static unsigned int pipe_poll(struct file * filp, poll_table * wait)
  * Argh!  Why does SunOS have to have different select() behaviour
  * for pipes and FIFOs?  Hate, hate, hate!  SunOS lacks POLLHUP.
  */
-static unsigned int fifo_poll(struct file * filp, poll_table * wait)
+static unsigned int
+fifo_poll(struct file *filp, poll_table *wait)
 {
        unsigned int mask;
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_dentry->d_inode;
+
+       poll_wait(filp, PIPE_WAIT(*inode), wait);
 
-       poll_wait(filp, &PIPE_WAIT(*inode), wait);
+       /* Reading only -- no need for aquiring the semaphore.  */
        mask = POLLIN | POLLRDNORM;
        if (PIPE_EMPTY(*inode))
                mask = POLLOUT | POLLWRNORM;
        if (!PIPE_READERS(*inode))
                mask |= POLLERR;
+
        return mask;
 }
 #else
@@ -242,82 +323,112 @@ static unsigned int fifo_poll(struct file * filp, poll_table * wait)
  * the open() code hasn't guaranteed a connection (O_NONBLOCK),
  * and we need to act differently until we do get a writer..
  */
-static ssize_t connect_read(struct file * filp, char * buf,
-                           size_t count, loff_t *ppos)
+static ssize_t
+connect_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
 {
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_dentry->d_inode;
+
+       /* Reading only -- no need for aquiring the semaphore.  */
        if (PIPE_EMPTY(*inode) && !PIPE_WRITERS(*inode))
                return 0;
+
        filp->f_op = &read_fifo_fops;
-       return pipe_read(filp,buf,count,ppos);
+       return pipe_read(filp, buf, count, ppos);
 }
 
-static unsigned int connect_poll(struct file * filp, poll_table * wait)
+static unsigned int
+connect_poll(struct file *filp, poll_table *wait)
 {
-       struct inode * inode = filp->f_dentry->d_inode;
+       struct inode *inode = filp->f_dentry->d_inode;
+       unsigned int mask = 0;
+
+       poll_wait(filp, PIPE_WAIT(*inode), wait);
 
-       poll_wait(filp, &PIPE_WAIT(*inode), wait);
+       /* Reading only -- no need for aquiring the semaphore.  */
        if (!PIPE_EMPTY(*inode)) {
                filp->f_op = &read_fifo_fops;
-               return POLLIN | POLLRDNORM;
-       }
-       if (PIPE_WRITERS(*inode))
+               mask = POLLIN | POLLRDNORM;
+       } else if (PIPE_WRITERS(*inode)) {
                filp->f_op = &read_fifo_fops;
-       return POLLOUT | POLLWRNORM;
+               mask = POLLOUT | POLLWRNORM;
+       }
+
+       return mask;
 }
 
-static int pipe_release(struct inode * inode)
+static int
+pipe_release(struct inode *inode, int decr, int decw)
 {
+       down(PIPE_SEM(*inode));
+       PIPE_READERS(*inode) -= decr;
+       PIPE_WRITERS(*inode) -= decw;
        if (!PIPE_READERS(*inode) && !PIPE_WRITERS(*inode)) {
                struct pipe_inode_info *info = inode->i_pipe;
                inode->i_pipe = NULL;
                free_page((unsigned long) info->base);
                kfree(info);
-               return 0;
+       } else {
+               wake_up_interruptible(PIPE_WAIT(*inode));
        }
-       wake_up_interruptible(&PIPE_WAIT(*inode));
+       up(PIPE_SEM(*inode));
+
        return 0;
 }
 
-static int pipe_read_release(struct inode * inode, struct file * filp)
+static int
+pipe_read_release(struct inode *inode, struct file *filp)
 {
-       PIPE_READERS(*inode)--;
-       return pipe_release(inode);
+       return pipe_release(inode, 1, 0);
 }
 
-static int pipe_write_release(struct inode * inode, struct file * filp)
+static int
+pipe_write_release(struct inode *inode, struct file *filp)
 {
-       PIPE_WRITERS(*inode)--;
-       return pipe_release(inode);
+       return pipe_release(inode, 0, 1);
 }
 
-static int pipe_rdwr_release(struct inode * inode, struct file * filp)
+static int
+pipe_rdwr_release(struct inode *inode, struct file *filp)
 {
-       if (filp->f_mode & FMODE_READ)
-               PIPE_READERS(*inode)--;
-       if (filp->f_mode & FMODE_WRITE)
-               PIPE_WRITERS(*inode)--;
-       return pipe_release(inode);
+       int decr, decw;
+
+       decr = (filp->f_mode & FMODE_READ) != 0;
+       decw = (filp->f_mode & FMODE_WRITE) != 0;
+       return pipe_release(inode, decr, decw);
 }
 
-static int pipe_read_open(struct inode * inode, struct file * filp)
+static int
+pipe_read_open(struct inode *inode, struct file *filp)
 {
+       /* We could have perhaps used atomic_t, but this and friends
+          below are the only places.  So it doesn't seem worthwhile.  */
+       down(PIPE_SEM(*inode));
        PIPE_READERS(*inode)++;
+       up(PIPE_SEM(*inode));
+
        return 0;
 }
 
-static int pipe_write_open(struct inode * inode, struct file * filp)
+static int
+pipe_write_open(struct inode *inode, struct file *filp)
 {
+       down(PIPE_SEM(*inode));
        PIPE_WRITERS(*inode)++;
+       up(PIPE_SEM(*inode));
+
        return 0;
 }
 
-static int pipe_rdwr_open(struct inode * inode, struct file * filp)
+static int
+pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
+       down(PIPE_SEM(*inode));
        if (filp->f_mode & FMODE_READ)
                PIPE_READERS(*inode)++;
        if (filp->f_mode & FMODE_WRITE)
                PIPE_WRITERS(*inode)++;
+       up(PIPE_SEM(*inode));
+
        return 0;
 }
 
@@ -433,22 +544,20 @@ static struct inode * get_pipe_inode(void)
                goto fail_inode;
 
        page = __get_free_page(GFP_USER);
-
        if (!page)
                goto fail_iput;
 
-       /* XXX */
        inode->i_pipe = kmalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
        if (!inode->i_pipe)
                goto fail_page;
 
-       PIPE_BASE(*inode) = (char *) page;
        inode->i_op = &pipe_inode_operations;
-       init_waitqueue_head(&PIPE_WAIT(*inode));
+
+       init_waitqueue_head(PIPE_WAIT(*inode));
+       PIPE_BASE(*inode) = (char *) page;
        PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
-       PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
        PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
-       PIPE_LOCK(*inode) = 0;
+
        /*
         * Mark the inode dirty from the very beginning,
         * that way it will never be moved to the dirty
index 70bd39f695d55a2b10be74dff2939172ece4919d..6346f91d19de28b790663255966156a1375293d6 100644 (file)
@@ -73,15 +73,15 @@ static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
        return c != 0;
 }
 
-extern __inline__ int atomic_inc_and_test_greater_zero(volatile atomic_t *v)
+extern __inline__ int atomic_add_negative(int i, volatile atomic_t *v)
 {
        unsigned char c;
 
        __asm__ __volatile__(
-               LOCK "incl %0; setg %1"
+               LOCK "addl %2,%0; sets %1"
                :"=m" (__atomic_fool_gcc(v)), "=qm" (c)
-               :"m" (__atomic_fool_gcc(v)));
-       return c; /* can be only 0 or 1 */
+               :"ir" (i), "m" (__atomic_fool_gcc(v)));
+       return c;
 }
 
 /* These are x86-specific, used by some header files */
index 93fd0c1b52d39eb77c7d7cd118108dc041fab010..2090dab84f8b2eecf907f4ce7f66a1fe314b8938 100644 (file)
@@ -152,10 +152,16 @@ extern void iounmap(void *addr);
 #define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
 #define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
 #define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
 
 #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
 #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
 #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
 
 #define memset_io(a,b,c)       memset(__io_virt(a),(b),(c))
 #define memcpy_fromio(a,b,c)   memcpy((a),__io_virt(b),(c))
diff --git a/include/asm-i386/semaphore-helper.h b/include/asm-i386/semaphore-helper.h
deleted file mode 100644 (file)
index a80dfe5..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef _I386_SEMAPHORE_HELPER_H
-#define _I386_SEMAPHORE_HELPER_H
-
-/*
- * SMP- and interrupt-safe semaphores helper functions.
- *
- * (C) Copyright 1996 Linus Torvalds
- * (C) Copyright 1999 Andrea Arcangeli
- */
-
-/*
- * These two _must_ execute atomically wrt each other.
- *
- * This is trivially done with load_locked/store_cond,
- * but on the x86 we need an external synchronizer.
- *
- * NOTE: we can't look at the semaphore count here since it can be
- * unreliable. Even if the count is minor than 1, the semaphore
- * could be just owned by another process (this because not only up() increases
- * the semaphore count, also the interruptible/trylock call can increment
- * the semaphore count when they fails).
- */
-static inline void wake_one_more(struct semaphore * sem)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&semaphore_wake_lock, flags);
-       sem->waking++;
-       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
-}
-
-static inline int waking_non_zero(struct semaphore *sem)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&semaphore_wake_lock, flags);
-       if (sem->waking > 0) {
-               sem->waking--;
-               ret = 1;
-       }
-       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
-       return ret;
-}
-
-/*
- * waking_non_zero_interruptible:
- *     1       got the lock
- *     0       go to sleep
- *     -EINTR  interrupted
- *
- * If we give up we must undo our count-decrease we previously did in down().
- * Subtle: up() can continue to happens and increase the semaphore count
- * even during our critical section protected by the spinlock. So
- * we must remeber to undo the sem->waking that will be run from
- * wake_one_more() some time soon, if the semaphore count become > 0.
- */
-static inline int waking_non_zero_interruptible(struct semaphore *sem,
-                                               struct task_struct *tsk)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&semaphore_wake_lock, flags);
-       if (sem->waking > 0) {
-               sem->waking--;
-               ret = 1;
-       } else if (signal_pending(tsk)) {
-               if (atomic_inc_and_test_greater_zero(&sem->count))
-                       sem->waking--;
-               ret = -EINTR;
-       }
-       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
-       return ret;
-}
-
-/*
- * waking_non_zero_trylock:
- *     1       failed to lock
- *     0       got the lock
- *
- * Implementation details are the same of the interruptible case.
- */
-static inline int waking_non_zero_trylock(struct semaphore *sem)
-{
-       unsigned long flags;
-       int ret = 1;
-
-       spin_lock_irqsave(&semaphore_wake_lock, flags);
-       if (sem->waking <= 0)
-       {
-               if (atomic_inc_and_test_greater_zero(&sem->count))
-                       sem->waking--;
-       } else {
-               sem->waking--;
-               ret = 0;
-       }
-       spin_unlock_irqrestore(&semaphore_wake_lock, flags);
-       return ret;
-}
-
-#endif
index 56c72335860d3160e6bce126ddbd864b4aaf4735..bd51aa8434bd5decb25dd96a63ec546877b9e761 100644 (file)
@@ -35,7 +35,7 @@
 
 struct semaphore {
        atomic_t count;
-       int waking;
+       int sleepers;
        wait_queue_head_t wait;
 #if WAITQUEUE_DEBUG
        long __magic;
@@ -71,7 +71,7 @@ extern inline void sema_init (struct semaphore *sem, int val)
  * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
  */
        atomic_set(&sem->count, val);
-       sem->waking = 0;
+       sem->sleepers = 0;
        init_waitqueue_head(&sem->wait);
 #if WAITQUEUE_DEBUG
        sem->__magic = (int)&sem->__magic;
index 7bece29f6321ee2205ecbbadf13ff2b86f3f9214..a0743ec146b8e98b5b257115277dbfd80c4f01db 100644 (file)
@@ -1,10 +1,11 @@
-/* $Id: concap.h,v 1.1 1998/02/01 00:15:11 keil Exp $
+/* $Id: concap.h,v 1.2 1999/08/23 15:54:21 keil Exp $
 */
 #ifndef _LINUX_CONCAP_H
 #define _LINUX_CONCAP_H
 #ifdef __KERNEL__
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
+#include <linux/isdn_compat.h>
 
 /* Stuff to support encapsulation protocols genericly. The encapsulation
    protocol is processed at the uppermost layer of the network interface.
@@ -25,11 +26,11 @@ struct concap_device_ops;
 /* this manages all data needed by the encapsulation protocol
  */
 struct concap_proto{
-       struct net_device *net_dev;             /* net device using our service  */
-       struct concap_device_ops *dops; /* callbacks provided by device */
-       struct concap_proto_ops  *pops; /* callbacks provided by us */
+       struct net_device *net_dev;     /* net device using our service  */
+       struct concap_device_ops *dops; /* callbacks provided by device */
+       struct concap_proto_ops  *pops; /* callbacks provided by us */
        int flags;
-       void *proto_data;               /* protocol specific private data, to
+       void *proto_data;               /* protocol specific private data, to
                                           be accessed via *pops methods only*/
        /*
          :
@@ -107,7 +108,3 @@ extern int concap_nop(struct concap_proto *cprot);
 extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
 #endif
 #endif
-
-
-
-
index a6c4a48f6f3b8208eaa599f3beba636484ee8b50..feb877ed0d103cb422845e941f4bc904af42f814 100644 (file)
@@ -92,8 +92,6 @@ struct i2c_driver
 
 /* needed: unsigned long flags */
 
-#include <linux/version.h>
-
 #if LINUX_VERSION_CODE >= 0x020100
 # if 0
 #  define LOCK_FLAGS unsigned long flags;
index 99bb97fa253ec85db6e5dde8a9f1f83198354989..2e58af4edd81e8a13045934f2a03108db477ad5f 100644 (file)
@@ -75,6 +75,7 @@
 #define ETH_P_MOBITEX  0x0015          /* Mobitex (kaz@cafe.net)       */
 #define ETH_P_CONTROL  0x0016          /* Card specific control frames */
 #define ETH_P_IRDA     0x0017          /* Linux/IR                     */
+#define ETH_P_ECONET   0x0018          /* Acorn Econet                 */
 
 /*
  *     This is an Ethernet frame header.
index 152b1169952216e33cbe21581d7ca454fcaf21cf..d1d7350b1cc6481ffb404f939110521c32b2b555 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.70 1999/07/31 12:59:58 armin Exp $
+/* $Id: isdn.h,v 1.71 1999/08/23 15:54:22 keil Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.71  1999/08/23 15:54:22  keil
+ * more backported changes from kernel 2.3.14
+ *
  * Revision 1.70  1999/07/31 12:59:58  armin
  * Added tty fax capabilities.
  *
@@ -577,13 +580,13 @@ typedef struct isdn_net_local_s {
   ulong                  sqfull_stamp; /* Start-Time of overload           */
   ulong                  slavedelay;   /* Dynamic bundling delaytime       */
   int                    triggercps;   /* BogoCPS needed for trigger slave */
-  struct net_device          *srobin;      /* Ptr to Master device for slaves  */
+  struct net_device      *srobin;      /* Ptr to Master device for slaves  */
   isdn_net_phone         *phone[2];    /* List of remote-phonenumbers      */
                                       /* phone[0] = Incoming Numbers      */
                                       /* phone[1] = Outgoing Numbers      */
   isdn_net_phone         *dial;        /* Pointer to dialed number         */
-  struct net_device          *master;      /* Ptr to Master device for slaves  */
-  struct net_device          *slave;       /* Ptr to Slave device for masters  */
+  struct net_device      *master;      /* Ptr to Master device for slaves  */
+  struct net_device      *slave;       /* Ptr to Slave device for masters  */
   struct isdn_net_local_s *next;       /* Ptr to next link in bundle       */
   struct isdn_net_local_s *last;       /* Ptr to last link in bundle       */
   struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
@@ -616,7 +619,7 @@ typedef struct isdn_net_dev_s {
   isdn_net_local *local;
   isdn_net_local *queue;
   void           *next;                /* Pointer to next isdn-interface   */
-  struct net_device   dev;            /* interface to upper levels        */
+  struct net_device dev;               /* interface to upper levels        */
 #ifdef CONFIG_ISDN_PPP
   struct mpqueue *mp_last; 
   struct ippp_bundle ib;
index db002c4153192722414a0a562c7721436f6b0b66..7750f63037eadb557880110bbc742ca6bc6cfbd2 100644 (file)
@@ -104,5 +104,13 @@ static inline unsigned long copy_to_user(void *to, const void *from, unsigned lo
 #define COMPAT_HAS_NEW_WAITQ
 #endif
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,12)
+#define COMPAT_HAS_NEW_SETUP
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)
+#define net_device device
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_ISDN_COMPAT_H */
index 35b66bba836d1ed57b9884a415f6f3cc739f9042..06206eb916d684e663dfaea812c99fce5146ca62 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.29 1999/07/31 13:00:02 armin Exp $
+/* $Id: isdnif.h,v 1.30 1999/08/23 15:54:29 keil Exp $
  *
  * Linux ISDN subsystem
  *
@@ -22,6 +22,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.30  1999/08/23 15:54:29  keil
+ * more backported changes from kernel 2.3.14
+ *
  * Revision 1.29  1999/07/31 13:00:02  armin
  * Added tty fax capabilities.
  *
index 1ee1c434c4d2e2260082afea204c1f1e1e6802cb..78abcc24463eb08499039610074c754b963dcd1a 100644 (file)
 #define MSG_NOERROR     010000  /* no error if message is too big */
 #define MSG_EXCEPT      020000  /* recv any msg except of specified type.*/
 
+#ifdef __KERNEL__
+
 /* one msqid structure for each queue on the system */
-struct msqid_ds {
+struct msqid_ds_kern {
        struct ipc_perm msg_perm;
        struct msg *msg_first;          /* first message on queue */
        struct msg *msg_last;           /* last message in queue */
@@ -28,6 +30,24 @@ struct msqid_ds {
        __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
 };
 
+#endif
+
+struct msqid_ds {
+       struct ipc_perm msg_perm;
+       struct msg *msg_first;          /* first message on queue */
+       struct msg *msg_last;           /* last message in queue */
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long  msg_cbytes;      /* Reuse junk fields for 32 bit */
+       unsigned long  msg_qbytes;      /* ditto */
+       unsigned short msg_cbytes_old;  /* current number of bytes on queue */
+       unsigned short msg_qnum;        /* number of messages in queue */
+       unsigned short msg_qbytes_old;  /* max number of bytes on queue */
+       __kernel_ipc_pid_t msg_lspid;   /* pid of last msgsnd */
+       __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
+};
+
 /* message buffer for msgsnd and msgrcv calls */
 struct msgbuf {
        long mtype;         /* type of message */
index a96ede0178089d3d183cb3d18e4f9d1cc24ed6ab..7989f6b10113ce8f1e2dbf7b09133b849144be49 100644 (file)
@@ -169,9 +169,6 @@ extern void nf_invalidate_cache(int pf);
  * seconds to see why.         - Linus
  */
 
-/* Use which one you mean explicitly.  You have been warned. */
-#include <linux/types.h>
-
 /* Two signed, return a signed. */
 #define SMAX(a,b) ((ssize_t)(a)>(ssize_t)(b) ? (ssize_t)(a) : (ssize_t)(b))
 #define SMIN(a,b) ((ssize_t)(a)<(ssize_t)(b) ? (ssize_t)(a) : (ssize_t)(b))
index 01cf240ddd4e02212fbfe1c204e7d25b08b09fbb..6c0427b01df19b665a90036b37c202c90716bef1 100644 (file)
@@ -5,6 +5,7 @@
  * (C)1998 Rusty Russell -- This code is GPL.
  */
 
+#include <linux/config.h>
 #include <linux/netfilter.h>
 
 /* IP Cache bits. */
index c00d37845cdf57d0f7c304f46e21facde084c556..eb2d9105417e9857b4a73f1bd49344f213a1844e 100644 (file)
@@ -3,32 +3,29 @@
 
 struct pipe_inode_info {
        wait_queue_head_t wait;
-       char * base;
+       char *base;
        unsigned int start;
-       unsigned int lock;
-       unsigned int rd_openers;
-       unsigned int wr_openers;
        unsigned int readers;
        unsigned int writers;
 };
 
-#define PIPE_WAIT(inode)       ((inode).i_pipe->wait)
+/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
+   memory allocation, whereas PIPE_BUF makes atomicity guarantees.  */
+#define PIPE_SIZE              PAGE_SIZE
+
+#define PIPE_SEM(inode)                (&(inode).i_sem)
+#define PIPE_WAIT(inode)       (&(inode).i_pipe->wait)
 #define PIPE_BASE(inode)       ((inode).i_pipe->base)
 #define PIPE_START(inode)      ((inode).i_pipe->start)
 #define PIPE_LEN(inode)                ((inode).i_size)
-#define PIPE_RD_OPENERS(inode) ((inode).i_pipe->rd_openers)
-#define PIPE_WR_OPENERS(inode) ((inode).i_pipe->wr_openers)
 #define PIPE_READERS(inode)    ((inode).i_pipe->readers)
 #define PIPE_WRITERS(inode)    ((inode).i_pipe->writers)
-#define PIPE_LOCK(inode)       ((inode).i_pipe->lock)
-#define PIPE_SIZE(inode)       PIPE_LEN(inode)
 
-#define PIPE_EMPTY(inode)      (PIPE_SIZE(inode)==0)
-#define PIPE_FULL(inode)       (PIPE_SIZE(inode)==PIPE_BUF)
-#define PIPE_FREE(inode)       (PIPE_BUF - PIPE_LEN(inode))
-#define PIPE_END(inode)                ((PIPE_START(inode)+PIPE_LEN(inode))&\
-                                                          (PIPE_BUF-1))
-#define PIPE_MAX_RCHUNK(inode) (PIPE_BUF - PIPE_START(inode))
-#define PIPE_MAX_WCHUNK(inode) (PIPE_BUF - PIPE_END(inode))
+#define PIPE_EMPTY(inode)      (PIPE_LEN(inode) == 0)
+#define PIPE_FULL(inode)       (PIPE_LEN(inode) == PIPE_SIZE)
+#define PIPE_FREE(inode)       (PIPE_SIZE - PIPE_LEN(inode))
+#define PIPE_END(inode)        ((PIPE_START(inode) + PIPE_LEN(inode)) & (PIPE_SIZE-1))
+#define PIPE_MAX_RCHUNK(inode) (PIPE_SIZE - PIPE_START(inode))
+#define PIPE_MAX_WCHUNK(inode) (PIPE_SIZE - PIPE_END(inode))
 
 #endif
index f08f3c36ed40d3b758319d99aa8770c523510808..3382a6a5732f54207ae187e94946aafa50773d9d 100644 (file)
@@ -1,9 +1,10 @@
 #ifndef _LINUX_PRCTL_H
 #define _LINUX_PRCTL_H
 
-/*  Values to pass as first argument to prctl()  */
+/* Values to pass as first argument to prctl() */
 
-#define PR_SET_PDEATHSIG  1  /*  Second arg is a signal  */
+#define PR_SET_PDEATHSIG  1  /* Second arg is a signal */
+#define PR_GET_PDEATHSIG  2  /* Second arg is a ptr to return the signal */
 
 
 #endif /* _LINUX_PRCTL_H */
index 812a2ff9bc0ed2f7692b5049e1ae63925b265fac..7927a25a6deadaffa99fe068332ff8c69cef1765 100644 (file)
@@ -510,4 +510,25 @@ static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
 
 #endif
 
+
+#if defined(__i386__) || defined(__alpha__)
+
+#define fb_readb __raw_readb
+#define fb_readw __raw_readw
+#define fb_readl __raw_readl
+#define fb_writeb __raw_writeb
+#define fb_writew __raw_writew
+#define fb_writel __raw_writel
+
+#else
+
+#define fb_readb(addr) (*(volatile unsigned char *) __io_virt(addr))
+#define fb_readw(addr) (*(volatile unsigned short *) __io_virt(addr))
+#define fb_readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+#define fb_writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
+#define fb_writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
+#define fb_writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+
+#endif
+
 #endif /* _VIDEO_FBCON_H */
index 731a7a6b4deb650c1378ef98e788028add0334c1..79ebbe4543b2867e65a737a01057f3266a593d8f 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -30,7 +30,7 @@ static int findkey (key_t key);
 static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-static struct msqid_ds *msgque[MSGMNI];
+static struct msqid_ds_kern *msgque[MSGMNI];
 static int msgbytes = 0;
 static int msghdrs = 0;
 static unsigned short msg_seq = 0;
@@ -46,7 +46,7 @@ void __init msg_init (void)
 #endif
 
        for (id = 0; id < MSGMNI; id++) 
-               msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+               msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED;
        msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
        init_waitqueue_head(&msg_lock);
 #ifdef CONFIG_PROC_FS
@@ -59,7 +59,7 @@ void __init msg_init (void)
 static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
 {
        int id;
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        struct ipc_perm *ipcp;
        struct msg *msgh;
        long mtype;
@@ -136,7 +136,7 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
 
 static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
 {
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        struct ipc_perm *ipcp;
        struct msg *tmsg, *leastp = NULL;
        struct msg *nmsg = NULL;
@@ -257,7 +257,7 @@ asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz,
 static int findkey (key_t key)
 {
        int id;
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        
        for (id = 0; id <= max_msqid; id++) {
                while ((msq = msgque[id]) == IPC_NOID) 
@@ -273,20 +273,20 @@ static int findkey (key_t key)
 static int newque (key_t key, int msgflg)
 {
        int id;
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        struct ipc_perm *ipcp;
 
        for (id = 0; id < MSGMNI; id++) 
                if (msgque[id] == IPC_UNUSED) {
-                       msgque[id] = (struct msqid_ds *) IPC_NOID;
+                       msgque[id] = (struct msqid_ds_kern *) IPC_NOID;
                        goto found;
                }
        return -ENOSPC;
 
 found:
-       msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL);
+       msq = (struct msqid_ds_kern *) kmalloc (sizeof (*msq), GFP_KERNEL);
        if (!msq) {
-               msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+               msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED;
                wake_up (&msg_lock);
                return -ENOMEM;
        }
@@ -315,7 +315,7 @@ found:
 asmlinkage long sys_msgget (key_t key, int msgflg)
 {
        int id, ret = -EPERM;
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        
        lock_kernel();
        if (key == IPC_PRIVATE) 
@@ -342,7 +342,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
 
 static void freeque (int id)
 {
-       struct msqid_ds *msq = msgque[id];
+       struct msqid_ds_kern *msq = msgque[id];
        struct msg *msgp, *msgh;
 
        msq->msg_perm.seq++;
@@ -350,7 +350,7 @@ static void freeque (int id)
        msgbytes -= msq->msg_cbytes;
        if (id == max_msqid)
                while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));
-       msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+       msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED;
        used_queues--;
        while (waitqueue_active(&msq->rwait) || waitqueue_active(&msq->wwait)) {
                wake_up (&msq->rwait); 
@@ -368,7 +368,7 @@ static void freeque (int id)
 asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 {
        int id, err = -EINVAL;
-       struct msqid_ds *msq;
+       struct msqid_ds_kern *msq;
        struct msqid_ds tbuf;
        struct ipc_perm *ipcp;
        
@@ -420,8 +420,10 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                tbuf.msg_stime  = msq->msg_stime;
                tbuf.msg_rtime  = msq->msg_rtime;
                tbuf.msg_ctime  = msq->msg_ctime;
+               tbuf.msg_cbytes_old = msq->msg_cbytes;
                tbuf.msg_cbytes = msq->msg_cbytes;
                tbuf.msg_qnum   = msq->msg_qnum;
+               tbuf.msg_qbytes_old = msq->msg_qbytes;
                tbuf.msg_qbytes = msq->msg_qbytes;
                tbuf.msg_lspid  = msq->msg_lspid;
                tbuf.msg_lrpid  = msq->msg_lrpid;
@@ -462,8 +464,10 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                tbuf.msg_stime  = msq->msg_stime;
                tbuf.msg_rtime  = msq->msg_rtime;
                tbuf.msg_ctime  = msq->msg_ctime;
+               tbuf.msg_cbytes_old = msq->msg_cbytes;
                tbuf.msg_cbytes = msq->msg_cbytes;
                tbuf.msg_qnum   = msq->msg_qnum;
+               tbuf.msg_qbytes_old = msq->msg_qbytes;
                tbuf.msg_qbytes = msq->msg_qbytes;
                tbuf.msg_lspid  = msq->msg_lspid;
                tbuf.msg_lrpid  = msq->msg_lrpid;
index 0701d7b3a023425ca00da74d04af705c2b9dba56..6f4ad977d846789645eedfed5160da3705085716 100644 (file)
@@ -57,7 +57,7 @@ static void free_module(struct module *, int tag_freed);
  * Called at boot time
  */
 
-__initfunc(void init_modules(void))
+void __init init_modules(void)
 {
        kernel_module.nsyms = __stop___ksymtab - __start___ksymtab;
 
index 26ddca2d9ec2956c20c68d8cb3ace23d80a199d4..431d5c719bb051e37c5899d29ca52e3b14cf8fed 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
-#include <asm/semaphore-helper.h>
 
 #include <linux/timex.h>
 
@@ -811,128 +810,6 @@ out:
        return;
 }
 
-/*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
- *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
- */
-void __up(struct semaphore *sem)
-{
-       wake_one_more(sem);
-       wake_up(&sem->wait);
-}
-
-/*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
- */
-
-#define DOWN_VAR                               \
-       struct task_struct *tsk = current;      \
-       wait_queue_t wait;                      \
-       init_waitqueue_entry(&wait, tsk);
-
-#define DOWN_HEAD(task_state)                                          \
-                                                                       \
-                                                                       \
-       tsk->state = (task_state);                                      \
-       add_wait_queue(&sem->wait, &wait);                              \
-                                                                       \
-       /*                                                              \
-        * Ok, we're set up.  sem->count is known to be less than zero  \
-        * so we must wait.                                             \
-        *                                                              \
-        * We can let go the lock for purposes of waiting.              \
-        * We re-acquire it after awaking so as to protect              \
-        * all semaphore operations.                                    \
-        *                                                              \
-        * If "up()" is called before we call waking_non_zero() then    \
-        * we will catch it right away.  If it is called later then     \
-        * we will have to go through a wakeup cycle to catch it.       \
-        *                                                              \
-        * Multiple waiters contend for the semaphore lock to see       \
-        * who gets to gate through and who has to wait some more.      \
-        */                                                             \
-       for (;;) {
-
-#define DOWN_TAIL(task_state)                  \
-               tsk->state = (task_state);      \
-       }                                       \
-       tsk->state = TASK_RUNNING;              \
-       remove_wait_queue(&sem->wait, &wait);
-
-void __down(struct semaphore * sem)
-{
-       DOWN_VAR
-       DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-       if (waking_non_zero(sem))
-               break;
-       schedule();
-       DOWN_TAIL(TASK_UNINTERRUPTIBLE)
-}
-
-int __down_interruptible(struct semaphore * sem)
-{
-       int ret = 0;
-       DOWN_VAR
-       DOWN_HEAD(TASK_INTERRUPTIBLE)
-
-       ret = waking_non_zero_interruptible(sem, tsk);
-       if (ret)
-       {
-               if (ret == 1)
-                       /* ret != 0 only if we get interrupted -arca */
-                       ret = 0;
-               break;
-       }
-       schedule();
-       DOWN_TAIL(TASK_INTERRUPTIBLE)
-       return ret;
-}
-
-int __down_trylock(struct semaphore * sem)
-{
-       return waking_non_zero_trylock(sem);
-}
-
 #define        SLEEP_ON_VAR                            \
        unsigned long flags;                    \
        wait_queue_t wait;                      \
index 3ec5bf54194b876a6c63ee88c47d17a64a8c6c7c..1cb14631629e17c6dbc2f3779917a3c8d47c17ea 100644 (file)
@@ -998,6 +998,9 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
                        }
                        current->pdeath_signal = sig;
                        break;
+               case PR_GET_PDEATHSIG:
+                       error = put_user(current->pdeath_signal, (int *)arg2);
+                       break;
                default:
                        error = -EINVAL;
                        break;
index c68c40f374284cfa623276902bfdfdcd5ee121b1..e9da61a5ebee805a8d773dc8159a7881ab991f8e 100644 (file)
@@ -821,7 +821,6 @@ static int do_wp_page(struct task_struct * tsk, struct vm_area_struct * vma,
                if (PageReserved(page))
                        ++vma->vm_mm->rss;
                copy_cow_page(old_page,new_page);
-               flush_page_to_ram(old_page);
                flush_page_to_ram(new_page);
                flush_cache_page(vma, address);
                set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
index 60996eb96cd167180edf056608c3a434880345e1..723e7dae59869bf24cb4860b528b212019a69ab5 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -25,7 +24,6 @@
 #include <linux/fcdevice.h>
 #include <linux/skbuff.h>
 #include <linux/errno.h>
-#include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/net.h>
 #include <linux/proc_fs.h>
index e00d565582dfa46fdd3ba22edfaf33a30a3029d6..792bfd5e8128373195db3024beb7550611f625d4 100644 (file)
@@ -204,7 +204,7 @@ EXPORT_SYMBOL(llc_cancel_timers);
 
 #define ALL_TYPES_8022 0
 
-__initfunc(void llc_init(struct net_proto *proto))
+void __init llc_init(struct net_proto *proto)
 {
        printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n");
        return;
index 06d4199c59f7353c358260a8271fc8dde797ed9a..7d03668d225f395ecab68750a4b0178527a6edaa 100644 (file)
@@ -90,7 +90,7 @@ static struct packet_type p8022_packet_type =
 EXPORT_SYMBOL(register_8022_client);
 EXPORT_SYMBOL(unregister_8022_client);
 
-__initfunc(void p8022_proto_init(struct net_proto *pro))
+void __init p8022_proto_init(struct net_proto *pro)
 {
        p8022_packet_type.type=htons(ETH_P_802_2);
        dev_add_pack(&p8022_packet_type);
index 7184b938b108e057e9dddaf285f9d7808f941699..7d8b120479b9e44ed8d8ead9805b95050c78fa61 100644 (file)
@@ -89,7 +89,7 @@ static void snap_datalink_header(struct datalink_proto *dl, struct sk_buff *skb,
 EXPORT_SYMBOL(register_snap_client);
 EXPORT_SYMBOL(unregister_snap_client);
 
-__initfunc(void snap_proto_init(struct net_proto *pro))
+void __init snap_proto_init(struct net_proto *pro)
 {
        snap_dl=register_8022_client(0xAA, snap_rcv);
        if(snap_dl==NULL)
index 28199f8893e784b90804523f761bf165c04dde00..f3fa70ac12488c14b91494abd8c988524948e670 100644 (file)
@@ -538,7 +538,7 @@ static struct proc_dir_entry tr_rif_proc = {
 };
 #endif
 
-__initfunc(void rif_init(struct net_proto *unused))
+void __init rif_init(struct net_proto *unused)
 {
        rif_timer.expires  = RIF_TIMEOUT;
        rif_timer.data     = 0L;
index 5410278f45d828ddb4f2941a0174430082c9ba89..6aba2f14fdc50742b7f3eb48c9f8ee44db02271d 100644 (file)
@@ -1021,7 +1021,7 @@ static struct notifier_block aarp_notifier={
 static char aarp_snap_id[]={0x00,0x00,0x00,0x80,0xF3};
 
 
-__initfunc(void aarp_proto_init(void))
+void __init aarp_proto_init(void)
 {
        if((aarp_dl=register_snap_client(aarp_snap_id, aarp_rcv))==NULL)
                printk(KERN_CRIT "Unable to register AARP with SNAP.\n");
index 7338305001a60ceffb3f06fb47bf459390ef82df..b5aebbb06b6108791357042f57da35a321803f4b 100644 (file)
@@ -2108,7 +2108,7 @@ static struct proc_dir_entry proc_atalk_iface=
 
 /* Called by proto.c on kernel start up */
 
-__initfunc(void atalk_proto_init(struct net_proto *pro))
+void __init atalk_proto_init(struct net_proto *pro)
 {
        (void) sock_register(&atalk_family_ops);
        if((ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv)) == NULL)
index 3f63b5ec991624edfb38d3a3945b268cfc610cf4..353321a93dd4c1b8833e925b5a00ad564518d723 100644 (file)
@@ -3,7 +3,6 @@
 /* Written 1995-1999 by Werner Almesberger, EPFL ICA */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
index 44b6af5a66a6d4650f6fcd948da73017205c9841..4bf7a1918b9a3d12dc83400f996f598c477218cf 100644 (file)
@@ -3,7 +3,6 @@
 /* Written 1996,1997 by Werner Almesberger, EPFL LRC */
 
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
index 3a94f7ec0993aa1366ee1e1fb90f6e057e20ab78..ab640c4e666b558a292041dde9372d7ae8bd2f75 100644 (file)
@@ -4,6 +4,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 
 /* We are ethernet device */
@@ -34,7 +35,6 @@
 #endif
 
 /* Modular too */
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include "lec.h"
index 1a119dcab369b362f8910c15ff5c834d1fb5dc91..0035800659cdb2d3fd8e06df9e6332e0400d1423 100644 (file)
@@ -1787,7 +1787,7 @@ static struct proc_dir_entry proc_ax25_calls = {
 };
 #endif
 
-__initfunc(void ax25_proto_init(struct net_proto *pro))
+void __init ax25_proto_init(struct net_proto *pro)
 {
        sock_register(&ax25_family_ops);
        ax25_packet_type.type = htons(ETH_P_AX25);
index 35e18c6d315b9570efd455cd55e90af79d4814b1..02a9f019bb48a4c510510b3b5903f04bc4e4a791 100644 (file)
@@ -1996,7 +1996,7 @@ static struct proc_dir_entry proc_net_wireless = {
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_NET_RADIO */
 
-__initfunc(int net_dev_init(void))
+int __init net_dev_init(void)
 {
        struct net_device *dev, **dp;
 
index 131b2e2a5c7c8cc3d6d5caeceffc667c01974290..c52df050710972c3c4963c246aaf5adcabd47351 100644 (file)
@@ -255,7 +255,7 @@ done:
 }
 #endif
 
-__initfunc(void dev_mcast_init(void))
+void __init dev_mcast_init(void)
 {
 #ifdef CONFIG_PROC_FS
        struct proc_dir_entry *ent;
index 03f1bfbe5aa85a4272250bcd6d14bc52b42ac319..f84896452d2630c8cbd867ac769730475cb3146a 100644 (file)
@@ -190,7 +190,7 @@ struct notifier_block dst_dev_notifier = {
        0
 };
 
-__initfunc(void dst_init(void))
+void __init dst_init(void)
 {
        register_netdevice_notifier(&dst_dev_notifier);
 }
index 5f5862c24cb581b66964584e08e10a6bf46b734a..9bc77bc2e441f8353015bc8cc0d195af1c00be2d 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Rusty Russell (C)1998 -- This code is GPL.
  */
+#include <linux/config.h>
 #include <linux/netfilter.h>
 #include <net/protocol.h>
 #include <linux/init.h>
@@ -149,7 +150,6 @@ void nf_unregister_sockopt(struct nf_setsockopt_ops *reg)
 
 #ifdef CONFIG_NETFILTER_DEBUG
 #include <net/ip.h>
-#include <net/protocol.h>
 #include <net/route.h>
 #include <net/tcp.h>
 #include <linux/netfilter_ipv4.h>
@@ -554,7 +554,6 @@ void nf_invalidate_cache(int pf)
 }
 
 #ifdef CONFIG_NETFILTER_DEBUG
-#include <linux/netfilter_ipv4.h>
 
 void debug_print_hooks_ip(unsigned int nf_debug)
 {
index 4913988642624851f5c3b77f15a41c543cd46aa1..e43a3d6e12082137d32424b72b3b264c4490ebdf 100644 (file)
@@ -210,7 +210,7 @@ static struct net_device_stats *whitehole_get_stats(struct net_device *dev)
        return stats;
 }
 
-__initfunc(int whitehole_init(struct net_device *dev))
+int __init whitehole_init(struct net_device *dev)
 {
        dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
        if (dev->priv == NULL)
@@ -260,7 +260,7 @@ int net_profile_unregister(struct net_profile_slot *slot)
 }
 
 
-__initfunc(int net_profile_init(void))
+int __init net_profile_init(void)
 {
        int i;
 
index 07600081744c18e5dba73fe5a13e2c61c890591c..b4d8582102e918bb7ceb2dd93243ac2f9e3e5958 100644 (file)
@@ -504,7 +504,7 @@ struct notifier_block rtnetlink_dev_notifier = {
 };
 
 
-__initfunc(void rtnetlink_init(void))
+void __init rtnetlink_init(void)
 {
 #ifdef RTNL_DEBUG
        printk("Initializing RT netlink socket\n");
index 9a116821dd0d735e022c3fd434f1bacb9a4b4f9b..616e5fd0866f859f714d7ff4396e71c02cf28e27 100644 (file)
@@ -1005,7 +1005,7 @@ extern void tcp_v4_init(struct net_proto_family *);
  *     Called by socket.c on kernel startup.  
  */
  
-__initfunc(void inet_proto_init(struct net_proto *pro))
+void __init inet_proto_init(struct net_proto *pro)
 {
        struct sk_buff *dummy_skb;
        struct inet_protocol *p;
index 5b4a59affb3fa6990565515ae856b5fd6b571cb3..5e3421daf3d237863993e2e293a5067b6cc61770 100644 (file)
@@ -1125,7 +1125,7 @@ static struct proc_dir_entry proc_net_arp = {
 };
 #endif
 
-__initfunc(void arp_init (void))
+void __init arp_init (void)
 {
        neigh_table_init(&arp_tbl);
 
index 68f1c9698ef627bdb1c5dec381d009bd86ba32aa..f673a8125d585fea9e6ff36fe52562674649e2fc 100644 (file)
@@ -20,6 +20,7 @@
  *             John McDonald   :       0 length frag bug.
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
index 01801c9b041f9d2b41bdfb680e13e80228aaab8c..5871f0c93898d301fb64de0fbd9559a413f70595 100644 (file)
@@ -2145,7 +2145,7 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
 #endif
 
 
-__initfunc(void ip_rt_init(void))
+void __init ip_rt_init(void)
 {
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_NET_CLS_ROUTE
index da958ae17959ab110899312212d3406876a15cf5..a23242eaa332526d2dfe0e52a209cb10cc7a71f3 100644 (file)
  * (Updated by AK, but not complete yet.)
  **/
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
index 8b292687cbb08327307ada1d330a6d5511197561..533195b3bd2b6ae034a4886bc96fb0b7c2f2a068 100644 (file)
@@ -34,6 +34,7 @@ Return value:
        The number of requests that changed status (ie: made some progress)
 */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 
index 7a57076a5bb90e4ca0d5c933487f3ab1276407e8..b1f67d9ae078792019cfc2ff167644edcc038119 100644 (file)
@@ -50,6 +50,7 @@ Userspace
  *
  ****************************************************************/
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
index ada7b1fa1cad5979ded24d9a382ccc47857249af..244eb76db353651156efac4fd145468064ccdb76 100644 (file)
@@ -24,7 +24,6 @@ Sysctl interface
 
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
 #include <linux/net.h>
index 88521138bb8d3b501dd6f6aaab8a555da8125335..2acb27ff1856c579f993fe41434aae2888700cfd 100644 (file)
@@ -199,6 +199,7 @@ static int AddSocketToAcceptQueue(struct socket *sock,const int Port)
        if (sk->state != TCP_LISTEN || 
            sk->ack_backlog > sk->max_ack_backlog) /* To many pending requests */
        {
+               release_sock(sk);
                sock_put(sk);
                return -1;
        }
@@ -207,6 +208,7 @@ static int AddSocketToAcceptQueue(struct socket *sock,const int Port)
        
        if (req==NULL)
        {       
+               release_sock(sk);
                sock_put(sk);
                return -1;
        }
index d9c701e7b9c4e282124caf9d6e1172c52c2d3c1c..a7d4b82e074596c6362f77ec40ef523b259d287c 100644 (file)
@@ -34,6 +34,7 @@ Return value:
        The number of requests that changed status
 */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/smp_lock.h>
index 83e55951b65657952058692b1dbdc4e454b6c9b3..882a63dff687a61689cd1e0b246d5c5e788187c5 100644 (file)
 #include <net/udp.h>
 #include <net/tcp.h>
 #include <net/icmp.h>
-#include <net/route.h>
 #include <net/inet_common.h>
 #include <linux/inet.h>
 #include <linux/mroute.h>
 #include <linux/igmp.h>
-#include <linux/inetdevice.h>
 
 extern struct net_proto_family inet_family_ops;
 extern __u32 sysctl_wmem_max;
index 8a45e1b32cb4019f14a8fc229adcd6022f420d87..e2d98e21310003b8b3360ceab0ccf2c6fea0f7c3 100644 (file)
@@ -1779,7 +1779,7 @@ extern void unix_sysctl_unregister(void);
 
 int init_module(void)
 #else
-__initfunc(void unix_proto_init(struct net_proto *pro))
+void __init unix_proto_init(struct net_proto *pro)
 #endif
 {
        struct sk_buff *dummy_skb;