Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1815 commits) mac80211: fix reorder buffer release iwmc3200wifi: Enable wimax core through module parameter iwmc3200wifi: Add wifi-wimax coexistence mode as a module parameter iwmc3200wifi: Coex table command does not expect a response iwmc3200wifi: Update wiwi priority table iwlwifi: driver version track kernel version iwlwifi: indicate uCode type when fail dump error/event log iwl3945: remove duplicated event logging code b43: fix two warnings ipw2100: fix rebooting hang with driver loaded cfg80211: indent regulatory messages with spaces iwmc3200wifi: fix NULL pointer dereference in pmkid update mac80211: Fix TX status reporting for injected data frames ath9k: enable 2GHz band only if the device supports it airo: Fix integer overflow warning rt2x00: Fix padding bug on L2PAD devices. WE: Fix set events not propagated b43legacy: avoid PPC fault during resume b43: avoid PPC fault during resume tcp: fix a timewait refcnt race ... Fix up conflicts due to sysctl cleanups (dead sysctl_check code and CTL_UNNUMBERED removed) in kernel/sysctl_check.c net/ipv4/sysctl_net_ipv4.c net/ipv6/addrconf.c net/sctp/sysctl.c
This commit is contained in:
commit
d7fc02c7ba
|
@ -317,18 +317,6 @@ Who: ocfs2-devel@oss.oracle.com
|
|||
|
||||
---------------------------
|
||||
|
||||
What: SCTP_GET_PEER_ADDRS_NUM_OLD, SCTP_GET_PEER_ADDRS_OLD,
|
||||
SCTP_GET_LOCAL_ADDRS_NUM_OLD, SCTP_GET_LOCAL_ADDRS_OLD
|
||||
When: June 2009
|
||||
Why: A newer version of the options have been introduced in 2005 that
|
||||
removes the limitions of the old API. The sctp library has been
|
||||
converted to use these new options at the same time. Any user
|
||||
space app that directly uses the old options should convert to using
|
||||
the new options.
|
||||
Who: Vlad Yasevich <vladislav.yasevich@hp.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Ability for non root users to shm_get hugetlb pages based on mlock
|
||||
resource limits
|
||||
When: 2.6.31
|
||||
|
|
|
@ -5,7 +5,7 @@ GigaSet 307x Device Driver
|
|||
------------
|
||||
1.1. Hardware
|
||||
--------
|
||||
This release supports the connection of the Gigaset 307x/417x family of
|
||||
This driver supports the connection of the Gigaset 307x/417x family of
|
||||
ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
|
||||
connection. The following devices are reported to be compatible:
|
||||
|
||||
|
@ -33,7 +33,7 @@ GigaSet 307x Device Driver
|
|||
http://gigaset307x.sourceforge.net/
|
||||
|
||||
We had also reports from users of Gigaset M105 who could use the drivers
|
||||
with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.4.)
|
||||
with SX 100 and CX 100 ISDN bases (only in unimodem mode, see section 2.5.)
|
||||
If you have another device that works with our driver, please let us know.
|
||||
|
||||
Chances of getting an USB device to work are good if the output of
|
||||
|
@ -49,7 +49,7 @@ GigaSet 307x Device Driver
|
|||
--------
|
||||
The driver works with ISDN4linux and so can be used with any software
|
||||
which is able to use ISDN4linux for ISDN connections (voice or data).
|
||||
CAPI4Linux support is planned but not yet available.
|
||||
Experimental Kernel CAPI support is available as a compilation option.
|
||||
|
||||
There are some user space tools available at
|
||||
http://sourceforge.net/projects/gigaset307x/
|
||||
|
@ -102,20 +102,28 @@ GigaSet 307x Device Driver
|
|||
2.3. ISDN4linux
|
||||
----------
|
||||
This is the "normal" mode of operation. After loading the module you can
|
||||
set up the ISDN system just as you'd do with any ISDN card.
|
||||
Your distribution should provide some configuration utility.
|
||||
If not, you can use some HOWTOs like
|
||||
set up the ISDN system just as you'd do with any ISDN card supported by
|
||||
the ISDN4Linux subsystem. Most distributions provide some configuration
|
||||
utility. If not, you can use some HOWTOs like
|
||||
http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
|
||||
If this doesn't work, because you have some recent device like SX100 where
|
||||
If this doesn't work, because you have some device like SX100 where
|
||||
debug output (see section 3.2.) shows something like this when dialing
|
||||
CMD Received: ERROR
|
||||
Available Params: 0
|
||||
Connection State: 0, Response: -1
|
||||
gigaset_process_response: resp_code -1 in ConState 0 !
|
||||
Timeout occurred
|
||||
you might need to use unimodem mode:
|
||||
you might need to use unimodem mode. (see section 2.5.)
|
||||
|
||||
2.4. Unimodem mode
|
||||
2.4. CAPI
|
||||
----
|
||||
If the driver is compiled with CAPI support (kernel configuration option
|
||||
GIGASET_CAPI, experimental) it can also be used with CAPI 2.0 kernel and
|
||||
user space applications. ISDN4Linux is supported in this configuration
|
||||
via the capidrv compatibility driver. The kernel module capidrv.ko must
|
||||
be loaded explicitly ("modprobe capidrv") if needed.
|
||||
|
||||
2.5. Unimodem mode
|
||||
-------------
|
||||
This is needed for some devices [e.g. SX100] as they have problems with
|
||||
the "normal" commands.
|
||||
|
@ -160,7 +168,7 @@ GigaSet 307x Device Driver
|
|||
configuration file like /etc/modprobe.conf.local,
|
||||
using that should be preferred.
|
||||
|
||||
2.5. Call-ID (CID) mode
|
||||
2.6. Call-ID (CID) mode
|
||||
------------------
|
||||
Call-IDs are numbers used to tag commands to, and responses from, the
|
||||
Gigaset base in order to support the simultaneous handling of multiple
|
||||
|
@ -188,7 +196,7 @@ GigaSet 307x Device Driver
|
|||
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
||||
setting (ttyGxy is ttyGU0 or ttyGB0).
|
||||
|
||||
2.6. Unregistered Wireless Devices (M101/M105)
|
||||
2.7. Unregistered Wireless Devices (M101/M105)
|
||||
-----------------------------------------
|
||||
The main purpose of the ser_gigaset and usb_gigaset drivers is to allow
|
||||
the M101 and M105 wireless devices to be used as ISDN devices for ISDN
|
||||
|
@ -228,7 +236,7 @@ GigaSet 307x Device Driver
|
|||
You have two or more DECT data adapters (M101/M105) and only the
|
||||
first one you turn on works.
|
||||
Solution:
|
||||
Select Unimodem mode for all DECT data adapters. (see section 2.4.)
|
||||
Select Unimodem mode for all DECT data adapters. (see section 2.5.)
|
||||
|
||||
Problem:
|
||||
Messages like this:
|
||||
|
@ -236,7 +244,7 @@ GigaSet 307x Device Driver
|
|||
appear in your syslog.
|
||||
Solution:
|
||||
Check whether your M10x wireless device is correctly registered to the
|
||||
Gigaset base. (see section 2.6.)
|
||||
Gigaset base. (see section 2.7.)
|
||||
|
||||
3.2. Telling the driver to provide more information
|
||||
----------------------------------------------
|
||||
|
|
|
@ -2605,6 +2605,9 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
uart6850= [HW,OSS]
|
||||
Format: <io>,<irq>
|
||||
|
||||
uhash_entries= [KNL,NET]
|
||||
Set number of hash buckets for UDP/UDP-Lite connections
|
||||
|
||||
uhci-hcd.ignore_oc=
|
||||
[USB] Ignore overcurrent events (default N).
|
||||
Some badly-designed motherboards generate lots of
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
Linux Ethernet Bonding Driver HOWTO
|
||||
|
||||
Latest update: 12 November 2007
|
||||
Latest update: 23 September 2009
|
||||
|
||||
Initial release : Thomas Davis <tadavis at lbl.gov>
|
||||
Corrections, HA extensions : 2000/10/03-15 :
|
||||
|
@ -614,6 +614,46 @@ primary
|
|||
|
||||
The primary option is only valid for active-backup mode.
|
||||
|
||||
primary_reselect
|
||||
|
||||
Specifies the reselection policy for the primary slave. This
|
||||
affects how the primary slave is chosen to become the active slave
|
||||
when failure of the active slave or recovery of the primary slave
|
||||
occurs. This option is designed to prevent flip-flopping between
|
||||
the primary slave and other slaves. Possible values are:
|
||||
|
||||
always or 0 (default)
|
||||
|
||||
The primary slave becomes the active slave whenever it
|
||||
comes back up.
|
||||
|
||||
better or 1
|
||||
|
||||
The primary slave becomes the active slave when it comes
|
||||
back up, if the speed and duplex of the primary slave is
|
||||
better than the speed and duplex of the current active
|
||||
slave.
|
||||
|
||||
failure or 2
|
||||
|
||||
The primary slave becomes the active slave only if the
|
||||
current active slave fails and the primary slave is up.
|
||||
|
||||
The primary_reselect setting is ignored in two cases:
|
||||
|
||||
If no slaves are active, the first slave to recover is
|
||||
made the active slave.
|
||||
|
||||
When initially enslaved, the primary slave is always made
|
||||
the active slave.
|
||||
|
||||
Changing the primary_reselect policy via sysfs will cause an
|
||||
immediate selection of the best active slave according to the new
|
||||
policy. This may or may not result in a change of the active
|
||||
slave, depending upon the circumstances.
|
||||
|
||||
This option was added for bonding version 3.6.0.
|
||||
|
||||
updelay
|
||||
|
||||
Specifies the time, in milliseconds, to wait before enabling a
|
||||
|
|
|
@ -164,6 +164,14 @@ tcp_congestion_control - STRING
|
|||
additional choices may be available based on kernel configuration.
|
||||
Default is set as part of kernel configuration.
|
||||
|
||||
tcp_cookie_size - INTEGER
|
||||
Default size of TCP Cookie Transactions (TCPCT) option, that may be
|
||||
overridden on a per socket basis by the TCPCT socket option.
|
||||
Values greater than the maximum (16) are interpreted as the maximum.
|
||||
Values greater than zero and less than the minimum (8) are interpreted
|
||||
as the minimum. Odd values are interpreted as the next even value.
|
||||
Default: 0 (off).
|
||||
|
||||
tcp_dsack - BOOLEAN
|
||||
Allows TCP to send "duplicate" SACKs.
|
||||
|
||||
|
@ -723,6 +731,12 @@ accept_source_route - BOOLEAN
|
|||
default TRUE (router)
|
||||
FALSE (host)
|
||||
|
||||
accept_local - BOOLEAN
|
||||
Accept packets with local source addresses. In combination with
|
||||
suitable routing, this can be used to direct packets between two
|
||||
local interfaces over the wire and have them accepted properly.
|
||||
default FALSE
|
||||
|
||||
rp_filter - INTEGER
|
||||
0 - No source validation.
|
||||
1 - Strict mode as defined in RFC3704 Strict Reverse Path
|
||||
|
@ -738,8 +752,8 @@ rp_filter - INTEGER
|
|||
to prevent IP spoofing from DDos attacks. If using asymmetric routing
|
||||
or other complicated routing, then loose mode is recommended.
|
||||
|
||||
conf/all/rp_filter must also be set to non-zero to do source validation
|
||||
on the interface
|
||||
The max value from conf/{all,interface}/rp_filter is used
|
||||
when doing source validation on the {interface}.
|
||||
|
||||
Default value is 0. Note that some distributions enable it
|
||||
in startup scripts.
|
||||
|
@ -1086,6 +1100,24 @@ accept_dad - INTEGER
|
|||
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
|
||||
link-local address has been found.
|
||||
|
||||
force_tllao - BOOLEAN
|
||||
Enable sending the target link-layer address option even when
|
||||
responding to a unicast neighbor solicitation.
|
||||
Default: FALSE
|
||||
|
||||
Quoting from RFC 2461, section 4.4, Target link-layer address:
|
||||
|
||||
"The option MUST be included for multicast solicitations in order to
|
||||
avoid infinite Neighbor Solicitation "recursion" when the peer node
|
||||
does not have a cache entry to return a Neighbor Advertisements
|
||||
message. When responding to unicast solicitations, the option can be
|
||||
omitted since the sender of the solicitation has the correct link-
|
||||
layer address; otherwise it would not have be able to send the unicast
|
||||
solicitation in the first place. However, including the link-layer
|
||||
address in this case adds little overhead and eliminates a potential
|
||||
race condition where the sender deletes the cached link-layer address
|
||||
prior to receiving a response to a previous solicitation."
|
||||
|
||||
icmp/*:
|
||||
ratelimit - INTEGER
|
||||
Limit the maximal rates for sending ICMPv6 packets.
|
||||
|
|
|
@ -178,3 +178,13 @@ External interrupts:
|
|||
external irq3: interrupts = <1 3 n>;
|
||||
'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
|
||||
|
||||
fsl,mpc5200-mscan nodes
|
||||
-----------------------
|
||||
In addition to the required compatible-, reg- and interrupt-properites, you can
|
||||
also specify which clock source shall be used for the controller:
|
||||
|
||||
- fsl,mscan-clock-source- a string describing the clock source. Valid values
|
||||
are: "ip" for ip bus clock
|
||||
"ref" for reference clock (XTAL)
|
||||
"ref" is default in case this property is not
|
||||
present.
|
||||
|
|
14
MAINTAINERS
14
MAINTAINERS
|
@ -1120,7 +1120,6 @@ F: include/net/ax25.h
|
|||
F: net/ax25/
|
||||
|
||||
B43 WIRELESS DRIVER
|
||||
M: Michael Buesch <mb@bu3sch.de>
|
||||
M: Stefano Brivio <stefano.brivio@polimi.it>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://linuxwireless.org/en/users/Drivers/b43
|
||||
|
@ -2817,6 +2816,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
|
|||
S: Supported
|
||||
F: drivers/net/wireless/iwlwifi/
|
||||
|
||||
INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
|
||||
M: Samuel Ortiz <samuel.ortiz@intel.com>
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
|
||||
F: drivers/net/wireless/iwmc3200wifi/
|
||||
|
||||
IOC3 ETHERNET DRIVER
|
||||
M: Ralf Baechle <ralf@linux-mips.org>
|
||||
L: linux-mips@linux-mips.org
|
||||
|
@ -3741,9 +3749,9 @@ F: include/linux/if_*
|
|||
F: include/linux/*device.h
|
||||
|
||||
NETXEN (1/10) GbE SUPPORT
|
||||
M: Dhananjay Phadke <dhananjay@netxen.com>
|
||||
M: Amit Kumar Salecha <amit.salecha@qlogic.com>
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://www.netxen.com
|
||||
W: http://www.qlogic.com
|
||||
S: Supported
|
||||
F: drivers/net/netxen/
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@
|
|||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||
* have to define SOCK_NONBLOCK to a different value here.
|
||||
*/
|
||||
|
|
|
@ -433,10 +433,11 @@
|
|||
#define __NR_signalfd 476
|
||||
#define __NR_timerfd 477
|
||||
#define __NR_eventfd 478
|
||||
#define __NR_recvmmsg 479
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define NR_SYSCALLS 479
|
||||
#define NR_SYSCALLS 480
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -497,6 +497,7 @@ sys_call_table:
|
|||
.quad sys_signalfd
|
||||
.quad sys_ni_syscall
|
||||
.quad sys_eventfd
|
||||
.quad sys_recvmmsg
|
||||
|
||||
.size sys_call_table, . - sys_call_table
|
||||
.type sys_call_table, @object
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
CALL(sys_pwritev)
|
||||
CALL(sys_rt_tgsigqueueinfo)
|
||||
CALL(sys_perf_event_open)
|
||||
/* 365 */ CALL(sys_recvmmsg)
|
||||
#ifndef syscalls_counted
|
||||
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
|
||||
#define syscalls_counted
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* __ASM_AVR32_SOCKET_H */
|
||||
|
|
|
@ -295,4 +295,5 @@ sys_call_table:
|
|||
.long sys_signalfd
|
||||
.long sys_ni_syscall /* 280, was sys_timerfd */
|
||||
.long sys_eventfd
|
||||
.long sys_recvmmsg
|
||||
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
|
||||
|
|
|
@ -1600,6 +1600,7 @@ ENTRY(_sys_call_table)
|
|||
.long _sys_pwritev
|
||||
.long _sys_rt_tgsigqueueinfo
|
||||
.long _sys_perf_event_open
|
||||
.long _sys_recvmmsg /* 370 */
|
||||
|
||||
.rept NR_syscalls-(.-_sys_call_table)/4
|
||||
.long _sys_ni_syscall
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
||||
|
|
|
@ -60,5 +60,7 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -69,4 +69,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_IA64_SOCKET_H */
|
||||
|
|
|
@ -311,11 +311,12 @@
|
|||
#define __NR_preadv 1319
|
||||
#define __NR_pwritev 1320
|
||||
#define __NR_rt_tgsigqueueinfo 1321
|
||||
#define __NR_rt_recvmmsg 1322
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
||||
#define NR_syscalls 298 /* length of syscall table */
|
||||
#define NR_syscalls 299 /* length of syscall table */
|
||||
|
||||
/*
|
||||
* The following defines stop scripts/checksyscalls.sh from complaining about
|
||||
|
|
|
@ -1806,6 +1806,7 @@ sys_call_table:
|
|||
data8 sys_preadv
|
||||
data8 sys_pwritev // 1320
|
||||
data8 sys_rt_tgsigqueueinfo
|
||||
data8 sys_recvmmsg
|
||||
|
||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_M32R_SOCKET_H */
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -371,3 +371,4 @@ ENTRY(sys_call_table)
|
|||
.long sys_ni_syscall
|
||||
.long sys_rt_tgsigqueueinfo /* 365 */
|
||||
.long sys_perf_event_open
|
||||
.long sys_recvmmsg
|
||||
|
|
|
@ -80,6 +80,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
|||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/** sock_type - Socket types
|
||||
|
|
|
@ -355,16 +355,17 @@
|
|||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
|
||||
#define __NR_perf_event_open (__NR_Linux + 333)
|
||||
#define __NR_accept4 (__NR_Linux + 334)
|
||||
#define __NR_recvmmsg (__NR_Linux + 335)
|
||||
|
||||
/*
|
||||
* Offset of the last Linux o32 flavoured syscall
|
||||
*/
|
||||
#define __NR_Linux_syscalls 334
|
||||
#define __NR_Linux_syscalls 335
|
||||
|
||||
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
||||
|
||||
#define __NR_O32_Linux 4000
|
||||
#define __NR_O32_Linux_syscalls 334
|
||||
#define __NR_O32_Linux_syscalls 335
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
||||
|
||||
|
@ -666,16 +667,17 @@
|
|||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
|
||||
#define __NR_perf_event_open (__NR_Linux + 292)
|
||||
#define __NR_accept4 (__NR_Linux + 293)
|
||||
#define __NR_recvmmsg (__NR_Linux + 294)
|
||||
|
||||
/*
|
||||
* Offset of the last Linux 64-bit flavoured syscall
|
||||
*/
|
||||
#define __NR_Linux_syscalls 293
|
||||
#define __NR_Linux_syscalls 294
|
||||
|
||||
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
|
||||
|
||||
#define __NR_64_Linux 5000
|
||||
#define __NR_64_Linux_syscalls 293
|
||||
#define __NR_64_Linux_syscalls 294
|
||||
|
||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||
|
||||
|
@ -981,16 +983,17 @@
|
|||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
|
||||
#define __NR_perf_event_open (__NR_Linux + 296)
|
||||
#define __NR_accept4 (__NR_Linux + 297)
|
||||
#define __NR_recvmmsg (__NR_Linux + 298)
|
||||
|
||||
/*
|
||||
* Offset of the last N32 flavoured syscall
|
||||
*/
|
||||
#define __NR_Linux_syscalls 297
|
||||
#define __NR_Linux_syscalls 298
|
||||
|
||||
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
|
||||
|
||||
#define __NR_N32_Linux 6000
|
||||
#define __NR_N32_Linux_syscalls 297
|
||||
#define __NR_N32_Linux_syscalls 298
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
|
|
|
@ -583,6 +583,7 @@ einval: li v0, -ENOSYS
|
|||
sys sys_rt_tgsigqueueinfo 4
|
||||
sys sys_perf_event_open 5
|
||||
sys sys_accept4 4
|
||||
sys sys_recvmmsg 5
|
||||
.endm
|
||||
|
||||
/* We pre-compute the number of _instruction_ bytes needed to
|
||||
|
|
|
@ -420,4 +420,5 @@ sys_call_table:
|
|||
PTR sys_rt_tgsigqueueinfo
|
||||
PTR sys_perf_event_open
|
||||
PTR sys_accept4
|
||||
PTR sys_recvmmsg
|
||||
.size sys_call_table,.-sys_call_table
|
||||
|
|
|
@ -418,4 +418,5 @@ EXPORT(sysn32_call_table)
|
|||
PTR compat_sys_rt_tgsigqueueinfo /* 5295 */
|
||||
PTR sys_perf_event_open
|
||||
PTR sys_accept4
|
||||
PTR compat_sys_recvmmsg
|
||||
.size sysn32_call_table,.-sysn32_call_table
|
||||
|
|
|
@ -538,4 +538,5 @@ sys_call_table:
|
|||
PTR compat_sys_rt_tgsigqueueinfo
|
||||
PTR sys_perf_event_open
|
||||
PTR sys_accept4
|
||||
PTR compat_sys_recvmmsg
|
||||
.size sys_call_table,.-sys_call_table
|
||||
|
|
|
@ -60,4 +60,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -59,6 +59,8 @@
|
|||
#define SO_TIMESTAMPING 0x4020
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_RXQ_OVFL 0x4021
|
||||
|
||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||
* have to define SOCK_NONBLOCK to a different value here.
|
||||
*/
|
||||
|
|
|
@ -67,4 +67,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||
|
|
|
@ -83,8 +83,9 @@ static void appldata_get_net_sum_data(void *data)
|
|||
rx_dropped = 0;
|
||||
tx_dropped = 0;
|
||||
collisions = 0;
|
||||
read_lock(&dev_base_lock);
|
||||
for_each_netdev(&init_net, dev) {
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(&init_net, dev) {
|
||||
const struct net_device_stats *stats = dev_get_stats(dev);
|
||||
|
||||
rx_packets += stats->rx_packets;
|
||||
|
@ -98,7 +99,8 @@ static void appldata_get_net_sum_data(void *data)
|
|||
collisions += stats->collisions;
|
||||
i++;
|
||||
}
|
||||
read_unlock(&dev_base_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
net_data->nr_interfaces = i;
|
||||
net_data->rx_packets = rx_packets;
|
||||
net_data->tx_packets = tx_packets;
|
||||
|
|
|
@ -68,4 +68,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
|
|
@ -7,6 +7,7 @@ struct sh_eth_plat_data {
|
|||
int phy;
|
||||
int edmac_endian;
|
||||
|
||||
unsigned char mac_addr[6];
|
||||
unsigned no_ether_link:1;
|
||||
unsigned ether_link_active_low:1;
|
||||
};
|
||||
|
|
|
@ -391,3 +391,4 @@ sys_call_table:
|
|||
.long sys_pwritev
|
||||
.long sys_rt_tgsigqueueinfo
|
||||
.long sys_perf_event_open
|
||||
.long sys_recvmmsg /* 365 */
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#define SO_TIMESTAMPING 0x0023
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_RXQ_OVFL 0x0024
|
||||
|
||||
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
||||
|
|
|
@ -396,8 +396,9 @@
|
|||
#define __NR_pwritev 325
|
||||
#define __NR_rt_tgsigqueueinfo 326
|
||||
#define __NR_perf_event_open 327
|
||||
#define __NR_recvmmsg 328
|
||||
|
||||
#define NR_SYSCALLS 328
|
||||
#define NR_SYSCALLS 329
|
||||
|
||||
#ifdef __32bit_syscall_numbers__
|
||||
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
|
||||
|
|
|
@ -82,5 +82,5 @@ sys_call_table:
|
|||
/*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
|
||||
/*315*/ .long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
|
||||
/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open
|
||||
/*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ sys_call_table32:
|
|||
/*310*/ .word compat_sys_utimensat, compat_sys_signalfd, sys_timerfd_create, sys_eventfd, compat_sys_fallocate
|
||||
.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
|
||||
.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open
|
||||
.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
|
@ -158,4 +158,4 @@ sys_call_table:
|
|||
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
|
||||
.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
|
||||
/*320*/ .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
|
||||
.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open
|
||||
.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg
|
||||
|
|
|
@ -841,4 +841,5 @@ ia32_sys_call_table:
|
|||
.quad compat_sys_pwritev
|
||||
.quad compat_sys_rt_tgsigqueueinfo /* 335 */
|
||||
.quad sys_perf_event_open
|
||||
.quad compat_sys_recvmmsg
|
||||
ia32_syscall_end:
|
||||
|
|
|
@ -342,10 +342,11 @@
|
|||
#define __NR_pwritev 334
|
||||
#define __NR_rt_tgsigqueueinfo 335
|
||||
#define __NR_perf_event_open 336
|
||||
#define __NR_recvmmsg 337
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define NR_syscalls 337
|
||||
#define NR_syscalls 338
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -661,6 +661,8 @@ __SYSCALL(__NR_pwritev, sys_pwritev)
|
|||
__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
|
||||
#define __NR_perf_event_open 298
|
||||
__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
|
||||
#define __NR_recvmmsg 299
|
||||
__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
|
||||
|
||||
#ifndef __NO_STUBS
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -336,3 +336,4 @@ ENTRY(sys_call_table)
|
|||
.long sys_pwritev
|
||||
.long sys_rt_tgsigqueueinfo /* 335 */
|
||||
.long sys_perf_event_open
|
||||
.long sys_recvmmsg
|
||||
|
|
|
@ -71,4 +71,6 @@
|
|||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#define SO_RXQ_OVFL 40
|
||||
|
||||
#endif /* _XTENSA_SOCKET_H */
|
||||
|
|
|
@ -681,8 +681,10 @@ __SYSCALL(304, sys_signalfd, 3)
|
|||
__SYSCALL(305, sys_ni_syscall, 0)
|
||||
#define __NR_eventfd 306
|
||||
__SYSCALL(306, sys_eventfd, 1)
|
||||
#define __NR_recvmmsg 307
|
||||
__SYSCALL(307, sys_recvmmsg, 5)
|
||||
|
||||
#define __NR_syscall_count 307
|
||||
#define __NR_syscall_count 308
|
||||
|
||||
/*
|
||||
* sysxtensa syscall handler
|
||||
|
|
|
@ -2351,6 +2351,7 @@ static void __init amb_check_args (void) {
|
|||
MODULE_AUTHOR(maintainer_string);
|
||||
MODULE_DESCRIPTION(description_string);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("atmsar11.fw");
|
||||
module_param(debug, ushort, 0644);
|
||||
module_param(cmds, uint, 0);
|
||||
module_param(txs, uint, 0);
|
||||
|
|
|
@ -2906,8 +2906,8 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
|
|||
u32 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
|
||||
u32 oc3_index;
|
||||
|
||||
if ((media_index < 0) || (media_index > 4))
|
||||
media_index = 5;
|
||||
if (media_index > 4)
|
||||
media_index = 5;
|
||||
|
||||
switch (fore200e->loop_mode) {
|
||||
case ATM_LM_NONE: oc3_index = 0;
|
||||
|
|
|
@ -2739,7 +2739,7 @@ he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __user *arg)
|
|||
spin_lock_irqsave(&he_dev->global_lock, flags);
|
||||
switch (reg.type) {
|
||||
case HE_REGTYPE_PCI:
|
||||
if (reg.addr < 0 || reg.addr >= HE_REGMAP_SIZE) {
|
||||
if (reg.addr >= HE_REGMAP_SIZE) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,9 @@ MODULE_AUTHOR("Traverse Technologies <support@traverse.com.au>");
|
|||
MODULE_DESCRIPTION("Solos PCI driver");
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_FIRMWARE("solos-FPGA.bin");
|
||||
MODULE_FIRMWARE("solos-Firmware.bin");
|
||||
MODULE_FIRMWARE("solos-db-FPGA.bin");
|
||||
MODULE_PARM_DESC(reset, "Reset Solos chips on startup");
|
||||
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
||||
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
||||
|
@ -528,34 +531,37 @@ static int flash_upgrade(struct solos_card *card, int chip)
|
|||
int numblocks = 0;
|
||||
int offset;
|
||||
|
||||
if (chip == 0) {
|
||||
switch (chip) {
|
||||
case 0:
|
||||
fw_name = "solos-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
}
|
||||
|
||||
if (chip == 1) {
|
||||
break;
|
||||
case 1:
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
}
|
||||
|
||||
if (chip == 2){
|
||||
break;
|
||||
case 2:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-db-FPGA.bin";
|
||||
blocksize = FPGA_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
if (chip == 3){
|
||||
break;
|
||||
case 3:
|
||||
if (card->fpga_version > LEGACY_BUFFERS){
|
||||
fw_name = "solos-Firmware.bin";
|
||||
blocksize = SOLOS_BLOCK;
|
||||
} else {
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
dev_info(&card->dev->dev, "FPGA version doesn't support"
|
||||
" daughter board upgrades\n");
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (request_firmware(&fw, fw_name, &card->dev->dev))
|
||||
|
|
|
@ -29,7 +29,6 @@ struct btmrvl_debugfs_data {
|
|||
struct dentry *root_dir, *config_dir, *status_dir;
|
||||
|
||||
/* config */
|
||||
struct dentry *drvdbg;
|
||||
struct dentry *psmode;
|
||||
struct dentry *pscmd;
|
||||
struct dentry *hsmode;
|
||||
|
|
|
@ -131,6 +131,7 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
|
|||
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
|
||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv);
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
|
|
@ -189,6 +189,38 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
|
||||
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF,
|
||||
BT_CMD_AUTO_SLEEP_MODE));
|
||||
cmd->length = 1;
|
||||
|
||||
if (priv->btmrvl_dev.psmode)
|
||||
cmd->data[0] = BT_PS_ENABLE;
|
||||
else
|
||||
cmd->data[0] = BT_PS_DISABLE;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
|
||||
|
||||
static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
@ -258,28 +290,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
|
|||
|
||||
if (priv->btmrvl_dev.pscmd) {
|
||||
priv->btmrvl_dev.pscmd = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE));
|
||||
cmd->length = 1;
|
||||
|
||||
if (priv->btmrvl_dev.psmode)
|
||||
cmd->data[0] = BT_PS_ENABLE;
|
||||
else
|
||||
cmd->data[0] = BT_PS_DISABLE;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
|
||||
btmrvl_enable_ps(priv);
|
||||
}
|
||||
|
||||
if (priv->btmrvl_dev.hscmd) {
|
||||
|
|
|
@ -930,6 +930,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
|||
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
|
||||
|
||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
priv->btmrvl_dev.psmode = 1;
|
||||
btmrvl_enable_ps(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1001,3 +1003,5 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
|||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||
MODULE_FIRMWARE("sd8688.bin");
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
|
||||
#define VERSION "1.3"
|
||||
|
||||
static int minor = MISC_DYNAMIC_MINOR;
|
||||
|
||||
struct vhci_data {
|
||||
struct hci_dev *hdev;
|
||||
|
||||
|
@ -218,12 +216,6 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
|||
return POLLOUT | POLLWRNORM;
|
||||
}
|
||||
|
||||
static int vhci_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int vhci_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct vhci_data *data;
|
||||
|
@ -284,10 +276,10 @@ static int vhci_release(struct inode *inode, struct file *file)
|
|||
}
|
||||
|
||||
static const struct file_operations vhci_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = vhci_read,
|
||||
.write = vhci_write,
|
||||
.poll = vhci_poll,
|
||||
.ioctl = vhci_ioctl,
|
||||
.open = vhci_open,
|
||||
.release = vhci_release,
|
||||
};
|
||||
|
@ -302,18 +294,12 @@ static int __init vhci_init(void)
|
|||
{
|
||||
BT_INFO("Virtual HCI driver ver %s", VERSION);
|
||||
|
||||
if (misc_register(&vhci_miscdev) < 0) {
|
||||
BT_ERR("Can't register misc device with minor %d", minor);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return misc_register(&vhci_miscdev);
|
||||
}
|
||||
|
||||
static void __exit vhci_exit(void)
|
||||
{
|
||||
if (misc_deregister(&vhci_miscdev) < 0)
|
||||
BT_ERR("Can't unregister misc device with minor %d", minor);
|
||||
misc_deregister(&vhci_miscdev);
|
||||
}
|
||||
|
||||
module_init(vhci_init);
|
||||
|
|
|
@ -32,9 +32,29 @@
|
|||
#include <net/nl802154.h>
|
||||
#include <net/wpan-phy.h>
|
||||
|
||||
struct wpan_phy *net_to_phy(struct net_device *dev)
|
||||
struct fakehard_priv {
|
||||
struct wpan_phy *phy;
|
||||
};
|
||||
|
||||
static struct wpan_phy *fake_to_phy(const struct net_device *dev)
|
||||
{
|
||||
return container_of(dev->dev.parent, struct wpan_phy, dev);
|
||||
struct fakehard_priv *priv = netdev_priv(dev);
|
||||
return priv->phy;
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_get_phy - Return a phy corresponding to this device.
|
||||
* @dev: The network device for which to return the wan-phy object
|
||||
*
|
||||
* This function returns a wpan-phy object corresponding to the passed
|
||||
* network device. Reference counter for wpan-phy object is incremented,
|
||||
* so when the wpan-phy isn't necessary, you should drop the reference
|
||||
* via @wpan_phy_put() call.
|
||||
*/
|
||||
static struct wpan_phy *fake_get_phy(const struct net_device *dev)
|
||||
{
|
||||
struct wpan_phy *phy = fake_to_phy(dev);
|
||||
return to_phy(get_device(&phy->dev));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,7 +63,7 @@ struct wpan_phy *net_to_phy(struct net_device *dev)
|
|||
*
|
||||
* Return the ID of the PAN from the PIB.
|
||||
*/
|
||||
static u16 fake_get_pan_id(struct net_device *dev)
|
||||
static u16 fake_get_pan_id(const struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
|
||||
|
@ -58,7 +78,7 @@ static u16 fake_get_pan_id(struct net_device *dev)
|
|||
* device. If the device has not yet had a short address assigned
|
||||
* then this should return 0xFFFF to indicate a lack of association.
|
||||
*/
|
||||
static u16 fake_get_short_addr(struct net_device *dev)
|
||||
static u16 fake_get_short_addr(const struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
|
||||
|
@ -78,7 +98,7 @@ static u16 fake_get_short_addr(struct net_device *dev)
|
|||
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||
* document.
|
||||
*/
|
||||
static u8 fake_get_dsn(struct net_device *dev)
|
||||
static u8 fake_get_dsn(const struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
|
||||
|
@ -98,7 +118,7 @@ static u8 fake_get_dsn(struct net_device *dev)
|
|||
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||
* document.
|
||||
*/
|
||||
static u8 fake_get_bsn(struct net_device *dev)
|
||||
static u8 fake_get_bsn(const struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
|
||||
|
@ -121,7 +141,7 @@ static u8 fake_get_bsn(struct net_device *dev)
|
|||
static int fake_assoc_req(struct net_device *dev,
|
||||
struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
struct wpan_phy *phy = fake_to_phy(dev);
|
||||
|
||||
mutex_lock(&phy->pib_lock);
|
||||
phy->current_channel = channel;
|
||||
|
@ -196,7 +216,7 @@ static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
|
|||
u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
|
||||
u8 coord_realign)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
struct wpan_phy *phy = fake_to_phy(dev);
|
||||
|
||||
mutex_lock(&phy->pib_lock);
|
||||
phy->current_channel = channel;
|
||||
|
@ -239,6 +259,8 @@ static struct ieee802154_mlme_ops fake_mlme = {
|
|||
.start_req = fake_start_req,
|
||||
.scan_req = fake_scan_req,
|
||||
|
||||
.get_phy = fake_get_phy,
|
||||
|
||||
.get_pan_id = fake_get_pan_id,
|
||||
.get_short_addr = fake_get_short_addr,
|
||||
.get_dsn = fake_get_dsn,
|
||||
|
@ -310,7 +332,7 @@ static const struct net_device_ops fake_ops = {
|
|||
|
||||
static void ieee802154_fake_destruct(struct net_device *dev)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
struct wpan_phy *phy = fake_to_phy(dev);
|
||||
|
||||
wpan_phy_unregister(phy);
|
||||
free_netdev(dev);
|
||||
|
@ -335,13 +357,14 @@ static void ieee802154_fake_setup(struct net_device *dev)
|
|||
static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct fakehard_priv *priv;
|
||||
struct wpan_phy *phy = wpan_phy_alloc(0);
|
||||
int err;
|
||||
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup);
|
||||
dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d", ieee802154_fake_setup);
|
||||
if (!dev) {
|
||||
wpan_phy_free(phy);
|
||||
return -ENOMEM;
|
||||
|
@ -353,12 +376,23 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
|||
dev->addr_len);
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
phy->channels_supported = (1 << 27) - 1;
|
||||
/*
|
||||
* For now we'd like to emulate 2.4 GHz-only device,
|
||||
* both O-QPSK and CSS
|
||||
*/
|
||||
/* 2.4 GHz O-QPSK 802.15.4-2003 */
|
||||
phy->channels_supported[0] |= 0x7FFF800;
|
||||
/* 2.4 GHz CSS 802.15.4a-2007 */
|
||||
phy->channels_supported[3] |= 0x3fff;
|
||||
|
||||
phy->transmit_power = 0xbf;
|
||||
|
||||
dev->netdev_ops = &fake_ops;
|
||||
dev->ml_priv = &fake_mlme;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
priv->phy = phy;
|
||||
|
||||
/*
|
||||
* If the name is a format string the caller wants us to do a
|
||||
* name allocation.
|
||||
|
@ -369,11 +403,12 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
wpan_phy_set_dev(phy, &pdev->dev);
|
||||
SET_NETDEV_DEV(dev, &phy->dev);
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
err = wpan_phy_register(&pdev->dev, phy);
|
||||
err = wpan_phy_register(phy);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -1080,11 +1080,14 @@ static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable)
|
|||
|
||||
|
||||
/**
|
||||
* nes_netdev_get_stats_count
|
||||
* nes_netdev_get_sset_count
|
||||
*/
|
||||
static int nes_netdev_get_stats_count(struct net_device *netdev)
|
||||
static int nes_netdev_get_sset_count(struct net_device *netdev, int stringset)
|
||||
{
|
||||
return NES_ETHTOOL_STAT_COUNT;
|
||||
if (stringset == ETH_SS_STATS)
|
||||
return NES_ETHTOOL_STAT_COUNT;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1264,7 +1267,6 @@ static void nes_netdev_get_drvinfo(struct net_device *netdev,
|
|||
sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,
|
||||
nesadapter->firmware_version & 0x000000ff);
|
||||
strcpy(drvinfo->version, DRV_VERSION);
|
||||
drvinfo->n_stats = nes_netdev_get_stats_count(netdev);
|
||||
drvinfo->testinfo_len = 0;
|
||||
drvinfo->eedump_len = 0;
|
||||
drvinfo->regdump_len = 0;
|
||||
|
@ -1516,7 +1518,7 @@ static const struct ethtool_ops nes_ethtool_ops = {
|
|||
.get_rx_csum = nes_netdev_get_rx_csum,
|
||||
.get_sg = ethtool_op_get_sg,
|
||||
.get_strings = nes_netdev_get_strings,
|
||||
.get_stats_count = nes_netdev_get_stats_count,
|
||||
.get_sset_count = nes_netdev_get_sset_count,
|
||||
.get_ethtool_stats = nes_netdev_get_ethtool_stats,
|
||||
.get_drvinfo = nes_netdev_get_drvinfo,
|
||||
.get_coalesce = nes_netdev_get_coalesce,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
menuconfig ISDN_DRV_GIGASET
|
||||
tristate "Siemens Gigaset support"
|
||||
depends on ISDN_I4L
|
||||
select CRC_CCITT
|
||||
select BITREVERSE
|
||||
help
|
||||
|
@ -11,9 +10,33 @@ menuconfig ISDN_DRV_GIGASET
|
|||
If you have one of these devices, say M here and for at least
|
||||
one of the connection specific parts that follow.
|
||||
This will build a module called "gigaset".
|
||||
Note: If you build your ISDN subsystem (ISDN_CAPI or ISDN_I4L)
|
||||
as a module, you have to build this driver as a module too,
|
||||
otherwise the Gigaset device won't show up as an ISDN device.
|
||||
|
||||
if ISDN_DRV_GIGASET
|
||||
|
||||
config GIGASET_CAPI
|
||||
bool "Gigaset CAPI support (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL
|
||||
depends on ISDN_CAPI='y'||(ISDN_CAPI='m'&&ISDN_DRV_GIGASET='m')
|
||||
default ISDN_I4L='n'
|
||||
help
|
||||
Build the Gigaset driver as a CAPI 2.0 driver interfacing with
|
||||
the Kernel CAPI subsystem. To use it with the old ISDN4Linux
|
||||
subsystem you'll have to enable the capidrv glue driver.
|
||||
(select ISDN_CAPI_CAPIDRV.)
|
||||
Say N to build the old native ISDN4Linux variant.
|
||||
|
||||
config GIGASET_I4L
|
||||
bool
|
||||
depends on ISDN_I4L='y'||(ISDN_I4L='m'&&ISDN_DRV_GIGASET='m')
|
||||
default !GIGASET_CAPI
|
||||
|
||||
config GIGASET_DUMMYLL
|
||||
bool
|
||||
default !GIGASET_CAPI&&!GIGASET_I4L
|
||||
|
||||
config GIGASET_BASE
|
||||
tristate "Gigaset base station support"
|
||||
depends on USB
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
gigaset-y := common.o interface.o proc.o ev-layer.o i4l.o asyncdata.o
|
||||
gigaset-y := common.o interface.o proc.o ev-layer.o asyncdata.o
|
||||
gigaset-$(CONFIG_GIGASET_CAPI) += capi.o
|
||||
gigaset-$(CONFIG_GIGASET_I4L) += i4l.o
|
||||
gigaset-$(CONFIG_GIGASET_DUMMYLL) += dummyll.o
|
||||
usb_gigaset-y := usb-gigaset.o
|
||||
ser_gigaset-y := ser-gigaset.o
|
||||
bas_gigaset-y := bas-gigaset.o isocdata.o
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
/* check if byte must be stuffed/escaped
|
||||
* I'm not sure which data should be encoded.
|
||||
* Therefore I will go the hard way and decode every value
|
||||
* Therefore I will go the hard way and encode every value
|
||||
* less than 0x20, the flag sequence and the control escape char.
|
||||
*/
|
||||
static inline int muststuff(unsigned char c)
|
||||
|
@ -35,303 +35,383 @@ static inline int muststuff(unsigned char c)
|
|||
|
||||
/* == data input =========================================================== */
|
||||
|
||||
/* process a block of received bytes in command mode (modem response)
|
||||
/* process a block of received bytes in command mode
|
||||
* (mstate != MS_LOCKED && (inputstate & INS_command))
|
||||
* Append received bytes to the command response buffer and forward them
|
||||
* line by line to the response handler. Exit whenever a mode/state change
|
||||
* might have occurred.
|
||||
* Return value:
|
||||
* number of processed bytes
|
||||
*/
|
||||
static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
|
||||
struct inbuf_t *inbuf)
|
||||
static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||
{
|
||||
unsigned char *src = inbuf->data + inbuf->head;
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
unsigned cbytes = cs->cbytes;
|
||||
int inputstate = inbuf->inputstate;
|
||||
int startbytes = numbytes;
|
||||
unsigned cbytes = cs->cbytes;
|
||||
unsigned procbytes = 0;
|
||||
unsigned char c;
|
||||
|
||||
for (;;) {
|
||||
cs->respdata[cbytes] = c;
|
||||
if (c == 10 || c == 13) {
|
||||
gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
|
||||
__func__, cbytes);
|
||||
cs->cbytes = cbytes;
|
||||
gigaset_handle_modem_response(cs); /* can change
|
||||
cs->dle */
|
||||
cbytes = 0;
|
||||
while (procbytes < numbytes) {
|
||||
c = *src++;
|
||||
procbytes++;
|
||||
|
||||
if (cs->dle &&
|
||||
!(inputstate & INS_DLE_command)) {
|
||||
inputstate &= ~INS_command;
|
||||
switch (c) {
|
||||
case '\n':
|
||||
if (cbytes == 0 && cs->respdata[0] == '\r') {
|
||||
/* collapse LF with preceding CR */
|
||||
cs->respdata[0] = 0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* advance in line buffer, checking for overflow */
|
||||
if (cbytes < MAX_RESP_SIZE - 1)
|
||||
cbytes++;
|
||||
else
|
||||
dev_warn(cs->dev, "response too large\n");
|
||||
}
|
||||
/* --v-- fall through --v-- */
|
||||
case '\r':
|
||||
/* end of message line, pass to response handler */
|
||||
gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)",
|
||||
__func__, cbytes);
|
||||
if (cbytes >= MAX_RESP_SIZE) {
|
||||
dev_warn(cs->dev, "response too large (%d)\n",
|
||||
cbytes);
|
||||
cbytes = MAX_RESP_SIZE;
|
||||
}
|
||||
cs->cbytes = cbytes;
|
||||
gigaset_handle_modem_response(cs);
|
||||
cbytes = 0;
|
||||
|
||||
if (!numbytes)
|
||||
break;
|
||||
c = *src++;
|
||||
--numbytes;
|
||||
if (c == DLE_FLAG &&
|
||||
(cs->dle || inputstate & INS_DLE_command)) {
|
||||
inputstate |= INS_DLE_char;
|
||||
break;
|
||||
/* store EOL byte for CRLF collapsing */
|
||||
cs->respdata[0] = c;
|
||||
|
||||
/* cs->dle may have changed */
|
||||
if (cs->dle && !(inbuf->inputstate & INS_DLE_command))
|
||||
inbuf->inputstate &= ~INS_command;
|
||||
|
||||
/* return for reevaluating state */
|
||||
goto exit;
|
||||
|
||||
case DLE_FLAG:
|
||||
if (inbuf->inputstate & INS_DLE_char) {
|
||||
/* quoted DLE: clear quote flag */
|
||||
inbuf->inputstate &= ~INS_DLE_char;
|
||||
} else if (cs->dle ||
|
||||
(inbuf->inputstate & INS_DLE_command)) {
|
||||
/* DLE escape, pass up for handling */
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
goto exit;
|
||||
}
|
||||
/* quoted or not in DLE mode: treat as regular data */
|
||||
/* --v-- fall through --v-- */
|
||||
default:
|
||||
/* append to line buffer if possible */
|
||||
if (cbytes < MAX_RESP_SIZE)
|
||||
cs->respdata[cbytes] = c;
|
||||
cbytes++;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
cs->cbytes = cbytes;
|
||||
inbuf->inputstate = inputstate;
|
||||
|
||||
return startbytes - numbytes;
|
||||
return procbytes;
|
||||
}
|
||||
|
||||
/* process a block of received bytes in lock mode (tty i/f)
|
||||
/* process a block of received bytes in lock mode
|
||||
* All received bytes are passed unmodified to the tty i/f.
|
||||
* Return value:
|
||||
* number of processed bytes
|
||||
*/
|
||||
static inline int lock_loop(unsigned char *src, int numbytes,
|
||||
struct inbuf_t *inbuf)
|
||||
static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||
{
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
|
||||
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
|
||||
numbytes, src);
|
||||
gigaset_if_receive(cs, src, numbytes);
|
||||
unsigned char *src = inbuf->data + inbuf->head;
|
||||
|
||||
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src);
|
||||
gigaset_if_receive(inbuf->cs, src, numbytes);
|
||||
return numbytes;
|
||||
}
|
||||
|
||||
/* set up next receive skb for data mode
|
||||
*/
|
||||
static void new_rcv_skb(struct bc_state *bcs)
|
||||
{
|
||||
struct cardstate *cs = bcs->cs;
|
||||
unsigned short hw_hdr_len = cs->hw_hdr_len;
|
||||
|
||||
if (bcs->ignore) {
|
||||
bcs->skb = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
bcs->skb = dev_alloc_skb(SBUFSIZE + hw_hdr_len);
|
||||
if (bcs->skb == NULL) {
|
||||
dev_warn(cs->dev, "could not allocate new skb\n");
|
||||
return;
|
||||
}
|
||||
skb_reserve(bcs->skb, hw_hdr_len);
|
||||
}
|
||||
|
||||
/* process a block of received bytes in HDLC data mode
|
||||
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 == L2_HDLC)
|
||||
* Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
|
||||
* When a frame is complete, check the FCS and pass valid frames to the LL.
|
||||
* If DLE is encountered, return immediately to let the caller handle it.
|
||||
* Return value:
|
||||
* number of processed bytes
|
||||
* numbytes (all bytes processed) on error --FIXME
|
||||
*/
|
||||
static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
|
||||
struct inbuf_t *inbuf)
|
||||
static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||
{
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
struct bc_state *bcs = inbuf->bcs;
|
||||
struct bc_state *bcs = cs->bcs;
|
||||
int inputstate = bcs->inputstate;
|
||||
__u16 fcs = bcs->fcs;
|
||||
struct sk_buff *skb = bcs->skb;
|
||||
unsigned char error;
|
||||
struct sk_buff *compskb;
|
||||
int startbytes = numbytes;
|
||||
int l;
|
||||
unsigned char *src = inbuf->data + inbuf->head;
|
||||
unsigned procbytes = 0;
|
||||
unsigned char c;
|
||||
|
||||
if (unlikely(inputstate & INS_byte_stuff)) {
|
||||
if (inputstate & INS_byte_stuff) {
|
||||
if (!numbytes)
|
||||
return 0;
|
||||
inputstate &= ~INS_byte_stuff;
|
||||
goto byte_stuff;
|
||||
}
|
||||
for (;;) {
|
||||
if (unlikely(c == PPP_ESCAPE)) {
|
||||
if (unlikely(!numbytes)) {
|
||||
inputstate |= INS_byte_stuff;
|
||||
|
||||
while (procbytes < numbytes) {
|
||||
c = *src++;
|
||||
procbytes++;
|
||||
if (c == DLE_FLAG) {
|
||||
if (inputstate & INS_DLE_char) {
|
||||
/* quoted DLE: clear quote flag */
|
||||
inputstate &= ~INS_DLE_char;
|
||||
} else if (cs->dle || (inputstate & INS_DLE_command)) {
|
||||
/* DLE escape, pass up for handling */
|
||||
inputstate |= INS_DLE_char;
|
||||
break;
|
||||
}
|
||||
c = *src++;
|
||||
--numbytes;
|
||||
if (unlikely(c == DLE_FLAG &&
|
||||
(cs->dle ||
|
||||
inbuf->inputstate & INS_DLE_command))) {
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
}
|
||||
|
||||
if (c == PPP_ESCAPE) {
|
||||
/* byte stuffing indicator: pull in next byte */
|
||||
if (procbytes >= numbytes) {
|
||||
/* end of buffer, save for later processing */
|
||||
inputstate |= INS_byte_stuff;
|
||||
break;
|
||||
}
|
||||
byte_stuff:
|
||||
c = *src++;
|
||||
procbytes++;
|
||||
if (c == DLE_FLAG) {
|
||||
if (inputstate & INS_DLE_char) {
|
||||
/* quoted DLE: clear quote flag */
|
||||
inputstate &= ~INS_DLE_char;
|
||||
} else if (cs->dle ||
|
||||
(inputstate & INS_DLE_command)) {
|
||||
/* DLE escape, pass up for handling */
|
||||
inputstate |=
|
||||
INS_DLE_char | INS_byte_stuff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c ^= PPP_TRANS;
|
||||
if (unlikely(!muststuff(c)))
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
if (!muststuff(c))
|
||||
gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
|
||||
} else if (unlikely(c == PPP_FLAG)) {
|
||||
if (unlikely(inputstate & INS_skip_frame)) {
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
if (!(inputstate & INS_have_data)) { /* 7E 7E */
|
||||
++bcs->emptycount;
|
||||
} else
|
||||
gig_dbg(DEBUG_HDLC,
|
||||
"7e----------------------------");
|
||||
#endif
|
||||
|
||||
/* end of frame */
|
||||
error = 1;
|
||||
gigaset_rcv_error(NULL, cs, bcs);
|
||||
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
++bcs->emptycount;
|
||||
#endif
|
||||
break;
|
||||
} else {
|
||||
} else if (c == PPP_FLAG) {
|
||||
/* end of frame: process content if any */
|
||||
if (inputstate & INS_have_data) {
|
||||
gig_dbg(DEBUG_HDLC,
|
||||
"7e----------------------------");
|
||||
|
||||
/* end of frame */
|
||||
error = 0;
|
||||
|
||||
if (unlikely(fcs != PPP_GOODFCS)) {
|
||||
/* check and pass received frame */
|
||||
if (!skb) {
|
||||
/* skipped frame */
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
} else if (skb->len < 2) {
|
||||
/* frame too short for FCS */
|
||||
dev_warn(cs->dev,
|
||||
"short frame (%d)\n",
|
||||
skb->len);
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
dev_kfree_skb_any(skb);
|
||||
} else if (fcs != PPP_GOODFCS) {
|
||||
/* frame check error */
|
||||
dev_err(cs->dev,
|
||||
"Checksum failed, %u bytes corrupted!\n",
|
||||
skb->len);
|
||||
compskb = NULL;
|
||||
gigaset_rcv_error(compskb, cs, bcs);
|
||||
error = 1;
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
dev_kfree_skb_any(skb);
|
||||
} else {
|
||||
if (likely((l = skb->len) > 2)) {
|
||||
skb->tail -= 2;
|
||||
skb->len -= 2;
|
||||
} else {
|
||||
dev_kfree_skb(skb);
|
||||
skb = NULL;
|
||||
inputstate |= INS_skip_frame;
|
||||
if (l == 1) {
|
||||
dev_err(cs->dev,
|
||||
"invalid packet size (1)!\n");
|
||||
error = 1;
|
||||
gigaset_rcv_error(NULL,
|
||||
cs, bcs);
|
||||
}
|
||||
}
|
||||
if (likely(!(error ||
|
||||
(inputstate &
|
||||
INS_skip_frame)))) {
|
||||
gigaset_rcv_skb(skb, cs, bcs);
|
||||
}
|
||||
/* good frame */
|
||||
__skb_trim(skb, skb->len - 2);
|
||||
gigaset_skb_rcvd(bcs, skb);
|
||||
}
|
||||
|
||||
/* prepare reception of next frame */
|
||||
inputstate &= ~INS_have_data;
|
||||
new_rcv_skb(bcs);
|
||||
skb = bcs->skb;
|
||||
} else {
|
||||
/* empty frame (7E 7E) */
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
++bcs->emptycount;
|
||||
#endif
|
||||
if (!skb) {
|
||||
/* skipped (?) */
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
new_rcv_skb(bcs);
|
||||
skb = bcs->skb;
|
||||
}
|
||||
}
|
||||
|
||||
if (unlikely(error))
|
||||
if (skb)
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
fcs = PPP_INITFCS;
|
||||
inputstate &= ~(INS_have_data | INS_skip_frame);
|
||||
if (unlikely(bcs->ignore)) {
|
||||
inputstate |= INS_skip_frame;
|
||||
skb = NULL;
|
||||
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
|
||||
skb_reserve(skb, HW_HDR_LEN);
|
||||
} else {
|
||||
dev_warn(cs->dev,
|
||||
"could not allocate new skb\n");
|
||||
inputstate |= INS_skip_frame;
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (unlikely(muststuff(c))) {
|
||||
continue;
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
} else if (muststuff(c)) {
|
||||
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
|
||||
gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* add character */
|
||||
|
||||
/* regular data byte, append to skb */
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
if (unlikely(!(inputstate & INS_have_data))) {
|
||||
if (!(inputstate & INS_have_data)) {
|
||||
gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
|
||||
bcs->emptycount);
|
||||
bcs->emptycount = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inputstate |= INS_have_data;
|
||||
|
||||
if (likely(!(inputstate & INS_skip_frame))) {
|
||||
if (unlikely(skb->len == SBUFSIZE)) {
|
||||
if (skb) {
|
||||
if (skb->len == SBUFSIZE) {
|
||||
dev_warn(cs->dev, "received packet too long\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
inputstate |= INS_skip_frame;
|
||||
break;
|
||||
/* skip remainder of packet */
|
||||
bcs->skb = skb = NULL;
|
||||
} else {
|
||||
*__skb_put(skb, 1) = c;
|
||||
fcs = crc_ccitt_byte(fcs, c);
|
||||
}
|
||||
*__skb_put(skb, 1) = c;
|
||||
fcs = crc_ccitt_byte(fcs, c);
|
||||
}
|
||||
|
||||
if (unlikely(!numbytes))
|
||||
break;
|
||||
c = *src++;
|
||||
--numbytes;
|
||||
if (unlikely(c == DLE_FLAG &&
|
||||
(cs->dle ||
|
||||
inbuf->inputstate & INS_DLE_command))) {
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bcs->inputstate = inputstate;
|
||||
bcs->fcs = fcs;
|
||||
bcs->skb = skb;
|
||||
return startbytes - numbytes;
|
||||
return procbytes;
|
||||
}
|
||||
|
||||
/* process a block of received bytes in transparent data mode
|
||||
* (mstate != MS_LOCKED && !(inputstate & INS_command) && proto2 != L2_HDLC)
|
||||
* Invert bytes, undoing byte stuffing and watching for DLE escapes.
|
||||
* If DLE is encountered, return immediately to let the caller handle it.
|
||||
* Return value:
|
||||
* number of processed bytes
|
||||
* numbytes (all bytes processed) on error --FIXME
|
||||
*/
|
||||
static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
|
||||
struct inbuf_t *inbuf)
|
||||
static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||
{
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
struct bc_state *bcs = inbuf->bcs;
|
||||
struct bc_state *bcs = cs->bcs;
|
||||
int inputstate = bcs->inputstate;
|
||||
struct sk_buff *skb = bcs->skb;
|
||||
int startbytes = numbytes;
|
||||
unsigned char *src = inbuf->data + inbuf->head;
|
||||
unsigned procbytes = 0;
|
||||
unsigned char c;
|
||||
|
||||
for (;;) {
|
||||
/* add character */
|
||||
inputstate |= INS_have_data;
|
||||
if (!skb) {
|
||||
/* skip this block */
|
||||
new_rcv_skb(bcs);
|
||||
return numbytes;
|
||||
}
|
||||
|
||||
if (likely(!(inputstate & INS_skip_frame))) {
|
||||
if (unlikely(skb->len == SBUFSIZE)) {
|
||||
//FIXME just pass skb up and allocate a new one
|
||||
dev_warn(cs->dev, "received packet too long\n");
|
||||
dev_kfree_skb_any(skb);
|
||||
skb = NULL;
|
||||
inputstate |= INS_skip_frame;
|
||||
while (procbytes < numbytes && skb->len < SBUFSIZE) {
|
||||
c = *src++;
|
||||
procbytes++;
|
||||
|
||||
if (c == DLE_FLAG) {
|
||||
if (inputstate & INS_DLE_char) {
|
||||
/* quoted DLE: clear quote flag */
|
||||
inputstate &= ~INS_DLE_char;
|
||||
} else if (cs->dle || (inputstate & INS_DLE_command)) {
|
||||
/* DLE escape, pass up for handling */
|
||||
inputstate |= INS_DLE_char;
|
||||
break;
|
||||
}
|
||||
*__skb_put(skb, 1) = bitrev8(c);
|
||||
}
|
||||
|
||||
if (unlikely(!numbytes))
|
||||
break;
|
||||
c = *src++;
|
||||
--numbytes;
|
||||
if (unlikely(c == DLE_FLAG &&
|
||||
(cs->dle ||
|
||||
inbuf->inputstate & INS_DLE_command))) {
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
break;
|
||||
}
|
||||
/* regular data byte: append to current skb */
|
||||
inputstate |= INS_have_data;
|
||||
*__skb_put(skb, 1) = bitrev8(c);
|
||||
}
|
||||
|
||||
/* pass data up */
|
||||
if (likely(inputstate & INS_have_data)) {
|
||||
if (likely(!(inputstate & INS_skip_frame))) {
|
||||
gigaset_rcv_skb(skb, cs, bcs);
|
||||
}
|
||||
inputstate &= ~(INS_have_data | INS_skip_frame);
|
||||
if (unlikely(bcs->ignore)) {
|
||||
inputstate |= INS_skip_frame;
|
||||
skb = NULL;
|
||||
} else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
|
||||
!= NULL)) {
|
||||
skb_reserve(skb, HW_HDR_LEN);
|
||||
} else {
|
||||
dev_warn(cs->dev, "could not allocate new skb\n");
|
||||
inputstate |= INS_skip_frame;
|
||||
}
|
||||
if (inputstate & INS_have_data) {
|
||||
gigaset_skb_rcvd(bcs, skb);
|
||||
inputstate &= ~INS_have_data;
|
||||
new_rcv_skb(bcs);
|
||||
}
|
||||
|
||||
bcs->inputstate = inputstate;
|
||||
bcs->skb = skb;
|
||||
return startbytes - numbytes;
|
||||
return procbytes;
|
||||
}
|
||||
|
||||
/* process DLE escapes
|
||||
* Called whenever a DLE sequence might be encountered in the input stream.
|
||||
* Either processes the entire DLE sequence or, if that isn't possible,
|
||||
* notes the fact that an initial DLE has been received in the INS_DLE_char
|
||||
* inputstate flag and resumes processing of the sequence on the next call.
|
||||
*/
|
||||
static void handle_dle(struct inbuf_t *inbuf)
|
||||
{
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
|
||||
if (cs->mstate == MS_LOCKED)
|
||||
return; /* no DLE processing in lock mode */
|
||||
|
||||
if (!(inbuf->inputstate & INS_DLE_char)) {
|
||||
/* no DLE pending */
|
||||
if (inbuf->data[inbuf->head] == DLE_FLAG &&
|
||||
(cs->dle || inbuf->inputstate & INS_DLE_command)) {
|
||||
/* start of DLE sequence */
|
||||
inbuf->head++;
|
||||
if (inbuf->head == inbuf->tail ||
|
||||
inbuf->head == RBUFSIZE) {
|
||||
/* end of buffer, save for later processing */
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* regular data byte */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* consume pending DLE */
|
||||
inbuf->inputstate &= ~INS_DLE_char;
|
||||
|
||||
switch (inbuf->data[inbuf->head]) {
|
||||
case 'X': /* begin of event message */
|
||||
if (inbuf->inputstate & INS_command)
|
||||
dev_notice(cs->dev,
|
||||
"received <DLE>X in command mode\n");
|
||||
inbuf->inputstate |= INS_command | INS_DLE_command;
|
||||
inbuf->head++; /* byte consumed */
|
||||
break;
|
||||
case '.': /* end of event message */
|
||||
if (!(inbuf->inputstate & INS_DLE_command))
|
||||
dev_notice(cs->dev,
|
||||
"received <DLE>. without <DLE>X\n");
|
||||
inbuf->inputstate &= ~INS_DLE_command;
|
||||
/* return to data mode if in DLE mode */
|
||||
if (cs->dle)
|
||||
inbuf->inputstate &= ~INS_command;
|
||||
inbuf->head++; /* byte consumed */
|
||||
break;
|
||||
case DLE_FLAG: /* DLE in data stream */
|
||||
/* mark as quoted */
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
if (!(cs->dle || inbuf->inputstate & INS_DLE_command))
|
||||
dev_notice(cs->dev,
|
||||
"received <DLE><DLE> not in DLE mode\n");
|
||||
break; /* quoted byte left in buffer */
|
||||
default:
|
||||
dev_notice(cs->dev, "received <DLE><%02x>\n",
|
||||
inbuf->data[inbuf->head]);
|
||||
/* quoted byte left in buffer */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -345,94 +425,39 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
|
|||
*/
|
||||
void gigaset_m10x_input(struct inbuf_t *inbuf)
|
||||
{
|
||||
struct cardstate *cs;
|
||||
unsigned tail, head, numbytes;
|
||||
unsigned char *src, c;
|
||||
int procbytes;
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
unsigned numbytes, procbytes;
|
||||
|
||||
head = inbuf->head;
|
||||
tail = inbuf->tail;
|
||||
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
|
||||
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail);
|
||||
|
||||
if (head != tail) {
|
||||
cs = inbuf->cs;
|
||||
src = inbuf->data + head;
|
||||
numbytes = (head > tail ? RBUFSIZE : tail) - head;
|
||||
while (inbuf->head != inbuf->tail) {
|
||||
/* check for DLE escape */
|
||||
handle_dle(inbuf);
|
||||
|
||||
/* process a contiguous block of bytes */
|
||||
numbytes = (inbuf->head > inbuf->tail ?
|
||||
RBUFSIZE : inbuf->tail) - inbuf->head;
|
||||
gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
|
||||
/*
|
||||
* numbytes may be 0 if handle_dle() ate the last byte.
|
||||
* This does no harm, *_loop() will just return 0 immediately.
|
||||
*/
|
||||
|
||||
while (numbytes) {
|
||||
if (cs->mstate == MS_LOCKED) {
|
||||
procbytes = lock_loop(src, numbytes, inbuf);
|
||||
src += procbytes;
|
||||
numbytes -= procbytes;
|
||||
} else {
|
||||
c = *src++;
|
||||
--numbytes;
|
||||
if (c == DLE_FLAG && (cs->dle ||
|
||||
inbuf->inputstate & INS_DLE_command)) {
|
||||
if (!(inbuf->inputstate & INS_DLE_char)) {
|
||||
inbuf->inputstate |= INS_DLE_char;
|
||||
goto nextbyte;
|
||||
}
|
||||
/* <DLE> <DLE> => <DLE> in data stream */
|
||||
inbuf->inputstate &= ~INS_DLE_char;
|
||||
}
|
||||
if (cs->mstate == MS_LOCKED)
|
||||
procbytes = lock_loop(numbytes, inbuf);
|
||||
else if (inbuf->inputstate & INS_command)
|
||||
procbytes = cmd_loop(numbytes, inbuf);
|
||||
else if (cs->bcs->proto2 == L2_HDLC)
|
||||
procbytes = hdlc_loop(numbytes, inbuf);
|
||||
else
|
||||
procbytes = iraw_loop(numbytes, inbuf);
|
||||
inbuf->head += procbytes;
|
||||
|
||||
if (!(inbuf->inputstate & INS_DLE_char)) {
|
||||
/* check for buffer wraparound */
|
||||
if (inbuf->head >= RBUFSIZE)
|
||||
inbuf->head = 0;
|
||||
|
||||
/* FIXME use function pointers? */
|
||||
if (inbuf->inputstate & INS_command)
|
||||
procbytes = cmd_loop(c, src, numbytes, inbuf);
|
||||
else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
|
||||
procbytes = hdlc_loop(c, src, numbytes, inbuf);
|
||||
else
|
||||
procbytes = iraw_loop(c, src, numbytes, inbuf);
|
||||
|
||||
src += procbytes;
|
||||
numbytes -= procbytes;
|
||||
} else { /* DLE char */
|
||||
inbuf->inputstate &= ~INS_DLE_char;
|
||||
switch (c) {
|
||||
case 'X': /*begin of command*/
|
||||
if (inbuf->inputstate & INS_command)
|
||||
dev_warn(cs->dev,
|
||||
"received <DLE> 'X' in command mode\n");
|
||||
inbuf->inputstate |=
|
||||
INS_command | INS_DLE_command;
|
||||
break;
|
||||
case '.': /*end of command*/
|
||||
if (!(inbuf->inputstate & INS_command))
|
||||
dev_warn(cs->dev,
|
||||
"received <DLE> '.' in hdlc mode\n");
|
||||
inbuf->inputstate &= cs->dle ?
|
||||
~(INS_DLE_command|INS_command)
|
||||
: ~INS_DLE_command;
|
||||
break;
|
||||
//case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
|
||||
default:
|
||||
dev_err(cs->dev,
|
||||
"received 0x10 0x%02x!\n",
|
||||
(int) c);
|
||||
/* FIXME: reset driver?? */
|
||||
}
|
||||
}
|
||||
}
|
||||
nextbyte:
|
||||
if (!numbytes) {
|
||||
/* end of buffer, check for wrap */
|
||||
if (head > tail) {
|
||||
head = 0;
|
||||
src = inbuf->data;
|
||||
numbytes = tail;
|
||||
} else {
|
||||
head = tail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_INTR, "setting head to %u", head);
|
||||
inbuf->head = head;
|
||||
gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_m10x_input);
|
||||
|
@ -440,16 +465,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input);
|
|||
|
||||
/* == data output ========================================================== */
|
||||
|
||||
/* Encoding of a PPP packet into an octet stuffed HDLC frame
|
||||
* with FCS, opening and closing flags.
|
||||
/*
|
||||
* Encode a data packet into an octet stuffed HDLC frame with FCS,
|
||||
* opening and closing flags, preserving headroom data.
|
||||
* parameters:
|
||||
* skb skb containing original packet (freed upon return)
|
||||
* head number of headroom bytes to allocate in result skb
|
||||
* tail number of tailroom bytes to allocate in result skb
|
||||
* skb skb containing original packet (freed upon return)
|
||||
* Return value:
|
||||
* pointer to newly allocated skb containing the result frame
|
||||
* and the original link layer header, NULL on error
|
||||
*/
|
||||
static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
|
||||
static struct sk_buff *HDLC_Encode(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *hdlc_skb;
|
||||
__u16 fcs;
|
||||
|
@ -471,16 +496,19 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
|
|||
|
||||
/* size of new buffer: original size + number of stuffing bytes
|
||||
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
|
||||
* + room for link layer header
|
||||
*/
|
||||
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
|
||||
hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + skb->mac_len);
|
||||
if (!hdlc_skb) {
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NULL;
|
||||
}
|
||||
skb_reserve(hdlc_skb, head);
|
||||
|
||||
/* Copy acknowledge request into new skb */
|
||||
memcpy(hdlc_skb->head, skb->head, 2);
|
||||
/* Copy link layer header into new skb */
|
||||
skb_reset_mac_header(hdlc_skb);
|
||||
skb_reserve(hdlc_skb, skb->mac_len);
|
||||
memcpy(skb_mac_header(hdlc_skb), skb_mac_header(skb), skb->mac_len);
|
||||
hdlc_skb->mac_len = skb->mac_len;
|
||||
|
||||
/* Add flag sequence in front of everything.. */
|
||||
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
|
||||
|
@ -511,33 +539,42 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
|
|||
|
||||
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
return hdlc_skb;
|
||||
}
|
||||
|
||||
/* Encoding of a raw packet into an octet stuffed bit inverted frame
|
||||
/*
|
||||
* Encode a data packet into an octet stuffed raw bit inverted frame,
|
||||
* preserving headroom data.
|
||||
* parameters:
|
||||
* skb skb containing original packet (freed upon return)
|
||||
* head number of headroom bytes to allocate in result skb
|
||||
* tail number of tailroom bytes to allocate in result skb
|
||||
* skb skb containing original packet (freed upon return)
|
||||
* Return value:
|
||||
* pointer to newly allocated skb containing the result frame
|
||||
* and the original link layer header, NULL on error
|
||||
*/
|
||||
static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
|
||||
static struct sk_buff *iraw_encode(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *iraw_skb;
|
||||
unsigned char c;
|
||||
unsigned char *cp;
|
||||
int len;
|
||||
|
||||
/* worst case: every byte must be stuffed */
|
||||
iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
|
||||
/* size of new buffer (worst case = every byte must be stuffed):
|
||||
* 2 * original size + room for link layer header
|
||||
*/
|
||||
iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len);
|
||||
if (!iraw_skb) {
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
return NULL;
|
||||
}
|
||||
skb_reserve(iraw_skb, head);
|
||||
|
||||
/* copy link layer header into new skb */
|
||||
skb_reset_mac_header(iraw_skb);
|
||||
skb_reserve(iraw_skb, skb->mac_len);
|
||||
memcpy(skb_mac_header(iraw_skb), skb_mac_header(skb), skb->mac_len);
|
||||
iraw_skb->mac_len = skb->mac_len;
|
||||
|
||||
/* copy and stuff data */
|
||||
cp = skb->data;
|
||||
len = skb->len;
|
||||
while (len--) {
|
||||
|
@ -546,7 +583,7 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
|
|||
*(skb_put(iraw_skb, 1)) = c;
|
||||
*(skb_put(iraw_skb, 1)) = c;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
return iraw_skb;
|
||||
}
|
||||
|
||||
|
@ -555,8 +592,10 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
|
|||
* @bcs: B channel descriptor structure.
|
||||
* @skb: data to send.
|
||||
*
|
||||
* Called by i4l.c to encode and queue an skb for sending, and start
|
||||
* Called by LL to encode and queue an skb for sending, and start
|
||||
* transmission if necessary.
|
||||
* Once the payload data has been transmitted completely, gigaset_skb_sent()
|
||||
* will be called with the skb's link layer header preserved.
|
||||
*
|
||||
* Return value:
|
||||
* number of bytes accepted for sending (skb->len) if ok,
|
||||
|
@ -564,24 +603,25 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
|
|||
*/
|
||||
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
|
||||
{
|
||||
struct cardstate *cs = bcs->cs;
|
||||
unsigned len = skb->len;
|
||||
unsigned long flags;
|
||||
|
||||
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
|
||||
skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
|
||||
if (bcs->proto2 == L2_HDLC)
|
||||
skb = HDLC_Encode(skb);
|
||||
else
|
||||
skb = iraw_encode(skb, HW_HDR_LEN, 0);
|
||||
skb = iraw_encode(skb);
|
||||
if (!skb) {
|
||||
dev_err(bcs->cs->dev,
|
||||
dev_err(cs->dev,
|
||||
"unable to allocate memory for encoding!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skb_queue_tail(&bcs->squeue, skb);
|
||||
spin_lock_irqsave(&bcs->cs->lock, flags);
|
||||
if (bcs->cs->connected)
|
||||
tasklet_schedule(&bcs->cs->write_tasklet);
|
||||
spin_unlock_irqrestore(&bcs->cs->lock, flags);
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (cs->connected)
|
||||
tasklet_schedule(&cs->write_tasklet);
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
|
||||
return len; /* ok so far */
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
|
|||
#define USB_SX353_PRODUCT_ID 0x0022
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id gigaset_table [] = {
|
||||
static const struct usb_device_id gigaset_table[] = {
|
||||
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3070_PRODUCT_ID) },
|
||||
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
|
||||
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_PRODUCT_ID) },
|
||||
|
@ -137,7 +137,7 @@ struct bas_cardstate {
|
|||
#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */
|
||||
|
||||
|
||||
static struct gigaset_driver *driver = NULL;
|
||||
static struct gigaset_driver *driver;
|
||||
|
||||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver gigaset_usb_driver = {
|
||||
|
@ -601,11 +601,12 @@ static int atread_submit(struct cardstate *cs, int timeout)
|
|||
ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
|
||||
usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
|
||||
usb_rcvctrlpipe(ucs->udev, 0),
|
||||
(unsigned char*) & ucs->dr_cmd_in,
|
||||
(unsigned char *) &ucs->dr_cmd_in,
|
||||
ucs->rcvbuf, ucs->rcvbuf_size,
|
||||
read_ctrl_callback, cs->inbuf);
|
||||
|
||||
if ((ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC)) != 0) {
|
||||
ret = usb_submit_urb(ucs->urb_cmd_in, GFP_ATOMIC);
|
||||
if (ret != 0) {
|
||||
update_basstate(ucs, 0, BS_ATRDPEND);
|
||||
dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
|
||||
get_usb_rcmsg(ret));
|
||||
|
@ -652,13 +653,11 @@ static void read_int_callback(struct urb *urb)
|
|||
return;
|
||||
case -ENODEV: /* device removed */
|
||||
case -ESHUTDOWN: /* device shut down */
|
||||
//FIXME use this as disconnect indicator?
|
||||
gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
|
||||
return;
|
||||
default: /* severe trouble */
|
||||
dev_warn(cs->dev, "interrupt read: %s\n",
|
||||
get_usb_statmsg(status));
|
||||
//FIXME corrective action? resubmission always ok?
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
|
@ -742,7 +741,8 @@ static void read_int_callback(struct urb *urb)
|
|||
kfree(ucs->rcvbuf);
|
||||
ucs->rcvbuf_size = 0;
|
||||
}
|
||||
if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) {
|
||||
ucs->rcvbuf = kmalloc(l, GFP_ATOMIC);
|
||||
if (ucs->rcvbuf == NULL) {
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
dev_err(cs->dev, "out of memory receiving AT data\n");
|
||||
error_reset(cs);
|
||||
|
@ -750,12 +750,12 @@ static void read_int_callback(struct urb *urb)
|
|||
}
|
||||
ucs->rcvbuf_size = l;
|
||||
ucs->retry_cmd_in = 0;
|
||||
if ((rc = atread_submit(cs, BAS_TIMEOUT)) < 0) {
|
||||
rc = atread_submit(cs, BAS_TIMEOUT);
|
||||
if (rc < 0) {
|
||||
kfree(ucs->rcvbuf);
|
||||
ucs->rcvbuf = NULL;
|
||||
ucs->rcvbuf_size = 0;
|
||||
if (rc != -ENODEV) {
|
||||
//FIXME corrective action?
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
error_reset(cs);
|
||||
break;
|
||||
|
@ -911,7 +911,7 @@ static int starturbs(struct bc_state *bcs)
|
|||
int rc;
|
||||
|
||||
/* initialize L2 reception */
|
||||
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
|
||||
if (bcs->proto2 == L2_HDLC)
|
||||
bcs->inputstate |= INS_flag_hunt;
|
||||
|
||||
/* submit all isochronous input URBs */
|
||||
|
@ -940,7 +940,8 @@ static int starturbs(struct bc_state *bcs)
|
|||
}
|
||||
|
||||
dump_urb(DEBUG_ISO, "Initial isoc read", urb);
|
||||
if ((rc = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
|
||||
rc = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -1045,7 +1046,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
|
|||
|
||||
/* compute frame length according to flow control */
|
||||
ifd->length = BAS_NORMFRAME;
|
||||
if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) {
|
||||
corrbytes = atomic_read(&ubc->corrbytes);
|
||||
if (corrbytes != 0) {
|
||||
gig_dbg(DEBUG_ISO, "%s: corrbytes=%d",
|
||||
__func__, corrbytes);
|
||||
if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
|
||||
|
@ -1064,7 +1066,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
|
|||
"%s: buffer busy at frame %d",
|
||||
__func__, nframe);
|
||||
/* tasklet will be restarted from
|
||||
gigaset_send_skb() */
|
||||
gigaset_isoc_send_skb() */
|
||||
} else {
|
||||
dev_err(ucx->bcs->cs->dev,
|
||||
"%s: buffer error %d at frame %d\n",
|
||||
|
@ -1284,7 +1286,8 @@ static void read_iso_tasklet(unsigned long data)
|
|||
for (;;) {
|
||||
/* retrieve URB */
|
||||
spin_lock_irqsave(&ubc->isoinlock, flags);
|
||||
if (!(urb = ubc->isoindone)) {
|
||||
urb = ubc->isoindone;
|
||||
if (!urb) {
|
||||
spin_unlock_irqrestore(&ubc->isoinlock, flags);
|
||||
return;
|
||||
}
|
||||
|
@ -1371,7 +1374,7 @@ static void read_iso_tasklet(unsigned long data)
|
|||
"isochronous read: %d data bytes missing\n",
|
||||
totleft);
|
||||
|
||||
error:
|
||||
error:
|
||||
/* URB processed, resubmit */
|
||||
for (frame = 0; frame < BAS_NUMFRAMES; frame++) {
|
||||
urb->iso_frame_desc[frame].status = 0;
|
||||
|
@ -1568,7 +1571,7 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout)
|
|||
ucs->dr_ctrl.wLength = 0;
|
||||
usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
|
||||
usb_sndctrlpipe(ucs->udev, 0),
|
||||
(unsigned char*) &ucs->dr_ctrl, NULL, 0,
|
||||
(unsigned char *) &ucs->dr_ctrl, NULL, 0,
|
||||
write_ctrl_callback, ucs);
|
||||
ucs->retry_ctrl = 0;
|
||||
ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC);
|
||||
|
@ -1621,7 +1624,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
|
|||
return -EHOSTUNREACH;
|
||||
}
|
||||
|
||||
if ((ret = starturbs(bcs)) < 0) {
|
||||
ret = starturbs(bcs);
|
||||
if (ret < 0) {
|
||||
dev_err(cs->dev,
|
||||
"could not start isochronous I/O for channel B%d: %s\n",
|
||||
bcs->channel + 1,
|
||||
|
@ -1633,7 +1637,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
|
|||
}
|
||||
|
||||
req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL;
|
||||
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) {
|
||||
ret = req_submit(bcs, req, 0, BAS_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
dev_err(cs->dev, "could not open channel B%d\n",
|
||||
bcs->channel + 1);
|
||||
stopurbs(bcs->hw.bas);
|
||||
|
@ -1677,7 +1682,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
|
|||
|
||||
/* channel running: tell device to close it */
|
||||
req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
|
||||
if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0)
|
||||
ret = req_submit(bcs, req, 0, BAS_TIMEOUT);
|
||||
if (ret < 0)
|
||||
dev_err(cs->dev, "closing channel B%d failed\n",
|
||||
bcs->channel + 1);
|
||||
|
||||
|
@ -1703,10 +1709,12 @@ static void complete_cb(struct cardstate *cs)
|
|||
gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
|
||||
"write_command: sent %u bytes, %u left",
|
||||
cs->curlen, cs->cmdbytes);
|
||||
if ((cs->cmdbuf = cb->next) != NULL) {
|
||||
if (cb->next != NULL) {
|
||||
cs->cmdbuf = cb->next;
|
||||
cs->cmdbuf->prev = NULL;
|
||||
cs->curlen = cs->cmdbuf->len;
|
||||
} else {
|
||||
cs->cmdbuf = NULL;
|
||||
cs->lastcmdbuf = NULL;
|
||||
cs->curlen = 0;
|
||||
}
|
||||
|
@ -1833,7 +1841,7 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len)
|
|||
ucs->dr_cmd_out.wLength = cpu_to_le16(len);
|
||||
usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev,
|
||||
usb_sndctrlpipe(ucs->udev, 0),
|
||||
(unsigned char*) &ucs->dr_cmd_out, buf, len,
|
||||
(unsigned char *) &ucs->dr_cmd_out, buf, len,
|
||||
write_command_callback, cs);
|
||||
rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC);
|
||||
if (unlikely(rc)) {
|
||||
|
@ -1953,7 +1961,8 @@ static int gigaset_write_cmd(struct cardstate *cs,
|
|||
|
||||
if (len > IF_WRITEBUF)
|
||||
len = IF_WRITEBUF;
|
||||
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
|
||||
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
|
||||
if (!cb) {
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
rc = -ENOMEM;
|
||||
goto notqueued;
|
||||
|
@ -2100,14 +2109,15 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
}
|
||||
ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL;
|
||||
ubc->numsub = 0;
|
||||
if (!(ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL))) {
|
||||
ubc->isooutbuf = kmalloc(sizeof(struct isowbuf_t), GFP_KERNEL);
|
||||
if (!ubc->isooutbuf) {
|
||||
pr_err("out of memory\n");
|
||||
kfree(ubc);
|
||||
bcs->hw.bas = NULL;
|
||||
return 0;
|
||||
}
|
||||
tasklet_init(&ubc->sent_tasklet,
|
||||
&write_iso_tasklet, (unsigned long) bcs);
|
||||
write_iso_tasklet, (unsigned long) bcs);
|
||||
|
||||
spin_lock_init(&ubc->isoinlock);
|
||||
for (i = 0; i < BAS_INURBS; ++i)
|
||||
|
@ -2128,7 +2138,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
|||
ubc->shared0s = 0;
|
||||
ubc->stolen0s = 0;
|
||||
tasklet_init(&ubc->rcvd_tasklet,
|
||||
&read_iso_tasklet, (unsigned long) bcs);
|
||||
read_iso_tasklet, (unsigned long) bcs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -2252,7 +2262,8 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
gig_dbg(DEBUG_ANY,
|
||||
"%s: wrong alternate setting %d - trying to switch",
|
||||
__func__, hostif->desc.bAlternateSetting);
|
||||
if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) {
|
||||
if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3)
|
||||
< 0) {
|
||||
dev_warn(&udev->dev, "usb_set_interface failed, "
|
||||
"device %d interface %d altsetting %d\n",
|
||||
udev->devnum, hostif->desc.bInterfaceNumber,
|
||||
|
@ -2321,14 +2332,16 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
(endpoint->bEndpointAddress) & 0x0f),
|
||||
ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs,
|
||||
endpoint->bInterval);
|
||||
if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) {
|
||||
rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL);
|
||||
if (rc != 0) {
|
||||
dev_err(cs->dev, "could not submit interrupt URB: %s\n",
|
||||
get_usb_rcmsg(rc));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* tell the device that the driver is ready */
|
||||
if ((rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0)) != 0)
|
||||
rc = req_submit(cs->bcs, HD_DEVICE_INIT_ACK, 0, 0);
|
||||
if (rc != 0)
|
||||
goto error;
|
||||
|
||||
/* tell common part that the device is ready */
|
||||
|
@ -2524,9 +2537,10 @@ static int __init bas_gigaset_init(void)
|
|||
int result;
|
||||
|
||||
/* allocate memory for our driver state and intialize it */
|
||||
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&gigops, THIS_MODULE)) == NULL)
|
||||
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&gigops, THIS_MODULE);
|
||||
if (driver == NULL)
|
||||
goto error;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -108,7 +108,7 @@ int gigaset_enterconfigmode(struct cardstate *cs)
|
|||
{
|
||||
int i, r;
|
||||
|
||||
cs->control_state = TIOCM_RTS; //FIXME
|
||||
cs->control_state = TIOCM_RTS;
|
||||
|
||||
r = setflags(cs, TIOCM_DTR, 200);
|
||||
if (r < 0)
|
||||
|
@ -132,10 +132,10 @@ int gigaset_enterconfigmode(struct cardstate *cs)
|
|||
|
||||
error:
|
||||
dev_err(cs->dev, "error %d on setuartbits\n", -r);
|
||||
cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value?
|
||||
cs->control_state = TIOCM_RTS|TIOCM_DTR;
|
||||
cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR);
|
||||
|
||||
return -1; //r
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int test_timeout(struct at_state_t *at_state)
|
||||
|
@ -150,10 +150,9 @@ static int test_timeout(struct at_state_t *at_state)
|
|||
}
|
||||
|
||||
if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
|
||||
at_state->timer_index, NULL)) {
|
||||
//FIXME what should we do?
|
||||
}
|
||||
|
||||
at_state->timer_index, NULL))
|
||||
dev_err(at_state->cs->dev, "%s: out of memory\n",
|
||||
__func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -207,6 +206,32 @@ int gigaset_get_channel(struct bc_state *bcs)
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct bc_state *gigaset_get_free_channel(struct cardstate *cs)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (!try_module_get(cs->driver->owner)) {
|
||||
gig_dbg(DEBUG_ANY,
|
||||
"could not get module for allocating channel");
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < cs->channels; ++i)
|
||||
if (!cs->bcs[i].use_count) {
|
||||
++cs->bcs[i].use_count;
|
||||
cs->bcs[i].busy = 1;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gig_dbg(DEBUG_ANY, "allocated channel %d", i);
|
||||
return cs->bcs + i;
|
||||
}
|
||||
module_put(cs->driver->owner);
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gig_dbg(DEBUG_ANY, "no free channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gigaset_free_channel(struct bc_state *bcs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -367,16 +392,15 @@ static void gigaset_freebcs(struct bc_state *bcs)
|
|||
int i;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
|
||||
if (!bcs->cs->ops->freebcshw(bcs)) {
|
||||
if (!bcs->cs->ops->freebcshw(bcs))
|
||||
gig_dbg(DEBUG_INIT, "failed");
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
|
||||
clear_at_state(&bcs->at_state);
|
||||
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
|
||||
dev_kfree_skb(bcs->skb);
|
||||
bcs->skb = NULL;
|
||||
|
||||
if (bcs->skb)
|
||||
dev_kfree_skb(bcs->skb);
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(bcs->commands[i]);
|
||||
bcs->commands[i] = NULL;
|
||||
|
@ -463,6 +487,12 @@ void gigaset_freecs(struct cardstate *cs)
|
|||
|
||||
switch (cs->cs_init) {
|
||||
default:
|
||||
/* clear B channel structures */
|
||||
for (i = 0; i < cs->channels; ++i) {
|
||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
|
||||
gigaset_freebcs(cs->bcs + i);
|
||||
}
|
||||
|
||||
/* clear device sysfs */
|
||||
gigaset_free_dev_sysfs(cs);
|
||||
|
||||
|
@ -471,28 +501,20 @@ void gigaset_freecs(struct cardstate *cs)
|
|||
gig_dbg(DEBUG_INIT, "clearing hw");
|
||||
cs->ops->freecshw(cs);
|
||||
|
||||
//FIXME cmdbuf
|
||||
|
||||
/* fall through */
|
||||
case 2: /* error in initcshw */
|
||||
/* Deregister from LL */
|
||||
make_invalid(cs, VALID_ID);
|
||||
gig_dbg(DEBUG_INIT, "clearing iif");
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
|
||||
gigaset_isdn_unregister(cs);
|
||||
|
||||
/* fall through */
|
||||
case 1: /* error when regestering to LL */
|
||||
case 1: /* error when registering to LL */
|
||||
gig_dbg(DEBUG_INIT, "clearing at_state");
|
||||
clear_at_state(&cs->at_state);
|
||||
dealloc_at_states(cs);
|
||||
|
||||
/* fall through */
|
||||
case 0: /* error in one call to initbcs */
|
||||
for (i = 0; i < cs->channels; ++i) {
|
||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
|
||||
gigaset_freebcs(cs->bcs + i);
|
||||
}
|
||||
|
||||
case 0: /* error in basic setup */
|
||||
clear_events(cs);
|
||||
gig_dbg(DEBUG_INIT, "freeing inbuf");
|
||||
kfree(cs->inbuf);
|
||||
|
@ -534,16 +556,13 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
|
|||
}
|
||||
|
||||
|
||||
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs,
|
||||
struct cardstate *cs, int inputstate)
|
||||
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
|
||||
/* inbuf->read must be allocated before! */
|
||||
{
|
||||
inbuf->head = 0;
|
||||
inbuf->tail = 0;
|
||||
inbuf->cs = cs;
|
||||
inbuf->bcs = bcs; /*base driver: NULL*/
|
||||
inbuf->rcvbuf = NULL;
|
||||
inbuf->inputstate = inputstate;
|
||||
inbuf->inputstate = INS_command;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -599,7 +618,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
|||
{
|
||||
int i;
|
||||
|
||||
bcs->tx_skb = NULL; //FIXME -> hw part
|
||||
bcs->tx_skb = NULL;
|
||||
|
||||
skb_queue_head_init(&bcs->squeue);
|
||||
|
||||
|
@ -618,13 +637,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
|||
bcs->fcs = PPP_INITFCS;
|
||||
bcs->inputstate = 0;
|
||||
if (cs->ignoreframes) {
|
||||
bcs->inputstate |= INS_skip_frame;
|
||||
bcs->skb = NULL;
|
||||
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
||||
else {
|
||||
pr_err("out of memory\n");
|
||||
bcs->inputstate |= INS_skip_frame;
|
||||
} else {
|
||||
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||
if (bcs->skb != NULL)
|
||||
skb_reserve(bcs->skb, cs->hw_hdr_len);
|
||||
else
|
||||
pr_err("out of memory\n");
|
||||
}
|
||||
|
||||
bcs->channel = channel;
|
||||
|
@ -645,8 +664,8 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
|||
gig_dbg(DEBUG_INIT, " failed");
|
||||
|
||||
gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
|
||||
if (bcs->skb)
|
||||
dev_kfree_skb(bcs->skb);
|
||||
dev_kfree_skb(bcs->skb);
|
||||
bcs->skb = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -673,12 +692,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
int onechannel, int ignoreframes,
|
||||
int cidmode, const char *modulename)
|
||||
{
|
||||
struct cardstate *cs = NULL;
|
||||
struct cardstate *cs;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "allocating cs");
|
||||
if (!(cs = alloc_cs(drv))) {
|
||||
cs = alloc_cs(drv);
|
||||
if (!cs) {
|
||||
pr_err("maximum number of devices exceeded\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -707,7 +727,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->ev_tail = 0;
|
||||
cs->ev_head = 0;
|
||||
|
||||
tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
|
||||
tasklet_init(&cs->event_tasklet, gigaset_handle_event,
|
||||
(unsigned long) cs);
|
||||
cs->commands_pending = 0;
|
||||
cs->cur_at_seq = 0;
|
||||
|
@ -726,14 +746,6 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->mode = M_UNKNOWN;
|
||||
cs->mstate = MS_UNINITIALIZED;
|
||||
|
||||
for (i = 0; i < channels; ++i) {
|
||||
gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i);
|
||||
if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
|
||||
pr_err("could not allocate channel %d data\n", i);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
++cs->cs_init;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up at_state");
|
||||
|
@ -743,10 +755,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->cbytes = 0;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up inbuf");
|
||||
if (onechannel) { //FIXME distinction necessary?
|
||||
gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
|
||||
} else
|
||||
gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
|
||||
gigaset_inbuf_init(cs->inbuf, cs);
|
||||
|
||||
cs->connected = 0;
|
||||
cs->isdn_up = 0;
|
||||
|
@ -758,7 +767,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
cs->cmdbytes = 0;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up iif");
|
||||
if (!gigaset_register_to_LL(cs, modulename)) {
|
||||
if (!gigaset_isdn_register(cs, modulename)) {
|
||||
pr_err("error registering ISDN device\n");
|
||||
goto error;
|
||||
}
|
||||
|
@ -777,6 +786,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
|||
/* set up device sysfs */
|
||||
gigaset_init_dev_sysfs(cs);
|
||||
|
||||
/* set up channel data structures */
|
||||
for (i = 0; i < channels; ++i) {
|
||||
gig_dbg(DEBUG_INIT, "setting up bcs[%d]", i);
|
||||
if (!gigaset_initbcs(cs->bcs + i, cs, i)) {
|
||||
pr_err("could not allocate channel %d data\n", i);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
cs->running = 1;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
|
@ -824,9 +842,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
|
|||
bcs->chstate = 0;
|
||||
|
||||
bcs->ignore = cs->ignoreframes;
|
||||
if (bcs->ignore)
|
||||
bcs->inputstate |= INS_skip_frame;
|
||||
|
||||
if (bcs->ignore) {
|
||||
dev_kfree_skb(bcs->skb);
|
||||
bcs->skb = NULL;
|
||||
}
|
||||
|
||||
cs->ops->reinitbcshw(bcs);
|
||||
}
|
||||
|
@ -847,8 +866,6 @@ static void cleanup_cs(struct cardstate *cs)
|
|||
free_strings(&cs->at_state);
|
||||
gigaset_at_init(&cs->at_state, NULL, cs, 0);
|
||||
|
||||
kfree(cs->inbuf->rcvbuf);
|
||||
cs->inbuf->rcvbuf = NULL;
|
||||
cs->inbuf->inputstate = INS_command;
|
||||
cs->inbuf->head = 0;
|
||||
cs->inbuf->tail = 0;
|
||||
|
@ -911,15 +928,13 @@ int gigaset_start(struct cardstate *cs)
|
|||
cs->ops->baud_rate(cs, B115200);
|
||||
cs->ops->set_line_ctrl(cs, CS8);
|
||||
cs->control_state = TIOCM_DTR|TIOCM_RTS;
|
||||
} else {
|
||||
//FIXME use some saved values?
|
||||
}
|
||||
|
||||
cs->waiting = 1;
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
|
||||
cs->waiting = 0;
|
||||
//FIXME what should we do?
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -959,7 +974,7 @@ int gigaset_shutdown(struct cardstate *cs)
|
|||
cs->waiting = 1;
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
|
||||
//FIXME what should we do?
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -990,7 +1005,7 @@ void gigaset_stop(struct cardstate *cs)
|
|||
cs->waiting = 1;
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
|
||||
//FIXME what should we do?
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Dummy LL interface for the Gigaset driver
|
||||
*
|
||||
* Copyright (c) 2009 by Tilman Schmidt <tilman@imap.cc>.
|
||||
*
|
||||
* =====================================================================
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
* =====================================================================
|
||||
*/
|
||||
|
||||
#include "gigaset.h"
|
||||
|
||||
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
|
||||
|
||||
void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);
|
||||
|
||||
void gigaset_isdn_rcv_err(struct bc_state *bcs)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err);
|
||||
|
||||
int gigaset_isdn_icall(struct at_state_t *at_state)
|
||||
{
|
||||
return ICALL_IGNORE;
|
||||
}
|
||||
|
||||
void gigaset_isdn_connD(struct bc_state *bcs)
|
||||
{
|
||||
}
|
||||
|
||||
void gigaset_isdn_hupD(struct bc_state *bcs)
|
||||
{
|
||||
}
|
||||
|
||||
void gigaset_isdn_connB(struct bc_state *bcs)
|
||||
{
|
||||
}
|
||||
|
||||
void gigaset_isdn_hupB(struct bc_state *bcs)
|
||||
{
|
||||
}
|
||||
|
||||
void gigaset_isdn_start(struct cardstate *cs)
|
||||
{
|
||||
}
|
||||
|
||||
void gigaset_isdn_stop(struct cardstate *cs)
|
||||
{
|
||||
}
|
||||
|
||||
int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
|
||||
{
|
||||
pr_info("no ISDN subsystem interface\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void gigaset_isdn_unregister(struct cardstate *cs)
|
||||
{
|
||||
}
|
|
@ -40,8 +40,8 @@
|
|||
|
||||
/* Possible ASCII responses */
|
||||
#define RSP_OK 0
|
||||
//#define RSP_BUSY 1
|
||||
//#define RSP_CONNECT 2
|
||||
#define RSP_BUSY 1
|
||||
#define RSP_CONNECT 2
|
||||
#define RSP_ZGCI 3
|
||||
#define RSP_RING 4
|
||||
#define RSP_ZAOC 5
|
||||
|
@ -68,7 +68,6 @@
|
|||
#define RSP_ZHLC (RSP_STR + STR_ZHLC)
|
||||
#define RSP_ERROR -1 /* ERROR */
|
||||
#define RSP_WRONG_CID -2 /* unknown cid in cmd */
|
||||
//#define RSP_EMPTY -3
|
||||
#define RSP_UNKNOWN -4 /* unknown response */
|
||||
#define RSP_FAIL -5 /* internal error */
|
||||
#define RSP_INVAL -6 /* invalid response */
|
||||
|
@ -76,9 +75,9 @@
|
|||
#define RSP_NONE -19
|
||||
#define RSP_STRING -20
|
||||
#define RSP_NULL -21
|
||||
//#define RSP_RETRYFAIL -22
|
||||
//#define RSP_RETRY -23
|
||||
//#define RSP_SKIP -24
|
||||
#define RSP_RETRYFAIL -22
|
||||
#define RSP_RETRY -23
|
||||
#define RSP_SKIP -24
|
||||
#define RSP_INIT -27
|
||||
#define RSP_ANY -26
|
||||
#define RSP_LAST -28
|
||||
|
@ -127,7 +126,6 @@
|
|||
#define ACT_NOTIFY_BC_UP 39
|
||||
#define ACT_DIAL 40
|
||||
#define ACT_ACCEPT 41
|
||||
#define ACT_PROTO_L2 42
|
||||
#define ACT_HUP 43
|
||||
#define ACT_IF_LOCK 44
|
||||
#define ACT_START 45
|
||||
|
@ -159,229 +157,229 @@
|
|||
#define SEQ_UMMODE 11
|
||||
|
||||
|
||||
// 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring
|
||||
/* 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid),
|
||||
* 400: hup, 500: reset, 600: dial, 700: ring */
|
||||
struct reply_t gigaset_tab_nocid[] =
|
||||
{
|
||||
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
|
||||
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout,
|
||||
* action, command */
|
||||
|
||||
/* initialize device, set cid mode if possible */
|
||||
//{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}},
|
||||
//{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}},
|
||||
//{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT,
|
||||
// {ACT_TIMEOUT}},
|
||||
/* initialize device, set cid mode if possible */
|
||||
{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
|
||||
|
||||
{RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT,
|
||||
{ACT_TIMEOUT}}, /* wait until device is ready */
|
||||
{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
|
||||
{RSP_OK, 101, 103, -1, 120, 5, {ACT_GETSTRING},
|
||||
"+GMR\r"},
|
||||
|
||||
{EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */
|
||||
{RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */
|
||||
{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||
|
||||
{EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */
|
||||
{RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */
|
||||
{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
|
||||
"^SDLE=0\r"},
|
||||
{RSP_OK, 108, 108, -1, 104, -1},
|
||||
{RSP_ZDLE, 104, 104, 0, 103, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 104, 104, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{RSP_ERROR, 108, 108, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{EV_TIMEOUT, 102,102, -1, 108, 5, {ACT_SETDLE1}, "^SDLE=0\r"}, /* timeout => try again in DLE mode. */
|
||||
{RSP_OK, 108,108, -1, 104,-1},
|
||||
{RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"},
|
||||
{EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
|
||||
ACT_HUPMODEM,
|
||||
ACT_TIMEOUT} },
|
||||
{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
|
||||
|
||||
{EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0,
|
||||
ACT_HUPMODEM,
|
||||
ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
|
||||
{EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"},
|
||||
{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
|
||||
{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
|
||||
{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */
|
||||
{RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}},
|
||||
{RSP_ERROR, 107,107, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{EV_TIMEOUT, 107,107, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{RSP_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||
|
||||
{RSP_ERROR, 103,103, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}},
|
||||
{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
|
||||
|
||||
{RSP_STRING, 120,120, -1, 121,-1, {ACT_SETVER}},
|
||||
{EV_TIMEOUT, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_ERROR, 120, 121, -1, 0, 0, {ACT_FAILVER,
|
||||
ACT_INIT} },
|
||||
{RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER,
|
||||
ACT_INIT} },
|
||||
|
||||
{EV_TIMEOUT, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}},
|
||||
{RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}},
|
||||
{RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}},
|
||||
/* leave dle mode */
|
||||
{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
||||
{RSP_OK, 201, 201, -1, 202, -1},
|
||||
{RSP_ZDLE, 202, 202, 0, 0, 0, {ACT_DLE0} },
|
||||
{RSP_NODEV, 200, 249, -1, 0, 0, {ACT_FAKEDLE0} },
|
||||
{RSP_ERROR, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
{EV_TIMEOUT, 200, 249, -1, 0, 0, {ACT_FAILDLE0} },
|
||||
|
||||
/* leave dle mode */
|
||||
{RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
||||
{RSP_OK, 201,201, -1, 202,-1},
|
||||
{RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}},
|
||||
{RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}},
|
||||
{RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
|
||||
{EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
|
||||
/* enter dle mode */
|
||||
{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
||||
{RSP_OK, 251, 251, -1, 252, -1},
|
||||
{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
|
||||
{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||
|
||||
/* enter dle mode */
|
||||
{RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
||||
{RSP_OK, 251,251, -1, 252,-1},
|
||||
{RSP_ZDLE, 252,252, 1, 0, 0, {ACT_DLE1}},
|
||||
{RSP_ERROR, 250,299, -1, 0, 0, {ACT_FAILDLE1}},
|
||||
{EV_TIMEOUT, 250,299, -1, 0, 0, {ACT_FAILDLE1}},
|
||||
/* incoming call */
|
||||
{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
|
||||
|
||||
/* incoming call */
|
||||
{RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}},
|
||||
/* get cid */
|
||||
{RSP_INIT, 0, 0, SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
|
||||
{RSP_OK, 301, 301, -1, 302, -1},
|
||||
{RSP_ZGCI, 302, 302, -1, 0, 0, {ACT_CID} },
|
||||
{RSP_ERROR, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
{EV_TIMEOUT, 301, 349, -1, 0, 0, {ACT_FAILCID} },
|
||||
|
||||
/* get cid */
|
||||
//{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}},
|
||||
//{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}},
|
||||
//{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"},
|
||||
/* enter cid mode */
|
||||
{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
||||
{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
|
||||
{RSP_ERROR, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
{EV_TIMEOUT, 150, 150, -1, 0, 0, {ACT_FAILCMODE} },
|
||||
|
||||
{RSP_INIT, 0, 0,SEQ_CID, 301, 5, {0}, "^SGCI?\r"},
|
||||
{RSP_OK, 301,301, -1, 302,-1},
|
||||
{RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}},
|
||||
{RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}},
|
||||
{EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}},
|
||||
/* leave cid mode */
|
||||
{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
|
||||
{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||
|
||||
/* enter cid mode */
|
||||
{RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
||||
{RSP_OK, 150,150, -1, 0, 0, {ACT_CMODESET}},
|
||||
{RSP_ERROR, 150,150, -1, 0, 0, {ACT_FAILCMODE}},
|
||||
{EV_TIMEOUT, 150,150, -1, 0, 0, {ACT_FAILCMODE}},
|
||||
/* abort getting cid */
|
||||
{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
|
||||
|
||||
/* leave cid mode */
|
||||
//{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"},
|
||||
{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}},
|
||||
{RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
|
||||
{EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
|
||||
/* reset */
|
||||
{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
|
||||
{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||
{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
|
||||
|
||||
/* abort getting cid */
|
||||
{RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}},
|
||||
{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
|
||||
{EV_IF_LOCK, -1, -1, -1, -1, -1, {ACT_IF_LOCK} },
|
||||
{EV_IF_VER, -1, -1, -1, -1, -1, {ACT_IF_VER} },
|
||||
{EV_START, -1, -1, -1, -1, -1, {ACT_START} },
|
||||
{EV_STOP, -1, -1, -1, -1, -1, {ACT_STOP} },
|
||||
{EV_SHUTDOWN, -1, -1, -1, -1, -1, {ACT_SHUTDOWN} },
|
||||
|
||||
/* reset */
|
||||
{RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
||||
{RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}},
|
||||
{RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
|
||||
{EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
|
||||
{RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}},
|
||||
/* misc. */
|
||||
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
|
||||
{RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZMWI, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZABINFO, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSMLSTCHG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
|
||||
{EV_PROC_CIDMODE,-1, -1, -1, -1,-1, {ACT_PROC_CIDMODE}}, //FIXME
|
||||
{EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME
|
||||
{EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME
|
||||
{EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME
|
||||
{EV_STOP, -1, -1, -1, -1,-1, {ACT_STOP}}, //FIXME
|
||||
{EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME
|
||||
|
||||
/* misc. */
|
||||
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
|
||||
{RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZLOG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZMWI, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZABINFO, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZSMLSTCHG,-1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
|
||||
{RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}},
|
||||
{RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}},
|
||||
{RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}},
|
||||
{RSP_LAST}
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_LAST}
|
||||
};
|
||||
|
||||
// 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring, 400: hup, 750: accepted icall
|
||||
/* 600: start dialing, 650: dial in progress, 800: connection is up, 700: ring,
|
||||
* 400: hup, 750: accepted icall */
|
||||
struct reply_t gigaset_tab_cid[] =
|
||||
{
|
||||
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */
|
||||
/* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout,
|
||||
* action, command */
|
||||
|
||||
/* dial */
|
||||
{EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME
|
||||
{RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}},
|
||||
{RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}},
|
||||
{RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}},
|
||||
{RSP_OK, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}},
|
||||
{RSP_OK, 603,603, -1, 604, 5, {ACT_CMD+AT_TYPE}},
|
||||
{RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}},
|
||||
{RSP_OK, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
|
||||
{RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
|
||||
{RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 607,607, -1, 608,-1},
|
||||
{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}},
|
||||
{RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}},
|
||||
/* dial */
|
||||
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
|
||||
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} },
|
||||
{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} },
|
||||
{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
|
||||
{RSP_OK, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
|
||||
{RSP_OK, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} },
|
||||
{RSP_OK, 604, 604, -1, 605, 5, {ACT_CMD+AT_MSN} },
|
||||
{RSP_NULL, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
|
||||
{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
|
||||
{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} },
|
||||
{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} },
|
||||
{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 608, 608, -1, 609, -1},
|
||||
{RSP_ZSAU, 609, 609, ZSAU_PROCEEDING, 610, 5, {ACT_CMD+AT_DIAL} },
|
||||
{RSP_OK, 610, 610, -1, 650, 0, {ACT_DIALING} },
|
||||
|
||||
{RSP_ERROR, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
|
||||
{EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
|
||||
{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||
|
||||
/* optional dialing responses */
|
||||
{EV_BC_OPEN, 650,650, -1, 651,-1},
|
||||
{RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}},
|
||||
{RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}},
|
||||
{RSP_ZCPN, 609,651, -1, -1,-1, {ACT_DEBUG}},
|
||||
{RSP_ZSAU, 650,651,ZSAU_CALL_DELIVERED, -1,-1, {ACT_DEBUG}},
|
||||
/* optional dialing responses */
|
||||
{EV_BC_OPEN, 650, 650, -1, 651, -1},
|
||||
{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCPN, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
|
||||
|
||||
/* connect */
|
||||
{RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
|
||||
{RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP}},
|
||||
{RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
|
||||
{RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP}},
|
||||
{EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}},
|
||||
/* connect */
|
||||
{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||
{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||
ACT_NOTIFY_BC_UP} },
|
||||
{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
|
||||
|
||||
/* remote hangup */
|
||||
{RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}},
|
||||
{RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
|
||||
{RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
|
||||
/* remote hangup */
|
||||
{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
|
||||
{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||
|
||||
/* hangup */
|
||||
{EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME
|
||||
{RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1?
|
||||
{RSP_OK, 401,401, -1, 402, 5},
|
||||
{RSP_ZVLS, 402,402, 0, 403, 5},
|
||||
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
||||
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
||||
{RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}},
|
||||
{EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}},
|
||||
/* hangup */
|
||||
{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
|
||||
{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
|
||||
{RSP_OK, 401, 401, -1, 402, 5},
|
||||
{RSP_ZVLS, 402, 402, 0, 403, 5},
|
||||
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
||||
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
||||
{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
{EV_TIMEOUT, 401, 403, -1, 0, 0, {ACT_ABORTHUP} },
|
||||
|
||||
{EV_BC_CLOSED, 0, 0, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME new constate + timeout
|
||||
{EV_BC_CLOSED, 0, 0, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/* ring */
|
||||
{RSP_ZBC, 700,700, -1, -1,-1, {0}},
|
||||
{RSP_ZHLC, 700,700, -1, -1,-1, {0}},
|
||||
{RSP_NMBR, 700,700, -1, -1,-1, {0}},
|
||||
{RSP_ZCPN, 700,700, -1, -1,-1, {0}},
|
||||
{RSP_ZCTP, 700,700, -1, -1,-1, {0}},
|
||||
{EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}},
|
||||
{EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}},
|
||||
/* ring */
|
||||
{RSP_ZBC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_NMBR, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
|
||||
{RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
|
||||
{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
|
||||
{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/*accept icall*/
|
||||
{EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME
|
||||
{RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}},
|
||||
{RSP_OK, 721,721, -1, 722, 5, {ACT_CMD+AT_ISO}},
|
||||
{RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */
|
||||
{RSP_OK, 723,723, -1, 724, 5, {0}},
|
||||
{RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}},
|
||||
{RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}},
|
||||
{EV_TIMEOUT, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}},
|
||||
{RSP_ZSAU, 700,729,ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT}},
|
||||
{RSP_ZSAU, 700,729,ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT}},
|
||||
{RSP_ZSAU, 700,729,ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT}},
|
||||
/*accept icall*/
|
||||
{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
|
||||
{RSP_INIT, 720, 720, SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO} },
|
||||
{RSP_OK, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} },
|
||||
{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
|
||||
{RSP_OK, 723, 723, -1, 724, 5, {0} },
|
||||
{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
|
||||
{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{EV_TIMEOUT, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_NULL, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_ACTIVE, 0, 0, {ACT_ABORTACCEPT} },
|
||||
{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
|
||||
|
||||
{EV_BC_OPEN, 750,750, -1, 751,-1},
|
||||
{EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}},
|
||||
{EV_BC_OPEN, 750, 750, -1, 751, -1},
|
||||
{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
|
||||
|
||||
/* B channel closed (general case) */
|
||||
{EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
|
||||
/* B channel closed (general case) */
|
||||
{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||
|
||||
/* misc. */
|
||||
{EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME
|
||||
/* misc. */
|
||||
{RSP_ZCON, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCCR, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZAOC, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ZCSTR, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
|
||||
{RSP_ZCON, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
{RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
||||
|
||||
{RSP_ZCAU, -1, -1, -1, -1,-1, {ACT_ZCAU}},
|
||||
{RSP_NONE, -1, -1, -1, -1,-1, {ACT_DEBUG}},
|
||||
{RSP_ANY, -1, -1, -1, -1,-1, {ACT_WARN}},
|
||||
{RSP_LAST}
|
||||
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||
{RSP_LAST}
|
||||
};
|
||||
|
||||
|
||||
static const struct resp_type_t resp_type[] =
|
||||
static const struct resp_type_t {
|
||||
unsigned char *response;
|
||||
int resp_code;
|
||||
int type;
|
||||
} resp_type[] =
|
||||
{
|
||||
/*{"", RSP_EMPTY, RT_NOTHING},*/
|
||||
{"OK", RSP_OK, RT_NOTHING},
|
||||
{"ERROR", RSP_ERROR, RT_NOTHING},
|
||||
{"ZSAU", RSP_ZSAU, RT_ZSAU},
|
||||
|
@ -405,7 +403,21 @@ static const struct resp_type_t resp_type[] =
|
|||
{"ZLOG", RSP_ZLOG, RT_NOTHING},
|
||||
{"ZABINFO", RSP_ZABINFO, RT_NOTHING},
|
||||
{"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING},
|
||||
{NULL,0,0}
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
static const struct zsau_resp_t {
|
||||
unsigned char *str;
|
||||
int code;
|
||||
} zsau_resp[] =
|
||||
{
|
||||
{"OUTGOING_CALL_PROCEEDING", ZSAU_OUTGOING_CALL_PROCEEDING},
|
||||
{"CALL_DELIVERED", ZSAU_CALL_DELIVERED},
|
||||
{"ACTIVE", ZSAU_ACTIVE},
|
||||
{"DISCONNECT_IND", ZSAU_DISCONNECT_IND},
|
||||
{"NULL", ZSAU_NULL},
|
||||
{"DISCONNECT_REQ", ZSAU_DISCONNECT_REQ},
|
||||
{NULL, ZSAU_UNKNOWN}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -470,7 +482,6 @@ static int cid_of_response(char *s)
|
|||
if (cid < 1 || cid > 65535)
|
||||
return -1; /* CID out of range */
|
||||
return cid;
|
||||
//FIXME is ;<digit>+ at end of non-CID response really impossible?
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -487,6 +498,7 @@ void gigaset_handle_modem_response(struct cardstate *cs)
|
|||
int params;
|
||||
int i, j;
|
||||
const struct resp_type_t *rt;
|
||||
const struct zsau_resp_t *zr;
|
||||
int curarg;
|
||||
unsigned long flags;
|
||||
unsigned next, tail, head;
|
||||
|
@ -613,24 +625,14 @@ void gigaset_handle_modem_response(struct cardstate *cs)
|
|||
event->parameter = ZSAU_NONE;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING"))
|
||||
event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING;
|
||||
else if (!strcmp(argv[curarg], "CALL_DELIVERED"))
|
||||
event->parameter = ZSAU_CALL_DELIVERED;
|
||||
else if (!strcmp(argv[curarg], "ACTIVE"))
|
||||
event->parameter = ZSAU_ACTIVE;
|
||||
else if (!strcmp(argv[curarg], "DISCONNECT_IND"))
|
||||
event->parameter = ZSAU_DISCONNECT_IND;
|
||||
else if (!strcmp(argv[curarg], "NULL"))
|
||||
event->parameter = ZSAU_NULL;
|
||||
else if (!strcmp(argv[curarg], "DISCONNECT_REQ"))
|
||||
event->parameter = ZSAU_DISCONNECT_REQ;
|
||||
else {
|
||||
event->parameter = ZSAU_UNKNOWN;
|
||||
for (zr = zsau_resp; zr->str; ++zr)
|
||||
if (!strcmp(argv[curarg], zr->str))
|
||||
break;
|
||||
event->parameter = zr->code;
|
||||
if (!zr->str)
|
||||
dev_warn(cs->dev,
|
||||
"%s: unknown parameter %s after ZSAU\n",
|
||||
__func__, argv[curarg]);
|
||||
}
|
||||
++curarg;
|
||||
break;
|
||||
case RT_STRING:
|
||||
|
@ -714,7 +716,7 @@ static void disconnect(struct at_state_t **at_state_p)
|
|||
/* notify LL */
|
||||
if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
|
||||
bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL);
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
|
||||
gigaset_isdn_hupD(bcs);
|
||||
}
|
||||
} else {
|
||||
/* no B channel assigned: just deallocate */
|
||||
|
@ -872,12 +874,12 @@ static void bchannel_down(struct bc_state *bcs)
|
|||
{
|
||||
if (bcs->chstate & CHS_B_UP) {
|
||||
bcs->chstate &= ~CHS_B_UP;
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
|
||||
gigaset_isdn_hupB(bcs);
|
||||
}
|
||||
|
||||
if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
|
||||
bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL);
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
|
||||
gigaset_isdn_hupD(bcs);
|
||||
}
|
||||
|
||||
gigaset_free_channel(bcs);
|
||||
|
@ -894,15 +896,17 @@ static void bchannel_up(struct bc_state *bcs)
|
|||
}
|
||||
|
||||
bcs->chstate |= CHS_B_UP;
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
|
||||
gigaset_isdn_connB(bcs);
|
||||
}
|
||||
|
||||
static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index)
|
||||
static void start_dial(struct at_state_t *at_state, void *data,
|
||||
unsigned seq_index)
|
||||
{
|
||||
struct bc_state *bcs = at_state->bcs;
|
||||
struct cardstate *cs = at_state->cs;
|
||||
int retval;
|
||||
char **commands = data;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
bcs->chstate |= CHS_NOTIFY_LL;
|
||||
|
||||
|
@ -913,10 +917,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind
|
|||
}
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
|
||||
retval = gigaset_isdn_setup_dial(at_state, data);
|
||||
if (retval != 0)
|
||||
goto error;
|
||||
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(bcs->commands[i]);
|
||||
bcs->commands[i] = commands[i];
|
||||
}
|
||||
|
||||
at_state->pending_commands |= PC_CID;
|
||||
gig_dbg(DEBUG_CMD, "Scheduling PC_CID");
|
||||
|
@ -924,6 +928,10 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind
|
|||
return;
|
||||
|
||||
error:
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(commands[i]);
|
||||
commands[i] = NULL;
|
||||
}
|
||||
at_state->pending_commands |= PC_NOCID;
|
||||
gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
|
||||
cs->commands_pending = 1;
|
||||
|
@ -933,20 +941,31 @@ error:
|
|||
static void start_accept(struct at_state_t *at_state)
|
||||
{
|
||||
struct cardstate *cs = at_state->cs;
|
||||
int retval;
|
||||
struct bc_state *bcs = at_state->bcs;
|
||||
int i;
|
||||
|
||||
retval = gigaset_isdn_setup_accept(at_state);
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(bcs->commands[i]);
|
||||
bcs->commands[i] = NULL;
|
||||
}
|
||||
|
||||
if (retval == 0) {
|
||||
at_state->pending_commands |= PC_ACCEPT;
|
||||
gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
|
||||
cs->commands_pending = 1;
|
||||
} else {
|
||||
bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
|
||||
bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
|
||||
if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) {
|
||||
dev_err(at_state->cs->dev, "out of memory\n");
|
||||
/* error reset */
|
||||
at_state->pending_commands |= PC_HUP;
|
||||
gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
|
||||
cs->commands_pending = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(bcs->commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2);
|
||||
snprintf(bcs->commands[AT_ISO], 9, "^SISO=%u\r", bcs->channel + 1);
|
||||
|
||||
at_state->pending_commands |= PC_ACCEPT;
|
||||
gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
|
||||
cs->commands_pending = 1;
|
||||
}
|
||||
|
||||
static void do_start(struct cardstate *cs)
|
||||
|
@ -957,9 +976,7 @@ static void do_start(struct cardstate *cs)
|
|||
schedule_init(cs, MS_INIT);
|
||||
|
||||
cs->isdn_up = 1;
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
|
||||
// FIXME: not in locked mode
|
||||
// FIXME 2: only after init sequence
|
||||
gigaset_isdn_start(cs);
|
||||
|
||||
cs->waiting = 0;
|
||||
wake_up(&cs->waitqueue);
|
||||
|
@ -975,7 +992,7 @@ static void finish_shutdown(struct cardstate *cs)
|
|||
/* Tell the LL that the device is not available .. */
|
||||
if (cs->isdn_up) {
|
||||
cs->isdn_up = 0;
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
|
||||
gigaset_isdn_stop(cs);
|
||||
}
|
||||
|
||||
/* The rest is done by cleanup_cs () in user mode. */
|
||||
|
@ -1113,7 +1130,6 @@ static int do_lock(struct cardstate *cs)
|
|||
|
||||
break;
|
||||
case MS_LOCKED:
|
||||
//retval = -EACCES;
|
||||
break;
|
||||
default:
|
||||
return -EBUSY;
|
||||
|
@ -1276,7 +1292,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
break;
|
||||
}
|
||||
bcs->chstate |= CHS_D_UP;
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
|
||||
gigaset_isdn_connD(bcs);
|
||||
cs->ops->init_bchannel(bcs);
|
||||
break;
|
||||
case ACT_DLE1:
|
||||
|
@ -1284,7 +1300,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
bcs = cs->bcs + cs->curchannel;
|
||||
|
||||
bcs->chstate |= CHS_D_UP;
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
|
||||
gigaset_isdn_connD(bcs);
|
||||
cs->ops->init_bchannel(bcs);
|
||||
break;
|
||||
case ACT_FAKEHUP:
|
||||
|
@ -1369,7 +1385,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
cs->cur_at_seq = SEQ_NONE;
|
||||
break;
|
||||
|
||||
case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */
|
||||
case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */
|
||||
disconnect(p_at_state);
|
||||
break;
|
||||
|
||||
|
@ -1443,17 +1459,6 @@ static void do_action(int action, struct cardstate *cs,
|
|||
__func__, at_state->ConState);
|
||||
cs->cur_at_seq = SEQ_NONE;
|
||||
break;
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
case ACT_TEST:
|
||||
{
|
||||
static int count = 3; //2; //1;
|
||||
*p_genresp = 1;
|
||||
*p_resp_code = count ? RSP_ERROR : RSP_OK;
|
||||
if (count > 0)
|
||||
--count;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ACT_DEBUG:
|
||||
gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
|
||||
__func__, ev->type, at_state->ConState);
|
||||
|
@ -1474,11 +1479,6 @@ static void do_action(int action, struct cardstate *cs,
|
|||
case ACT_ACCEPT:
|
||||
start_accept(at_state);
|
||||
break;
|
||||
case ACT_PROTO_L2:
|
||||
gig_dbg(DEBUG_CMD, "set protocol to %u",
|
||||
(unsigned) ev->parameter);
|
||||
at_state->bcs->proto2 = ev->parameter;
|
||||
break;
|
||||
case ACT_HUP:
|
||||
at_state->pending_commands |= PC_HUP;
|
||||
cs->commands_pending = 1;
|
||||
|
@ -1493,7 +1493,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
do_start(cs);
|
||||
break;
|
||||
|
||||
/* events from the interface */ // FIXME without ACT_xxxx?
|
||||
/* events from the interface */
|
||||
case ACT_IF_LOCK:
|
||||
cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
|
||||
cs->waiting = 0;
|
||||
|
@ -1512,7 +1512,7 @@ static void do_action(int action, struct cardstate *cs,
|
|||
wake_up(&cs->waitqueue);
|
||||
break;
|
||||
|
||||
/* events from the proc file system */ // FIXME without ACT_xxxx?
|
||||
/* events from the proc file system */
|
||||
case ACT_PROC_CIDMODE:
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (ev->parameter != cs->cidmode) {
|
||||
|
@ -1649,7 +1649,8 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
for (curact = 0; curact < MAXACT; ++curact) {
|
||||
/* The row tells us what we should do ..
|
||||
*/
|
||||
do_action(rep->action[curact], cs, bcs, &at_state, &p_command, &genresp, &resp_code, ev);
|
||||
do_action(rep->action[curact], cs, bcs, &at_state, &p_command,
|
||||
&genresp, &resp_code, ev);
|
||||
if (!at_state)
|
||||
break; /* may be freed after disconnect */
|
||||
}
|
||||
|
@ -1661,13 +1662,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
|||
|
||||
if (genresp) {
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
at_state->timer_expires = 0; //FIXME
|
||||
at_state->timer_active = 0; //FIXME
|
||||
at_state->timer_expires = 0;
|
||||
at_state->timer_active = 0;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
gigaset_add_event(cs, at_state, resp_code, NULL, 0, NULL);
|
||||
gigaset_add_event(cs, at_state, resp_code,
|
||||
NULL, 0, NULL);
|
||||
} else {
|
||||
/* Send command to modem if not NULL... */
|
||||
if (p_command/*rep->command*/) {
|
||||
if (p_command) {
|
||||
if (cs->connected)
|
||||
send_command(cs, p_command,
|
||||
sendcid, cs->dle,
|
||||
|
@ -1754,7 +1756,8 @@ static void process_command_flags(struct cardstate *cs)
|
|||
}
|
||||
}
|
||||
|
||||
/* only switch back to unimodem mode, if no commands are pending and no channels are up */
|
||||
/* only switch back to unimodem mode if no commands are pending and
|
||||
* no channels are up */
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if (cs->at_state.pending_commands == PC_UMMODE
|
||||
&& !cs->cidmode
|
||||
|
@ -1813,9 +1816,8 @@ static void process_command_flags(struct cardstate *cs)
|
|||
|
||||
if (cs->at_state.pending_commands & PC_INIT) {
|
||||
cs->at_state.pending_commands &= ~PC_INIT;
|
||||
cs->dle = 0; //FIXME
|
||||
cs->dle = 0;
|
||||
cs->inbuf->inputstate = INS_command;
|
||||
//FIXME reset card state (or -> LOCK0)?
|
||||
schedule_sequence(cs, &cs->at_state, SEQ_INIT);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/isdnif.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
@ -35,12 +34,11 @@
|
|||
#include <linux/list.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#define GIG_VERSION {0,5,0,0}
|
||||
#define GIG_COMPAT {0,4,0,0}
|
||||
#define GIG_VERSION {0, 5, 0, 0}
|
||||
#define GIG_COMPAT {0, 4, 0, 0}
|
||||
|
||||
#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
|
||||
#define MAX_RESP_SIZE 512 /* Max. size of a response string */
|
||||
#define HW_HDR_LEN 2 /* Header size used to store ack info */
|
||||
|
||||
#define MAX_EVENTS 64 /* size of event queue */
|
||||
|
||||
|
@ -135,35 +133,32 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
|
||||
#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT)
|
||||
|
||||
/* int-in-events 3070 */
|
||||
/* interrupt pipe messages */
|
||||
#define HD_B1_FLOW_CONTROL 0x80
|
||||
#define HD_B2_FLOW_CONTROL 0x81
|
||||
#define HD_RECEIVEATDATA_ACK (0x35) // 3070
|
||||
// att: HD_RECEIVE>>AT<<DATA_ACK
|
||||
#define HD_READY_SEND_ATDATA (0x36) // 3070
|
||||
#define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070
|
||||
#define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070
|
||||
#define HD_DEVICE_INIT_OK (0x11) // ISurf USB + 3070
|
||||
#define HD_OPEN_B1CHANNEL_ACK (0x51) // ISurf USB + 3070
|
||||
#define HD_OPEN_B2CHANNEL_ACK (0x52) // ISurf USB + 3070
|
||||
#define HD_CLOSE_B1CHANNEL_ACK (0x53) // ISurf USB + 3070
|
||||
#define HD_CLOSE_B2CHANNEL_ACK (0x54) // ISurf USB + 3070
|
||||
// Powermangment
|
||||
#define HD_SUSPEND_END (0x61) // ISurf USB
|
||||
// Configuration
|
||||
#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) // ISurf USB + 3070
|
||||
#define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */
|
||||
#define HD_READY_SEND_ATDATA (0x36) /* 3070 */
|
||||
#define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */
|
||||
#define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */
|
||||
#define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */
|
||||
#define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */
|
||||
#define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */
|
||||
#define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */
|
||||
#define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */
|
||||
#define HD_SUSPEND_END (0x61) /* ISurf USB */
|
||||
#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */
|
||||
|
||||
/* control requests 3070 */
|
||||
#define HD_OPEN_B1CHANNEL (0x23) // ISurf USB + 3070
|
||||
#define HD_CLOSE_B1CHANNEL (0x24) // ISurf USB + 3070
|
||||
#define HD_OPEN_B2CHANNEL (0x25) // ISurf USB + 3070
|
||||
#define HD_CLOSE_B2CHANNEL (0x26) // ISurf USB + 3070
|
||||
#define HD_RESET_INTERRUPT_PIPE (0x27) // ISurf USB + 3070
|
||||
#define HD_DEVICE_INIT_ACK (0x34) // ISurf USB + 3070
|
||||
#define HD_WRITE_ATMESSAGE (0x12) // 3070
|
||||
#define HD_READ_ATMESSAGE (0x13) // 3070
|
||||
#define HD_OPEN_ATCHANNEL (0x28) // 3070
|
||||
#define HD_CLOSE_ATCHANNEL (0x29) // 3070
|
||||
/* control requests */
|
||||
#define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */
|
||||
#define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */
|
||||
#define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */
|
||||
#define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */
|
||||
#define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */
|
||||
#define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */
|
||||
#define HD_WRITE_ATMESSAGE (0x12) /* 3070 */
|
||||
#define HD_READ_ATMESSAGE (0x13) /* 3070 */
|
||||
#define HD_OPEN_ATCHANNEL (0x28) /* 3070 */
|
||||
#define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */
|
||||
|
||||
/* number of B channels supported by base driver */
|
||||
#define BAS_CHANNELS 2
|
||||
|
@ -193,7 +188,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define AT_PROTO 4
|
||||
#define AT_TYPE 5
|
||||
#define AT_HLC 6
|
||||
#define AT_NUM 7
|
||||
#define AT_CLIP 7
|
||||
/* total number */
|
||||
#define AT_NUM 8
|
||||
|
||||
/* variables in struct at_state_t */
|
||||
#define VAR_ZSAU 0
|
||||
|
@ -216,7 +213,6 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define EV_START -110
|
||||
#define EV_STOP -111
|
||||
#define EV_IF_LOCK -112
|
||||
#define EV_PROTO_L2 -113
|
||||
#define EV_ACCEPT -114
|
||||
#define EV_DIAL -115
|
||||
#define EV_HUP -116
|
||||
|
@ -224,12 +220,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define EV_BC_CLOSED -118
|
||||
|
||||
/* input state */
|
||||
#define INS_command 0x0001
|
||||
#define INS_DLE_char 0x0002
|
||||
#define INS_command 0x0001 /* receiving messages (not payload data) */
|
||||
#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */
|
||||
#define INS_byte_stuff 0x0004
|
||||
#define INS_have_data 0x0008
|
||||
#define INS_skip_frame 0x0010
|
||||
#define INS_DLE_command 0x0020
|
||||
#define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */
|
||||
#define INS_flag_hunt 0x0040
|
||||
|
||||
/* channel state */
|
||||
|
@ -259,6 +254,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
|||
#define SM_LOCKED 0
|
||||
#define SM_ISDN 1 /* default */
|
||||
|
||||
/* layer 2 protocols (AT^SBPR=...) */
|
||||
#define L2_BITSYNC 0
|
||||
#define L2_HDLC 1
|
||||
#define L2_VOICE 2
|
||||
|
||||
struct gigaset_ops;
|
||||
struct gigaset_driver;
|
||||
|
||||
|
@ -286,8 +286,6 @@ extern struct reply_t gigaset_tab_cid[];
|
|||
extern struct reply_t gigaset_tab_nocid[];
|
||||
|
||||
struct inbuf_t {
|
||||
unsigned char *rcvbuf; /* usb-gigaset receive buffer */
|
||||
struct bc_state *bcs;
|
||||
struct cardstate *cs;
|
||||
int inputstate;
|
||||
int head, tail;
|
||||
|
@ -359,12 +357,6 @@ struct at_state_t {
|
|||
struct bc_state *bcs;
|
||||
};
|
||||
|
||||
struct resp_type_t {
|
||||
unsigned char *response;
|
||||
int resp_code; /* RSP_XXXX */
|
||||
int type; /* RT_XXXX */
|
||||
};
|
||||
|
||||
struct event_t {
|
||||
int type;
|
||||
void *ptr, *arg;
|
||||
|
@ -395,7 +387,7 @@ struct bc_state {
|
|||
|
||||
unsigned chstate; /* bitmap (CHS_*) */
|
||||
int ignore;
|
||||
unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
|
||||
unsigned proto2; /* layer 2 protocol (L2_*) */
|
||||
char *commands[AT_NUM]; /* see AT_XXXX */
|
||||
|
||||
#ifdef CONFIG_GIGASET_DEBUG
|
||||
|
@ -410,6 +402,8 @@ struct bc_state {
|
|||
struct usb_bc_state *usb; /* usb hardware driver (m105) */
|
||||
struct bas_bc_state *bas; /* usb hardware driver (base) */
|
||||
} hw;
|
||||
|
||||
void *ap; /* LL application structure */
|
||||
};
|
||||
|
||||
struct cardstate {
|
||||
|
@ -456,12 +450,13 @@ struct cardstate {
|
|||
|
||||
unsigned running; /* !=0 if events are handled */
|
||||
unsigned connected; /* !=0 if hardware is connected */
|
||||
unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */
|
||||
unsigned isdn_up; /* !=0 after gigaset_isdn_start() */
|
||||
|
||||
unsigned cidmode;
|
||||
|
||||
int myid; /* id for communication with LL */
|
||||
isdn_if iif;
|
||||
void *iif; /* LL interface structure */
|
||||
unsigned short hw_hdr_len; /* headroom needed in data skbs */
|
||||
|
||||
struct reply_t *tabnocid;
|
||||
struct reply_t *tabcid;
|
||||
|
@ -476,8 +471,8 @@ struct cardstate {
|
|||
|
||||
struct timer_list timer;
|
||||
int retry_count;
|
||||
int dle; /* !=0 if modem commands/responses are
|
||||
dle encoded */
|
||||
int dle; /* !=0 if DLE mode is active
|
||||
(ZDLE=1 received -- M10x only) */
|
||||
int cur_at_seq; /* sequence of AT commands being
|
||||
processed */
|
||||
int curchannel; /* channel those commands are meant
|
||||
|
@ -616,7 +611,9 @@ struct gigaset_ops {
|
|||
int (*baud_rate)(struct cardstate *cs, unsigned cflag);
|
||||
int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag);
|
||||
|
||||
/* Called from i4l.c to put an skb into the send-queue. */
|
||||
/* Called from LL interface to put an skb into the send-queue.
|
||||
* After sending is completed, gigaset_skb_sent() must be called
|
||||
* with the skb's link layer header preserved. */
|
||||
int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb);
|
||||
|
||||
/* Called from ev-layer.c to process a block of data
|
||||
|
@ -625,7 +622,8 @@ struct gigaset_ops {
|
|||
|
||||
};
|
||||
|
||||
/* = Common structures and definitions ======================================= */
|
||||
/* = Common structures and definitions =======================================
|
||||
*/
|
||||
|
||||
/* Parser states for DLE-Event:
|
||||
* <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "."
|
||||
|
@ -638,8 +636,7 @@ struct gigaset_ops {
|
|||
* Functions implemented in asyncdata.c
|
||||
*/
|
||||
|
||||
/* Called from i4l.c to put an skb into the send-queue.
|
||||
* After sending gigaset_skb_sent() should be called. */
|
||||
/* Called from LL interface to put an skb into the send queue. */
|
||||
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
||||
|
||||
/* Called from ev-layer.c to process a block of data
|
||||
|
@ -650,8 +647,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf);
|
|||
* Functions implemented in isocdata.c
|
||||
*/
|
||||
|
||||
/* Called from i4l.c to put an skb into the send-queue.
|
||||
* After sending gigaset_skb_sent() should be called. */
|
||||
/* Called from LL interface to put an skb into the send queue. */
|
||||
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
||||
|
||||
/* Called from ev-layer.c to process a block of data
|
||||
|
@ -674,36 +670,26 @@ void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle);
|
|||
int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size);
|
||||
|
||||
/* ===========================================================================
|
||||
* Functions implemented in i4l.c/gigaset.h
|
||||
* Functions implemented in LL interface
|
||||
*/
|
||||
|
||||
/* Called by gigaset_initcs() for setting up with the isdn4linux subsystem */
|
||||
int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid);
|
||||
/* Called from common.c for setting up/shutting down with the ISDN subsystem */
|
||||
int gigaset_isdn_register(struct cardstate *cs, const char *isdnid);
|
||||
void gigaset_isdn_unregister(struct cardstate *cs);
|
||||
|
||||
/* Called from xxx-gigaset.c to indicate completion of sending an skb */
|
||||
/* Called from hardware module to indicate completion of an skb */
|
||||
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
|
||||
void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb);
|
||||
void gigaset_isdn_rcv_err(struct bc_state *bcs);
|
||||
|
||||
/* Called from common.c/ev-layer.c to indicate events relevant to the LL */
|
||||
void gigaset_isdn_start(struct cardstate *cs);
|
||||
void gigaset_isdn_stop(struct cardstate *cs);
|
||||
int gigaset_isdn_icall(struct at_state_t *at_state);
|
||||
int gigaset_isdn_setup_accept(struct at_state_t *at_state);
|
||||
int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data);
|
||||
|
||||
void gigaset_i4l_cmd(struct cardstate *cs, int cmd);
|
||||
void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd);
|
||||
|
||||
|
||||
static inline void gigaset_isdn_rcv_err(struct bc_state *bcs)
|
||||
{
|
||||
isdn_ctrl response;
|
||||
|
||||
/* error -> LL */
|
||||
gig_dbg(DEBUG_CMD, "sending L1ERR");
|
||||
response.driver = bcs->cs->myid;
|
||||
response.command = ISDN_STAT_L1ERR;
|
||||
response.arg = bcs->channel;
|
||||
response.parm.errcode = ISDN_STAT_L1ERR_RECV;
|
||||
bcs->cs->iif.statcallb(&response);
|
||||
}
|
||||
void gigaset_isdn_connD(struct bc_state *bcs);
|
||||
void gigaset_isdn_hupD(struct bc_state *bcs);
|
||||
void gigaset_isdn_connB(struct bc_state *bcs);
|
||||
void gigaset_isdn_hupB(struct bc_state *bcs);
|
||||
|
||||
/* ===========================================================================
|
||||
* Functions implemented in ev-layer.c
|
||||
|
@ -732,6 +718,7 @@ void gigaset_bcs_reinit(struct bc_state *bcs);
|
|||
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
|
||||
struct cardstate *cs, int cid);
|
||||
int gigaset_get_channel(struct bc_state *bcs);
|
||||
struct bc_state *gigaset_get_free_channel(struct cardstate *cs);
|
||||
void gigaset_free_channel(struct bc_state *bcs);
|
||||
int gigaset_get_channels(struct cardstate *cs);
|
||||
void gigaset_free_channels(struct cardstate *cs);
|
||||
|
@ -781,7 +768,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs,
|
|||
void *ptr, int parameter, void *arg);
|
||||
|
||||
/* Called on CONFIG1 command from frontend. */
|
||||
int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode
|
||||
int gigaset_enterconfigmode(struct cardstate *cs);
|
||||
|
||||
/* cs->lock must not be locked */
|
||||
static inline void gigaset_schedule_event(struct cardstate *cs)
|
||||
|
@ -816,35 +803,6 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs)
|
|||
/* handling routines for sk_buff */
|
||||
/* ============================= */
|
||||
|
||||
/* pass received skb to LL
|
||||
* Warning: skb must not be accessed anymore!
|
||||
*/
|
||||
static inline void gigaset_rcv_skb(struct sk_buff *skb,
|
||||
struct cardstate *cs,
|
||||
struct bc_state *bcs)
|
||||
{
|
||||
cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb);
|
||||
bcs->trans_down++;
|
||||
}
|
||||
|
||||
/* handle reception of corrupted skb
|
||||
* Warning: skb must not be accessed anymore!
|
||||
*/
|
||||
static inline void gigaset_rcv_error(struct sk_buff *procskb,
|
||||
struct cardstate *cs,
|
||||
struct bc_state *bcs)
|
||||
{
|
||||
if (procskb)
|
||||
dev_kfree_skb(procskb);
|
||||
|
||||
if (bcs->ignore)
|
||||
--bcs->ignore;
|
||||
else {
|
||||
++bcs->corrupted;
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
}
|
||||
}
|
||||
|
||||
/* append received bytes to inbuf */
|
||||
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
|
||||
unsigned numbytes);
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
*/
|
||||
|
||||
#include "gigaset.h"
|
||||
#include <linux/isdnif.h>
|
||||
|
||||
#define HW_HDR_LEN 2 /* Header size used to store ack info */
|
||||
|
||||
/* == Handling of I4L IO =====================================================*/
|
||||
|
||||
|
@ -36,12 +39,12 @@
|
|||
static int writebuf_from_LL(int driverID, int channel, int ack,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct cardstate *cs;
|
||||
struct cardstate *cs = gigaset_get_cs_by_id(driverID);
|
||||
struct bc_state *bcs;
|
||||
unsigned char *ack_header;
|
||||
unsigned len;
|
||||
unsigned skblen;
|
||||
|
||||
if (!(cs = gigaset_get_cs_by_id(driverID))) {
|
||||
if (!cs) {
|
||||
pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -75,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
skblen = ack ? len : 0;
|
||||
skb->head[0] = skblen & 0xff;
|
||||
skb->head[1] = skblen >> 8;
|
||||
gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
|
||||
len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
|
||||
/* set up acknowledgement header */
|
||||
if (skb_headroom(skb) < HW_HDR_LEN) {
|
||||
/* should never happen */
|
||||
dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
skb_set_mac_header(skb, -HW_HDR_LEN);
|
||||
skb->mac_len = HW_HDR_LEN;
|
||||
ack_header = skb_mac_header(skb);
|
||||
if (ack) {
|
||||
ack_header[0] = len & 0xff;
|
||||
ack_header[1] = len >> 8;
|
||||
} else {
|
||||
ack_header[0] = ack_header[1] = 0;
|
||||
}
|
||||
gig_dbg(DEBUG_MCMD, "skb: len=%u, ack=%d: %02x %02x",
|
||||
len, ack, ack_header[0], ack_header[1]);
|
||||
|
||||
/* pass to device-specific module */
|
||||
return cs->ops->send_skb(bcs, skb);
|
||||
|
@ -95,6 +110,8 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
|
|||
*/
|
||||
void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
|
||||
{
|
||||
isdn_if *iif = bcs->cs->iif;
|
||||
unsigned char *ack_header = skb_mac_header(skb);
|
||||
unsigned len;
|
||||
isdn_ctrl response;
|
||||
|
||||
|
@ -104,8 +121,7 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
|
|||
dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
|
||||
__func__, skb->len);
|
||||
|
||||
len = (unsigned char) skb->head[0] |
|
||||
(unsigned) (unsigned char) skb->head[1] << 8;
|
||||
len = ack_header[0] + ((unsigned) ack_header[1] << 8);
|
||||
if (len) {
|
||||
gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
|
||||
bcs->cs->myid, bcs->channel, len);
|
||||
|
@ -114,71 +130,177 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb)
|
|||
response.command = ISDN_STAT_BSENT;
|
||||
response.arg = bcs->channel;
|
||||
response.parm.length = len;
|
||||
bcs->cs->iif.statcallb(&response);
|
||||
iif->statcallb(&response);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
|
||||
|
||||
/**
|
||||
* gigaset_skb_rcvd() - pass received skb to LL
|
||||
* @bcs: B channel descriptor structure.
|
||||
* @skb: received data.
|
||||
*
|
||||
* Called by hardware module {bas,ser,usb}_gigaset when user data has
|
||||
* been successfully received, for passing to the LL.
|
||||
* Warning: skb must not be accessed anymore!
|
||||
*/
|
||||
void gigaset_skb_rcvd(struct bc_state *bcs, struct sk_buff *skb)
|
||||
{
|
||||
isdn_if *iif = bcs->cs->iif;
|
||||
|
||||
iif->rcvcallb_skb(bcs->cs->myid, bcs->channel, skb);
|
||||
bcs->trans_down++;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_skb_rcvd);
|
||||
|
||||
/**
|
||||
* gigaset_isdn_rcv_err() - signal receive error
|
||||
* @bcs: B channel descriptor structure.
|
||||
*
|
||||
* Called by hardware module {bas,ser,usb}_gigaset when a receive error
|
||||
* has occurred, for signalling to the LL.
|
||||
*/
|
||||
void gigaset_isdn_rcv_err(struct bc_state *bcs)
|
||||
{
|
||||
isdn_if *iif = bcs->cs->iif;
|
||||
isdn_ctrl response;
|
||||
|
||||
/* if currently ignoring packets, just count down */
|
||||
if (bcs->ignore) {
|
||||
bcs->ignore--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* update statistics */
|
||||
bcs->corrupted++;
|
||||
|
||||
/* error -> LL */
|
||||
gig_dbg(DEBUG_CMD, "sending L1ERR");
|
||||
response.driver = bcs->cs->myid;
|
||||
response.command = ISDN_STAT_L1ERR;
|
||||
response.arg = bcs->channel;
|
||||
response.parm.errcode = ISDN_STAT_L1ERR_RECV;
|
||||
iif->statcallb(&response);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gigaset_isdn_rcv_err);
|
||||
|
||||
/* This function will be called by LL to send commands
|
||||
* NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
|
||||
* so don't put too much effort into it.
|
||||
*/
|
||||
static int command_from_LL(isdn_ctrl *cntrl)
|
||||
{
|
||||
struct cardstate *cs = gigaset_get_cs_by_id(cntrl->driver);
|
||||
struct cardstate *cs;
|
||||
struct bc_state *bcs;
|
||||
int retval = 0;
|
||||
struct setup_parm *sp;
|
||||
char **commands;
|
||||
int ch;
|
||||
int i;
|
||||
size_t l;
|
||||
|
||||
gigaset_debugdrivers();
|
||||
|
||||
if (!cs) {
|
||||
gig_dbg(DEBUG_CMD, "driver: %d, command: %d, arg: 0x%lx",
|
||||
cntrl->driver, cntrl->command, cntrl->arg);
|
||||
|
||||
cs = gigaset_get_cs_by_id(cntrl->driver);
|
||||
if (cs == NULL) {
|
||||
pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
|
||||
return -ENODEV;
|
||||
}
|
||||
ch = cntrl->arg & 0xff;
|
||||
|
||||
switch (cntrl->command) {
|
||||
case ISDN_CMD_IOCTL:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)",
|
||||
cntrl->driver, cntrl->arg);
|
||||
|
||||
dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
|
||||
return -EINVAL;
|
||||
|
||||
case ISDN_CMD_DIAL:
|
||||
gig_dbg(DEBUG_ANY,
|
||||
"ISDN_CMD_DIAL (driver: %d, ch: %ld, "
|
||||
"phone: %s, ownmsn: %s, si1: %d, si2: %d)",
|
||||
cntrl->driver, cntrl->arg,
|
||||
"ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)",
|
||||
cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
|
||||
cntrl->parm.setup.si1, cntrl->parm.setup.si2);
|
||||
|
||||
if (cntrl->arg >= cs->channels) {
|
||||
if (ch >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_DIAL: invalid channel (%d)\n",
|
||||
(int) cntrl->arg);
|
||||
"ISDN_CMD_DIAL: invalid channel (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcs = cs->bcs + cntrl->arg;
|
||||
|
||||
bcs = cs->bcs + ch;
|
||||
if (!gigaset_get_channel(bcs)) {
|
||||
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
sp = kmalloc(sizeof *sp, GFP_ATOMIC);
|
||||
if (!sp) {
|
||||
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
|
||||
if (!commands) {
|
||||
gigaset_free_channel(bcs);
|
||||
dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
*sp = cntrl->parm.setup;
|
||||
|
||||
if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp,
|
||||
l = 3 + strlen(cntrl->parm.setup.phone);
|
||||
commands[AT_DIAL] = kmalloc(l, GFP_ATOMIC);
|
||||
if (!commands[AT_DIAL])
|
||||
goto oom;
|
||||
if (cntrl->parm.setup.phone[0] == '*' &&
|
||||
cntrl->parm.setup.phone[1] == '*') {
|
||||
/* internal call: translate ** prefix to CTP value */
|
||||
commands[AT_TYPE] = kstrdup("^SCTP=0\r", GFP_ATOMIC);
|
||||
if (!commands[AT_TYPE])
|
||||
goto oom;
|
||||
snprintf(commands[AT_DIAL], l,
|
||||
"D%s\r", cntrl->parm.setup.phone+2);
|
||||
} else {
|
||||
commands[AT_TYPE] = kstrdup("^SCTP=1\r", GFP_ATOMIC);
|
||||
if (!commands[AT_TYPE])
|
||||
goto oom;
|
||||
snprintf(commands[AT_DIAL], l,
|
||||
"D%s\r", cntrl->parm.setup.phone);
|
||||
}
|
||||
|
||||
l = strlen(cntrl->parm.setup.eazmsn);
|
||||
if (l) {
|
||||
l += 8;
|
||||
commands[AT_MSN] = kmalloc(l, GFP_ATOMIC);
|
||||
if (!commands[AT_MSN])
|
||||
goto oom;
|
||||
snprintf(commands[AT_MSN], l, "^SMSN=%s\r",
|
||||
cntrl->parm.setup.eazmsn);
|
||||
}
|
||||
|
||||
switch (cntrl->parm.setup.si1) {
|
||||
case 1: /* audio */
|
||||
/* BC = 9090A3: 3.1 kHz audio, A-law */
|
||||
commands[AT_BC] = kstrdup("^SBC=9090A3\r", GFP_ATOMIC);
|
||||
if (!commands[AT_BC])
|
||||
goto oom;
|
||||
break;
|
||||
case 7: /* data */
|
||||
default: /* hope the app knows what it is doing */
|
||||
/* BC = 8890: unrestricted digital information */
|
||||
commands[AT_BC] = kstrdup("^SBC=8890\r", GFP_ATOMIC);
|
||||
if (!commands[AT_BC])
|
||||
goto oom;
|
||||
}
|
||||
/* ToDo: other si1 values, inspect si2, set HLC/LLC */
|
||||
|
||||
commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
|
||||
if (!commands[AT_PROTO])
|
||||
goto oom;
|
||||
snprintf(commands[AT_PROTO], 9, "^SBPR=%u\r", bcs->proto2);
|
||||
|
||||
commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
|
||||
if (!commands[AT_ISO])
|
||||
goto oom;
|
||||
snprintf(commands[AT_ISO], 9, "^SISO=%u\r",
|
||||
(unsigned) bcs->channel + 1);
|
||||
|
||||
if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, commands,
|
||||
bcs->at_state.seq_index, NULL)) {
|
||||
//FIXME what should we do?
|
||||
kfree(sp);
|
||||
for (i = 0; i < AT_NUM; ++i)
|
||||
kfree(commands[i]);
|
||||
kfree(commands);
|
||||
gigaset_free_channel(bcs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -186,115 +308,102 @@ static int command_from_LL(isdn_ctrl *cntrl)
|
|||
gig_dbg(DEBUG_CMD, "scheduling DIAL");
|
||||
gigaset_schedule_event(cs);
|
||||
break;
|
||||
case ISDN_CMD_ACCEPTD: //FIXME
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
|
||||
|
||||
if (cntrl->arg >= cs->channels) {
|
||||
case ISDN_CMD_ACCEPTD:
|
||||
if (ch >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
|
||||
(int) cntrl->arg);
|
||||
"ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
|
||||
EV_ACCEPT, NULL, 0, NULL)) {
|
||||
//FIXME what should we do?
|
||||
bcs = cs->bcs + ch;
|
||||
if (!gigaset_add_event(cs, &bcs->at_state,
|
||||
EV_ACCEPT, NULL, 0, NULL))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
|
||||
gigaset_schedule_event(cs);
|
||||
|
||||
break;
|
||||
case ISDN_CMD_ACCEPTB:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
|
||||
break;
|
||||
case ISDN_CMD_HANGUP:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
|
||||
(int) cntrl->arg);
|
||||
|
||||
if (cntrl->arg >= cs->channels) {
|
||||
if (ch >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_HANGUP: invalid channel (%d)\n",
|
||||
(int) cntrl->arg);
|
||||
"ISDN_CMD_HANGUP: invalid channel (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
|
||||
EV_HUP, NULL, 0, NULL)) {
|
||||
//FIXME what should we do?
|
||||
bcs = cs->bcs + ch;
|
||||
if (!gigaset_add_event(cs, &bcs->at_state,
|
||||
EV_HUP, NULL, 0, NULL))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_CMD, "scheduling HUP");
|
||||
gigaset_schedule_event(cs);
|
||||
|
||||
break;
|
||||
case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
|
||||
case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */
|
||||
dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n");
|
||||
break;
|
||||
case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
|
||||
gig_dbg(DEBUG_ANY,
|
||||
"ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
|
||||
cntrl->driver, cntrl->arg, cntrl->parm.num);
|
||||
case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */
|
||||
dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n",
|
||||
cntrl->parm.num);
|
||||
break;
|
||||
case ISDN_CMD_SETL2: /* Set L2 to given protocol */
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
|
||||
cntrl->arg & 0xff, (cntrl->arg >> 8));
|
||||
|
||||
if ((cntrl->arg & 0xff) >= cs->channels) {
|
||||
if (ch >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_SETL2: invalid channel (%d)\n",
|
||||
(int) cntrl->arg & 0xff);
|
||||
"ISDN_CMD_SETL2: invalid channel (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
|
||||
EV_PROTO_L2, NULL, cntrl->arg >> 8,
|
||||
NULL)) {
|
||||
//FIXME what should we do?
|
||||
return -ENOMEM;
|
||||
bcs = cs->bcs + ch;
|
||||
if (bcs->chstate & CHS_D_UP) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_SETL2: channel active (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
switch (cntrl->arg >> 8) {
|
||||
case ISDN_PROTO_L2_HDLC:
|
||||
gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_HDLC");
|
||||
bcs->proto2 = L2_HDLC;
|
||||
break;
|
||||
case ISDN_PROTO_L2_TRANS:
|
||||
gig_dbg(DEBUG_CMD, "ISDN_CMD_SETL2: setting L2_VOICE");
|
||||
bcs->proto2 = L2_VOICE;
|
||||
break;
|
||||
default:
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_SETL2: unsupported protocol (%lu)\n",
|
||||
cntrl->arg >> 8);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_CMD, "scheduling PROTO_L2");
|
||||
gigaset_schedule_event(cs);
|
||||
break;
|
||||
case ISDN_CMD_SETL3: /* Set L3 to given protocol */
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
|
||||
cntrl->arg & 0xff, (cntrl->arg >> 8));
|
||||
|
||||
if ((cntrl->arg & 0xff) >= cs->channels) {
|
||||
if (ch >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_SETL3: invalid channel (%d)\n",
|
||||
(int) cntrl->arg & 0xff);
|
||||
"ISDN_CMD_SETL3: invalid channel (%d)\n", ch);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_SETL3: invalid protocol %lu\n",
|
||||
"ISDN_CMD_SETL3: unsupported protocol (%lu)\n",
|
||||
cntrl->arg >> 8);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case ISDN_CMD_PROCEED:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED");
|
||||
break;
|
||||
case ISDN_CMD_ALERT:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT");
|
||||
if (cntrl->arg >= cs->channels) {
|
||||
dev_err(cs->dev,
|
||||
"ISDN_CMD_ALERT: invalid channel (%d)\n",
|
||||
(int) cntrl->arg);
|
||||
return -EINVAL;
|
||||
}
|
||||
//bcs = cs->bcs + cntrl->arg;
|
||||
//bcs->proto2 = -1;
|
||||
// FIXME
|
||||
break;
|
||||
case ISDN_CMD_REDIR:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR");
|
||||
break;
|
||||
case ISDN_CMD_PROT_IO:
|
||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO");
|
||||
|
@ -324,149 +433,34 @@ static int command_from_LL(isdn_ctrl *cntrl)
|
|||
}
|
||||
|
||||
return retval;
|
||||
|
||||
oom:
|
||||
dev_err(bcs->cs->dev, "out of memory\n");
|
||||
for (i = 0; i < AT_NUM; ++i)
|
||||
kfree(commands[i]);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
|
||||
static void gigaset_i4l_cmd(struct cardstate *cs, int cmd)
|
||||
{
|
||||
isdn_if *iif = cs->iif;
|
||||
isdn_ctrl command;
|
||||
|
||||
command.driver = cs->myid;
|
||||
command.command = cmd;
|
||||
command.arg = 0;
|
||||
cs->iif.statcallb(&command);
|
||||
iif->statcallb(&command);
|
||||
}
|
||||
|
||||
void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
|
||||
static void gigaset_i4l_channel_cmd(struct bc_state *bcs, int cmd)
|
||||
{
|
||||
isdn_if *iif = bcs->cs->iif;
|
||||
isdn_ctrl command;
|
||||
|
||||
command.driver = bcs->cs->myid;
|
||||
command.command = cmd;
|
||||
command.arg = bcs->channel;
|
||||
bcs->cs->iif.statcallb(&command);
|
||||
}
|
||||
|
||||
int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data)
|
||||
{
|
||||
struct bc_state *bcs = at_state->bcs;
|
||||
unsigned proto;
|
||||
const char *bc;
|
||||
size_t length[AT_NUM];
|
||||
size_t l;
|
||||
int i;
|
||||
struct setup_parm *sp = data;
|
||||
|
||||
switch (bcs->proto2) {
|
||||
case ISDN_PROTO_L2_HDLC:
|
||||
proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
|
||||
break;
|
||||
case ISDN_PROTO_L2_TRANS:
|
||||
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
|
||||
break;
|
||||
default:
|
||||
dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n",
|
||||
__func__, bcs->proto2);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (sp->si1) {
|
||||
case 1: /* audio */
|
||||
bc = "9090A3"; /* 3.1 kHz audio, A-law */
|
||||
break;
|
||||
case 7: /* data */
|
||||
default: /* hope the app knows what it is doing */
|
||||
bc = "8890"; /* unrestricted digital information */
|
||||
}
|
||||
//FIXME add missing si1 values from 1TR6, inspect si2, set HLC/LLC
|
||||
|
||||
length[AT_DIAL ] = 1 + strlen(sp->phone) + 1 + 1;
|
||||
l = strlen(sp->eazmsn);
|
||||
length[AT_MSN ] = l ? 6 + l + 1 + 1 : 0;
|
||||
length[AT_BC ] = 5 + strlen(bc) + 1 + 1;
|
||||
length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
|
||||
length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */
|
||||
length[AT_TYPE ] = 6 + 1 + 1 + 1; /* call type: 1 character */
|
||||
length[AT_HLC ] = 0;
|
||||
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(bcs->commands[i]);
|
||||
bcs->commands[i] = NULL;
|
||||
if (length[i] &&
|
||||
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
|
||||
dev_err(bcs->cs->dev, "out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* type = 1: extern, 0: intern, 2: recall, 3: door, 4: centrex */
|
||||
if (sp->phone[0] == '*' && sp->phone[1] == '*') {
|
||||
/* internal call: translate ** prefix to CTP value */
|
||||
snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
|
||||
"D%s\r", sp->phone+2);
|
||||
strncpy(bcs->commands[AT_TYPE], "^SCTP=0\r", length[AT_TYPE]);
|
||||
} else {
|
||||
snprintf(bcs->commands[AT_DIAL], length[AT_DIAL],
|
||||
"D%s\r", sp->phone);
|
||||
strncpy(bcs->commands[AT_TYPE], "^SCTP=1\r", length[AT_TYPE]);
|
||||
}
|
||||
|
||||
if (bcs->commands[AT_MSN])
|
||||
snprintf(bcs->commands[AT_MSN], length[AT_MSN],
|
||||
"^SMSN=%s\r", sp->eazmsn);
|
||||
snprintf(bcs->commands[AT_BC ], length[AT_BC ],
|
||||
"^SBC=%s\r", bc);
|
||||
snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
|
||||
"^SBPR=%u\r", proto);
|
||||
snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
|
||||
"^SISO=%u\r", (unsigned)bcs->channel + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gigaset_isdn_setup_accept(struct at_state_t *at_state)
|
||||
{
|
||||
unsigned proto;
|
||||
size_t length[AT_NUM];
|
||||
int i;
|
||||
struct bc_state *bcs = at_state->bcs;
|
||||
|
||||
switch (bcs->proto2) {
|
||||
case ISDN_PROTO_L2_HDLC:
|
||||
proto = 1; /* 0: Bitsynchron, 1: HDLC, 2: voice */
|
||||
break;
|
||||
case ISDN_PROTO_L2_TRANS:
|
||||
proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */
|
||||
break;
|
||||
default:
|
||||
dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n",
|
||||
__func__, bcs->proto2);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
length[AT_DIAL ] = 0;
|
||||
length[AT_MSN ] = 0;
|
||||
length[AT_BC ] = 0;
|
||||
length[AT_PROTO] = 6 + 1 + 1 + 1; /* proto: 1 character */
|
||||
length[AT_ISO ] = 6 + 1 + 1 + 1; /* channel: 1 character */
|
||||
length[AT_TYPE ] = 0;
|
||||
length[AT_HLC ] = 0;
|
||||
|
||||
for (i = 0; i < AT_NUM; ++i) {
|
||||
kfree(bcs->commands[i]);
|
||||
bcs->commands[i] = NULL;
|
||||
if (length[i] &&
|
||||
!(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) {
|
||||
dev_err(at_state->cs->dev, "out of memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(bcs->commands[AT_PROTO], length[AT_PROTO],
|
||||
"^SBPR=%u\r", proto);
|
||||
snprintf(bcs->commands[AT_ISO ], length[AT_ISO ],
|
||||
"^SISO=%u\r", (unsigned) bcs->channel + 1);
|
||||
|
||||
return 0;
|
||||
iif->statcallb(&command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -482,13 +476,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
|
|||
{
|
||||
struct cardstate *cs = at_state->cs;
|
||||
struct bc_state *bcs = at_state->bcs;
|
||||
isdn_if *iif = cs->iif;
|
||||
isdn_ctrl response;
|
||||
int retval;
|
||||
|
||||
/* fill ICALL structure */
|
||||
response.parm.setup.si1 = 0; /* default: unknown */
|
||||
response.parm.setup.si2 = 0;
|
||||
response.parm.setup.screen = 0; //FIXME how to set these?
|
||||
response.parm.setup.screen = 0;
|
||||
response.parm.setup.plan = 0;
|
||||
if (!at_state->str_var[STR_ZBC]) {
|
||||
/* no BC (internal call): assume speech, A-law */
|
||||
|
@ -509,29 +504,27 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
|
|||
return ICALL_IGNORE;
|
||||
}
|
||||
if (at_state->str_var[STR_NMBR]) {
|
||||
strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
|
||||
sizeof response.parm.setup.phone - 1);
|
||||
response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0;
|
||||
strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
|
||||
sizeof response.parm.setup.phone);
|
||||
} else
|
||||
response.parm.setup.phone[0] = 0;
|
||||
if (at_state->str_var[STR_ZCPN]) {
|
||||
strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
|
||||
sizeof response.parm.setup.eazmsn - 1);
|
||||
response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0;
|
||||
strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
|
||||
sizeof response.parm.setup.eazmsn);
|
||||
} else
|
||||
response.parm.setup.eazmsn[0] = 0;
|
||||
|
||||
if (!bcs) {
|
||||
dev_notice(cs->dev, "no channel for incoming call\n");
|
||||
response.command = ISDN_STAT_ICALLW;
|
||||
response.arg = 0; //FIXME
|
||||
response.arg = 0;
|
||||
} else {
|
||||
gig_dbg(DEBUG_CMD, "Sending ICALL");
|
||||
response.command = ISDN_STAT_ICALL;
|
||||
response.arg = bcs->channel; //FIXME
|
||||
response.arg = bcs->channel;
|
||||
}
|
||||
response.driver = cs->myid;
|
||||
retval = cs->iif.statcallb(&response);
|
||||
retval = iif->statcallb(&response);
|
||||
gig_dbg(DEBUG_CMD, "Response: %d", retval);
|
||||
switch (retval) {
|
||||
case 0: /* no takers */
|
||||
|
@ -560,16 +553,109 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
|
|||
}
|
||||
}
|
||||
|
||||
/* Set Callback function pointer */
|
||||
int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
|
||||
/**
|
||||
* gigaset_isdn_connD() - signal D channel connect
|
||||
* @bcs: B channel descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the D channel connection has
|
||||
* been established.
|
||||
*/
|
||||
void gigaset_isdn_connD(struct bc_state *bcs)
|
||||
{
|
||||
isdn_if *iif = &cs->iif;
|
||||
gig_dbg(DEBUG_CMD, "sending DCONN");
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
|
||||
}
|
||||
|
||||
gig_dbg(DEBUG_ANY, "Register driver capabilities to LL");
|
||||
/**
|
||||
* gigaset_isdn_hupD() - signal D channel hangup
|
||||
* @bcs: B channel descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the D channel connection has
|
||||
* been shut down.
|
||||
*/
|
||||
void gigaset_isdn_hupD(struct bc_state *bcs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending DHUP");
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_connB() - signal B channel connect
|
||||
* @bcs: B channel descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the B channel connection has
|
||||
* been established.
|
||||
*/
|
||||
void gigaset_isdn_connB(struct bc_state *bcs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending BCONN");
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN);
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_hupB() - signal B channel hangup
|
||||
* @bcs: B channel descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the B channel connection has
|
||||
* been shut down.
|
||||
*/
|
||||
void gigaset_isdn_hupB(struct bc_state *bcs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending BHUP");
|
||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_start() - signal device availability
|
||||
* @cs: device descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the device is available for
|
||||
* use.
|
||||
*/
|
||||
void gigaset_isdn_start(struct cardstate *cs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending RUN");
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_stop() - signal device unavailability
|
||||
* @cs: device descriptor structure.
|
||||
*
|
||||
* Called by main module to notify the LL that the device is no longer
|
||||
* available for use.
|
||||
*/
|
||||
void gigaset_isdn_stop(struct cardstate *cs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending STOP");
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_STOP);
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_register() - register to LL
|
||||
* @cs: device descriptor structure.
|
||||
* @isdnid: device name.
|
||||
*
|
||||
* Called by main module to register the device with the LL.
|
||||
*
|
||||
* Return value: 1 for success, 0 for failure
|
||||
*/
|
||||
int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
|
||||
{
|
||||
isdn_if *iif;
|
||||
|
||||
pr_info("ISDN4Linux interface\n");
|
||||
|
||||
iif = kmalloc(sizeof *iif, GFP_KERNEL);
|
||||
if (!iif) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
|
||||
>= sizeof iif->id) {
|
||||
pr_err("ID too long: %s\n", isdnid);
|
||||
kfree(iif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -593,9 +679,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
|
|||
|
||||
if (!register_isdn(iif)) {
|
||||
pr_err("register_isdn failed\n");
|
||||
kfree(iif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cs->iif = iif;
|
||||
cs->myid = iif->channels; /* Set my device id */
|
||||
cs->hw_hdr_len = HW_HDR_LEN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gigaset_isdn_unregister() - unregister from LL
|
||||
* @cs: device descriptor structure.
|
||||
*
|
||||
* Called by main module to unregister the device from the LL.
|
||||
*/
|
||||
void gigaset_isdn_unregister(struct cardstate *cs)
|
||||
{
|
||||
gig_dbg(DEBUG_CMD, "sending UNLOAD");
|
||||
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
|
||||
kfree(cs->iif);
|
||||
cs->iif = NULL;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
|
|||
return -ENODEV;
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
tty->driver_data = cs;
|
||||
|
||||
++cs->open_count;
|
||||
|
@ -171,7 +171,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
|
|||
spin_lock_irqsave(&cs->lock, flags);
|
||||
cs->tty = tty;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
tty->low_latency = 1; //FIXME test
|
||||
tty->low_latency = 1;
|
||||
}
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
|
@ -228,7 +228,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
|
|||
gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!cs->connected) {
|
||||
gig_dbg(DEBUG_IF, "not connected");
|
||||
|
@ -299,9 +299,8 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file)
|
|||
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
// FIXME read from device?
|
||||
retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
|
@ -326,7 +325,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file,
|
|||
cs->minor_index, __func__, set, clear);
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!cs->connected) {
|
||||
gig_dbg(DEBUG_IF, "not connected");
|
||||
|
@ -356,7 +355,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count)
|
|||
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!cs->connected) {
|
||||
gig_dbg(DEBUG_IF, "not connected");
|
||||
|
@ -390,7 +389,7 @@ static int if_write_room(struct tty_struct *tty)
|
|||
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
if (!cs->connected) {
|
||||
gig_dbg(DEBUG_IF, "not connected");
|
||||
|
@ -455,9 +454,8 @@ static void if_throttle(struct tty_struct *tty)
|
|||
gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
|
||||
else if (!cs->open_count)
|
||||
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
||||
else {
|
||||
//FIXME
|
||||
}
|
||||
else
|
||||
gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__);
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
}
|
||||
|
@ -480,9 +478,8 @@ static void if_unthrottle(struct tty_struct *tty)
|
|||
gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
|
||||
else if (!cs->open_count)
|
||||
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
||||
else {
|
||||
//FIXME
|
||||
}
|
||||
else
|
||||
gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__);
|
||||
|
||||
mutex_unlock(&cs->mutex);
|
||||
}
|
||||
|
@ -515,10 +512,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
|
|||
goto out;
|
||||
}
|
||||
|
||||
// stolen from mct_u232.c
|
||||
iflag = tty->termios->c_iflag;
|
||||
cflag = tty->termios->c_cflag;
|
||||
old_cflag = old ? old->c_cflag : cflag; //FIXME?
|
||||
old_cflag = old ? old->c_cflag : cflag;
|
||||
gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
|
||||
cs->minor_index, iflag, cflag, old_cflag);
|
||||
|
||||
|
@ -588,7 +584,7 @@ void gigaset_if_init(struct cardstate *cs)
|
|||
if (!drv->have_tty)
|
||||
return;
|
||||
|
||||
tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
|
||||
tasklet_init(&cs->if_wake_tasklet, if_wake, (unsigned long) cs);
|
||||
|
||||
mutex_lock(&cs->mutex);
|
||||
cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
|
||||
|
@ -632,7 +628,8 @@ void gigaset_if_receive(struct cardstate *cs,
|
|||
struct tty_struct *tty;
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
if ((tty = cs->tty) == NULL)
|
||||
tty = cs->tty;
|
||||
if (tty == NULL)
|
||||
gig_dbg(DEBUG_ANY, "receive on closed device");
|
||||
else {
|
||||
tty_buffer_request_room(tty, len);
|
||||
|
@ -659,9 +656,9 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
|
|||
|
||||
drv->have_tty = 0;
|
||||
|
||||
if ((drv->tty = alloc_tty_driver(minors)) == NULL)
|
||||
drv->tty = tty = alloc_tty_driver(minors);
|
||||
if (tty == NULL)
|
||||
goto enomem;
|
||||
tty = drv->tty;
|
||||
|
||||
tty->magic = TTY_DRIVER_MAGIC,
|
||||
tty->major = GIG_MAJOR,
|
||||
|
@ -676,8 +673,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
|
|||
|
||||
tty->owner = THIS_MODULE;
|
||||
|
||||
tty->init_termios = tty_std_termios; //FIXME
|
||||
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME
|
||||
tty->init_termios = tty_std_termios;
|
||||
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
tty_set_operations(tty, &if_ops);
|
||||
|
||||
ret = tty_register_driver(tty);
|
||||
|
|
|
@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
|
|||
|
||||
read = iwb->read;
|
||||
write = iwb->write;
|
||||
if ((freebytes = read - write) > 0) {
|
||||
freebytes = read - write;
|
||||
if (freebytes > 0) {
|
||||
/* no wraparound: need padding space within regular area */
|
||||
return freebytes - BAS_OUTBUFPAD;
|
||||
} else if (read < BAS_OUTBUFPAD) {
|
||||
|
@ -53,29 +54,6 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
|
|||
}
|
||||
}
|
||||
|
||||
/* compare two offsets within the buffer
|
||||
* The buffer is seen as circular, with the read position as start
|
||||
* returns -1/0/1 if position a </=/> position b without crossing 'read'
|
||||
*/
|
||||
static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b)
|
||||
{
|
||||
int read;
|
||||
if (a == b)
|
||||
return 0;
|
||||
read = iwb->read;
|
||||
if (a < b) {
|
||||
if (a < read && read <= b)
|
||||
return +1;
|
||||
else
|
||||
return -1;
|
||||
} else {
|
||||
if (b < read && read <= a)
|
||||
return -1;
|
||||
else
|
||||
return +1;
|
||||
}
|
||||
}
|
||||
|
||||
/* start writing
|
||||
* acquire the write semaphore
|
||||
* return true if acquired, false if busy
|
||||
|
@ -271,7 +249,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag,
|
|||
* bit 14..13 = number of bits added by stuffing
|
||||
*/
|
||||
static const u16 stufftab[5 * 256] = {
|
||||
// previous 1s = 0:
|
||||
/* previous 1s = 0: */
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
|
||||
|
@ -289,7 +267,7 @@ static const u16 stufftab[5 * 256] = {
|
|||
0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
|
||||
0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf,
|
||||
|
||||
// previous 1s = 1:
|
||||
/* previous 1s = 1: */
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f,
|
||||
|
@ -307,7 +285,7 @@ static const u16 stufftab[5 * 256] = {
|
|||
0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf,
|
||||
0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef,
|
||||
|
||||
// previous 1s = 2:
|
||||
/* previous 1s = 2: */
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017,
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037,
|
||||
0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057,
|
||||
|
@ -325,7 +303,7 @@ static const u16 stufftab[5 * 256] = {
|
|||
0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7,
|
||||
0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7,
|
||||
|
||||
// previous 1s = 3:
|
||||
/* previous 1s = 3: */
|
||||
0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b,
|
||||
0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b,
|
||||
0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b,
|
||||
|
@ -343,7 +321,7 @@ static const u16 stufftab[5 * 256] = {
|
|||
0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb,
|
||||
0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb,
|
||||
|
||||
// previous 1s = 4:
|
||||
/* previous 1s = 4: */
|
||||
0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d,
|
||||
0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d,
|
||||
0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d,
|
||||
|
@ -367,7 +345,8 @@ static const u16 stufftab[5 * 256] = {
|
|||
* parameters:
|
||||
* cin input byte
|
||||
* ones number of trailing '1' bits in result before this step
|
||||
* iwb pointer to output buffer structure (write semaphore must be held)
|
||||
* iwb pointer to output buffer structure
|
||||
* (write semaphore must be held)
|
||||
* return value:
|
||||
* number of trailing '1' bits in result after this step
|
||||
*/
|
||||
|
@ -408,7 +387,8 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
|
|||
* parameters:
|
||||
* in input buffer
|
||||
* count number of bytes in input buffer
|
||||
* iwb pointer to output buffer structure (write semaphore must be held)
|
||||
* iwb pointer to output buffer structure
|
||||
* (write semaphore must be held)
|
||||
* return value:
|
||||
* position of end of packet in output buffer on success,
|
||||
* -EAGAIN if write semaphore busy or buffer full
|
||||
|
@ -440,7 +420,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
|
|||
fcs = crc_ccitt_byte(fcs, c);
|
||||
}
|
||||
|
||||
/* bitstuff and append FCS (complemented, least significant byte first) */
|
||||
/* bitstuff and append FCS
|
||||
* (complemented, least significant byte first) */
|
||||
fcs ^= 0xffff;
|
||||
ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
|
||||
ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones);
|
||||
|
@ -459,7 +440,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb,
|
|||
* parameters:
|
||||
* in input buffer
|
||||
* count number of bytes in input buffer
|
||||
* iwb pointer to output buffer structure (write semaphore must be held)
|
||||
* iwb pointer to output buffer structure
|
||||
* (write semaphore must be held)
|
||||
* return value:
|
||||
* position of end of packet in output buffer on success,
|
||||
* -EAGAIN if write semaphore busy or buffer full
|
||||
|
@ -500,7 +482,7 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
|
|||
int result;
|
||||
|
||||
switch (bcs->proto2) {
|
||||
case ISDN_PROTO_L2_HDLC:
|
||||
case L2_HDLC:
|
||||
result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
|
||||
gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
|
||||
__func__, len, result);
|
||||
|
@ -542,8 +524,9 @@ static inline void hdlc_flush(struct bc_state *bcs)
|
|||
if (likely(bcs->skb != NULL))
|
||||
skb_trim(bcs->skb, 0);
|
||||
else if (!bcs->ignore) {
|
||||
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
||||
bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
|
||||
if (bcs->skb)
|
||||
skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
|
||||
else
|
||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
||||
}
|
||||
|
@ -557,43 +540,46 @@ static inline void hdlc_flush(struct bc_state *bcs)
|
|||
*/
|
||||
static inline void hdlc_done(struct bc_state *bcs)
|
||||
{
|
||||
struct cardstate *cs = bcs->cs;
|
||||
struct sk_buff *procskb;
|
||||
unsigned int len;
|
||||
|
||||
if (unlikely(bcs->ignore)) {
|
||||
bcs->ignore--;
|
||||
hdlc_flush(bcs);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((procskb = bcs->skb) == NULL) {
|
||||
procskb = bcs->skb;
|
||||
if (procskb == NULL) {
|
||||
/* previous error */
|
||||
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
|
||||
gigaset_rcv_error(NULL, bcs->cs, bcs);
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
} else if (procskb->len < 2) {
|
||||
dev_notice(bcs->cs->dev, "received short frame (%d octets)\n",
|
||||
dev_notice(cs->dev, "received short frame (%d octets)\n",
|
||||
procskb->len);
|
||||
bcs->hw.bas->runts++;
|
||||
gigaset_rcv_error(procskb, bcs->cs, bcs);
|
||||
dev_kfree_skb_any(procskb);
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
} else if (bcs->fcs != PPP_GOODFCS) {
|
||||
dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
|
||||
bcs->fcs);
|
||||
dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
|
||||
bcs->hw.bas->fcserrs++;
|
||||
gigaset_rcv_error(procskb, bcs->cs, bcs);
|
||||
dev_kfree_skb_any(procskb);
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
} else {
|
||||
procskb->len -= 2; /* subtract FCS */
|
||||
procskb->tail -= 2;
|
||||
gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
|
||||
__func__, procskb->len);
|
||||
len = procskb->len;
|
||||
__skb_trim(procskb, len -= 2); /* subtract FCS */
|
||||
gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len);
|
||||
dump_bytes(DEBUG_STREAM_DUMP,
|
||||
"rcv data", procskb->data, procskb->len);
|
||||
bcs->hw.bas->goodbytes += procskb->len;
|
||||
gigaset_rcv_skb(procskb, bcs->cs, bcs);
|
||||
"rcv data", procskb->data, len);
|
||||
bcs->hw.bas->goodbytes += len;
|
||||
gigaset_skb_rcvd(bcs, procskb);
|
||||
}
|
||||
|
||||
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
||||
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||
if (bcs->skb)
|
||||
skb_reserve(bcs->skb, cs->hw_hdr_len);
|
||||
else
|
||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
||||
dev_err(cs->dev, "could not allocate skb\n");
|
||||
bcs->fcs = PPP_INITFCS;
|
||||
}
|
||||
|
||||
|
@ -610,12 +596,8 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
|
|||
|
||||
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
|
||||
bcs->hw.bas->alignerrs++;
|
||||
gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
|
||||
|
||||
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
||||
else
|
||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
||||
gigaset_isdn_rcv_err(bcs);
|
||||
__skb_trim(bcs->skb, 0);
|
||||
bcs->fcs = PPP_INITFCS;
|
||||
}
|
||||
|
||||
|
@ -646,10 +628,10 @@ static const unsigned char bitcounts[256] = {
|
|||
};
|
||||
|
||||
/* hdlc_unpack
|
||||
* perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation)
|
||||
* on a sequence of received data bytes (8 bits each, LSB first)
|
||||
* pass on successfully received, complete frames as SKBs via gigaset_rcv_skb
|
||||
* notify of errors via gigaset_rcv_error
|
||||
* perform HDLC frame processing (bit unstuffing, flag detection, FCS
|
||||
* calculation) on a sequence of received data bytes (8 bits each, LSB first)
|
||||
* pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd
|
||||
* notify of errors via gigaset_isdn_rcv_err
|
||||
* tally frames, errors etc. in BC structure counters
|
||||
* parameters:
|
||||
* src received data
|
||||
|
@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
|
||||
/* load previous state:
|
||||
* inputstate = set of flag bits:
|
||||
* - INS_flag_hunt: no complete opening flag received since connection setup or last abort
|
||||
* - INS_have_data: at least one complete data byte received since last flag
|
||||
* seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7)
|
||||
* - INS_flag_hunt: no complete opening flag received since connection
|
||||
* setup or last abort
|
||||
* - INS_have_data: at least one complete data byte received since last
|
||||
* flag
|
||||
* seqlen = number of consecutive '1' bits in last 7 input stream bits
|
||||
* (0..7)
|
||||
* inbyte = accumulated partial data byte (if !INS_flag_hunt)
|
||||
* inbits = number of valid bits in inbyte, starting at LSB (0..6)
|
||||
*/
|
||||
|
@ -701,9 +686,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
inbyte = c >> (lead1 + 1);
|
||||
inbits = 7 - lead1;
|
||||
if (trail1 >= 8) {
|
||||
/* interior stuffing: omitting the MSB handles most cases */
|
||||
/* interior stuffing:
|
||||
* omitting the MSB handles most cases,
|
||||
* correct the incorrectly handled
|
||||
* cases individually */
|
||||
inbits--;
|
||||
/* correct the incorrectly handled cases individually */
|
||||
switch (c) {
|
||||
case 0xbe:
|
||||
inbyte = 0x3f;
|
||||
|
@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
hdlc_flush(bcs);
|
||||
inputstate |= INS_flag_hunt;
|
||||
} else if (seqlen == 6) {
|
||||
/* closing flag, including (6 - lead1) '1's and one '0' from inbits */
|
||||
/* closing flag, including (6 - lead1) '1's
|
||||
* and one '0' from inbits */
|
||||
if (inbits > 7 - lead1) {
|
||||
hdlc_frag(bcs, inbits + lead1 - 7);
|
||||
inputstate &= ~INS_have_data;
|
||||
} else {
|
||||
if (inbits < 7 - lead1)
|
||||
ubc->stolen0s ++;
|
||||
ubc->stolen0s++;
|
||||
if (inputstate & INS_have_data) {
|
||||
hdlc_done(bcs);
|
||||
inputstate &= ~INS_have_data;
|
||||
|
@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
|
||||
if (c == PPP_FLAG) {
|
||||
/* complete flag, LSB overlaps preceding flag */
|
||||
ubc->shared0s ++;
|
||||
ubc->shared0s++;
|
||||
inbits = 0;
|
||||
inbyte = 0;
|
||||
} else if (trail1 != 7) {
|
||||
|
@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
inbyte = c >> (lead1 + 1);
|
||||
inbits = 7 - lead1;
|
||||
if (trail1 >= 8) {
|
||||
/* interior stuffing: omitting the MSB handles most cases */
|
||||
/* interior stuffing:
|
||||
* omitting the MSB handles most cases,
|
||||
* correct the incorrectly handled
|
||||
* cases individually */
|
||||
inbits--;
|
||||
/* correct the incorrectly handled cases individually */
|
||||
switch (c) {
|
||||
case 0xbe:
|
||||
inbyte = 0x3f;
|
||||
|
@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
}
|
||||
}
|
||||
} else {
|
||||
/* abort sequence follows, skb already empty anyway */
|
||||
/* abort sequence follows,
|
||||
* skb already empty anyway */
|
||||
ubc->aborts++;
|
||||
inputstate |= INS_flag_hunt;
|
||||
}
|
||||
|
@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
} else {
|
||||
/* stuffed data */
|
||||
if (trail1 < 7) { /* => seqlen == 5 */
|
||||
/* stuff bit at position lead1, no interior stuffing */
|
||||
/* stuff bit at position lead1,
|
||||
* no interior stuffing */
|
||||
unsigned char mask = (1 << lead1) - 1;
|
||||
c = (c & mask) | ((c & ~mask) >> 1);
|
||||
inbyte |= c << inbits;
|
||||
inbits += 7;
|
||||
} else if (seqlen < 5) { /* trail1 >= 8 */
|
||||
/* interior stuffing: omitting the MSB handles most cases */
|
||||
/* correct the incorrectly handled cases individually */
|
||||
/* interior stuffing:
|
||||
* omitting the MSB handles most cases,
|
||||
* correct the incorrectly handled
|
||||
* cases individually */
|
||||
switch (c) {
|
||||
case 0xbe:
|
||||
c = 0x7e;
|
||||
|
@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
inbits += 7;
|
||||
} else { /* seqlen == 5 && trail1 >= 8 */
|
||||
|
||||
/* stuff bit at lead1 *and* interior stuffing */
|
||||
switch (c) { /* unstuff individually */
|
||||
/* stuff bit at lead1 *and* interior
|
||||
* stuffing -- unstuff individually */
|
||||
switch (c) {
|
||||
case 0x7d:
|
||||
c = 0x3f;
|
||||
break;
|
||||
|
@ -841,7 +836,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
}
|
||||
|
||||
/* trans_receive
|
||||
* pass on received USB frame transparently as SKB via gigaset_rcv_skb
|
||||
* pass on received USB frame transparently as SKB via gigaset_skb_rcvd
|
||||
* invert bytes
|
||||
* tally frames, errors etc. in BC structure counters
|
||||
* parameters:
|
||||
|
@ -852,6 +847,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
|||
static inline void trans_receive(unsigned char *src, unsigned count,
|
||||
struct bc_state *bcs)
|
||||
{
|
||||
struct cardstate *cs = bcs->cs;
|
||||
struct sk_buff *skb;
|
||||
int dobytes;
|
||||
unsigned char *dst;
|
||||
|
@ -861,13 +857,14 @@ static inline void trans_receive(unsigned char *src, unsigned count,
|
|||
hdlc_flush(bcs);
|
||||
return;
|
||||
}
|
||||
if (unlikely((skb = bcs->skb) == NULL)) {
|
||||
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
|
||||
skb = bcs->skb;
|
||||
if (unlikely(skb == NULL)) {
|
||||
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||
if (!skb) {
|
||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
||||
dev_err(cs->dev, "could not allocate skb\n");
|
||||
return;
|
||||
}
|
||||
skb_reserve(skb, HW_HDR_LEN);
|
||||
skb_reserve(skb, cs->hw_hdr_len);
|
||||
}
|
||||
bcs->hw.bas->goodbytes += skb->len;
|
||||
dobytes = TRANSBUFSIZE - skb->len;
|
||||
|
@ -881,23 +878,24 @@ static inline void trans_receive(unsigned char *src, unsigned count,
|
|||
if (dobytes == 0) {
|
||||
dump_bytes(DEBUG_STREAM_DUMP,
|
||||
"rcv data", skb->data, skb->len);
|
||||
gigaset_rcv_skb(skb, bcs->cs, bcs);
|
||||
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
|
||||
gigaset_skb_rcvd(bcs, skb);
|
||||
bcs->skb = skb =
|
||||
dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||
if (!skb) {
|
||||
dev_err(bcs->cs->dev,
|
||||
"could not allocate skb\n");
|
||||
dev_err(cs->dev, "could not allocate skb\n");
|
||||
return;
|
||||
}
|
||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
||||
skb_reserve(skb, cs->hw_hdr_len);
|
||||
dobytes = TRANSBUFSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs)
|
||||
void gigaset_isoc_receive(unsigned char *src, unsigned count,
|
||||
struct bc_state *bcs)
|
||||
{
|
||||
switch (bcs->proto2) {
|
||||
case ISDN_PROTO_L2_HDLC:
|
||||
case L2_HDLC:
|
||||
hdlc_unpack(src, count, bcs);
|
||||
break;
|
||||
default: /* assume transparent */
|
||||
|
@ -981,8 +979,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
|
|||
* @bcs: B channel descriptor structure.
|
||||
* @skb: data to send.
|
||||
*
|
||||
* Called by i4l.c to queue an skb for sending, and start transmission if
|
||||
* Called by LL to queue an skb for sending, and start transmission if
|
||||
* necessary.
|
||||
* Once the payload data has been transmitted completely, gigaset_skb_sent()
|
||||
* will be called with the skb's link layer header preserved.
|
||||
*
|
||||
* Return value:
|
||||
* number of bytes accepted for sending (skb->len) if ok,
|
||||
|
|
|
@ -39,7 +39,7 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
|
|||
return -EINVAL;
|
||||
|
||||
if (mutex_lock_interruptible(&cs->mutex))
|
||||
return -ERESTARTSYS; // FIXME -EINTR?
|
||||
return -ERESTARTSYS;
|
||||
|
||||
cs->waiting = 1;
|
||||
if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
|
||||
|
|
|
@ -164,9 +164,15 @@ static void gigaset_modem_fill(unsigned long data)
|
|||
{
|
||||
struct cardstate *cs = (struct cardstate *) data;
|
||||
struct bc_state *bcs;
|
||||
struct sk_buff *nextskb;
|
||||
int sent = 0;
|
||||
|
||||
if (!cs || !(bcs = cs->bcs)) {
|
||||
if (!cs) {
|
||||
gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
|
||||
return;
|
||||
}
|
||||
bcs = cs->bcs;
|
||||
if (!bcs) {
|
||||
gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
|
||||
return;
|
||||
}
|
||||
|
@ -179,9 +185,11 @@ static void gigaset_modem_fill(unsigned long data)
|
|||
return;
|
||||
|
||||
/* no command to send; get skb */
|
||||
if (!(bcs->tx_skb = skb_dequeue(&bcs->squeue)))
|
||||
nextskb = skb_dequeue(&bcs->squeue);
|
||||
if (!nextskb)
|
||||
/* no skb either, nothing to do */
|
||||
return;
|
||||
bcs->tx_skb = nextskb;
|
||||
|
||||
gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
|
||||
(unsigned long) bcs->tx_skb);
|
||||
|
@ -236,19 +244,20 @@ static void flush_send_queue(struct cardstate *cs)
|
|||
* number of bytes queued, or error code < 0
|
||||
*/
|
||||
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
|
||||
int len, struct tasklet_struct *wake_tasklet)
|
||||
int len, struct tasklet_struct *wake_tasklet)
|
||||
{
|
||||
struct cmdbuf_t *cb;
|
||||
unsigned long flags;
|
||||
|
||||
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
|
||||
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
|
||||
"CMD Transmit", len, buf);
|
||||
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
|
||||
"CMD Transmit", len, buf);
|
||||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
|
||||
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
|
||||
if (!cb) {
|
||||
dev_err(cs->dev, "%s: out of memory!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -392,7 +401,6 @@ static void gigaset_device_release(struct device *dev)
|
|||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
/* adapted from platform_device_release() in drivers/base/platform.c */
|
||||
//FIXME is this actually necessary?
|
||||
kfree(dev->platform_data);
|
||||
kfree(pdev->resource);
|
||||
}
|
||||
|
@ -404,16 +412,20 @@ static void gigaset_device_release(struct device *dev)
|
|||
static int gigaset_initcshw(struct cardstate *cs)
|
||||
{
|
||||
int rc;
|
||||
struct ser_cardstate *scs;
|
||||
|
||||
if (!(cs->hw.ser = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL))) {
|
||||
scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL);
|
||||
if (!scs) {
|
||||
pr_err("out of memory\n");
|
||||
return 0;
|
||||
}
|
||||
cs->hw.ser = scs;
|
||||
|
||||
cs->hw.ser->dev.name = GIGASET_MODULENAME;
|
||||
cs->hw.ser->dev.id = cs->minor_index;
|
||||
cs->hw.ser->dev.dev.release = gigaset_device_release;
|
||||
if ((rc = platform_device_register(&cs->hw.ser->dev)) != 0) {
|
||||
rc = platform_device_register(&cs->hw.ser->dev);
|
||||
if (rc != 0) {
|
||||
pr_err("error %d registering platform device\n", rc);
|
||||
kfree(cs->hw.ser);
|
||||
cs->hw.ser = NULL;
|
||||
|
@ -422,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
|
||||
|
||||
tasklet_init(&cs->write_tasklet,
|
||||
&gigaset_modem_fill, (unsigned long) cs);
|
||||
gigaset_modem_fill, (unsigned long) cs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -434,7 +446,8 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
* Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
|
||||
* and by "if_lock" and "if_termios" in interface.c
|
||||
*/
|
||||
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsigned new_state)
|
||||
static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
|
||||
unsigned new_state)
|
||||
{
|
||||
struct tty_struct *tty = cs->hw.ser->tty;
|
||||
unsigned int set, clear;
|
||||
|
@ -520,8 +533,8 @@ gigaset_tty_open(struct tty_struct *tty)
|
|||
}
|
||||
|
||||
/* allocate memory for our device state and intialize it */
|
||||
if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode,
|
||||
GIGASET_MODULENAME)))
|
||||
cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
|
||||
if (!cs)
|
||||
goto error;
|
||||
|
||||
cs->dev = &cs->hw.ser->dev.dev;
|
||||
|
@ -690,7 +703,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
|
|||
|
||||
if (!cs)
|
||||
return;
|
||||
if (!(inbuf = cs->inbuf)) {
|
||||
inbuf = cs->inbuf;
|
||||
if (!inbuf) {
|
||||
dev_err(cs->dev, "%s: no inbuf\n", __func__);
|
||||
cs_put(cs);
|
||||
return;
|
||||
|
@ -770,18 +784,21 @@ static int __init ser_gigaset_init(void)
|
|||
int rc;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "%s", __func__);
|
||||
if ((rc = platform_driver_register(&device_driver)) != 0) {
|
||||
rc = platform_driver_register(&device_driver);
|
||||
if (rc != 0) {
|
||||
pr_err("error %d registering platform driver\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* allocate memory for our driver state and intialize it */
|
||||
if (!(driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&ops, THIS_MODULE)))
|
||||
&ops, THIS_MODULE);
|
||||
if (!driver)
|
||||
goto error;
|
||||
|
||||
if ((rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc)) != 0) {
|
||||
rc = tty_register_ldisc(N_GIGASET_M101, &gigaset_ldisc);
|
||||
if (rc != 0) {
|
||||
pr_err("error %d registering line discipline\n", rc);
|
||||
goto error;
|
||||
}
|
||||
|
@ -808,7 +825,8 @@ static void __exit ser_gigaset_exit(void)
|
|||
driver = NULL;
|
||||
}
|
||||
|
||||
if ((rc = tty_unregister_ldisc(N_GIGASET_M101)) != 0)
|
||||
rc = tty_unregister_ldisc(N_GIGASET_M101);
|
||||
if (rc != 0)
|
||||
pr_err("error %d unregistering line discipline\n", rc);
|
||||
|
||||
platform_driver_unregister(&device_driver);
|
||||
|
|
|
@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
|
|||
#define GIGASET_MODULENAME "usb_gigaset"
|
||||
#define GIGASET_DEVNAME "ttyGU"
|
||||
|
||||
#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256
|
||||
#define IF_WRITEBUF 2000 /* arbitrary limit */
|
||||
|
||||
/* Values for the Gigaset M105 Data */
|
||||
#define USB_M105_VENDOR_ID 0x0681
|
||||
#define USB_M105_PRODUCT_ID 0x0009
|
||||
|
||||
/* table of devices that work with this driver */
|
||||
static const struct usb_device_id gigaset_table [] = {
|
||||
static const struct usb_device_id gigaset_table[] = {
|
||||
{ USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
|
|||
* 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13
|
||||
* Used after every "configuration sequence" (RQ 12, RQs 01/03/13).
|
||||
* xx is usually 0x00 but was 0x7e before starting data transfer
|
||||
* in unimodem mode. So, this might be an array of characters that need
|
||||
* special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
|
||||
* in unimodem mode. So, this might be an array of characters that
|
||||
* need special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
|
||||
*
|
||||
* Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two
|
||||
* flags per packet.
|
||||
|
@ -114,7 +114,7 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message);
|
|||
static int gigaset_resume(struct usb_interface *intf);
|
||||
static int gigaset_pre_reset(struct usb_interface *intf);
|
||||
|
||||
static struct gigaset_driver *driver = NULL;
|
||||
static struct gigaset_driver *driver;
|
||||
|
||||
/* usb specific object needed to register this driver with the usb subsystem */
|
||||
static struct usb_driver gigaset_usb_driver = {
|
||||
|
@ -141,6 +141,7 @@ struct usb_cardstate {
|
|||
struct urb *bulk_out_urb;
|
||||
|
||||
/* Input buffer */
|
||||
unsigned char *rcvbuf;
|
||||
int rcvbuf_size;
|
||||
struct urb *read_urb;
|
||||
__u8 int_in_endpointAddr;
|
||||
|
@ -164,13 +165,11 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
|
|||
val = tiocm_to_gigaset(new_state);
|
||||
|
||||
gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
|
||||
// don't use this in an interrupt/BH
|
||||
r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
|
||||
(val & 0xff) | ((mask & 0xff) << 8), 0,
|
||||
NULL, 0, 2000 /* timeout? */);
|
||||
if (r < 0)
|
||||
return r;
|
||||
//..
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
|
|||
cflag &= CBAUD;
|
||||
|
||||
switch (cflag) {
|
||||
//FIXME more values?
|
||||
case B300: rate = 300; break;
|
||||
case B600: rate = 600; break;
|
||||
case B1200: rate = 1200; break;
|
||||
|
@ -273,7 +271,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
|
|||
/* set the number of stop bits */
|
||||
if (cflag & CSTOPB) {
|
||||
if ((cflag & CSIZE) == CS5)
|
||||
val |= 1; /* 1.5 stop bits */ //FIXME is this okay?
|
||||
val |= 1; /* 1.5 stop bits */
|
||||
else
|
||||
val |= 2; /* 2 stop bits */
|
||||
}
|
||||
|
@ -282,7 +280,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag)
|
|||
}
|
||||
|
||||
|
||||
/*================================================================================================================*/
|
||||
/*============================================================================*/
|
||||
static int gigaset_init_bchannel(struct bc_state *bcs)
|
||||
{
|
||||
/* nothing to do for M10x */
|
||||
|
@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data)
|
|||
if (write_modem(cs) < 0) {
|
||||
gig_dbg(DEBUG_OUTPUT,
|
||||
"modem_fill: write_modem failed");
|
||||
// FIXME should we tell the LL?
|
||||
again = 1; /* no callback will be called! */
|
||||
}
|
||||
}
|
||||
|
@ -356,8 +353,8 @@ static void gigaset_modem_fill(unsigned long data)
|
|||
*/
|
||||
static void gigaset_read_int_callback(struct urb *urb)
|
||||
{
|
||||
struct inbuf_t *inbuf = urb->context;
|
||||
struct cardstate *cs = inbuf->cs;
|
||||
struct cardstate *cs = urb->context;
|
||||
struct inbuf_t *inbuf = cs->inbuf;
|
||||
int status = urb->status;
|
||||
int r;
|
||||
unsigned numbytes;
|
||||
|
@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb)
|
|||
numbytes = urb->actual_length;
|
||||
|
||||
if (numbytes) {
|
||||
src = inbuf->rcvbuf;
|
||||
src = cs->hw.usb->rcvbuf;
|
||||
if (unlikely(*src))
|
||||
dev_warn(cs->dev,
|
||||
"%s: There was no leading 0, but 0x%02x!\n",
|
||||
|
@ -440,7 +437,7 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
|
|||
struct cmdbuf_t *tcb;
|
||||
unsigned long flags;
|
||||
int count;
|
||||
int status = -ENOENT; // FIXME
|
||||
int status = -ENOENT;
|
||||
struct usb_cardstate *ucs = cs->hw.usb;
|
||||
|
||||
do {
|
||||
|
@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
|
|||
ucs->busy = 1;
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV;
|
||||
status = cs->connected ?
|
||||
usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) :
|
||||
-ENODEV;
|
||||
spin_unlock_irqrestore(&cs->lock, flags);
|
||||
|
||||
if (status) {
|
||||
|
@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
|
|||
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
|
||||
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
|
||||
if (!cb) {
|
||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -615,7 +614,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
|||
ucs->bulk_out_urb = NULL;
|
||||
ucs->read_urb = NULL;
|
||||
tasklet_init(&cs->write_tasklet,
|
||||
&gigaset_modem_fill, (unsigned long) cs);
|
||||
gigaset_modem_fill, (unsigned long) cs);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Copy data to bulk out buffer and // FIXME copying not necessary
|
||||
* transmit data
|
||||
*/
|
||||
/* Copy data to bulk out buffer and transmit data */
|
||||
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
|
||||
skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
|
||||
skb_pull(bcs->tx_skb, count);
|
||||
|
@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs)
|
|||
if (cs->connected) {
|
||||
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
|
||||
usb_sndbulkpipe(ucs->udev,
|
||||
ucs->bulk_out_endpointAddr & 0x0f),
|
||||
ucs->bulk_out_endpointAddr &
|
||||
0x0f),
|
||||
ucs->bulk_out_buffer, count,
|
||||
gigaset_write_bulk_callback, cs);
|
||||
ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC);
|
||||
|
@ -666,7 +664,7 @@ static int write_modem(struct cardstate *cs)
|
|||
|
||||
if (!bcs->tx_skb->len) {
|
||||
/* skb sent completely */
|
||||
gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0?
|
||||
gigaset_skb_sent(bcs, bcs->tx_skb);
|
||||
|
||||
gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
|
||||
(unsigned long) bcs->tx_skb);
|
||||
|
@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
ucs->rcvbuf_size = buffer_size;
|
||||
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
|
||||
cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!cs->inbuf[0].rcvbuf) {
|
||||
ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
|
||||
if (!ucs->rcvbuf) {
|
||||
dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
|
@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
usb_fill_int_urb(ucs->read_urb, udev,
|
||||
usb_rcvintpipe(udev,
|
||||
endpoint->bEndpointAddress & 0x0f),
|
||||
cs->inbuf[0].rcvbuf, buffer_size,
|
||||
ucs->rcvbuf, buffer_size,
|
||||
gigaset_read_int_callback,
|
||||
cs->inbuf + 0, endpoint->bInterval);
|
||||
cs, endpoint->bInterval);
|
||||
|
||||
retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL);
|
||||
if (retval) {
|
||||
|
@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface,
|
|||
|
||||
if (!gigaset_start(cs)) {
|
||||
tasklet_kill(&cs->write_tasklet);
|
||||
retval = -ENODEV; //FIXME
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
@ -798,11 +796,11 @@ error:
|
|||
usb_kill_urb(ucs->read_urb);
|
||||
kfree(ucs->bulk_out_buffer);
|
||||
usb_free_urb(ucs->bulk_out_urb);
|
||||
kfree(cs->inbuf[0].rcvbuf);
|
||||
kfree(ucs->rcvbuf);
|
||||
usb_free_urb(ucs->read_urb);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
ucs->read_urb = ucs->bulk_out_urb = NULL;
|
||||
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
|
||||
ucs->rcvbuf = ucs->bulk_out_buffer = NULL;
|
||||
usb_put_dev(ucs->udev);
|
||||
ucs->udev = NULL;
|
||||
ucs->interface = NULL;
|
||||
|
@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface)
|
|||
|
||||
kfree(ucs->bulk_out_buffer);
|
||||
usb_free_urb(ucs->bulk_out_urb);
|
||||
kfree(cs->inbuf[0].rcvbuf);
|
||||
kfree(ucs->rcvbuf);
|
||||
usb_free_urb(ucs->read_urb);
|
||||
ucs->read_urb = ucs->bulk_out_urb = NULL;
|
||||
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
|
||||
ucs->rcvbuf = ucs->bulk_out_buffer = NULL;
|
||||
|
||||
usb_put_dev(ucs->udev);
|
||||
ucs->interface = NULL;
|
||||
|
@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void)
|
|||
int result;
|
||||
|
||||
/* allocate memory for our driver state and intialize it */
|
||||
if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&ops, THIS_MODULE)) == NULL)
|
||||
driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS,
|
||||
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||
&ops, THIS_MODULE);
|
||||
if (driver == NULL)
|
||||
goto error;
|
||||
|
||||
/* register this driver with the USB subsystem */
|
||||
|
|
|
@ -110,6 +110,7 @@ set_debug(const char *val, struct kernel_param *kp)
|
|||
MODULE_AUTHOR("Karsten Keil");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION(SPEEDFAX_REV);
|
||||
MODULE_FIRMWARE("isdn/ISAR.BIN");
|
||||
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Speedfax debug mask");
|
||||
module_param(irqloops, uint, S_IRUGO | S_IWUSR);
|
||||
|
|
|
@ -779,7 +779,7 @@ base_sock_create(struct net *net, struct socket *sock, int protocol)
|
|||
}
|
||||
|
||||
static int
|
||||
mISDN_sock_create(struct net *net, struct socket *sock, int proto)
|
||||
mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern)
|
||||
{
|
||||
int err = -EPROTONOSUPPORT;
|
||||
|
||||
|
@ -808,8 +808,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto)
|
|||
return err;
|
||||
}
|
||||
|
||||
static struct
|
||||
net_proto_family mISDN_sock_family_ops = {
|
||||
static const struct net_proto_family mISDN_sock_family_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.family = PF_ISDN,
|
||||
.create = mISDN_sock_create,
|
||||
|
|
|
@ -249,5 +249,6 @@ config EP93XX_PWM
|
|||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
source "drivers/misc/iwmc3200top/Kconfig"
|
||||
|
||||
endif # MISC_DEVICES
|
||||
|
|
|
@ -21,5 +21,6 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
|
|||
obj-$(CONFIG_ISL29003) += isl29003.o
|
||||
obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
|
||||
obj-$(CONFIG_C2PORT) += c2port/
|
||||
obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
|
||||
obj-y += eeprom/
|
||||
obj-y += cb710/
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
config IWMC3200TOP
|
||||
tristate "Intel Wireless MultiCom Top Driver"
|
||||
depends on MMC && EXPERIMENTAL
|
||||
select FW_LOADER
|
||||
---help---
|
||||
Intel Wireless MultiCom 3200 Top driver is responsible for
|
||||
for firmware load and enabled coms enumeration
|
||||
|
||||
config IWMC3200TOP_DEBUG
|
||||
bool "Enable full debug output of iwmc3200top Driver"
|
||||
depends on IWMC3200TOP
|
||||
---help---
|
||||
Enable full debug output of iwmc3200top Driver
|
||||
|
||||
config IWMC3200TOP_DEBUGFS
|
||||
bool "Enable Debugfs debugging interface for iwmc3200top"
|
||||
depends on IWMC3200TOP
|
||||
---help---
|
||||
Enable creation of debugfs files for iwmc3200top
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
# drivers/misc/iwmc3200top/Makefile
|
||||
#
|
||||
# Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version
|
||||
# 2 as published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
#
|
||||
# Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
# -
|
||||
#
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IWMC3200TOP) += iwmc3200top.o
|
||||
iwmc3200top-objs := main.o fw-download.o
|
||||
iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUG) += log.o
|
||||
iwmc3200top-$(CONFIG_IWMC3200TOP_DEBUGFS) += debugfs.o
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/debufs.c
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "iwmc3200top.h"
|
||||
#include "fw-msg.h"
|
||||
#include "log.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
|
||||
|
||||
/* Constants definition */
|
||||
#define HEXADECIMAL_RADIX 16
|
||||
|
||||
/* Functions definition */
|
||||
|
||||
|
||||
#define DEBUGFS_ADD(name, parent) do { \
|
||||
dbgfs->dbgfs_##parent##_files.file_##name = \
|
||||
debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \
|
||||
&iwmct_dbgfs_##name##_ops); \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_RM(name) do { \
|
||||
debugfs_remove(name); \
|
||||
name = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_READ_FUNC(name) \
|
||||
ssize_t iwmct_dbgfs_##name##_read(struct file *file, \
|
||||
char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_WRITE_FUNC(name) \
|
||||
ssize_t iwmct_dbgfs_##name##_write(struct file *file, \
|
||||
const char __user *user_buf, \
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
#define DEBUGFS_READ_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name) \
|
||||
static const struct file_operations iwmct_dbgfs_##name##_ops = { \
|
||||
.read = iwmct_dbgfs_##name##_read, \
|
||||
.open = iwmct_dbgfs_open_file_generic, \
|
||||
};
|
||||
|
||||
#define DEBUGFS_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_WRITE_FUNC(name) \
|
||||
static const struct file_operations iwmct_dbgfs_##name##_ops = { \
|
||||
.write = iwmct_dbgfs_##name##_write, \
|
||||
.open = iwmct_dbgfs_open_file_generic, \
|
||||
};
|
||||
|
||||
#define DEBUGFS_READ_WRITE_FILE_OPS(name) \
|
||||
DEBUGFS_READ_FUNC(name) \
|
||||
DEBUGFS_WRITE_FUNC(name) \
|
||||
static const struct file_operations iwmct_dbgfs_##name##_ops = {\
|
||||
.write = iwmct_dbgfs_##name##_write, \
|
||||
.read = iwmct_dbgfs_##name##_read, \
|
||||
.open = iwmct_dbgfs_open_file_generic, \
|
||||
};
|
||||
|
||||
|
||||
/* Debugfs file ops definitions */
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
|
||||
{
|
||||
struct iwmct_debugfs *dbgfs;
|
||||
|
||||
dbgfs = kzalloc(sizeof(struct iwmct_debugfs), GFP_KERNEL);
|
||||
if (!dbgfs) {
|
||||
LOG_ERROR(priv, DEBUGFS, "failed to allocate %zd bytes\n",
|
||||
sizeof(struct iwmct_debugfs));
|
||||
return;
|
||||
}
|
||||
|
||||
priv->dbgfs = dbgfs;
|
||||
dbgfs->name = name;
|
||||
dbgfs->dir_drv = debugfs_create_dir(name, NULL);
|
||||
if (!dbgfs->dir_drv) {
|
||||
LOG_ERROR(priv, DEBUGFS, "failed to create debugfs dir\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the debugfs files and directories
|
||||
*
|
||||
*/
|
||||
void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
|
||||
{
|
||||
if (!dbgfs)
|
||||
return;
|
||||
|
||||
DEBUGFS_RM(dbgfs->dir_drv);
|
||||
kfree(dbgfs);
|
||||
dbgfs = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/debufs.h
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __DEBUGFS_H__
|
||||
#define __DEBUGFS_H__
|
||||
|
||||
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUGFS
|
||||
|
||||
struct iwmct_debugfs {
|
||||
const char *name;
|
||||
struct dentry *dir_drv;
|
||||
struct dir_drv_files {
|
||||
} dbgfs_drv_files;
|
||||
};
|
||||
|
||||
void iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name);
|
||||
void iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs);
|
||||
|
||||
#else /* CONFIG_IWMC3200TOP_DEBUGFS */
|
||||
|
||||
struct iwmct_debugfs;
|
||||
|
||||
static inline void
|
||||
iwmct_dbgfs_register(struct iwmct_priv *priv, const char *name)
|
||||
{}
|
||||
|
||||
static inline void
|
||||
iwmct_dbgfs_unregister(struct iwmct_debugfs *dbgfs)
|
||||
{}
|
||||
|
||||
#endif /* CONFIG_IWMC3200TOP_DEBUGFS */
|
||||
|
||||
#endif /* __DEBUGFS_H__ */
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/fw-download.c
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "iwmc3200top.h"
|
||||
#include "log.h"
|
||||
#include "fw-msg.h"
|
||||
|
||||
#define CHECKSUM_BYTES_NUM sizeof(u32)
|
||||
|
||||
/**
|
||||
init parser struct with file
|
||||
*/
|
||||
static int iwmct_fw_parser_init(struct iwmct_priv *priv, const u8 *file,
|
||||
size_t file_size, size_t block_size)
|
||||
{
|
||||
struct iwmct_parser *parser = &priv->parser;
|
||||
struct iwmct_fw_hdr *fw_hdr = &parser->versions;
|
||||
|
||||
LOG_INFOEX(priv, INIT, "-->\n");
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "file_size=%zd\n", file_size);
|
||||
|
||||
parser->file = file;
|
||||
parser->file_size = file_size;
|
||||
parser->cur_pos = 0;
|
||||
parser->buf = NULL;
|
||||
|
||||
parser->buf = kzalloc(block_size, GFP_KERNEL);
|
||||
if (!parser->buf) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD, "kzalloc error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
parser->buf_size = block_size;
|
||||
|
||||
/* extract fw versions */
|
||||
memcpy(fw_hdr, parser->file, sizeof(struct iwmct_fw_hdr));
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "fw versions are:\n"
|
||||
"top %u.%u.%u gps %u.%u.%u bt %u.%u.%u tic %s\n",
|
||||
fw_hdr->top_major, fw_hdr->top_minor, fw_hdr->top_revision,
|
||||
fw_hdr->gps_major, fw_hdr->gps_minor, fw_hdr->gps_revision,
|
||||
fw_hdr->bt_major, fw_hdr->bt_minor, fw_hdr->bt_revision,
|
||||
fw_hdr->tic_name);
|
||||
|
||||
parser->cur_pos += sizeof(struct iwmct_fw_hdr);
|
||||
|
||||
LOG_INFOEX(priv, INIT, "<--\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool iwmct_checksum(struct iwmct_priv *priv)
|
||||
{
|
||||
struct iwmct_parser *parser = &priv->parser;
|
||||
__le32 *file = (__le32 *)parser->file;
|
||||
int i, pad, steps;
|
||||
u32 accum = 0;
|
||||
u32 checksum;
|
||||
u32 mask = 0xffffffff;
|
||||
|
||||
pad = (parser->file_size - CHECKSUM_BYTES_NUM) % 4;
|
||||
steps = (parser->file_size - CHECKSUM_BYTES_NUM) / 4;
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "pad=%d steps=%d\n", pad, steps);
|
||||
|
||||
for (i = 0; i < steps; i++)
|
||||
accum += le32_to_cpu(file[i]);
|
||||
|
||||
if (pad) {
|
||||
mask <<= 8 * (4 - pad);
|
||||
accum += le32_to_cpu(file[steps]) & mask;
|
||||
}
|
||||
|
||||
checksum = get_unaligned_le32((__le32 *)(parser->file +
|
||||
parser->file_size - CHECKSUM_BYTES_NUM));
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"compare checksum accum=0x%x to checksum=0x%x\n",
|
||||
accum, checksum);
|
||||
|
||||
return checksum == accum;
|
||||
}
|
||||
|
||||
static int iwmct_parse_next_section(struct iwmct_priv *priv, const u8 **p_sec,
|
||||
size_t *sec_size, __le32 *sec_addr)
|
||||
{
|
||||
struct iwmct_parser *parser = &priv->parser;
|
||||
struct iwmct_dbg *dbg = &priv->dbg;
|
||||
struct iwmct_fw_sec_hdr *sec_hdr;
|
||||
|
||||
LOG_INFOEX(priv, INIT, "-->\n");
|
||||
|
||||
while (parser->cur_pos + sizeof(struct iwmct_fw_sec_hdr)
|
||||
<= parser->file_size) {
|
||||
|
||||
sec_hdr = (struct iwmct_fw_sec_hdr *)
|
||||
(parser->file + parser->cur_pos);
|
||||
parser->cur_pos += sizeof(struct iwmct_fw_sec_hdr);
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"sec hdr: type=%s addr=0x%x size=%d\n",
|
||||
sec_hdr->type, sec_hdr->target_addr,
|
||||
sec_hdr->data_size);
|
||||
|
||||
if (strcmp(sec_hdr->type, "ENT") == 0)
|
||||
parser->entry_point = le32_to_cpu(sec_hdr->target_addr);
|
||||
else if (strcmp(sec_hdr->type, "LBL") == 0)
|
||||
strcpy(dbg->label_fw, parser->file + parser->cur_pos);
|
||||
else if (((strcmp(sec_hdr->type, "TOP") == 0) &&
|
||||
(priv->barker & BARKER_DNLOAD_TOP_MSK)) ||
|
||||
((strcmp(sec_hdr->type, "GPS") == 0) &&
|
||||
(priv->barker & BARKER_DNLOAD_GPS_MSK)) ||
|
||||
((strcmp(sec_hdr->type, "BTH") == 0) &&
|
||||
(priv->barker & BARKER_DNLOAD_BT_MSK))) {
|
||||
*sec_addr = sec_hdr->target_addr;
|
||||
*sec_size = le32_to_cpu(sec_hdr->data_size);
|
||||
*p_sec = parser->file + parser->cur_pos;
|
||||
parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
|
||||
return 1;
|
||||
} else if (strcmp(sec_hdr->type, "LOG") != 0)
|
||||
LOG_WARNING(priv, FW_DOWNLOAD,
|
||||
"skipping section type %s\n",
|
||||
sec_hdr->type);
|
||||
|
||||
parser->cur_pos += le32_to_cpu(sec_hdr->data_size);
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"finished with section cur_pos=%zd\n", parser->cur_pos);
|
||||
}
|
||||
|
||||
LOG_INFOEX(priv, INIT, "<--\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwmct_download_section(struct iwmct_priv *priv, const u8 *p_sec,
|
||||
size_t sec_size, __le32 addr)
|
||||
{
|
||||
struct iwmct_parser *parser = &priv->parser;
|
||||
struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
|
||||
const u8 *cur_block = p_sec;
|
||||
size_t sent = 0;
|
||||
int cnt = 0;
|
||||
int ret = 0;
|
||||
u32 cmd = 0;
|
||||
|
||||
LOG_INFOEX(priv, INIT, "-->\n");
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "Download address 0x%x size 0x%zx\n",
|
||||
addr, sec_size);
|
||||
|
||||
while (sent < sec_size) {
|
||||
int i;
|
||||
u32 chksm = 0;
|
||||
u32 reset = atomic_read(&priv->reset);
|
||||
/* actual FW data */
|
||||
u32 data_size = min(parser->buf_size - sizeof(*hdr),
|
||||
sec_size - sent);
|
||||
/* Pad to block size */
|
||||
u32 trans_size = (data_size + sizeof(*hdr) +
|
||||
IWMC_SDIO_BLK_SIZE - 1) &
|
||||
~(IWMC_SDIO_BLK_SIZE - 1);
|
||||
++cnt;
|
||||
|
||||
/* in case of reset, interrupt FW DOWNLAOD */
|
||||
if (reset) {
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"Reset detected. Abort FW download!!!");
|
||||
ret = -ECANCELED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(parser->buf, 0, parser->buf_size);
|
||||
cmd |= IWMC_OPCODE_WRITE << CMD_HDR_OPCODE_POS;
|
||||
cmd |= IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
|
||||
cmd |= (priv->dbg.direct ? 1 : 0) << CMD_HDR_DIRECT_ACCESS_POS;
|
||||
cmd |= (priv->dbg.checksum ? 1 : 0) << CMD_HDR_USE_CHECKSUM_POS;
|
||||
hdr->data_size = cpu_to_le32(data_size);
|
||||
hdr->target_addr = addr;
|
||||
|
||||
/* checksum is allowed for sizes divisible by 4 */
|
||||
if (data_size & 0x3)
|
||||
cmd &= ~CMD_HDR_USE_CHECKSUM_MSK;
|
||||
|
||||
memcpy(hdr->data, cur_block, data_size);
|
||||
|
||||
|
||||
if (cmd & CMD_HDR_USE_CHECKSUM_MSK) {
|
||||
|
||||
chksm = data_size + le32_to_cpu(addr) + cmd;
|
||||
for (i = 0; i < data_size >> 2; i++)
|
||||
chksm += ((u32 *)cur_block)[i];
|
||||
|
||||
hdr->block_chksm = cpu_to_le32(chksm);
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "Checksum = 0x%X\n",
|
||||
hdr->block_chksm);
|
||||
}
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "trans#%d, len=%d, sent=%zd, "
|
||||
"sec_size=%zd, startAddress 0x%X\n",
|
||||
cnt, trans_size, sent, sec_size, addr);
|
||||
|
||||
if (priv->dbg.dump)
|
||||
LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, trans_size);
|
||||
|
||||
|
||||
hdr->cmd = cpu_to_le32(cmd);
|
||||
/* send it down */
|
||||
/* TODO: add more proper sending and error checking */
|
||||
ret = iwmct_tx(priv, 0, parser->buf, trans_size);
|
||||
if (ret != 0) {
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"iwmct_tx returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
addr = cpu_to_le32(le32_to_cpu(addr) + data_size);
|
||||
sent += data_size;
|
||||
cur_block = p_sec + sent;
|
||||
|
||||
if (priv->dbg.blocks && (cnt + 1) >= priv->dbg.blocks) {
|
||||
LOG_INFO(priv, FW_DOWNLOAD,
|
||||
"Block number limit is reached [%d]\n",
|
||||
priv->dbg.blocks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sent < sec_size)
|
||||
ret = -EINVAL;
|
||||
exit:
|
||||
LOG_INFOEX(priv, INIT, "<--\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwmct_kick_fw(struct iwmct_priv *priv, bool jump)
|
||||
{
|
||||
struct iwmct_parser *parser = &priv->parser;
|
||||
struct iwmct_fw_load_hdr *hdr = (struct iwmct_fw_load_hdr *)parser->buf;
|
||||
int ret;
|
||||
u32 cmd;
|
||||
|
||||
LOG_INFOEX(priv, INIT, "-->\n");
|
||||
|
||||
memset(parser->buf, 0, parser->buf_size);
|
||||
cmd = IWMC_CMD_SIGNATURE << CMD_HDR_SIGNATURE_POS;
|
||||
if (jump) {
|
||||
cmd |= IWMC_OPCODE_JUMP << CMD_HDR_OPCODE_POS;
|
||||
hdr->target_addr = cpu_to_le32(parser->entry_point);
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "jump address 0x%x\n",
|
||||
parser->entry_point);
|
||||
} else {
|
||||
cmd |= IWMC_OPCODE_LAST_COMMAND << CMD_HDR_OPCODE_POS;
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "last command\n");
|
||||
}
|
||||
|
||||
hdr->cmd = cpu_to_le32(cmd);
|
||||
|
||||
LOG_HEXDUMP(FW_DOWNLOAD, parser->buf, sizeof(*hdr));
|
||||
/* send it down */
|
||||
/* TODO: add more proper sending and error checking */
|
||||
ret = iwmct_tx(priv, 0, parser->buf, IWMC_SDIO_BLK_SIZE);
|
||||
if (ret)
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "iwmct_tx returned %d", ret);
|
||||
|
||||
LOG_INFOEX(priv, INIT, "<--\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwmct_fw_load(struct iwmct_priv *priv)
|
||||
{
|
||||
const u8 *fw_name = FW_NAME(FW_API_VER);
|
||||
const struct firmware *raw;
|
||||
const u8 *pdata;
|
||||
size_t len;
|
||||
__le32 addr;
|
||||
int ret;
|
||||
|
||||
/* clear parser struct */
|
||||
memset(&priv->parser, 0, sizeof(struct iwmct_parser));
|
||||
|
||||
/* get the firmware */
|
||||
ret = request_firmware(&raw, fw_name, &priv->func->dev);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD, "%s request_firmware failed %d\n",
|
||||
fw_name, ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (raw->size < sizeof(struct iwmct_fw_sec_hdr)) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD, "%s smaller then (%zd) (%zd)\n",
|
||||
fw_name, sizeof(struct iwmct_fw_sec_hdr), raw->size);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "Read firmware '%s'\n", fw_name);
|
||||
|
||||
ret = iwmct_fw_parser_init(priv, raw->data, raw->size, priv->trans_len);
|
||||
if (ret < 0) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD,
|
||||
"iwmct_parser_init failed: Reason %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* checksum */
|
||||
if (!iwmct_checksum(priv)) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD, "checksum error\n");
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* download firmware to device */
|
||||
while (iwmct_parse_next_section(priv, &pdata, &len, &addr)) {
|
||||
if (iwmct_download_section(priv, pdata, len, addr)) {
|
||||
LOG_ERROR(priv, FW_DOWNLOAD,
|
||||
"%s download section failed\n", fw_name);
|
||||
ret = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
iwmct_kick_fw(priv, !!(priv->barker & BARKER_DNLOAD_JUMP_MSK));
|
||||
|
||||
exit:
|
||||
kfree(priv->parser.buf);
|
||||
|
||||
if (raw)
|
||||
release_firmware(raw);
|
||||
|
||||
raw = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/fw-msg.h
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __FWMSG_H__
|
||||
#define __FWMSG_H__
|
||||
|
||||
#define COMM_TYPE_D2H 0xFF
|
||||
#define COMM_TYPE_H2D 0xEE
|
||||
|
||||
#define COMM_CATEGORY_OPERATIONAL 0x00
|
||||
#define COMM_CATEGORY_DEBUG 0x01
|
||||
#define COMM_CATEGORY_TESTABILITY 0x02
|
||||
#define COMM_CATEGORY_DIAGNOSTICS 0x03
|
||||
|
||||
#define OP_DBG_ZSTR_MSG cpu_to_le16(0x1A)
|
||||
|
||||
#define FW_LOG_SRC_MAX 32
|
||||
#define FW_LOG_SRC_ALL 255
|
||||
|
||||
#define FW_STRING_TABLE_ADDR cpu_to_le32(0x0C000000)
|
||||
|
||||
#define CMD_DBG_LOG_LEVEL cpu_to_le16(0x0001)
|
||||
#define CMD_TST_DEV_RESET cpu_to_le16(0x0060)
|
||||
#define CMD_TST_FUNC_RESET cpu_to_le16(0x0062)
|
||||
#define CMD_TST_IFACE_RESET cpu_to_le16(0x0064)
|
||||
#define CMD_TST_CPU_UTILIZATION cpu_to_le16(0x0065)
|
||||
#define CMD_TST_TOP_DEEP_SLEEP cpu_to_le16(0x0080)
|
||||
#define CMD_TST_WAKEUP cpu_to_le16(0x0081)
|
||||
#define CMD_TST_FUNC_WAKEUP cpu_to_le16(0x0082)
|
||||
#define CMD_TST_FUNC_DEEP_SLEEP_REQUEST cpu_to_le16(0x0083)
|
||||
#define CMD_TST_GET_MEM_DUMP cpu_to_le16(0x0096)
|
||||
|
||||
#define OP_OPR_ALIVE cpu_to_le16(0x0010)
|
||||
#define OP_OPR_CMD_ACK cpu_to_le16(0x001F)
|
||||
#define OP_OPR_CMD_NACK cpu_to_le16(0x0020)
|
||||
#define OP_TST_MEM_DUMP cpu_to_le16(0x0043)
|
||||
|
||||
#define CMD_FLAG_PADDING_256 0x80
|
||||
|
||||
#define FW_HCMD_BLOCK_SIZE 256
|
||||
|
||||
struct msg_hdr {
|
||||
u8 type;
|
||||
u8 category;
|
||||
__le16 opcode;
|
||||
u8 seqnum;
|
||||
u8 flags;
|
||||
__le16 length;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct log_hdr {
|
||||
__le32 timestamp;
|
||||
u8 severity;
|
||||
u8 logsource;
|
||||
__le16 reserved;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct mdump_hdr {
|
||||
u8 dmpid;
|
||||
u8 frag;
|
||||
__le16 size;
|
||||
__le32 addr;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct top_msg {
|
||||
struct msg_hdr hdr;
|
||||
union {
|
||||
/* D2H messages */
|
||||
struct {
|
||||
struct log_hdr log_hdr;
|
||||
u8 data[1];
|
||||
} __attribute__((__packed__)) log;
|
||||
|
||||
struct {
|
||||
struct log_hdr log_hdr;
|
||||
struct mdump_hdr md_hdr;
|
||||
u8 data[1];
|
||||
} __attribute__((__packed__)) mdump;
|
||||
|
||||
/* H2D messages */
|
||||
struct {
|
||||
u8 logsource;
|
||||
u8 sevmask;
|
||||
} __attribute__((__packed__)) logdefs[FW_LOG_SRC_MAX];
|
||||
struct mdump_hdr mdump_req;
|
||||
} u;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
|
||||
#endif /* __FWMSG_H__ */
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/iwmc3200top.h
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __IWMC3200TOP_H__
|
||||
#define __IWMC3200TOP_H__
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define DRV_NAME "iwmc3200top"
|
||||
#define FW_API_VER 1
|
||||
#define _FW_NAME(api) DRV_NAME "." #api ".fw"
|
||||
#define FW_NAME(api) _FW_NAME(api)
|
||||
|
||||
#define IWMC_SDIO_BLK_SIZE 256
|
||||
#define IWMC_DEFAULT_TR_BLK 64
|
||||
#define IWMC_SDIO_DATA_ADDR 0x0
|
||||
#define IWMC_SDIO_INTR_ENABLE_ADDR 0x14
|
||||
#define IWMC_SDIO_INTR_STATUS_ADDR 0x13
|
||||
#define IWMC_SDIO_INTR_CLEAR_ADDR 0x13
|
||||
#define IWMC_SDIO_INTR_GET_SIZE_ADDR 0x2C
|
||||
|
||||
#define COMM_HUB_HEADER_LENGTH 16
|
||||
#define LOGGER_HEADER_LENGTH 10
|
||||
|
||||
|
||||
#define BARKER_DNLOAD_BT_POS 0
|
||||
#define BARKER_DNLOAD_BT_MSK BIT(BARKER_DNLOAD_BT_POS)
|
||||
#define BARKER_DNLOAD_GPS_POS 1
|
||||
#define BARKER_DNLOAD_GPS_MSK BIT(BARKER_DNLOAD_GPS_POS)
|
||||
#define BARKER_DNLOAD_TOP_POS 2
|
||||
#define BARKER_DNLOAD_TOP_MSK BIT(BARKER_DNLOAD_TOP_POS)
|
||||
#define BARKER_DNLOAD_RESERVED1_POS 3
|
||||
#define BARKER_DNLOAD_RESERVED1_MSK BIT(BARKER_DNLOAD_RESERVED1_POS)
|
||||
#define BARKER_DNLOAD_JUMP_POS 4
|
||||
#define BARKER_DNLOAD_JUMP_MSK BIT(BARKER_DNLOAD_JUMP_POS)
|
||||
#define BARKER_DNLOAD_SYNC_POS 5
|
||||
#define BARKER_DNLOAD_SYNC_MSK BIT(BARKER_DNLOAD_SYNC_POS)
|
||||
#define BARKER_DNLOAD_RESERVED2_POS 6
|
||||
#define BARKER_DNLOAD_RESERVED2_MSK (0x3 << BARKER_DNLOAD_RESERVED2_POS)
|
||||
#define BARKER_DNLOAD_BARKER_POS 8
|
||||
#define BARKER_DNLOAD_BARKER_MSK (0xffffff << BARKER_DNLOAD_BARKER_POS)
|
||||
|
||||
#define IWMC_BARKER_REBOOT (0xdeadbe << BARKER_DNLOAD_BARKER_POS)
|
||||
/* whole field barker */
|
||||
#define IWMC_BARKER_ACK 0xfeedbabe
|
||||
|
||||
#define IWMC_CMD_SIGNATURE 0xcbbc
|
||||
|
||||
#define CMD_HDR_OPCODE_POS 0
|
||||
#define CMD_HDR_OPCODE_MSK_MSK (0xf << CMD_HDR_OPCODE_MSK_POS)
|
||||
#define CMD_HDR_RESPONSE_CODE_POS 4
|
||||
#define CMD_HDR_RESPONSE_CODE_MSK (0xf << CMD_HDR_RESPONSE_CODE_POS)
|
||||
#define CMD_HDR_USE_CHECKSUM_POS 8
|
||||
#define CMD_HDR_USE_CHECKSUM_MSK BIT(CMD_HDR_USE_CHECKSUM_POS)
|
||||
#define CMD_HDR_RESPONSE_REQUIRED_POS 9
|
||||
#define CMD_HDR_RESPONSE_REQUIRED_MSK BIT(CMD_HDR_RESPONSE_REQUIRED_POS)
|
||||
#define CMD_HDR_DIRECT_ACCESS_POS 10
|
||||
#define CMD_HDR_DIRECT_ACCESS_MSK BIT(CMD_HDR_DIRECT_ACCESS_POS)
|
||||
#define CMD_HDR_RESERVED_POS 11
|
||||
#define CMD_HDR_RESERVED_MSK BIT(0x1f << CMD_HDR_RESERVED_POS)
|
||||
#define CMD_HDR_SIGNATURE_POS 16
|
||||
#define CMD_HDR_SIGNATURE_MSK BIT(0xffff << CMD_HDR_SIGNATURE_POS)
|
||||
|
||||
enum {
|
||||
IWMC_OPCODE_PING = 0,
|
||||
IWMC_OPCODE_READ = 1,
|
||||
IWMC_OPCODE_WRITE = 2,
|
||||
IWMC_OPCODE_JUMP = 3,
|
||||
IWMC_OPCODE_REBOOT = 4,
|
||||
IWMC_OPCODE_PERSISTENT_WRITE = 5,
|
||||
IWMC_OPCODE_PERSISTENT_READ = 6,
|
||||
IWMC_OPCODE_READ_MODIFY_WRITE = 7,
|
||||
IWMC_OPCODE_LAST_COMMAND = 15
|
||||
};
|
||||
|
||||
struct iwmct_fw_load_hdr {
|
||||
__le32 cmd;
|
||||
__le32 target_addr;
|
||||
__le32 data_size;
|
||||
__le32 block_chksm;
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwmct_fw_hdr
|
||||
* holds all sw components versions
|
||||
*/
|
||||
struct iwmct_fw_hdr {
|
||||
u8 top_major;
|
||||
u8 top_minor;
|
||||
u8 top_revision;
|
||||
u8 gps_major;
|
||||
u8 gps_minor;
|
||||
u8 gps_revision;
|
||||
u8 bt_major;
|
||||
u8 bt_minor;
|
||||
u8 bt_revision;
|
||||
u8 tic_name[31];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwmct_fw_sec_hdr
|
||||
* @type: function type
|
||||
* @data_size: section's data size
|
||||
* @target_addr: download address
|
||||
*/
|
||||
struct iwmct_fw_sec_hdr {
|
||||
u8 type[4];
|
||||
__le32 data_size;
|
||||
__le32 target_addr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwmct_parser
|
||||
* @file: fw image
|
||||
* @file_size: fw size
|
||||
* @cur_pos: position in file
|
||||
* @buf: temp buf for download
|
||||
* @buf_size: size of buf
|
||||
* @entry_point: address to jump in fw kick-off
|
||||
*/
|
||||
struct iwmct_parser {
|
||||
const u8 *file;
|
||||
size_t file_size;
|
||||
size_t cur_pos;
|
||||
u8 *buf;
|
||||
size_t buf_size;
|
||||
u32 entry_point;
|
||||
struct iwmct_fw_hdr versions;
|
||||
};
|
||||
|
||||
|
||||
struct iwmct_work_struct {
|
||||
struct list_head list;
|
||||
ssize_t iosize;
|
||||
};
|
||||
|
||||
struct iwmct_dbg {
|
||||
int blocks;
|
||||
bool dump;
|
||||
bool jump;
|
||||
bool direct;
|
||||
bool checksum;
|
||||
bool fw_download;
|
||||
int block_size;
|
||||
int download_trans_blks;
|
||||
|
||||
char label_fw[256];
|
||||
};
|
||||
|
||||
struct iwmct_debugfs;
|
||||
|
||||
struct iwmct_priv {
|
||||
struct sdio_func *func;
|
||||
struct iwmct_debugfs *dbgfs;
|
||||
struct iwmct_parser parser;
|
||||
atomic_t reset;
|
||||
atomic_t dev_sync;
|
||||
u32 trans_len;
|
||||
u32 barker;
|
||||
struct iwmct_dbg dbg;
|
||||
|
||||
/* drivers work queue */
|
||||
struct workqueue_struct *wq;
|
||||
struct workqueue_struct *bus_rescan_wq;
|
||||
struct work_struct bus_rescan_worker;
|
||||
struct work_struct isr_worker;
|
||||
|
||||
/* drivers wait queue */
|
||||
wait_queue_head_t wait_q;
|
||||
|
||||
/* rx request list */
|
||||
struct list_head read_req_list;
|
||||
};
|
||||
|
||||
extern int iwmct_tx(struct iwmct_priv *priv, unsigned int addr,
|
||||
void *src, int count);
|
||||
|
||||
extern int iwmct_fw_load(struct iwmct_priv *priv);
|
||||
|
||||
extern void iwmct_dbg_init_params(struct iwmct_priv *drv);
|
||||
extern void iwmct_dbg_init_drv_attrs(struct device_driver *drv);
|
||||
extern void iwmct_dbg_remove_drv_attrs(struct device_driver *drv);
|
||||
extern int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len);
|
||||
|
||||
#endif /* __IWMC3200TOP_H__ */
|
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/log.c
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "fw-msg.h"
|
||||
#include "iwmc3200top.h"
|
||||
#include "log.h"
|
||||
|
||||
/* Maximal hexadecimal string size of the FW memdump message */
|
||||
#define LOG_MSG_SIZE_MAX 12400
|
||||
|
||||
/* iwmct_logdefs is a global used by log macros */
|
||||
u8 iwmct_logdefs[LOG_SRC_MAX];
|
||||
static u8 iwmct_fw_logdefs[FW_LOG_SRC_MAX];
|
||||
|
||||
|
||||
static int _log_set_log_filter(u8 *logdefs, int size, u8 src, u8 logmask)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (src < size)
|
||||
logdefs[src] = logmask;
|
||||
else if (src == LOG_SRC_ALL)
|
||||
for (i = 0; i < size; i++)
|
||||
logdefs[i] = logmask;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int iwmct_log_set_filter(u8 src, u8 logmask)
|
||||
{
|
||||
return _log_set_log_filter(iwmct_logdefs, LOG_SRC_MAX, src, logmask);
|
||||
}
|
||||
|
||||
|
||||
int iwmct_log_set_fw_filter(u8 src, u8 logmask)
|
||||
{
|
||||
return _log_set_log_filter(iwmct_fw_logdefs,
|
||||
FW_LOG_SRC_MAX, src, logmask);
|
||||
}
|
||||
|
||||
|
||||
static int log_msg_format_hex(char *str, int slen, u8 *ibuf,
|
||||
int ilen, char *pref)
|
||||
{
|
||||
int pos = 0;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
for (pos = 0, i = 0; pos < slen - 2 && pref[i] != '\0'; i++, pos++)
|
||||
str[pos] = pref[i];
|
||||
|
||||
for (i = 0; pos < slen - 2 && i < ilen; pos += len, i++)
|
||||
len = snprintf(&str[pos], slen - pos - 1, " %2.2X", ibuf[i]);
|
||||
|
||||
if (i < ilen)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NOTE: This function is not thread safe.
|
||||
Currently it's called only from sdio rx worker - no race there
|
||||
*/
|
||||
void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len)
|
||||
{
|
||||
struct top_msg *msg;
|
||||
static char logbuf[LOG_MSG_SIZE_MAX];
|
||||
|
||||
msg = (struct top_msg *)buf;
|
||||
|
||||
if (len < sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr)) {
|
||||
LOG_ERROR(priv, FW_MSG, "Log message from TOP "
|
||||
"is too short %d (expected %zd)\n",
|
||||
len, sizeof(msg->hdr) + sizeof(msg->u.log.log_hdr));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(iwmct_fw_logdefs[msg->u.log.log_hdr.logsource] &
|
||||
BIT(msg->u.log.log_hdr.severity)) ||
|
||||
!(iwmct_logdefs[LOG_SRC_FW_MSG] & BIT(msg->u.log.log_hdr.severity)))
|
||||
return;
|
||||
|
||||
switch (msg->hdr.category) {
|
||||
case COMM_CATEGORY_TESTABILITY:
|
||||
if (!(iwmct_logdefs[LOG_SRC_TST] &
|
||||
BIT(msg->u.log.log_hdr.severity)))
|
||||
return;
|
||||
if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
|
||||
le16_to_cpu(msg->hdr.length) +
|
||||
sizeof(msg->hdr), "<TST>"))
|
||||
LOG_WARNING(priv, TST,
|
||||
"TOP TST message is too long, truncating...");
|
||||
LOG_WARNING(priv, TST, "%s\n", logbuf);
|
||||
break;
|
||||
case COMM_CATEGORY_DEBUG:
|
||||
if (msg->hdr.opcode == OP_DBG_ZSTR_MSG)
|
||||
LOG_INFO(priv, FW_MSG, "%s %s", "<DBG>",
|
||||
((u8 *)msg) + sizeof(msg->hdr)
|
||||
+ sizeof(msg->u.log.log_hdr));
|
||||
else {
|
||||
if (log_msg_format_hex(logbuf, LOG_MSG_SIZE_MAX, buf,
|
||||
le16_to_cpu(msg->hdr.length)
|
||||
+ sizeof(msg->hdr),
|
||||
"<DBG>"))
|
||||
LOG_WARNING(priv, FW_MSG,
|
||||
"TOP DBG message is too long,"
|
||||
"truncating...");
|
||||
LOG_WARNING(priv, FW_MSG, "%s\n", logbuf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int _log_get_filter_str(u8 *logdefs, int logdefsz, char *buf, int size)
|
||||
{
|
||||
int i, pos, len;
|
||||
for (i = 0, pos = 0; (pos < size-1) && (i < logdefsz); i++) {
|
||||
len = snprintf(&buf[pos], size - pos - 1, "0x%02X%02X,",
|
||||
i, logdefs[i]);
|
||||
pos += len;
|
||||
}
|
||||
buf[pos-1] = '\n';
|
||||
buf[pos] = '\0';
|
||||
|
||||
if (i < logdefsz)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_get_filter_str(char *buf, int size)
|
||||
{
|
||||
return _log_get_filter_str(iwmct_logdefs, LOG_SRC_MAX, buf, size);
|
||||
}
|
||||
|
||||
int log_get_fw_filter_str(char *buf, int size)
|
||||
{
|
||||
return _log_get_filter_str(iwmct_fw_logdefs, FW_LOG_SRC_MAX, buf, size);
|
||||
}
|
||||
|
||||
#define HEXADECIMAL_RADIX 16
|
||||
#define LOG_SRC_FORMAT 7 /* log level is in format of "0xXXXX," */
|
||||
|
||||
ssize_t show_iwmct_log_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwmct_priv *priv = dev_get_drvdata(d);
|
||||
char *str_buf;
|
||||
int buf_size;
|
||||
ssize_t ret;
|
||||
|
||||
buf_size = (LOG_SRC_FORMAT * LOG_SRC_MAX) + 1;
|
||||
str_buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (!str_buf) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to allocate %d bytes\n", buf_size);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (log_get_filter_str(str_buf, buf_size) < 0) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%s", str_buf);
|
||||
|
||||
exit:
|
||||
kfree(str_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t store_iwmct_log_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwmct_priv *priv = dev_get_drvdata(d);
|
||||
char *token, *str_buf = NULL;
|
||||
long val;
|
||||
ssize_t ret = count;
|
||||
u8 src, mask;
|
||||
|
||||
if (!count)
|
||||
goto exit;
|
||||
|
||||
str_buf = kzalloc(count, GFP_KERNEL);
|
||||
if (!str_buf) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to allocate %zd bytes\n", count);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(str_buf, buf, count);
|
||||
|
||||
while ((token = strsep(&str_buf, ",")) != NULL) {
|
||||
while (isspace(*token))
|
||||
++token;
|
||||
if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to convert string to long %s\n",
|
||||
token);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mask = val & 0xFF;
|
||||
src = (val & 0XFF00) >> 8;
|
||||
iwmct_log_set_filter(src, mask);
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree(str_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t show_iwmct_log_level_fw(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwmct_priv *priv = dev_get_drvdata(d);
|
||||
char *str_buf;
|
||||
int buf_size;
|
||||
ssize_t ret;
|
||||
|
||||
buf_size = (LOG_SRC_FORMAT * FW_LOG_SRC_MAX) + 2;
|
||||
|
||||
str_buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (!str_buf) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to allocate %d bytes\n", buf_size);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (log_get_fw_filter_str(str_buf, buf_size) < 0) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = sprintf(buf, "%s", str_buf);
|
||||
|
||||
exit:
|
||||
kfree(str_buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t store_iwmct_log_level_fw(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwmct_priv *priv = dev_get_drvdata(d);
|
||||
struct top_msg cmd;
|
||||
char *token, *str_buf = NULL;
|
||||
ssize_t ret = count;
|
||||
u16 cmdlen = 0;
|
||||
int i;
|
||||
long val;
|
||||
u8 src, mask;
|
||||
|
||||
if (!count)
|
||||
goto exit;
|
||||
|
||||
str_buf = kzalloc(count, GFP_KERNEL);
|
||||
if (!str_buf) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to allocate %zd bytes\n", count);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(str_buf, buf, count);
|
||||
|
||||
cmd.hdr.type = COMM_TYPE_H2D;
|
||||
cmd.hdr.category = COMM_CATEGORY_DEBUG;
|
||||
cmd.hdr.opcode = CMD_DBG_LOG_LEVEL;
|
||||
|
||||
for (i = 0; ((token = strsep(&str_buf, ",")) != NULL) &&
|
||||
(i < FW_LOG_SRC_MAX); i++) {
|
||||
|
||||
while (isspace(*token))
|
||||
++token;
|
||||
|
||||
if (strict_strtol(token, HEXADECIMAL_RADIX, &val)) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"failed to convert string to long %s\n",
|
||||
token);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mask = val & 0xFF; /* LSB */
|
||||
src = (val & 0XFF00) >> 8; /* 2nd least significant byte. */
|
||||
iwmct_log_set_fw_filter(src, mask);
|
||||
|
||||
cmd.u.logdefs[i].logsource = src;
|
||||
cmd.u.logdefs[i].sevmask = mask;
|
||||
}
|
||||
|
||||
cmd.hdr.length = cpu_to_le16(i * sizeof(cmd.u.logdefs[0]));
|
||||
cmdlen = (i * sizeof(cmd.u.logdefs[0]) + sizeof(cmd.hdr));
|
||||
|
||||
ret = iwmct_send_hcmd(priv, (u8 *)&cmd, cmdlen);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, DEBUGFS,
|
||||
"Failed to send %d bytes of fwcmd, ret=%zd\n",
|
||||
cmdlen, ret);
|
||||
goto exit;
|
||||
} else
|
||||
LOG_INFO(priv, DEBUGFS, "fwcmd sent (%d bytes)\n", cmdlen);
|
||||
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
kfree(str_buf);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/log.h
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LOG_H__
|
||||
#define __LOG_H__
|
||||
|
||||
|
||||
/* log severity:
|
||||
* The log levels here match FW log levels
|
||||
* so values need to stay as is */
|
||||
#define LOG_SEV_CRITICAL 0
|
||||
#define LOG_SEV_ERROR 1
|
||||
#define LOG_SEV_WARNING 2
|
||||
#define LOG_SEV_INFO 3
|
||||
#define LOG_SEV_INFOEX 4
|
||||
|
||||
#define LOG_SEV_FILTER_ALL \
|
||||
(BIT(LOG_SEV_CRITICAL) | \
|
||||
BIT(LOG_SEV_ERROR) | \
|
||||
BIT(LOG_SEV_WARNING) | \
|
||||
BIT(LOG_SEV_INFO) | \
|
||||
BIT(LOG_SEV_INFOEX))
|
||||
|
||||
/* log source */
|
||||
#define LOG_SRC_INIT 0
|
||||
#define LOG_SRC_DEBUGFS 1
|
||||
#define LOG_SRC_FW_DOWNLOAD 2
|
||||
#define LOG_SRC_FW_MSG 3
|
||||
#define LOG_SRC_TST 4
|
||||
#define LOG_SRC_IRQ 5
|
||||
|
||||
#define LOG_SRC_MAX 6
|
||||
#define LOG_SRC_ALL 0xFF
|
||||
|
||||
/**
|
||||
* Default intitialization runtime log level
|
||||
*/
|
||||
#ifndef LOG_SEV_FILTER_RUNTIME
|
||||
#define LOG_SEV_FILTER_RUNTIME \
|
||||
(BIT(LOG_SEV_CRITICAL) | \
|
||||
BIT(LOG_SEV_ERROR) | \
|
||||
BIT(LOG_SEV_WARNING))
|
||||
#endif
|
||||
|
||||
#ifndef FW_LOG_SEV_FILTER_RUNTIME
|
||||
#define FW_LOG_SEV_FILTER_RUNTIME LOG_SEV_FILTER_ALL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUG
|
||||
/**
|
||||
* Log macros
|
||||
*/
|
||||
|
||||
#define priv2dev(priv) (&(priv->func)->dev)
|
||||
|
||||
#define LOG_CRITICAL(priv, src, fmt, args...) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_CRITICAL)) \
|
||||
dev_crit(priv2dev(priv), "%s %d: " fmt, \
|
||||
__func__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_ERROR(priv, src, fmt, args...) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_ERROR)) \
|
||||
dev_err(priv2dev(priv), "%s %d: " fmt, \
|
||||
__func__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_WARNING(priv, src, fmt, args...) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_WARNING)) \
|
||||
dev_warn(priv2dev(priv), "%s %d: " fmt, \
|
||||
__func__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_INFO(priv, src, fmt, args...) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFO)) \
|
||||
dev_info(priv2dev(priv), "%s %d: " fmt, \
|
||||
__func__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_INFOEX(priv, src, fmt, args...) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFOEX)) \
|
||||
dev_dbg(priv2dev(priv), "%s %d: " fmt, \
|
||||
__func__, __LINE__, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_HEXDUMP(src, ptr, len) \
|
||||
do { \
|
||||
if (iwmct_logdefs[LOG_SRC_ ## src] & BIT(LOG_SEV_INFOEX)) \
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, \
|
||||
16, 1, ptr, len, false); \
|
||||
} while (0)
|
||||
|
||||
void iwmct_log_top_message(struct iwmct_priv *priv, u8 *buf, int len);
|
||||
|
||||
extern u8 iwmct_logdefs[];
|
||||
|
||||
int iwmct_log_set_filter(u8 src, u8 logmask);
|
||||
int iwmct_log_set_fw_filter(u8 src, u8 logmask);
|
||||
|
||||
ssize_t show_iwmct_log_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf);
|
||||
ssize_t store_iwmct_log_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
ssize_t show_iwmct_log_level_fw(struct device *d,
|
||||
struct device_attribute *attr, char *buf);
|
||||
ssize_t store_iwmct_log_level_fw(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count);
|
||||
|
||||
#else
|
||||
|
||||
#define LOG_CRITICAL(priv, src, fmt, args...)
|
||||
#define LOG_ERROR(priv, src, fmt, args...)
|
||||
#define LOG_WARNING(priv, src, fmt, args...)
|
||||
#define LOG_INFO(priv, src, fmt, args...)
|
||||
#define LOG_INFOEX(priv, src, fmt, args...)
|
||||
#define LOG_HEXDUMP(src, ptr, len)
|
||||
|
||||
static inline void iwmct_log_top_message(struct iwmct_priv *priv,
|
||||
u8 *buf, int len) {}
|
||||
static inline int iwmct_log_set_filter(u8 src, u8 logmask) { return 0; }
|
||||
static inline int iwmct_log_set_fw_filter(u8 src, u8 logmask) { return 0; }
|
||||
|
||||
#endif /* CONFIG_IWMC3200TOP_DEBUG */
|
||||
|
||||
int log_get_filter_str(char *buf, int size);
|
||||
int log_get_fw_filter_str(char *buf, int size);
|
||||
|
||||
#endif /* __LOG_H__ */
|
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
* iwmc3200top - Intel Wireless MultiCom 3200 Top Driver
|
||||
* drivers/misc/iwmc3200top/main.c
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version
|
||||
* 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
* Author Name: Maxim Grabarnik <maxim.grabarnink@intel.com>
|
||||
* -
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
|
||||
#include "iwmc3200top.h"
|
||||
#include "log.h"
|
||||
#include "fw-msg.h"
|
||||
#include "debugfs.h"
|
||||
|
||||
|
||||
#define DRIVER_DESCRIPTION "Intel(R) IWMC 3200 Top Driver"
|
||||
#define DRIVER_COPYRIGHT "Copyright (c) 2008 Intel Corporation."
|
||||
|
||||
#define DRIVER_VERSION "0.1.62"
|
||||
|
||||
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
|
||||
MODULE_VERSION(DRIVER_VERSION);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR(DRIVER_COPYRIGHT);
|
||||
MODULE_FIRMWARE(FW_NAME(FW_API_VER));
|
||||
|
||||
/*
|
||||
* This workers main task is to wait for OP_OPR_ALIVE
|
||||
* from TOP FW until ALIVE_MSG_TIMOUT timeout is elapsed.
|
||||
* When OP_OPR_ALIVE received it will issue
|
||||
* a call to "bus_rescan_devices".
|
||||
*/
|
||||
static void iwmct_rescan_worker(struct work_struct *ws)
|
||||
{
|
||||
struct iwmct_priv *priv;
|
||||
int ret;
|
||||
|
||||
priv = container_of(ws, struct iwmct_priv, bus_rescan_worker);
|
||||
|
||||
LOG_INFO(priv, FW_MSG, "Calling bus_rescan\n");
|
||||
|
||||
ret = bus_rescan_devices(priv->func->dev.bus);
|
||||
if (ret < 0)
|
||||
LOG_INFO(priv, FW_DOWNLOAD, "bus_rescan_devices FAILED!!!\n");
|
||||
}
|
||||
|
||||
static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg)
|
||||
{
|
||||
switch (msg->hdr.opcode) {
|
||||
case OP_OPR_ALIVE:
|
||||
LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
|
||||
queue_work(priv->bus_rescan_wq, &priv->bus_rescan_worker);
|
||||
break;
|
||||
default:
|
||||
LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
|
||||
msg->hdr.opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void handle_top_message(struct iwmct_priv *priv, u8 *buf, int len)
|
||||
{
|
||||
struct top_msg *msg;
|
||||
|
||||
msg = (struct top_msg *)buf;
|
||||
|
||||
if (msg->hdr.type != COMM_TYPE_D2H) {
|
||||
LOG_ERROR(priv, FW_MSG,
|
||||
"Message from TOP with invalid message type 0x%X\n",
|
||||
msg->hdr.type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < sizeof(msg->hdr)) {
|
||||
LOG_ERROR(priv, FW_MSG,
|
||||
"Message from TOP is too short for message header "
|
||||
"received %d bytes, expected at least %zd bytes\n",
|
||||
len, sizeof(msg->hdr));
|
||||
return;
|
||||
}
|
||||
|
||||
if (len < le16_to_cpu(msg->hdr.length) + sizeof(msg->hdr)) {
|
||||
LOG_ERROR(priv, FW_MSG,
|
||||
"Message length (%d bytes) is shorter than "
|
||||
"in header (%d bytes)\n",
|
||||
len, le16_to_cpu(msg->hdr.length));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->hdr.category) {
|
||||
case COMM_CATEGORY_OPERATIONAL:
|
||||
op_top_message(priv, (struct top_msg *)buf);
|
||||
break;
|
||||
|
||||
case COMM_CATEGORY_DEBUG:
|
||||
case COMM_CATEGORY_TESTABILITY:
|
||||
case COMM_CATEGORY_DIAGNOSTICS:
|
||||
iwmct_log_top_message(priv, buf, len);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERROR(priv, FW_MSG,
|
||||
"Message from TOP with unknown category 0x%X\n",
|
||||
msg->hdr.category);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int iwmct_send_hcmd(struct iwmct_priv *priv, u8 *cmd, u16 len)
|
||||
{
|
||||
int ret;
|
||||
u8 *buf;
|
||||
|
||||
LOG_INFOEX(priv, FW_MSG, "Sending hcmd:\n");
|
||||
|
||||
/* add padding to 256 for IWMC */
|
||||
((struct top_msg *)cmd)->hdr.flags |= CMD_FLAG_PADDING_256;
|
||||
|
||||
LOG_HEXDUMP(FW_MSG, cmd, len);
|
||||
|
||||
if (len > FW_HCMD_BLOCK_SIZE) {
|
||||
LOG_ERROR(priv, FW_MSG, "size %d exceeded hcmd max size %d\n",
|
||||
len, FW_HCMD_BLOCK_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = kzalloc(FW_HCMD_BLOCK_SIZE, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
LOG_ERROR(priv, FW_MSG, "kzalloc error, buf size %d\n",
|
||||
FW_HCMD_BLOCK_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(buf, cmd, len);
|
||||
|
||||
sdio_claim_host(priv->func);
|
||||
ret = sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR, buf,
|
||||
FW_HCMD_BLOCK_SIZE);
|
||||
sdio_release_host(priv->func);
|
||||
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwmct_tx(struct iwmct_priv *priv, unsigned int addr,
|
||||
void *src, int count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
sdio_claim_host(priv->func);
|
||||
ret = sdio_memcpy_toio(priv->func, addr, src, count);
|
||||
sdio_release_host(priv->func);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwmct_irq_read_worker(struct work_struct *ws)
|
||||
{
|
||||
struct iwmct_priv *priv;
|
||||
struct iwmct_work_struct *read_req;
|
||||
__le32 *buf = NULL;
|
||||
int ret;
|
||||
int iosize;
|
||||
u32 barker;
|
||||
bool is_barker;
|
||||
|
||||
priv = container_of(ws, struct iwmct_priv, isr_worker);
|
||||
|
||||
LOG_INFO(priv, IRQ, "enter iwmct_irq_read_worker %p\n", ws);
|
||||
|
||||
/* --------------------- Handshake with device -------------------- */
|
||||
sdio_claim_host(priv->func);
|
||||
|
||||
/* all list manipulations have to be protected by
|
||||
* sdio_claim_host/sdio_release_host */
|
||||
if (list_empty(&priv->read_req_list)) {
|
||||
LOG_ERROR(priv, IRQ, "read_req_list empty in read worker\n");
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
read_req = list_entry(priv->read_req_list.next,
|
||||
struct iwmct_work_struct, list);
|
||||
|
||||
list_del(&read_req->list);
|
||||
iosize = read_req->iosize;
|
||||
kfree(read_req);
|
||||
|
||||
buf = kzalloc(iosize, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
LOG_ERROR(priv, IRQ, "kzalloc error, buf size %d\n", iosize);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
LOG_INFO(priv, IRQ, "iosize=%d, buf=%p, func=%d\n",
|
||||
iosize, buf, priv->func->num);
|
||||
|
||||
/* read from device */
|
||||
ret = sdio_memcpy_fromio(priv->func, buf, IWMC_SDIO_DATA_ADDR, iosize);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, IRQ, "error %d reading buffer\n", ret);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
LOG_HEXDUMP(IRQ, (u8 *)buf, iosize);
|
||||
|
||||
barker = le32_to_cpu(buf[0]);
|
||||
|
||||
/* Verify whether it's a barker and if not - treat as regular Rx */
|
||||
if (barker == IWMC_BARKER_ACK ||
|
||||
(barker & BARKER_DNLOAD_BARKER_MSK) == IWMC_BARKER_REBOOT) {
|
||||
|
||||
/* Valid Barker is equal on first 4 dwords */
|
||||
is_barker = (buf[1] == buf[0]) &&
|
||||
(buf[2] == buf[0]) &&
|
||||
(buf[3] == buf[0]);
|
||||
|
||||
if (!is_barker) {
|
||||
LOG_WARNING(priv, IRQ,
|
||||
"Potentially inconsistent barker "
|
||||
"%08X_%08X_%08X_%08X\n",
|
||||
le32_to_cpu(buf[0]), le32_to_cpu(buf[1]),
|
||||
le32_to_cpu(buf[2]), le32_to_cpu(buf[3]));
|
||||
}
|
||||
} else {
|
||||
is_barker = false;
|
||||
}
|
||||
|
||||
/* Handle Top CommHub message */
|
||||
if (!is_barker) {
|
||||
sdio_release_host(priv->func);
|
||||
handle_top_message(priv, (u8 *)buf, iosize);
|
||||
goto exit;
|
||||
} else if (barker == IWMC_BARKER_ACK) { /* Handle barkers */
|
||||
if (atomic_read(&priv->dev_sync) == 0) {
|
||||
LOG_ERROR(priv, IRQ,
|
||||
"ACK barker arrived out-of-sync\n");
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
/* Continuing to FW download (after Sync is completed)*/
|
||||
atomic_set(&priv->dev_sync, 0);
|
||||
LOG_INFO(priv, IRQ, "ACK barker arrived "
|
||||
"- starting FW download\n");
|
||||
} else { /* REBOOT barker */
|
||||
LOG_INFO(priv, IRQ, "Recieved reboot barker: %x\n", barker);
|
||||
priv->barker = barker;
|
||||
|
||||
if (barker & BARKER_DNLOAD_SYNC_MSK) {
|
||||
/* Send the same barker back */
|
||||
ret = sdio_memcpy_toio(priv->func, IWMC_SDIO_DATA_ADDR,
|
||||
buf, iosize);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, IRQ,
|
||||
"error %d echoing barker\n", ret);
|
||||
goto exit_release;
|
||||
}
|
||||
LOG_INFO(priv, IRQ, "Echoing barker to device\n");
|
||||
atomic_set(&priv->dev_sync, 1);
|
||||
goto exit_release;
|
||||
}
|
||||
|
||||
/* Continuing to FW download (without Sync) */
|
||||
LOG_INFO(priv, IRQ, "No sync requested "
|
||||
"- starting FW download\n");
|
||||
}
|
||||
|
||||
sdio_release_host(priv->func);
|
||||
|
||||
|
||||
LOG_INFO(priv, IRQ, "barker download request 0x%x is:\n", priv->barker);
|
||||
LOG_INFO(priv, IRQ, "******* Top FW %s requested ********\n",
|
||||
(priv->barker & BARKER_DNLOAD_TOP_MSK) ? "was" : "not");
|
||||
LOG_INFO(priv, IRQ, "******* GPS FW %s requested ********\n",
|
||||
(priv->barker & BARKER_DNLOAD_GPS_MSK) ? "was" : "not");
|
||||
LOG_INFO(priv, IRQ, "******* BT FW %s requested ********\n",
|
||||
(priv->barker & BARKER_DNLOAD_BT_MSK) ? "was" : "not");
|
||||
|
||||
if (priv->dbg.fw_download)
|
||||
iwmct_fw_load(priv);
|
||||
else
|
||||
LOG_ERROR(priv, IRQ, "FW download not allowed\n");
|
||||
|
||||
goto exit;
|
||||
|
||||
exit_release:
|
||||
sdio_release_host(priv->func);
|
||||
exit:
|
||||
kfree(buf);
|
||||
LOG_INFO(priv, IRQ, "exit iwmct_irq_read_worker\n");
|
||||
}
|
||||
|
||||
static void iwmct_irq(struct sdio_func *func)
|
||||
{
|
||||
struct iwmct_priv *priv;
|
||||
int val, ret;
|
||||
int iosize;
|
||||
int addr = IWMC_SDIO_INTR_GET_SIZE_ADDR;
|
||||
struct iwmct_work_struct *read_req;
|
||||
|
||||
priv = sdio_get_drvdata(func);
|
||||
|
||||
LOG_INFO(priv, IRQ, "enter iwmct_irq\n");
|
||||
|
||||
/* read the function's status register */
|
||||
val = sdio_readb(func, IWMC_SDIO_INTR_STATUS_ADDR, &ret);
|
||||
|
||||
LOG_INFO(priv, IRQ, "iir value = %d, ret=%d\n", val, ret);
|
||||
|
||||
if (!val) {
|
||||
LOG_ERROR(priv, IRQ, "iir = 0, exiting ISR\n");
|
||||
goto exit_clear_intr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* read 2 bytes of the transaction size
|
||||
* IMPORTANT: sdio transaction size has to be read before clearing
|
||||
* sdio interrupt!!!
|
||||
*/
|
||||
val = sdio_readb(priv->func, addr++, &ret);
|
||||
iosize = val;
|
||||
val = sdio_readb(priv->func, addr++, &ret);
|
||||
iosize += val << 8;
|
||||
|
||||
LOG_INFO(priv, IRQ, "READ size %d\n", iosize);
|
||||
|
||||
if (iosize == 0) {
|
||||
LOG_ERROR(priv, IRQ, "READ size %d, exiting ISR\n", iosize);
|
||||
goto exit_clear_intr;
|
||||
}
|
||||
|
||||
/* allocate a work structure to pass iosize to the worker */
|
||||
read_req = kzalloc(sizeof(struct iwmct_work_struct), GFP_KERNEL);
|
||||
if (!read_req) {
|
||||
LOG_ERROR(priv, IRQ, "failed to allocate read_req, exit ISR\n");
|
||||
goto exit_clear_intr;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&read_req->list);
|
||||
read_req->iosize = iosize;
|
||||
|
||||
list_add_tail(&priv->read_req_list, &read_req->list);
|
||||
|
||||
/* clear the function's interrupt request bit (write 1 to clear) */
|
||||
sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
|
||||
|
||||
queue_work(priv->wq, &priv->isr_worker);
|
||||
|
||||
LOG_INFO(priv, IRQ, "exit iwmct_irq\n");
|
||||
|
||||
return;
|
||||
|
||||
exit_clear_intr:
|
||||
/* clear the function's interrupt request bit (write 1 to clear) */
|
||||
sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
|
||||
}
|
||||
|
||||
|
||||
static int blocks;
|
||||
module_param(blocks, int, 0604);
|
||||
MODULE_PARM_DESC(blocks, "max_blocks_to_send");
|
||||
|
||||
static int dump;
|
||||
module_param(dump, bool, 0604);
|
||||
MODULE_PARM_DESC(dump, "dump_hex_content");
|
||||
|
||||
static int jump = 1;
|
||||
module_param(jump, bool, 0604);
|
||||
|
||||
static int direct = 1;
|
||||
module_param(direct, bool, 0604);
|
||||
|
||||
static int checksum = 1;
|
||||
module_param(checksum, bool, 0604);
|
||||
|
||||
static int fw_download = 1;
|
||||
module_param(fw_download, bool, 0604);
|
||||
|
||||
static int block_size = IWMC_SDIO_BLK_SIZE;
|
||||
module_param(block_size, int, 0404);
|
||||
|
||||
static int download_trans_blks = IWMC_DEFAULT_TR_BLK;
|
||||
module_param(download_trans_blks, int, 0604);
|
||||
|
||||
static int rubbish_barker;
|
||||
module_param(rubbish_barker, bool, 0604);
|
||||
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUG
|
||||
static int log_level[LOG_SRC_MAX];
|
||||
static unsigned int log_level_argc;
|
||||
module_param_array(log_level, int, &log_level_argc, 0604);
|
||||
MODULE_PARM_DESC(log_level, "log_level");
|
||||
|
||||
static int log_level_fw[FW_LOG_SRC_MAX];
|
||||
static unsigned int log_level_fw_argc;
|
||||
module_param_array(log_level_fw, int, &log_level_fw_argc, 0604);
|
||||
MODULE_PARM_DESC(log_level_fw, "log_level_fw");
|
||||
#endif
|
||||
|
||||
void iwmct_dbg_init_params(struct iwmct_priv *priv)
|
||||
{
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUG
|
||||
int i;
|
||||
|
||||
for (i = 0; i < log_level_argc; i++) {
|
||||
dev_notice(&priv->func->dev, "log_level[%d]=0x%X\n",
|
||||
i, log_level[i]);
|
||||
iwmct_log_set_filter((log_level[i] >> 8) & 0xFF,
|
||||
log_level[i] & 0xFF);
|
||||
}
|
||||
for (i = 0; i < log_level_fw_argc; i++) {
|
||||
dev_notice(&priv->func->dev, "log_level_fw[%d]=0x%X\n",
|
||||
i, log_level_fw[i]);
|
||||
iwmct_log_set_fw_filter((log_level_fw[i] >> 8) & 0xFF,
|
||||
log_level_fw[i] & 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
priv->dbg.blocks = blocks;
|
||||
LOG_INFO(priv, INIT, "blocks=%d\n", blocks);
|
||||
priv->dbg.dump = (bool)dump;
|
||||
LOG_INFO(priv, INIT, "dump=%d\n", dump);
|
||||
priv->dbg.jump = (bool)jump;
|
||||
LOG_INFO(priv, INIT, "jump=%d\n", jump);
|
||||
priv->dbg.direct = (bool)direct;
|
||||
LOG_INFO(priv, INIT, "direct=%d\n", direct);
|
||||
priv->dbg.checksum = (bool)checksum;
|
||||
LOG_INFO(priv, INIT, "checksum=%d\n", checksum);
|
||||
priv->dbg.fw_download = (bool)fw_download;
|
||||
LOG_INFO(priv, INIT, "fw_download=%d\n", fw_download);
|
||||
priv->dbg.block_size = block_size;
|
||||
LOG_INFO(priv, INIT, "block_size=%d\n", block_size);
|
||||
priv->dbg.download_trans_blks = download_trans_blks;
|
||||
LOG_INFO(priv, INIT, "download_trans_blks=%d\n", download_trans_blks);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
static ssize_t show_iwmct_fw_version(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwmct_priv *priv = dev_get_drvdata(d);
|
||||
return sprintf(buf, "%s\n", priv->dbg.label_fw);
|
||||
}
|
||||
static DEVICE_ATTR(cc_label_fw, S_IRUGO, show_iwmct_fw_version, NULL);
|
||||
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUG
|
||||
static DEVICE_ATTR(log_level, S_IWUSR | S_IRUGO,
|
||||
show_iwmct_log_level, store_iwmct_log_level);
|
||||
static DEVICE_ATTR(log_level_fw, S_IWUSR | S_IRUGO,
|
||||
show_iwmct_log_level_fw, store_iwmct_log_level_fw);
|
||||
#endif
|
||||
|
||||
static struct attribute *iwmct_sysfs_entries[] = {
|
||||
&dev_attr_cc_label_fw.attr,
|
||||
#ifdef CONFIG_IWMC3200TOP_DEBUG
|
||||
&dev_attr_log_level.attr,
|
||||
&dev_attr_log_level_fw.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwmct_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwmct_sysfs_entries,
|
||||
};
|
||||
|
||||
|
||||
static int iwmct_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
struct iwmct_priv *priv;
|
||||
int ret;
|
||||
int val = 1;
|
||||
int addr = IWMC_SDIO_INTR_ENABLE_ADDR;
|
||||
|
||||
dev_dbg(&func->dev, "enter iwmct_probe\n");
|
||||
|
||||
dev_dbg(&func->dev, "IRQ polling period id %u msecs, HZ is %d\n",
|
||||
jiffies_to_msecs(2147483647), HZ);
|
||||
|
||||
priv = kzalloc(sizeof(struct iwmct_priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
dev_err(&func->dev, "kzalloc error\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
priv->func = func;
|
||||
sdio_set_drvdata(func, priv);
|
||||
|
||||
|
||||
/* create drivers work queue */
|
||||
priv->wq = create_workqueue(DRV_NAME "_wq");
|
||||
priv->bus_rescan_wq = create_workqueue(DRV_NAME "_rescan_wq");
|
||||
INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
|
||||
INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
|
||||
|
||||
init_waitqueue_head(&priv->wait_q);
|
||||
|
||||
sdio_claim_host(func);
|
||||
/* FIXME: Remove after it is fixed in the Boot ROM upgrade */
|
||||
func->enable_timeout = 10;
|
||||
|
||||
/* In our HW, setting the block size also wakes up the boot rom. */
|
||||
ret = sdio_set_block_size(func, priv->dbg.block_size);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, INIT,
|
||||
"sdio_set_block_size() failure: %d\n", ret);
|
||||
goto error_sdio_enable;
|
||||
}
|
||||
|
||||
ret = sdio_enable_func(func);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, INIT, "sdio_enable_func() failure: %d\n", ret);
|
||||
goto error_sdio_enable;
|
||||
}
|
||||
|
||||
/* init reset and dev_sync states */
|
||||
atomic_set(&priv->reset, 0);
|
||||
atomic_set(&priv->dev_sync, 0);
|
||||
|
||||
/* init read req queue */
|
||||
INIT_LIST_HEAD(&priv->read_req_list);
|
||||
|
||||
/* process configurable parameters */
|
||||
iwmct_dbg_init_params(priv);
|
||||
ret = sysfs_create_group(&func->dev.kobj, &iwmct_attribute_group);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, INIT, "Failed to register attributes and "
|
||||
"initialize module_params\n");
|
||||
goto error_dev_attrs;
|
||||
}
|
||||
|
||||
iwmct_dbgfs_register(priv, DRV_NAME);
|
||||
|
||||
if (!priv->dbg.direct && priv->dbg.download_trans_blks > 8) {
|
||||
LOG_INFO(priv, INIT,
|
||||
"Reducing transaction to 8 blocks = 2K (from %d)\n",
|
||||
priv->dbg.download_trans_blks);
|
||||
priv->dbg.download_trans_blks = 8;
|
||||
}
|
||||
priv->trans_len = priv->dbg.download_trans_blks * priv->dbg.block_size;
|
||||
LOG_INFO(priv, INIT, "Transaction length = %d\n", priv->trans_len);
|
||||
|
||||
ret = sdio_claim_irq(func, iwmct_irq);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, INIT, "sdio_claim_irq() failure: %d\n", ret);
|
||||
goto error_claim_irq;
|
||||
}
|
||||
|
||||
|
||||
/* Enable function's interrupt */
|
||||
sdio_writeb(priv->func, val, addr, &ret);
|
||||
if (ret) {
|
||||
LOG_ERROR(priv, INIT, "Failure writing to "
|
||||
"Interrupt Enable Register (%d): %d\n", addr, ret);
|
||||
goto error_enable_int;
|
||||
}
|
||||
|
||||
sdio_release_host(func);
|
||||
|
||||
LOG_INFO(priv, INIT, "exit iwmct_probe\n");
|
||||
|
||||
return ret;
|
||||
|
||||
error_enable_int:
|
||||
sdio_release_irq(func);
|
||||
error_claim_irq:
|
||||
sdio_disable_func(func);
|
||||
error_dev_attrs:
|
||||
iwmct_dbgfs_unregister(priv->dbgfs);
|
||||
sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
|
||||
error_sdio_enable:
|
||||
sdio_release_host(func);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwmct_remove(struct sdio_func *func)
|
||||
{
|
||||
struct iwmct_work_struct *read_req;
|
||||
struct iwmct_priv *priv = sdio_get_drvdata(func);
|
||||
|
||||
priv = sdio_get_drvdata(func);
|
||||
|
||||
LOG_INFO(priv, INIT, "enter\n");
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_release_irq(func);
|
||||
sdio_release_host(func);
|
||||
|
||||
/* Safely destroy osc workqueue */
|
||||
destroy_workqueue(priv->bus_rescan_wq);
|
||||
destroy_workqueue(priv->wq);
|
||||
|
||||
sdio_claim_host(func);
|
||||
sdio_disable_func(func);
|
||||
sysfs_remove_group(&func->dev.kobj, &iwmct_attribute_group);
|
||||
iwmct_dbgfs_unregister(priv->dbgfs);
|
||||
sdio_release_host(func);
|
||||
|
||||
/* free read requests */
|
||||
while (!list_empty(&priv->read_req_list)) {
|
||||
read_req = list_entry(priv->read_req_list.next,
|
||||
struct iwmct_work_struct, list);
|
||||
|
||||
list_del(&read_req->list);
|
||||
kfree(read_req);
|
||||
}
|
||||
|
||||
kfree(priv);
|
||||
}
|
||||
|
||||
|
||||
static const struct sdio_device_id iwmct_ids[] = {
|
||||
/* Intel Wireless MultiCom 3200 Top Driver */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1404)},
|
||||
{ }, /* Terminating entry */
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(sdio, iwmct_ids);
|
||||
|
||||
static struct sdio_driver iwmct_driver = {
|
||||
.probe = iwmct_probe,
|
||||
.remove = iwmct_remove,
|
||||
.name = DRV_NAME,
|
||||
.id_table = iwmct_ids,
|
||||
};
|
||||
|
||||
static int __init iwmct_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Default log filter settings */
|
||||
iwmct_log_set_filter(LOG_SRC_ALL, LOG_SEV_FILTER_RUNTIME);
|
||||
iwmct_log_set_filter(LOG_SRC_FW_MSG, LOG_SEV_FILTER_ALL);
|
||||
iwmct_log_set_fw_filter(LOG_SRC_ALL, FW_LOG_SEV_FILTER_RUNTIME);
|
||||
|
||||
rc = sdio_register_driver(&iwmct_driver);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit iwmct_exit(void)
|
||||
{
|
||||
sdio_unregister_driver(&iwmct_driver);
|
||||
}
|
||||
|
||||
module_init(iwmct_init);
|
||||
module_exit(iwmct_exit);
|
||||
|
|
@ -249,11 +249,11 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
|
|||
* for the Sager NP943 prefix.
|
||||
*/
|
||||
|
||||
if (station_addr[0] == 0x02 && station_addr[1] == 0x60
|
||||
&& station_addr[2] == 0x8c)
|
||||
if (station_addr[0] == 0x02 && station_addr[1] == 0x60 &&
|
||||
station_addr[2] == 0x8c)
|
||||
mname = "3c501";
|
||||
else if (station_addr[0] == 0x00 && station_addr[1] == 0x80
|
||||
&& station_addr[2] == 0xC8)
|
||||
else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 &&
|
||||
station_addr[2] == 0xC8)
|
||||
mname = "NP943";
|
||||
else {
|
||||
release_region(ioaddr, EL1_IO_EXTENT);
|
||||
|
@ -345,7 +345,7 @@ static int el_open(struct net_device *dev)
|
|||
if (el_debug > 2)
|
||||
pr_debug("%s: Doing el_open()...\n", dev->name);
|
||||
|
||||
retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev);
|
||||
retval = request_irq(dev->irq, el_interrupt, 0, dev->name, dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
|
|
@ -214,8 +214,8 @@ el2_probe1(struct net_device *dev, int ioaddr)
|
|||
iobase_reg = inb(ioaddr+0x403);
|
||||
membase_reg = inb(ioaddr+0x404);
|
||||
/* ASIC location registers should be 0 or have only a single bit set. */
|
||||
if ( (iobase_reg & (iobase_reg - 1))
|
||||
|| (membase_reg & (membase_reg - 1))) {
|
||||
if ((iobase_reg & (iobase_reg - 1)) ||
|
||||
(membase_reg & (membase_reg - 1))) {
|
||||
retval = -ENODEV;
|
||||
goto out1;
|
||||
}
|
||||
|
@ -291,8 +291,8 @@ el2_probe1(struct net_device *dev, int ioaddr)
|
|||
writel(0xba5eba5e, mem_base);
|
||||
for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
|
||||
writel(test_val, mem_base + i);
|
||||
if (readl(mem_base) != 0xba5eba5e
|
||||
|| readl(mem_base + i) != test_val) {
|
||||
if (readl(mem_base) != 0xba5eba5e ||
|
||||
readl(mem_base + i) != test_val) {
|
||||
pr_warning("3c503: memory failure or memory address conflict.\n");
|
||||
dev->mem_start = 0;
|
||||
ei_status.name = "3c503-PIO";
|
||||
|
@ -397,9 +397,10 @@ el2_open(struct net_device *dev)
|
|||
unsigned long cookie = probe_irq_on();
|
||||
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
|
||||
outb_p(0x00, E33G_IDCFR);
|
||||
if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */
|
||||
&& ((retval = request_irq(dev->irq = *irqp,
|
||||
eip_interrupt, 0, dev->name, dev)) == 0))
|
||||
if (*irqp == probe_irq_off(cookie) && /* It's a good IRQ line! */
|
||||
((retval = request_irq(dev->irq = *irqp,
|
||||
eip_interrupt, 0,
|
||||
dev->name, dev)) == 0))
|
||||
break;
|
||||
} else {
|
||||
if (retval != -EBUSY)
|
||||
|
|
|
@ -886,7 +886,7 @@ static int elp_open(struct net_device *dev)
|
|||
/*
|
||||
* install our interrupt service routine
|
||||
*/
|
||||
if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) {
|
||||
if ((retval = request_irq(dev->irq, elp_interrupt, 0, dev->name, dev))) {
|
||||
pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -399,7 +399,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
|
|||
|
||||
irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
|
||||
|
||||
irqval = request_irq(irq, &el16_interrupt, 0, DRV_NAME, dev);
|
||||
irqval = request_irq(irq, el16_interrupt, 0, DRV_NAME, dev);
|
||||
if (irqval) {
|
||||
pr_cont("\n");
|
||||
pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval);
|
||||
|
@ -836,8 +836,8 @@ static void el16_rx(struct net_device *dev)
|
|||
void __iomem *data_frame = lp->base + data_buffer_addr;
|
||||
ushort pkt_len = readw(data_frame);
|
||||
|
||||
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|
||||
|| (pkt_len & 0xC000) != 0xC000) {
|
||||
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 ||
|
||||
(pkt_len & 0xC000) != 0xC000) {
|
||||
pr_err("%s: Rx frame at %#x corrupted, "
|
||||
"status %04x cmd %04x next %04x "
|
||||
"data-buf @%04x %04x.\n",
|
||||
|
|
|
@ -253,9 +253,9 @@ static int el3_isa_id_sequence(__be16 *phys_addr)
|
|||
This check is needed in order not to register them twice. */
|
||||
for (i = 0; i < el3_cards; i++) {
|
||||
struct el3_private *lp = netdev_priv(el3_devs[i]);
|
||||
if (lp->type == EL3_PNP
|
||||
&& !memcmp(phys_addr, el3_devs[i]->dev_addr,
|
||||
ETH_ALEN)) {
|
||||
if (lp->type == EL3_PNP &&
|
||||
!memcmp(phys_addr, el3_devs[i]->dev_addr,
|
||||
ETH_ALEN)) {
|
||||
if (el3_debug > 3)
|
||||
pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
|
||||
phys_addr[0] & 0xff, phys_addr[0] >> 8,
|
||||
|
@ -780,7 +780,7 @@ el3_open(struct net_device *dev)
|
|||
outw(RxReset, ioaddr + EL3_CMD);
|
||||
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
|
||||
|
||||
i = request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev);
|
||||
i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
|
||||
if (i)
|
||||
return i;
|
||||
|
||||
|
@ -835,8 +835,8 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
#ifndef final_version
|
||||
{ /* Error-checking code, delete someday. */
|
||||
ushort status = inw(ioaddr + EL3_STATUS);
|
||||
if (status & 0x0001 /* IRQ line active, missed one. */
|
||||
&& inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
|
||||
if (status & 0x0001 && /* IRQ line active, missed one. */
|
||||
inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
|
||||
pr_debug("%s: Missed interrupt, status then %04x now %04x"
|
||||
" Tx %2.2x Rx %4.4x.\n", dev->name, status,
|
||||
inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
|
||||
|
|
|
@ -764,13 +764,14 @@ static int corkscrew_open(struct net_device *dev)
|
|||
/* Use the now-standard shared IRQ implementation. */
|
||||
if (vp->capabilities == 0x11c7) {
|
||||
/* Corkscrew: Cannot share ISA resources. */
|
||||
if (dev->irq == 0
|
||||
|| dev->dma == 0
|
||||
|| request_irq(dev->irq, &corkscrew_interrupt, 0,
|
||||
vp->product_name, dev)) return -EAGAIN;
|
||||
if (dev->irq == 0 ||
|
||||
dev->dma == 0 ||
|
||||
request_irq(dev->irq, corkscrew_interrupt, 0,
|
||||
vp->product_name, dev))
|
||||
return -EAGAIN;
|
||||
enable_dma(dev->dma);
|
||||
set_dma_mode(dev->dma, DMA_MODE_CASCADE);
|
||||
} else if (request_irq(dev->irq, &corkscrew_interrupt, IRQF_SHARED,
|
||||
} else if (request_irq(dev->irq, corkscrew_interrupt, IRQF_SHARED,
|
||||
vp->product_name, dev)) {
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
@ -1368,8 +1369,8 @@ static int boomerang_rx(struct net_device *dev)
|
|||
|
||||
/* Check if the packet is long enough to just accept without
|
||||
copying to a properly sized skbuff. */
|
||||
if (pkt_len < rx_copybreak
|
||||
&& (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
|
||||
if (pkt_len < rx_copybreak &&
|
||||
(skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
|
||||
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
||||
/* 'skb_put()' points to the start of sk_buff data area. */
|
||||
memcpy(skb_put(skb, pkt_len),
|
||||
|
|
|
@ -288,7 +288,7 @@ static int elmc_open(struct net_device *dev)
|
|||
|
||||
elmc_id_attn586(); /* disable interrupts */
|
||||
|
||||
ret = request_irq(dev->irq, &elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM,
|
||||
dev->name, dev);
|
||||
if (ret) {
|
||||
pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
|
||||
|
|
|
@ -443,7 +443,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
|
|||
* Grab the IRQ
|
||||
*/
|
||||
|
||||
err = request_irq(dev->irq, &mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev);
|
||||
err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DRV_NAME, dev);
|
||||
if (err) {
|
||||
release_region(dev->base_addr, MC32_IO_EXTENT);
|
||||
pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
|
||||
|
@ -1168,8 +1168,8 @@ static void mc32_rx_ring(struct net_device *dev)
|
|||
|
||||
/* Try to save time by avoiding a copy on big frames */
|
||||
|
||||
if ((length > RX_COPYBREAK)
|
||||
&& ((newskb=dev_alloc_skb(1532)) != NULL))
|
||||
if ((length > RX_COPYBREAK) &&
|
||||
((newskb=dev_alloc_skb(1532)) != NULL))
|
||||
{
|
||||
skb=lp->rx_ring[rx_ring_tail].skb;
|
||||
skb_put(skb, length);
|
||||
|
|
|
@ -1942,8 +1942,8 @@ vortex_error(struct net_device *dev, int status)
|
|||
if (status & TxComplete) { /* Really "TxError" for us. */
|
||||
tx_status = ioread8(ioaddr + TxStatus);
|
||||
/* Presumably a tx-timeout. We must merely re-enable. */
|
||||
if (vortex_debug > 2
|
||||
|| (tx_status != 0x88 && vortex_debug > 0)) {
|
||||
if (vortex_debug > 2 ||
|
||||
(tx_status != 0x88 && vortex_debug > 0)) {
|
||||
pr_err("%s: Transmit error, Tx status register %2.2x.\n",
|
||||
dev->name, tx_status);
|
||||
if (tx_status == 0x82) {
|
||||
|
@ -2560,7 +2560,7 @@ boomerang_rx(struct net_device *dev)
|
|||
struct sk_buff *skb;
|
||||
entry = vp->dirty_rx % RX_RING_SIZE;
|
||||
if (vp->rx_skbuff[entry] == NULL) {
|
||||
skb = netdev_alloc_skb(dev, PKT_BUF_SZ + NET_IP_ALIGN);
|
||||
skb = netdev_alloc_skb_ip_align(dev, PKT_BUF_SZ);
|
||||
if (skb == NULL) {
|
||||
static unsigned long last_jif;
|
||||
if (time_after(jiffies, last_jif + 10 * HZ)) {
|
||||
|
@ -2572,7 +2572,6 @@ boomerang_rx(struct net_device *dev)
|
|||
break; /* Bad news! */
|
||||
}
|
||||
|
||||
skb_reserve(skb, NET_IP_ALIGN);
|
||||
vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
|
||||
vp->rx_skbuff[entry] = skb;
|
||||
}
|
||||
|
|
|
@ -549,14 +549,12 @@ rx_status_loop:
|
|||
pr_debug("%s: rx slot %d status 0x%x len %d\n",
|
||||
dev->name, rx_tail, status, len);
|
||||
|
||||
new_skb = netdev_alloc_skb(dev, buflen + NET_IP_ALIGN);
|
||||
new_skb = netdev_alloc_skb_ip_align(dev, buflen);
|
||||
if (!new_skb) {
|
||||
dev->stats.rx_dropped++;
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
skb_reserve(new_skb, NET_IP_ALIGN);
|
||||
|
||||
dma_unmap_single(&cp->pdev->dev, mapping,
|
||||
buflen, PCI_DMA_FROMDEVICE);
|
||||
|
||||
|
@ -911,8 +909,8 @@ static void __cp_set_rx_mode (struct net_device *dev)
|
|||
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
||||
AcceptAllPhys;
|
||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||
} else if ((dev->mc_count > multicast_filter_limit)
|
||||
|| (dev->flags & IFF_ALLMULTI)) {
|
||||
} else if ((dev->mc_count > multicast_filter_limit) ||
|
||||
(dev->flags & IFF_ALLMULTI)) {
|
||||
/* Too many to filter perfectly -- accept all multicasts. */
|
||||
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||
|
@ -1057,12 +1055,10 @@ static int cp_refill_rx(struct cp_private *cp)
|
|||
struct sk_buff *skb;
|
||||
dma_addr_t mapping;
|
||||
|
||||
skb = netdev_alloc_skb(dev, cp->rx_buf_sz + NET_IP_ALIGN);
|
||||
skb = netdev_alloc_skb_ip_align(dev, cp->rx_buf_sz);
|
||||
if (!skb)
|
||||
goto err_out;
|
||||
|
||||
skb_reserve(skb, NET_IP_ALIGN);
|
||||
|
||||
mapping = dma_map_single(&cp->pdev->dev, skb->data,
|
||||
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||
cp->rx_skb[i] = skb;
|
||||
|
|
|
@ -1549,8 +1549,8 @@ static inline void rtl8139_thread_iter (struct net_device *dev,
|
|||
mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
|
||||
|
||||
if (!tp->mii.force_media && mii_lpa != 0xffff) {
|
||||
int duplex = (mii_lpa & LPA_100FULL)
|
||||
|| (mii_lpa & 0x01C0) == 0x0040;
|
||||
int duplex = ((mii_lpa & LPA_100FULL) ||
|
||||
(mii_lpa & 0x01C0) == 0x0040);
|
||||
if (tp->mii.full_duplex != duplex) {
|
||||
tp->mii.full_duplex = duplex;
|
||||
|
||||
|
@ -1936,8 +1936,8 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
|
|||
RTL_R16 (RxBufAddr),
|
||||
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
|
||||
|
||||
while (netif_running(dev) && received < budget
|
||||
&& (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
|
||||
while (netif_running(dev) && received < budget &&
|
||||
(RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
|
||||
u32 ring_offset = cur_rx % RX_BUF_LEN;
|
||||
u32 rx_status;
|
||||
unsigned int pkt_size;
|
||||
|
@ -2004,9 +2004,8 @@ no_early_rx:
|
|||
/* Malloc up new buffer, compatible with net-2e. */
|
||||
/* Omit the four octet CRC from the length. */
|
||||
|
||||
skb = netdev_alloc_skb(dev, pkt_size + NET_IP_ALIGN);
|
||||
skb = netdev_alloc_skb_ip_align(dev, pkt_size);
|
||||
if (likely(skb)) {
|
||||
skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */
|
||||
#if RX_BUF_IDX == 3
|
||||
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
|
||||
#else
|
||||
|
@ -2522,8 +2521,8 @@ static void __set_rx_mode (struct net_device *dev)
|
|||
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
||||
AcceptAllPhys;
|
||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||
} else if ((dev->mc_count > multicast_filter_limit)
|
||||
|| (dev->flags & IFF_ALLMULTI)) {
|
||||
} else if ((dev->mc_count > multicast_filter_limit) ||
|
||||
(dev->flags & IFF_ALLMULTI)) {
|
||||
/* Too many to filter perfectly -- accept all multicasts. */
|
||||
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||
|
|
|
@ -1001,7 +1001,7 @@ config SMC911X
|
|||
|
||||
config SMSC911X
|
||||
tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
|
||||
depends on ARM || SUPERH || BLACKFIN
|
||||
depends on ARM || SUPERH || BLACKFIN || MIPS
|
||||
select CRC32
|
||||
select MII
|
||||
select PHYLIB
|
||||
|
@ -3235,7 +3235,7 @@ config VIRTIO_NET
|
|||
|
||||
config VMXNET3
|
||||
tristate "VMware VMXNET3 ethernet driver"
|
||||
depends on PCI && X86 && INET
|
||||
depends on PCI && INET
|
||||
help
|
||||
This driver supports VMware's vmxnet3 virtual ethernet NIC.
|
||||
To compile this driver as a module, choose M here: the
|
||||
|
|
|
@ -328,7 +328,7 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
|
|||
|
||||
/* Reserve any actual interrupt. */
|
||||
if (dev->irq) {
|
||||
retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev);
|
||||
retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev);
|
||||
if (retval)
|
||||
goto err_out;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue