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
|
What: Ability for non root users to shm_get hugetlb pages based on mlock
|
||||||
resource limits
|
resource limits
|
||||||
When: 2.6.31
|
When: 2.6.31
|
||||||
|
|
|
@ -5,7 +5,7 @@ GigaSet 307x Device Driver
|
||||||
------------
|
------------
|
||||||
1.1. Hardware
|
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
|
ISDN DECT bases via Gigaset M101 Data, Gigaset M105 Data or direct USB
|
||||||
connection. The following devices are reported to be compatible:
|
connection. The following devices are reported to be compatible:
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ GigaSet 307x Device Driver
|
||||||
http://gigaset307x.sourceforge.net/
|
http://gigaset307x.sourceforge.net/
|
||||||
|
|
||||||
We had also reports from users of Gigaset M105 who could use the drivers
|
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.
|
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
|
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
|
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).
|
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
|
There are some user space tools available at
|
||||||
http://sourceforge.net/projects/gigaset307x/
|
http://sourceforge.net/projects/gigaset307x/
|
||||||
|
@ -102,20 +102,28 @@ GigaSet 307x Device Driver
|
||||||
2.3. ISDN4linux
|
2.3. ISDN4linux
|
||||||
----------
|
----------
|
||||||
This is the "normal" mode of operation. After loading the module you can
|
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.
|
set up the ISDN system just as you'd do with any ISDN card supported by
|
||||||
Your distribution should provide some configuration utility.
|
the ISDN4Linux subsystem. Most distributions provide some configuration
|
||||||
If not, you can use some HOWTOs like
|
utility. If not, you can use some HOWTOs like
|
||||||
http://www.linuxhaven.de/dlhp/HOWTO/DE-ISDN-HOWTO-5.html
|
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
|
debug output (see section 3.2.) shows something like this when dialing
|
||||||
CMD Received: ERROR
|
CMD Received: ERROR
|
||||||
Available Params: 0
|
Available Params: 0
|
||||||
Connection State: 0, Response: -1
|
Connection State: 0, Response: -1
|
||||||
gigaset_process_response: resp_code -1 in ConState 0 !
|
gigaset_process_response: resp_code -1 in ConState 0 !
|
||||||
Timeout occurred
|
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
|
This is needed for some devices [e.g. SX100] as they have problems with
|
||||||
the "normal" commands.
|
the "normal" commands.
|
||||||
|
@ -160,7 +168,7 @@ GigaSet 307x Device Driver
|
||||||
configuration file like /etc/modprobe.conf.local,
|
configuration file like /etc/modprobe.conf.local,
|
||||||
using that should be preferred.
|
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
|
Call-IDs are numbers used to tag commands to, and responses from, the
|
||||||
Gigaset base in order to support the simultaneous handling of multiple
|
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
|
You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
|
||||||
setting (ttyGxy is ttyGU0 or ttyGB0).
|
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 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
|
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
|
You have two or more DECT data adapters (M101/M105) and only the
|
||||||
first one you turn on works.
|
first one you turn on works.
|
||||||
Solution:
|
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:
|
Problem:
|
||||||
Messages like this:
|
Messages like this:
|
||||||
|
@ -236,7 +244,7 @@ GigaSet 307x Device Driver
|
||||||
appear in your syslog.
|
appear in your syslog.
|
||||||
Solution:
|
Solution:
|
||||||
Check whether your M10x wireless device is correctly registered to the
|
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
|
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]
|
uart6850= [HW,OSS]
|
||||||
Format: <io>,<irq>
|
Format: <io>,<irq>
|
||||||
|
|
||||||
|
uhash_entries= [KNL,NET]
|
||||||
|
Set number of hash buckets for UDP/UDP-Lite connections
|
||||||
|
|
||||||
uhci-hcd.ignore_oc=
|
uhci-hcd.ignore_oc=
|
||||||
[USB] Ignore overcurrent events (default N).
|
[USB] Ignore overcurrent events (default N).
|
||||||
Some badly-designed motherboards generate lots of
|
Some badly-designed motherboards generate lots of
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Linux Ethernet Bonding Driver HOWTO
|
Linux Ethernet Bonding Driver HOWTO
|
||||||
|
|
||||||
Latest update: 12 November 2007
|
Latest update: 23 September 2009
|
||||||
|
|
||||||
Initial release : Thomas Davis <tadavis at lbl.gov>
|
Initial release : Thomas Davis <tadavis at lbl.gov>
|
||||||
Corrections, HA extensions : 2000/10/03-15 :
|
Corrections, HA extensions : 2000/10/03-15 :
|
||||||
|
@ -614,6 +614,46 @@ primary
|
||||||
|
|
||||||
The primary option is only valid for active-backup mode.
|
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
|
updelay
|
||||||
|
|
||||||
Specifies the time, in milliseconds, to wait before enabling a
|
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.
|
additional choices may be available based on kernel configuration.
|
||||||
Default is set as part of 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
|
tcp_dsack - BOOLEAN
|
||||||
Allows TCP to send "duplicate" SACKs.
|
Allows TCP to send "duplicate" SACKs.
|
||||||
|
|
||||||
|
@ -723,6 +731,12 @@ accept_source_route - BOOLEAN
|
||||||
default TRUE (router)
|
default TRUE (router)
|
||||||
FALSE (host)
|
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
|
rp_filter - INTEGER
|
||||||
0 - No source validation.
|
0 - No source validation.
|
||||||
1 - Strict mode as defined in RFC3704 Strict Reverse Path
|
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
|
to prevent IP spoofing from DDos attacks. If using asymmetric routing
|
||||||
or other complicated routing, then loose mode is recommended.
|
or other complicated routing, then loose mode is recommended.
|
||||||
|
|
||||||
conf/all/rp_filter must also be set to non-zero to do source validation
|
The max value from conf/{all,interface}/rp_filter is used
|
||||||
on the interface
|
when doing source validation on the {interface}.
|
||||||
|
|
||||||
Default value is 0. Note that some distributions enable it
|
Default value is 0. Note that some distributions enable it
|
||||||
in startup scripts.
|
in startup scripts.
|
||||||
|
@ -1086,6 +1100,24 @@ accept_dad - INTEGER
|
||||||
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
|
2: Enable DAD, and disable IPv6 operation if MAC-based duplicate
|
||||||
link-local address has been found.
|
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/*:
|
icmp/*:
|
||||||
ratelimit - INTEGER
|
ratelimit - INTEGER
|
||||||
Limit the maximal rates for sending ICMPv6 packets.
|
Limit the maximal rates for sending ICMPv6 packets.
|
||||||
|
|
|
@ -178,3 +178,13 @@ External interrupts:
|
||||||
external irq3: interrupts = <1 3 n>;
|
external irq3: interrupts = <1 3 n>;
|
||||||
'n' is sense (0: level high, 1: edge rising, 2: edge falling 3: level low)
|
'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/
|
F: net/ax25/
|
||||||
|
|
||||||
B43 WIRELESS DRIVER
|
B43 WIRELESS DRIVER
|
||||||
M: Michael Buesch <mb@bu3sch.de>
|
|
||||||
M: Stefano Brivio <stefano.brivio@polimi.it>
|
M: Stefano Brivio <stefano.brivio@polimi.it>
|
||||||
L: linux-wireless@vger.kernel.org
|
L: linux-wireless@vger.kernel.org
|
||||||
W: http://linuxwireless.org/en/users/Drivers/b43
|
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
|
S: Supported
|
||||||
F: drivers/net/wireless/iwlwifi/
|
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
|
IOC3 ETHERNET DRIVER
|
||||||
M: Ralf Baechle <ralf@linux-mips.org>
|
M: Ralf Baechle <ralf@linux-mips.org>
|
||||||
L: linux-mips@linux-mips.org
|
L: linux-mips@linux-mips.org
|
||||||
|
@ -3741,9 +3749,9 @@ F: include/linux/if_*
|
||||||
F: include/linux/*device.h
|
F: include/linux/*device.h
|
||||||
|
|
||||||
NETXEN (1/10) GbE SUPPORT
|
NETXEN (1/10) GbE SUPPORT
|
||||||
M: Dhananjay Phadke <dhananjay@netxen.com>
|
M: Amit Kumar Salecha <amit.salecha@qlogic.com>
|
||||||
L: netdev@vger.kernel.org
|
L: netdev@vger.kernel.org
|
||||||
W: http://www.netxen.com
|
W: http://www.qlogic.com
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/netxen/
|
F: drivers/net/netxen/
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,8 @@
|
||||||
#define SO_TIMESTAMPING 37
|
#define SO_TIMESTAMPING 37
|
||||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||||
* have to define SOCK_NONBLOCK to a different value here.
|
* have to define SOCK_NONBLOCK to a different value here.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -433,10 +433,11 @@
|
||||||
#define __NR_signalfd 476
|
#define __NR_signalfd 476
|
||||||
#define __NR_timerfd 477
|
#define __NR_timerfd 477
|
||||||
#define __NR_eventfd 478
|
#define __NR_eventfd 478
|
||||||
|
#define __NR_recvmmsg 479
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#define NR_SYSCALLS 479
|
#define NR_SYSCALLS 480
|
||||||
|
|
||||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||||
#define __ARCH_WANT_OLD_READDIR
|
#define __ARCH_WANT_OLD_READDIR
|
||||||
|
|
|
@ -497,6 +497,7 @@ sys_call_table:
|
||||||
.quad sys_signalfd
|
.quad sys_signalfd
|
||||||
.quad sys_ni_syscall
|
.quad sys_ni_syscall
|
||||||
.quad sys_eventfd
|
.quad sys_eventfd
|
||||||
|
.quad sys_recvmmsg
|
||||||
|
|
||||||
.size sys_call_table, . - sys_call_table
|
.size sys_call_table, . - sys_call_table
|
||||||
.type sys_call_table, @object
|
.type sys_call_table, @object
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -374,6 +374,7 @@
|
||||||
CALL(sys_pwritev)
|
CALL(sys_pwritev)
|
||||||
CALL(sys_rt_tgsigqueueinfo)
|
CALL(sys_rt_tgsigqueueinfo)
|
||||||
CALL(sys_perf_event_open)
|
CALL(sys_perf_event_open)
|
||||||
|
/* 365 */ CALL(sys_recvmmsg)
|
||||||
#ifndef syscalls_counted
|
#ifndef syscalls_counted
|
||||||
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
|
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
|
||||||
#define syscalls_counted
|
#define syscalls_counted
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* __ASM_AVR32_SOCKET_H */
|
#endif /* __ASM_AVR32_SOCKET_H */
|
||||||
|
|
|
@ -295,4 +295,5 @@ sys_call_table:
|
||||||
.long sys_signalfd
|
.long sys_signalfd
|
||||||
.long sys_ni_syscall /* 280, was sys_timerfd */
|
.long sys_ni_syscall /* 280, was sys_timerfd */
|
||||||
.long sys_eventfd
|
.long sys_eventfd
|
||||||
|
.long sys_recvmmsg
|
||||||
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
|
.long sys_ni_syscall /* r8 is saturated at nr_syscalls */
|
||||||
|
|
|
@ -1600,6 +1600,7 @@ ENTRY(_sys_call_table)
|
||||||
.long _sys_pwritev
|
.long _sys_pwritev
|
||||||
.long _sys_rt_tgsigqueueinfo
|
.long _sys_rt_tgsigqueueinfo
|
||||||
.long _sys_perf_event_open
|
.long _sys_perf_event_open
|
||||||
|
.long _sys_recvmmsg /* 370 */
|
||||||
|
|
||||||
.rept NR_syscalls-(.-_sys_call_table)/4
|
.rept NR_syscalls-(.-_sys_call_table)/4
|
||||||
.long _sys_ni_syscall
|
.long _sys_ni_syscall
|
||||||
|
|
|
@ -62,6 +62,8 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -60,5 +60,7 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -69,4 +69,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_IA64_SOCKET_H */
|
#endif /* _ASM_IA64_SOCKET_H */
|
||||||
|
|
|
@ -311,11 +311,12 @@
|
||||||
#define __NR_preadv 1319
|
#define __NR_preadv 1319
|
||||||
#define __NR_pwritev 1320
|
#define __NR_pwritev 1320
|
||||||
#define __NR_rt_tgsigqueueinfo 1321
|
#define __NR_rt_tgsigqueueinfo 1321
|
||||||
|
#define __NR_rt_recvmmsg 1322
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#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
|
* The following defines stop scripts/checksyscalls.sh from complaining about
|
||||||
|
|
|
@ -1806,6 +1806,7 @@ sys_call_table:
|
||||||
data8 sys_preadv
|
data8 sys_preadv
|
||||||
data8 sys_pwritev // 1320
|
data8 sys_pwritev // 1320
|
||||||
data8 sys_rt_tgsigqueueinfo
|
data8 sys_rt_tgsigqueueinfo
|
||||||
|
data8 sys_recvmmsg
|
||||||
|
|
||||||
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
|
||||||
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_M32R_SOCKET_H */
|
#endif /* _ASM_M32R_SOCKET_H */
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -371,3 +371,4 @@ ENTRY(sys_call_table)
|
||||||
.long sys_ni_syscall
|
.long sys_ni_syscall
|
||||||
.long sys_rt_tgsigqueueinfo /* 365 */
|
.long sys_rt_tgsigqueueinfo /* 365 */
|
||||||
.long sys_perf_event_open
|
.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 SO_TIMESTAMPING 37
|
||||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/** sock_type - Socket types
|
/** sock_type - Socket types
|
||||||
|
|
|
@ -355,16 +355,17 @@
|
||||||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
|
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 332)
|
||||||
#define __NR_perf_event_open (__NR_Linux + 333)
|
#define __NR_perf_event_open (__NR_Linux + 333)
|
||||||
#define __NR_accept4 (__NR_Linux + 334)
|
#define __NR_accept4 (__NR_Linux + 334)
|
||||||
|
#define __NR_recvmmsg (__NR_Linux + 335)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last Linux o32 flavoured syscall
|
* Offset of the last Linux o32 flavoured syscall
|
||||||
*/
|
*/
|
||||||
#define __NR_Linux_syscalls 334
|
#define __NR_Linux_syscalls 335
|
||||||
|
|
||||||
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
|
||||||
|
|
||||||
#define __NR_O32_Linux 4000
|
#define __NR_O32_Linux 4000
|
||||||
#define __NR_O32_Linux_syscalls 334
|
#define __NR_O32_Linux_syscalls 335
|
||||||
|
|
||||||
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
#if _MIPS_SIM == _MIPS_SIM_ABI64
|
||||||
|
|
||||||
|
@ -666,16 +667,17 @@
|
||||||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
|
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 291)
|
||||||
#define __NR_perf_event_open (__NR_Linux + 292)
|
#define __NR_perf_event_open (__NR_Linux + 292)
|
||||||
#define __NR_accept4 (__NR_Linux + 293)
|
#define __NR_accept4 (__NR_Linux + 293)
|
||||||
|
#define __NR_recvmmsg (__NR_Linux + 294)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last Linux 64-bit flavoured syscall
|
* 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 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
|
||||||
|
|
||||||
#define __NR_64_Linux 5000
|
#define __NR_64_Linux 5000
|
||||||
#define __NR_64_Linux_syscalls 293
|
#define __NR_64_Linux_syscalls 294
|
||||||
|
|
||||||
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
#if _MIPS_SIM == _MIPS_SIM_NABI32
|
||||||
|
|
||||||
|
@ -981,16 +983,17 @@
|
||||||
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
|
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 295)
|
||||||
#define __NR_perf_event_open (__NR_Linux + 296)
|
#define __NR_perf_event_open (__NR_Linux + 296)
|
||||||
#define __NR_accept4 (__NR_Linux + 297)
|
#define __NR_accept4 (__NR_Linux + 297)
|
||||||
|
#define __NR_recvmmsg (__NR_Linux + 298)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Offset of the last N32 flavoured syscall
|
* Offset of the last N32 flavoured syscall
|
||||||
*/
|
*/
|
||||||
#define __NR_Linux_syscalls 297
|
#define __NR_Linux_syscalls 298
|
||||||
|
|
||||||
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
|
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
|
||||||
|
|
||||||
#define __NR_N32_Linux 6000
|
#define __NR_N32_Linux 6000
|
||||||
#define __NR_N32_Linux_syscalls 297
|
#define __NR_N32_Linux_syscalls 298
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
|
|
@ -583,6 +583,7 @@ einval: li v0, -ENOSYS
|
||||||
sys sys_rt_tgsigqueueinfo 4
|
sys sys_rt_tgsigqueueinfo 4
|
||||||
sys sys_perf_event_open 5
|
sys sys_perf_event_open 5
|
||||||
sys sys_accept4 4
|
sys sys_accept4 4
|
||||||
|
sys sys_recvmmsg 5
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
/* We pre-compute the number of _instruction_ bytes needed to
|
/* We pre-compute the number of _instruction_ bytes needed to
|
||||||
|
|
|
@ -420,4 +420,5 @@ sys_call_table:
|
||||||
PTR sys_rt_tgsigqueueinfo
|
PTR sys_rt_tgsigqueueinfo
|
||||||
PTR sys_perf_event_open
|
PTR sys_perf_event_open
|
||||||
PTR sys_accept4
|
PTR sys_accept4
|
||||||
|
PTR sys_recvmmsg
|
||||||
.size sys_call_table,.-sys_call_table
|
.size sys_call_table,.-sys_call_table
|
||||||
|
|
|
@ -418,4 +418,5 @@ EXPORT(sysn32_call_table)
|
||||||
PTR compat_sys_rt_tgsigqueueinfo /* 5295 */
|
PTR compat_sys_rt_tgsigqueueinfo /* 5295 */
|
||||||
PTR sys_perf_event_open
|
PTR sys_perf_event_open
|
||||||
PTR sys_accept4
|
PTR sys_accept4
|
||||||
|
PTR compat_sys_recvmmsg
|
||||||
.size sysn32_call_table,.-sysn32_call_table
|
.size sysn32_call_table,.-sysn32_call_table
|
||||||
|
|
|
@ -538,4 +538,5 @@ sys_call_table:
|
||||||
PTR compat_sys_rt_tgsigqueueinfo
|
PTR compat_sys_rt_tgsigqueueinfo
|
||||||
PTR sys_perf_event_open
|
PTR sys_perf_event_open
|
||||||
PTR sys_accept4
|
PTR sys_accept4
|
||||||
|
PTR compat_sys_recvmmsg
|
||||||
.size sys_call_table,.-sys_call_table
|
.size sys_call_table,.-sys_call_table
|
||||||
|
|
|
@ -60,4 +60,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -59,6 +59,8 @@
|
||||||
#define SO_TIMESTAMPING 0x4020
|
#define SO_TIMESTAMPING 0x4020
|
||||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 0x4021
|
||||||
|
|
||||||
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
|
||||||
* have to define SOCK_NONBLOCK to a different value here.
|
* have to define SOCK_NONBLOCK to a different value here.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -67,4 +67,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||||
|
|
|
@ -83,8 +83,9 @@ static void appldata_get_net_sum_data(void *data)
|
||||||
rx_dropped = 0;
|
rx_dropped = 0;
|
||||||
tx_dropped = 0;
|
tx_dropped = 0;
|
||||||
collisions = 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);
|
const struct net_device_stats *stats = dev_get_stats(dev);
|
||||||
|
|
||||||
rx_packets += stats->rx_packets;
|
rx_packets += stats->rx_packets;
|
||||||
|
@ -98,7 +99,8 @@ static void appldata_get_net_sum_data(void *data)
|
||||||
collisions += stats->collisions;
|
collisions += stats->collisions;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
read_unlock(&dev_base_lock);
|
rcu_read_unlock();
|
||||||
|
|
||||||
net_data->nr_interfaces = i;
|
net_data->nr_interfaces = i;
|
||||||
net_data->rx_packets = rx_packets;
|
net_data->rx_packets = rx_packets;
|
||||||
net_data->tx_packets = tx_packets;
|
net_data->tx_packets = tx_packets;
|
||||||
|
|
|
@ -68,4 +68,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _ASM_SOCKET_H */
|
#endif /* _ASM_SOCKET_H */
|
||||||
|
|
|
@ -7,6 +7,7 @@ struct sh_eth_plat_data {
|
||||||
int phy;
|
int phy;
|
||||||
int edmac_endian;
|
int edmac_endian;
|
||||||
|
|
||||||
|
unsigned char mac_addr[6];
|
||||||
unsigned no_ether_link:1;
|
unsigned no_ether_link:1;
|
||||||
unsigned ether_link_active_low:1;
|
unsigned ether_link_active_low:1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -391,3 +391,4 @@ sys_call_table:
|
||||||
.long sys_pwritev
|
.long sys_pwritev
|
||||||
.long sys_rt_tgsigqueueinfo
|
.long sys_rt_tgsigqueueinfo
|
||||||
.long sys_perf_event_open
|
.long sys_perf_event_open
|
||||||
|
.long sys_recvmmsg /* 365 */
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
#define SO_TIMESTAMPING 0x0023
|
#define SO_TIMESTAMPING 0x0023
|
||||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 0x0024
|
||||||
|
|
||||||
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
/* Security levels - as per NRL IPv6 - don't actually do anything */
|
||||||
#define SO_SECURITY_AUTHENTICATION 0x5001
|
#define SO_SECURITY_AUTHENTICATION 0x5001
|
||||||
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
|
||||||
|
|
|
@ -396,8 +396,9 @@
|
||||||
#define __NR_pwritev 325
|
#define __NR_pwritev 325
|
||||||
#define __NR_rt_tgsigqueueinfo 326
|
#define __NR_rt_tgsigqueueinfo 326
|
||||||
#define __NR_perf_event_open 327
|
#define __NR_perf_event_open 327
|
||||||
|
#define __NR_recvmmsg 328
|
||||||
|
|
||||||
#define NR_SYSCALLS 328
|
#define NR_SYSCALLS 329
|
||||||
|
|
||||||
#ifdef __32bit_syscall_numbers__
|
#ifdef __32bit_syscall_numbers__
|
||||||
/* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
|
/* 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
|
/*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
|
/*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
|
/*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
|
/*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
|
.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
|
/*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 */
|
#endif /* CONFIG_COMPAT */
|
||||||
|
|
||||||
|
@ -158,4 +158,4 @@ sys_call_table:
|
||||||
/*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate
|
/*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
|
.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
|
/*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_pwritev
|
||||||
.quad compat_sys_rt_tgsigqueueinfo /* 335 */
|
.quad compat_sys_rt_tgsigqueueinfo /* 335 */
|
||||||
.quad sys_perf_event_open
|
.quad sys_perf_event_open
|
||||||
|
.quad compat_sys_recvmmsg
|
||||||
ia32_syscall_end:
|
ia32_syscall_end:
|
||||||
|
|
|
@ -342,10 +342,11 @@
|
||||||
#define __NR_pwritev 334
|
#define __NR_pwritev 334
|
||||||
#define __NR_rt_tgsigqueueinfo 335
|
#define __NR_rt_tgsigqueueinfo 335
|
||||||
#define __NR_perf_event_open 336
|
#define __NR_perf_event_open 336
|
||||||
|
#define __NR_recvmmsg 337
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#define NR_syscalls 337
|
#define NR_syscalls 338
|
||||||
|
|
||||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||||
#define __ARCH_WANT_OLD_READDIR
|
#define __ARCH_WANT_OLD_READDIR
|
||||||
|
|
|
@ -661,6 +661,8 @@ __SYSCALL(__NR_pwritev, sys_pwritev)
|
||||||
__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
|
__SYSCALL(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo)
|
||||||
#define __NR_perf_event_open 298
|
#define __NR_perf_event_open 298
|
||||||
__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
|
__SYSCALL(__NR_perf_event_open, sys_perf_event_open)
|
||||||
|
#define __NR_recvmmsg 299
|
||||||
|
__SYSCALL(__NR_recvmmsg, sys_recvmmsg)
|
||||||
|
|
||||||
#ifndef __NO_STUBS
|
#ifndef __NO_STUBS
|
||||||
#define __ARCH_WANT_OLD_READDIR
|
#define __ARCH_WANT_OLD_READDIR
|
||||||
|
|
|
@ -336,3 +336,4 @@ ENTRY(sys_call_table)
|
||||||
.long sys_pwritev
|
.long sys_pwritev
|
||||||
.long sys_rt_tgsigqueueinfo /* 335 */
|
.long sys_rt_tgsigqueueinfo /* 335 */
|
||||||
.long sys_perf_event_open
|
.long sys_perf_event_open
|
||||||
|
.long sys_recvmmsg
|
||||||
|
|
|
@ -71,4 +71,6 @@
|
||||||
#define SO_PROTOCOL 38
|
#define SO_PROTOCOL 38
|
||||||
#define SO_DOMAIN 39
|
#define SO_DOMAIN 39
|
||||||
|
|
||||||
|
#define SO_RXQ_OVFL 40
|
||||||
|
|
||||||
#endif /* _XTENSA_SOCKET_H */
|
#endif /* _XTENSA_SOCKET_H */
|
||||||
|
|
|
@ -681,8 +681,10 @@ __SYSCALL(304, sys_signalfd, 3)
|
||||||
__SYSCALL(305, sys_ni_syscall, 0)
|
__SYSCALL(305, sys_ni_syscall, 0)
|
||||||
#define __NR_eventfd 306
|
#define __NR_eventfd 306
|
||||||
__SYSCALL(306, sys_eventfd, 1)
|
__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
|
* sysxtensa syscall handler
|
||||||
|
|
|
@ -2351,6 +2351,7 @@ static void __init amb_check_args (void) {
|
||||||
MODULE_AUTHOR(maintainer_string);
|
MODULE_AUTHOR(maintainer_string);
|
||||||
MODULE_DESCRIPTION(description_string);
|
MODULE_DESCRIPTION(description_string);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_FIRMWARE("atmsar11.fw");
|
||||||
module_param(debug, ushort, 0644);
|
module_param(debug, ushort, 0644);
|
||||||
module_param(cmds, uint, 0);
|
module_param(cmds, uint, 0);
|
||||||
module_param(txs, 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 media_index = FORE200E_MEDIA_INDEX(fore200e->bus->read(&fore200e->cp_queues->media_type));
|
||||||
u32 oc3_index;
|
u32 oc3_index;
|
||||||
|
|
||||||
if ((media_index < 0) || (media_index > 4))
|
if (media_index > 4)
|
||||||
media_index = 5;
|
media_index = 5;
|
||||||
|
|
||||||
switch (fore200e->loop_mode) {
|
switch (fore200e->loop_mode) {
|
||||||
case ATM_LM_NONE: oc3_index = 0;
|
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);
|
spin_lock_irqsave(&he_dev->global_lock, flags);
|
||||||
switch (reg.type) {
|
switch (reg.type) {
|
||||||
case HE_REGTYPE_PCI:
|
case HE_REGTYPE_PCI:
|
||||||
if (reg.addr < 0 || reg.addr >= HE_REGMAP_SIZE) {
|
if (reg.addr >= HE_REGMAP_SIZE) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,9 @@ MODULE_AUTHOR("Traverse Technologies <support@traverse.com.au>");
|
||||||
MODULE_DESCRIPTION("Solos PCI driver");
|
MODULE_DESCRIPTION("Solos PCI driver");
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
MODULE_LICENSE("GPL");
|
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(reset, "Reset Solos chips on startup");
|
||||||
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
||||||
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
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 numblocks = 0;
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
if (chip == 0) {
|
switch (chip) {
|
||||||
|
case 0:
|
||||||
fw_name = "solos-FPGA.bin";
|
fw_name = "solos-FPGA.bin";
|
||||||
blocksize = FPGA_BLOCK;
|
blocksize = FPGA_BLOCK;
|
||||||
}
|
break;
|
||||||
|
case 1:
|
||||||
if (chip == 1) {
|
|
||||||
fw_name = "solos-Firmware.bin";
|
fw_name = "solos-Firmware.bin";
|
||||||
blocksize = SOLOS_BLOCK;
|
blocksize = SOLOS_BLOCK;
|
||||||
}
|
break;
|
||||||
|
case 2:
|
||||||
if (chip == 2){
|
|
||||||
if (card->fpga_version > LEGACY_BUFFERS){
|
if (card->fpga_version > LEGACY_BUFFERS){
|
||||||
fw_name = "solos-db-FPGA.bin";
|
fw_name = "solos-db-FPGA.bin";
|
||||||
blocksize = FPGA_BLOCK;
|
blocksize = FPGA_BLOCK;
|
||||||
} else {
|
} 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;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
case 3:
|
||||||
if (chip == 3){
|
|
||||||
if (card->fpga_version > LEGACY_BUFFERS){
|
if (card->fpga_version > LEGACY_BUFFERS){
|
||||||
fw_name = "solos-Firmware.bin";
|
fw_name = "solos-Firmware.bin";
|
||||||
blocksize = SOLOS_BLOCK;
|
blocksize = SOLOS_BLOCK;
|
||||||
} else {
|
} 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"
|
||||||
return -EPERM;
|
" daughter board upgrades\n");
|
||||||
|
return -EPERM;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_firmware(&fw, fw_name, &card->dev->dev))
|
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;
|
struct dentry *root_dir, *config_dir, *status_dir;
|
||||||
|
|
||||||
/* config */
|
/* config */
|
||||||
struct dentry *drvdbg;
|
|
||||||
struct dentry *psmode;
|
struct dentry *psmode;
|
||||||
struct dentry *pscmd;
|
struct dentry *pscmd;
|
||||||
struct dentry *hsmode;
|
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_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||||
|
|
||||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
|
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);
|
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#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);
|
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)
|
static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
@ -258,28 +290,7 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||||
|
|
||||||
if (priv->btmrvl_dev.pscmd) {
|
if (priv->btmrvl_dev.pscmd) {
|
||||||
priv->btmrvl_dev.pscmd = 0;
|
priv->btmrvl_dev.pscmd = 0;
|
||||||
|
btmrvl_enable_ps(priv);
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->btmrvl_dev.hscmd) {
|
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;
|
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
|
||||||
|
|
||||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||||
|
priv->btmrvl_dev.psmode = 1;
|
||||||
|
btmrvl_enable_ps(priv);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1001,3 +1003,5 @@ MODULE_AUTHOR("Marvell International Ltd.");
|
||||||
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
MODULE_DESCRIPTION("Marvell BT-over-SDIO driver ver " VERSION);
|
||||||
MODULE_VERSION(VERSION);
|
MODULE_VERSION(VERSION);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_FIRMWARE("sd8688_helper.bin");
|
||||||
|
MODULE_FIRMWARE("sd8688.bin");
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
|
|
||||||
#define VERSION "1.3"
|
#define VERSION "1.3"
|
||||||
|
|
||||||
static int minor = MISC_DYNAMIC_MINOR;
|
|
||||||
|
|
||||||
struct vhci_data {
|
struct vhci_data {
|
||||||
struct hci_dev *hdev;
|
struct hci_dev *hdev;
|
||||||
|
|
||||||
|
@ -218,12 +216,6 @@ static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
||||||
return POLLOUT | POLLWRNORM;
|
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)
|
static int vhci_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
struct vhci_data *data;
|
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 = {
|
static const struct file_operations vhci_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
.read = vhci_read,
|
.read = vhci_read,
|
||||||
.write = vhci_write,
|
.write = vhci_write,
|
||||||
.poll = vhci_poll,
|
.poll = vhci_poll,
|
||||||
.ioctl = vhci_ioctl,
|
|
||||||
.open = vhci_open,
|
.open = vhci_open,
|
||||||
.release = vhci_release,
|
.release = vhci_release,
|
||||||
};
|
};
|
||||||
|
@ -302,18 +294,12 @@ static int __init vhci_init(void)
|
||||||
{
|
{
|
||||||
BT_INFO("Virtual HCI driver ver %s", VERSION);
|
BT_INFO("Virtual HCI driver ver %s", VERSION);
|
||||||
|
|
||||||
if (misc_register(&vhci_miscdev) < 0) {
|
return misc_register(&vhci_miscdev);
|
||||||
BT_ERR("Can't register misc device with minor %d", minor);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit vhci_exit(void)
|
static void __exit vhci_exit(void)
|
||||||
{
|
{
|
||||||
if (misc_deregister(&vhci_miscdev) < 0)
|
misc_deregister(&vhci_miscdev);
|
||||||
BT_ERR("Can't unregister misc device with minor %d", minor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(vhci_init);
|
module_init(vhci_init);
|
||||||
|
|
|
@ -32,9 +32,29 @@
|
||||||
#include <net/nl802154.h>
|
#include <net/nl802154.h>
|
||||||
#include <net/wpan-phy.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.
|
* 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);
|
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
|
* device. If the device has not yet had a short address assigned
|
||||||
* then this should return 0xFFFF to indicate a lack of association.
|
* 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);
|
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
|
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||||
* document.
|
* 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);
|
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
|
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||||
* document.
|
* 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);
|
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,
|
static int fake_assoc_req(struct net_device *dev,
|
||||||
struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
|
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);
|
mutex_lock(&phy->pib_lock);
|
||||||
phy->current_channel = channel;
|
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 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
|
||||||
u8 coord_realign)
|
u8 coord_realign)
|
||||||
{
|
{
|
||||||
struct wpan_phy *phy = net_to_phy(dev);
|
struct wpan_phy *phy = fake_to_phy(dev);
|
||||||
|
|
||||||
mutex_lock(&phy->pib_lock);
|
mutex_lock(&phy->pib_lock);
|
||||||
phy->current_channel = channel;
|
phy->current_channel = channel;
|
||||||
|
@ -239,6 +259,8 @@ static struct ieee802154_mlme_ops fake_mlme = {
|
||||||
.start_req = fake_start_req,
|
.start_req = fake_start_req,
|
||||||
.scan_req = fake_scan_req,
|
.scan_req = fake_scan_req,
|
||||||
|
|
||||||
|
.get_phy = fake_get_phy,
|
||||||
|
|
||||||
.get_pan_id = fake_get_pan_id,
|
.get_pan_id = fake_get_pan_id,
|
||||||
.get_short_addr = fake_get_short_addr,
|
.get_short_addr = fake_get_short_addr,
|
||||||
.get_dsn = fake_get_dsn,
|
.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)
|
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);
|
wpan_phy_unregister(phy);
|
||||||
free_netdev(dev);
|
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)
|
static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
struct fakehard_priv *priv;
|
||||||
struct wpan_phy *phy = wpan_phy_alloc(0);
|
struct wpan_phy *phy = wpan_phy_alloc(0);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!phy)
|
if (!phy)
|
||||||
return -ENOMEM;
|
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) {
|
if (!dev) {
|
||||||
wpan_phy_free(phy);
|
wpan_phy_free(phy);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -353,12 +376,23 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||||
dev->addr_len);
|
dev->addr_len);
|
||||||
memcpy(dev->perm_addr, dev->dev_addr, 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;
|
phy->transmit_power = 0xbf;
|
||||||
|
|
||||||
dev->netdev_ops = &fake_ops;
|
dev->netdev_ops = &fake_ops;
|
||||||
dev->ml_priv = &fake_mlme;
|
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
|
* If the name is a format string the caller wants us to do a
|
||||||
* name allocation.
|
* name allocation.
|
||||||
|
@ -369,11 +403,12 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wpan_phy_set_dev(phy, &pdev->dev);
|
||||||
SET_NETDEV_DEV(dev, &phy->dev);
|
SET_NETDEV_DEV(dev, &phy->dev);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, dev);
|
platform_set_drvdata(pdev, dev);
|
||||||
|
|
||||||
err = wpan_phy_register(&pdev->dev, phy);
|
err = wpan_phy_register(phy);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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,
|
sprintf(drvinfo->fw_version, "%u.%u", nesadapter->firmware_version>>16,
|
||||||
nesadapter->firmware_version & 0x000000ff);
|
nesadapter->firmware_version & 0x000000ff);
|
||||||
strcpy(drvinfo->version, DRV_VERSION);
|
strcpy(drvinfo->version, DRV_VERSION);
|
||||||
drvinfo->n_stats = nes_netdev_get_stats_count(netdev);
|
|
||||||
drvinfo->testinfo_len = 0;
|
drvinfo->testinfo_len = 0;
|
||||||
drvinfo->eedump_len = 0;
|
drvinfo->eedump_len = 0;
|
||||||
drvinfo->regdump_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_rx_csum = nes_netdev_get_rx_csum,
|
||||||
.get_sg = ethtool_op_get_sg,
|
.get_sg = ethtool_op_get_sg,
|
||||||
.get_strings = nes_netdev_get_strings,
|
.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_ethtool_stats = nes_netdev_get_ethtool_stats,
|
||||||
.get_drvinfo = nes_netdev_get_drvinfo,
|
.get_drvinfo = nes_netdev_get_drvinfo,
|
||||||
.get_coalesce = nes_netdev_get_coalesce,
|
.get_coalesce = nes_netdev_get_coalesce,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
menuconfig ISDN_DRV_GIGASET
|
menuconfig ISDN_DRV_GIGASET
|
||||||
tristate "Siemens Gigaset support"
|
tristate "Siemens Gigaset support"
|
||||||
depends on ISDN_I4L
|
|
||||||
select CRC_CCITT
|
select CRC_CCITT
|
||||||
select BITREVERSE
|
select BITREVERSE
|
||||||
help
|
help
|
||||||
|
@ -11,9 +10,33 @@ menuconfig ISDN_DRV_GIGASET
|
||||||
If you have one of these devices, say M here and for at least
|
If you have one of these devices, say M here and for at least
|
||||||
one of the connection specific parts that follow.
|
one of the connection specific parts that follow.
|
||||||
This will build a module called "gigaset".
|
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
|
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
|
config GIGASET_BASE
|
||||||
tristate "Gigaset base station support"
|
tristate "Gigaset base station support"
|
||||||
depends on USB
|
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
|
usb_gigaset-y := usb-gigaset.o
|
||||||
ser_gigaset-y := ser-gigaset.o
|
ser_gigaset-y := ser-gigaset.o
|
||||||
bas_gigaset-y := bas-gigaset.o isocdata.o
|
bas_gigaset-y := bas-gigaset.o isocdata.o
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
/* check if byte must be stuffed/escaped
|
/* check if byte must be stuffed/escaped
|
||||||
* I'm not sure which data should be encoded.
|
* 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.
|
* less than 0x20, the flag sequence and the control escape char.
|
||||||
*/
|
*/
|
||||||
static inline int muststuff(unsigned char c)
|
static inline int muststuff(unsigned char c)
|
||||||
|
@ -35,303 +35,383 @@ static inline int muststuff(unsigned char c)
|
||||||
|
|
||||||
/* == data input =========================================================== */
|
/* == 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:
|
* Return value:
|
||||||
* number of processed bytes
|
* number of processed bytes
|
||||||
*/
|
*/
|
||||||
static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
|
static unsigned cmd_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||||
struct inbuf_t *inbuf)
|
|
||||||
{
|
{
|
||||||
|
unsigned char *src = inbuf->data + inbuf->head;
|
||||||
struct cardstate *cs = inbuf->cs;
|
struct cardstate *cs = inbuf->cs;
|
||||||
unsigned cbytes = cs->cbytes;
|
unsigned cbytes = cs->cbytes;
|
||||||
int inputstate = inbuf->inputstate;
|
unsigned procbytes = 0;
|
||||||
int startbytes = numbytes;
|
unsigned char c;
|
||||||
|
|
||||||
for (;;) {
|
while (procbytes < numbytes) {
|
||||||
cs->respdata[cbytes] = c;
|
c = *src++;
|
||||||
if (c == 10 || c == 13) {
|
procbytes++;
|
||||||
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;
|
|
||||||
|
|
||||||
if (cs->dle &&
|
switch (c) {
|
||||||
!(inputstate & INS_DLE_command)) {
|
case '\n':
|
||||||
inputstate &= ~INS_command;
|
if (cbytes == 0 && cs->respdata[0] == '\r') {
|
||||||
|
/* collapse LF with preceding CR */
|
||||||
|
cs->respdata[0] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
/* --v-- fall through --v-- */
|
||||||
/* advance in line buffer, checking for overflow */
|
case '\r':
|
||||||
if (cbytes < MAX_RESP_SIZE - 1)
|
/* end of message line, pass to response handler */
|
||||||
cbytes++;
|
gig_dbg(DEBUG_TRANSCMD, "%s: End of Message (%d Bytes)",
|
||||||
else
|
__func__, cbytes);
|
||||||
dev_warn(cs->dev, "response too large\n");
|
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)
|
/* store EOL byte for CRLF collapsing */
|
||||||
break;
|
cs->respdata[0] = c;
|
||||||
c = *src++;
|
|
||||||
--numbytes;
|
/* cs->dle may have changed */
|
||||||
if (c == DLE_FLAG &&
|
if (cs->dle && !(inbuf->inputstate & INS_DLE_command))
|
||||||
(cs->dle || inputstate & INS_DLE_command)) {
|
inbuf->inputstate &= ~INS_command;
|
||||||
inputstate |= INS_DLE_char;
|
|
||||||
break;
|
/* 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;
|
cs->cbytes = cbytes;
|
||||||
inbuf->inputstate = inputstate;
|
return procbytes;
|
||||||
|
|
||||||
return startbytes - numbytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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:
|
* Return value:
|
||||||
* number of processed bytes
|
* number of processed bytes
|
||||||
*/
|
*/
|
||||||
static inline int lock_loop(unsigned char *src, int numbytes,
|
static unsigned lock_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||||
struct inbuf_t *inbuf)
|
|
||||||
{
|
{
|
||||||
struct cardstate *cs = inbuf->cs;
|
unsigned char *src = inbuf->data + inbuf->head;
|
||||||
|
|
||||||
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
|
|
||||||
numbytes, src);
|
|
||||||
gigaset_if_receive(cs, src, numbytes);
|
|
||||||
|
|
||||||
|
gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src);
|
||||||
|
gigaset_if_receive(inbuf->cs, src, numbytes);
|
||||||
return 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
|
/* 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.
|
* 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.
|
* 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.
|
* If DLE is encountered, return immediately to let the caller handle it.
|
||||||
* Return value:
|
* Return value:
|
||||||
* number of processed bytes
|
* number of processed bytes
|
||||||
* numbytes (all bytes processed) on error --FIXME
|
|
||||||
*/
|
*/
|
||||||
static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
|
static unsigned hdlc_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||||
struct inbuf_t *inbuf)
|
|
||||||
{
|
{
|
||||||
struct cardstate *cs = inbuf->cs;
|
struct cardstate *cs = inbuf->cs;
|
||||||
struct bc_state *bcs = inbuf->bcs;
|
struct bc_state *bcs = cs->bcs;
|
||||||
int inputstate = bcs->inputstate;
|
int inputstate = bcs->inputstate;
|
||||||
__u16 fcs = bcs->fcs;
|
__u16 fcs = bcs->fcs;
|
||||||
struct sk_buff *skb = bcs->skb;
|
struct sk_buff *skb = bcs->skb;
|
||||||
unsigned char error;
|
unsigned char *src = inbuf->data + inbuf->head;
|
||||||
struct sk_buff *compskb;
|
unsigned procbytes = 0;
|
||||||
int startbytes = numbytes;
|
unsigned char c;
|
||||||
int l;
|
|
||||||
|
|
||||||
if (unlikely(inputstate & INS_byte_stuff)) {
|
if (inputstate & INS_byte_stuff) {
|
||||||
|
if (!numbytes)
|
||||||
|
return 0;
|
||||||
inputstate &= ~INS_byte_stuff;
|
inputstate &= ~INS_byte_stuff;
|
||||||
goto byte_stuff;
|
goto byte_stuff;
|
||||||
}
|
}
|
||||||
for (;;) {
|
|
||||||
if (unlikely(c == PPP_ESCAPE)) {
|
while (procbytes < numbytes) {
|
||||||
if (unlikely(!numbytes)) {
|
c = *src++;
|
||||||
inputstate |= INS_byte_stuff;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
c = *src++;
|
}
|
||||||
--numbytes;
|
|
||||||
if (unlikely(c == DLE_FLAG &&
|
if (c == PPP_ESCAPE) {
|
||||||
(cs->dle ||
|
/* byte stuffing indicator: pull in next byte */
|
||||||
inbuf->inputstate & INS_DLE_command))) {
|
if (procbytes >= numbytes) {
|
||||||
inbuf->inputstate |= INS_DLE_char;
|
/* end of buffer, save for later processing */
|
||||||
inputstate |= INS_byte_stuff;
|
inputstate |= INS_byte_stuff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
byte_stuff:
|
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;
|
c ^= PPP_TRANS;
|
||||||
if (unlikely(!muststuff(c)))
|
#ifdef CONFIG_GIGASET_DEBUG
|
||||||
|
if (!muststuff(c))
|
||||||
gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", 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
|
#endif
|
||||||
|
} else if (c == PPP_FLAG) {
|
||||||
/* end of frame */
|
/* end of frame: process content if any */
|
||||||
error = 1;
|
if (inputstate & INS_have_data) {
|
||||||
gigaset_rcv_error(NULL, cs, bcs);
|
|
||||||
} else if (!(inputstate & INS_have_data)) { /* 7E 7E */
|
|
||||||
#ifdef CONFIG_GIGASET_DEBUG
|
|
||||||
++bcs->emptycount;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
gig_dbg(DEBUG_HDLC,
|
gig_dbg(DEBUG_HDLC,
|
||||||
"7e----------------------------");
|
"7e----------------------------");
|
||||||
|
|
||||||
/* end of frame */
|
/* check and pass received frame */
|
||||||
error = 0;
|
if (!skb) {
|
||||||
|
/* skipped frame */
|
||||||
if (unlikely(fcs != PPP_GOODFCS)) {
|
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,
|
dev_err(cs->dev,
|
||||||
"Checksum failed, %u bytes corrupted!\n",
|
"Checksum failed, %u bytes corrupted!\n",
|
||||||
skb->len);
|
skb->len);
|
||||||
compskb = NULL;
|
gigaset_isdn_rcv_err(bcs);
|
||||||
gigaset_rcv_error(compskb, cs, bcs);
|
dev_kfree_skb_any(skb);
|
||||||
error = 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (likely((l = skb->len) > 2)) {
|
/* good frame */
|
||||||
skb->tail -= 2;
|
__skb_trim(skb, skb->len - 2);
|
||||||
skb->len -= 2;
|
gigaset_skb_rcvd(bcs, skb);
|
||||||
} else {
|
}
|
||||||
dev_kfree_skb(skb);
|
|
||||||
skb = NULL;
|
/* prepare reception of next frame */
|
||||||
inputstate |= INS_skip_frame;
|
inputstate &= ~INS_have_data;
|
||||||
if (l == 1) {
|
new_rcv_skb(bcs);
|
||||||
dev_err(cs->dev,
|
skb = bcs->skb;
|
||||||
"invalid packet size (1)!\n");
|
} else {
|
||||||
error = 1;
|
/* empty frame (7E 7E) */
|
||||||
gigaset_rcv_error(NULL,
|
#ifdef CONFIG_GIGASET_DEBUG
|
||||||
cs, bcs);
|
++bcs->emptycount;
|
||||||
}
|
#endif
|
||||||
}
|
if (!skb) {
|
||||||
if (likely(!(error ||
|
/* skipped (?) */
|
||||||
(inputstate &
|
gigaset_isdn_rcv_err(bcs);
|
||||||
INS_skip_frame)))) {
|
new_rcv_skb(bcs);
|
||||||
gigaset_rcv_skb(skb, cs, bcs);
|
skb = bcs->skb;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(error))
|
|
||||||
if (skb)
|
|
||||||
dev_kfree_skb(skb);
|
|
||||||
|
|
||||||
fcs = PPP_INITFCS;
|
fcs = PPP_INITFCS;
|
||||||
inputstate &= ~(INS_have_data | INS_skip_frame);
|
continue;
|
||||||
if (unlikely(bcs->ignore)) {
|
#ifdef CONFIG_GIGASET_DEBUG
|
||||||
inputstate |= INS_skip_frame;
|
} else if (muststuff(c)) {
|
||||||
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))) {
|
|
||||||
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
|
/* Should not happen. Possible after ZDLE=1<CR><LF>. */
|
||||||
gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
|
gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add character */
|
/* regular data byte, append to skb */
|
||||||
|
|
||||||
#ifdef CONFIG_GIGASET_DEBUG
|
#ifdef CONFIG_GIGASET_DEBUG
|
||||||
if (unlikely(!(inputstate & INS_have_data))) {
|
if (!(inputstate & INS_have_data)) {
|
||||||
gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
|
gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
|
||||||
bcs->emptycount);
|
bcs->emptycount);
|
||||||
bcs->emptycount = 0;
|
bcs->emptycount = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inputstate |= INS_have_data;
|
inputstate |= INS_have_data;
|
||||||
|
if (skb) {
|
||||||
if (likely(!(inputstate & INS_skip_frame))) {
|
if (skb->len == SBUFSIZE) {
|
||||||
if (unlikely(skb->len == SBUFSIZE)) {
|
|
||||||
dev_warn(cs->dev, "received packet too long\n");
|
dev_warn(cs->dev, "received packet too long\n");
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
skb = NULL;
|
/* skip remainder of packet */
|
||||||
inputstate |= INS_skip_frame;
|
bcs->skb = skb = NULL;
|
||||||
break;
|
} 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->inputstate = inputstate;
|
||||||
bcs->fcs = fcs;
|
bcs->fcs = fcs;
|
||||||
bcs->skb = skb;
|
return procbytes;
|
||||||
return startbytes - numbytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process a block of received bytes in transparent data mode
|
/* 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.
|
* Invert bytes, undoing byte stuffing and watching for DLE escapes.
|
||||||
* If DLE is encountered, return immediately to let the caller handle it.
|
* If DLE is encountered, return immediately to let the caller handle it.
|
||||||
* Return value:
|
* Return value:
|
||||||
* number of processed bytes
|
* number of processed bytes
|
||||||
* numbytes (all bytes processed) on error --FIXME
|
|
||||||
*/
|
*/
|
||||||
static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
|
static unsigned iraw_loop(unsigned numbytes, struct inbuf_t *inbuf)
|
||||||
struct inbuf_t *inbuf)
|
|
||||||
{
|
{
|
||||||
struct cardstate *cs = inbuf->cs;
|
struct cardstate *cs = inbuf->cs;
|
||||||
struct bc_state *bcs = inbuf->bcs;
|
struct bc_state *bcs = cs->bcs;
|
||||||
int inputstate = bcs->inputstate;
|
int inputstate = bcs->inputstate;
|
||||||
struct sk_buff *skb = bcs->skb;
|
struct sk_buff *skb = bcs->skb;
|
||||||
int startbytes = numbytes;
|
unsigned char *src = inbuf->data + inbuf->head;
|
||||||
|
unsigned procbytes = 0;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
for (;;) {
|
if (!skb) {
|
||||||
/* add character */
|
/* skip this block */
|
||||||
inputstate |= INS_have_data;
|
new_rcv_skb(bcs);
|
||||||
|
return numbytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (likely(!(inputstate & INS_skip_frame))) {
|
while (procbytes < numbytes && skb->len < SBUFSIZE) {
|
||||||
if (unlikely(skb->len == SBUFSIZE)) {
|
c = *src++;
|
||||||
//FIXME just pass skb up and allocate a new one
|
procbytes++;
|
||||||
dev_warn(cs->dev, "received packet too long\n");
|
|
||||||
dev_kfree_skb_any(skb);
|
if (c == DLE_FLAG) {
|
||||||
skb = NULL;
|
if (inputstate & INS_DLE_char) {
|
||||||
inputstate |= INS_skip_frame;
|
/* 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;
|
break;
|
||||||
}
|
}
|
||||||
*__skb_put(skb, 1) = bitrev8(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(!numbytes))
|
/* regular data byte: append to current skb */
|
||||||
break;
|
inputstate |= INS_have_data;
|
||||||
c = *src++;
|
*__skb_put(skb, 1) = bitrev8(c);
|
||||||
--numbytes;
|
|
||||||
if (unlikely(c == DLE_FLAG &&
|
|
||||||
(cs->dle ||
|
|
||||||
inbuf->inputstate & INS_DLE_command))) {
|
|
||||||
inbuf->inputstate |= INS_DLE_char;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pass data up */
|
/* pass data up */
|
||||||
if (likely(inputstate & INS_have_data)) {
|
if (inputstate & INS_have_data) {
|
||||||
if (likely(!(inputstate & INS_skip_frame))) {
|
gigaset_skb_rcvd(bcs, skb);
|
||||||
gigaset_rcv_skb(skb, cs, bcs);
|
inputstate &= ~INS_have_data;
|
||||||
}
|
new_rcv_skb(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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bcs->inputstate = inputstate;
|
bcs->inputstate = inputstate;
|
||||||
bcs->skb = skb;
|
return procbytes;
|
||||||
return startbytes - numbytes;
|
}
|
||||||
|
|
||||||
|
/* 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)
|
void gigaset_m10x_input(struct inbuf_t *inbuf)
|
||||||
{
|
{
|
||||||
struct cardstate *cs;
|
struct cardstate *cs = inbuf->cs;
|
||||||
unsigned tail, head, numbytes;
|
unsigned numbytes, procbytes;
|
||||||
unsigned char *src, c;
|
|
||||||
int procbytes;
|
|
||||||
|
|
||||||
head = inbuf->head;
|
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", inbuf->head, inbuf->tail);
|
||||||
tail = inbuf->tail;
|
|
||||||
gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
|
|
||||||
|
|
||||||
if (head != tail) {
|
while (inbuf->head != inbuf->tail) {
|
||||||
cs = inbuf->cs;
|
/* check for DLE escape */
|
||||||
src = inbuf->data + head;
|
handle_dle(inbuf);
|
||||||
numbytes = (head > tail ? RBUFSIZE : tail) - head;
|
|
||||||
|
/* process a contiguous block of bytes */
|
||||||
|
numbytes = (inbuf->head > inbuf->tail ?
|
||||||
|
RBUFSIZE : inbuf->tail) - inbuf->head;
|
||||||
gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
|
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)
|
||||||
if (cs->mstate == MS_LOCKED) {
|
procbytes = lock_loop(numbytes, inbuf);
|
||||||
procbytes = lock_loop(src, numbytes, inbuf);
|
else if (inbuf->inputstate & INS_command)
|
||||||
src += procbytes;
|
procbytes = cmd_loop(numbytes, inbuf);
|
||||||
numbytes -= procbytes;
|
else if (cs->bcs->proto2 == L2_HDLC)
|
||||||
} else {
|
procbytes = hdlc_loop(numbytes, inbuf);
|
||||||
c = *src++;
|
else
|
||||||
--numbytes;
|
procbytes = iraw_loop(numbytes, inbuf);
|
||||||
if (c == DLE_FLAG && (cs->dle ||
|
inbuf->head += procbytes;
|
||||||
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 (!(inbuf->inputstate & INS_DLE_char)) {
|
/* check for buffer wraparound */
|
||||||
|
if (inbuf->head >= RBUFSIZE)
|
||||||
|
inbuf->head = 0;
|
||||||
|
|
||||||
/* FIXME use function pointers? */
|
gig_dbg(DEBUG_INTR, "head set to %u", inbuf->head);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gigaset_m10x_input);
|
EXPORT_SYMBOL_GPL(gigaset_m10x_input);
|
||||||
|
@ -440,16 +465,16 @@ EXPORT_SYMBOL_GPL(gigaset_m10x_input);
|
||||||
|
|
||||||
/* == data output ========================================================== */
|
/* == 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:
|
* parameters:
|
||||||
* skb skb containing original packet (freed upon return)
|
* 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
|
|
||||||
* Return value:
|
* Return value:
|
||||||
* pointer to newly allocated skb containing the result frame
|
* 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;
|
struct sk_buff *hdlc_skb;
|
||||||
__u16 fcs;
|
__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
|
/* size of new buffer: original size + number of stuffing bytes
|
||||||
* + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag 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) {
|
if (!hdlc_skb) {
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
skb_reserve(hdlc_skb, head);
|
|
||||||
|
|
||||||
/* Copy acknowledge request into new skb */
|
/* Copy link layer header into new skb */
|
||||||
memcpy(hdlc_skb->head, skb->head, 2);
|
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.. */
|
/* Add flag sequence in front of everything.. */
|
||||||
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
|
*(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;
|
*(skb_put(hdlc_skb, 1)) = PPP_FLAG;
|
||||||
|
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return hdlc_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:
|
* parameters:
|
||||||
* skb skb containing original packet (freed upon return)
|
* 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
|
|
||||||
* Return value:
|
* Return value:
|
||||||
* pointer to newly allocated skb containing the result frame
|
* 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;
|
struct sk_buff *iraw_skb;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
/* worst case: every byte must be stuffed */
|
/* size of new buffer (worst case = every byte must be stuffed):
|
||||||
iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
|
* 2 * original size + room for link layer header
|
||||||
|
*/
|
||||||
|
iraw_skb = dev_alloc_skb(2*skb->len + skb->mac_len);
|
||||||
if (!iraw_skb) {
|
if (!iraw_skb) {
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return NULL;
|
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;
|
cp = skb->data;
|
||||||
len = skb->len;
|
len = skb->len;
|
||||||
while (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;
|
||||||
*(skb_put(iraw_skb, 1)) = c;
|
*(skb_put(iraw_skb, 1)) = c;
|
||||||
}
|
}
|
||||||
dev_kfree_skb(skb);
|
dev_kfree_skb_any(skb);
|
||||||
return iraw_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.
|
* @bcs: B channel descriptor structure.
|
||||||
* @skb: data to send.
|
* @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.
|
* 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:
|
* Return value:
|
||||||
* number of bytes accepted for sending (skb->len) if ok,
|
* 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)
|
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct cardstate *cs = bcs->cs;
|
||||||
unsigned len = skb->len;
|
unsigned len = skb->len;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
|
if (bcs->proto2 == L2_HDLC)
|
||||||
skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
|
skb = HDLC_Encode(skb);
|
||||||
else
|
else
|
||||||
skb = iraw_encode(skb, HW_HDR_LEN, 0);
|
skb = iraw_encode(skb);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
dev_err(bcs->cs->dev,
|
dev_err(cs->dev,
|
||||||
"unable to allocate memory for encoding!\n");
|
"unable to allocate memory for encoding!\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_queue_tail(&bcs->squeue, skb);
|
skb_queue_tail(&bcs->squeue, skb);
|
||||||
spin_lock_irqsave(&bcs->cs->lock, flags);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
if (bcs->cs->connected)
|
if (cs->connected)
|
||||||
tasklet_schedule(&bcs->cs->write_tasklet);
|
tasklet_schedule(&cs->write_tasklet);
|
||||||
spin_unlock_irqrestore(&bcs->cs->lock, flags);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
|
|
||||||
return len; /* ok so far */
|
return len; /* ok so far */
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
|
||||||
#define USB_SX353_PRODUCT_ID 0x0022
|
#define USB_SX353_PRODUCT_ID 0x0022
|
||||||
|
|
||||||
/* table of devices that work with this driver */
|
/* 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_3070_PRODUCT_ID) },
|
||||||
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
|
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_3075_PRODUCT_ID) },
|
||||||
{ USB_DEVICE(USB_GIGA_VENDOR_ID, USB_SX303_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 */
|
#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 */
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
static struct usb_driver gigaset_usb_driver = {
|
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);
|
ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size);
|
||||||
usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
|
usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev,
|
||||||
usb_rcvctrlpipe(ucs->udev, 0),
|
usb_rcvctrlpipe(ucs->udev, 0),
|
||||||
(unsigned char*) & ucs->dr_cmd_in,
|
(unsigned char *) &ucs->dr_cmd_in,
|
||||||
ucs->rcvbuf, ucs->rcvbuf_size,
|
ucs->rcvbuf, ucs->rcvbuf_size,
|
||||||
read_ctrl_callback, cs->inbuf);
|
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);
|
update_basstate(ucs, 0, BS_ATRDPEND);
|
||||||
dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
|
dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
|
||||||
get_usb_rcmsg(ret));
|
get_usb_rcmsg(ret));
|
||||||
|
@ -652,13 +653,11 @@ static void read_int_callback(struct urb *urb)
|
||||||
return;
|
return;
|
||||||
case -ENODEV: /* device removed */
|
case -ENODEV: /* device removed */
|
||||||
case -ESHUTDOWN: /* device shut down */
|
case -ESHUTDOWN: /* device shut down */
|
||||||
//FIXME use this as disconnect indicator?
|
|
||||||
gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
|
gig_dbg(DEBUG_USBREQ, "%s: device disconnected", __func__);
|
||||||
return;
|
return;
|
||||||
default: /* severe trouble */
|
default: /* severe trouble */
|
||||||
dev_warn(cs->dev, "interrupt read: %s\n",
|
dev_warn(cs->dev, "interrupt read: %s\n",
|
||||||
get_usb_statmsg(status));
|
get_usb_statmsg(status));
|
||||||
//FIXME corrective action? resubmission always ok?
|
|
||||||
goto resubmit;
|
goto resubmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +741,8 @@ static void read_int_callback(struct urb *urb)
|
||||||
kfree(ucs->rcvbuf);
|
kfree(ucs->rcvbuf);
|
||||||
ucs->rcvbuf_size = 0;
|
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);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
dev_err(cs->dev, "out of memory receiving AT data\n");
|
dev_err(cs->dev, "out of memory receiving AT data\n");
|
||||||
error_reset(cs);
|
error_reset(cs);
|
||||||
|
@ -750,12 +750,12 @@ static void read_int_callback(struct urb *urb)
|
||||||
}
|
}
|
||||||
ucs->rcvbuf_size = l;
|
ucs->rcvbuf_size = l;
|
||||||
ucs->retry_cmd_in = 0;
|
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);
|
kfree(ucs->rcvbuf);
|
||||||
ucs->rcvbuf = NULL;
|
ucs->rcvbuf = NULL;
|
||||||
ucs->rcvbuf_size = 0;
|
ucs->rcvbuf_size = 0;
|
||||||
if (rc != -ENODEV) {
|
if (rc != -ENODEV) {
|
||||||
//FIXME corrective action?
|
|
||||||
spin_unlock_irqrestore(&cs->lock, flags);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
error_reset(cs);
|
error_reset(cs);
|
||||||
break;
|
break;
|
||||||
|
@ -911,7 +911,7 @@ static int starturbs(struct bc_state *bcs)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* initialize L2 reception */
|
/* initialize L2 reception */
|
||||||
if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
|
if (bcs->proto2 == L2_HDLC)
|
||||||
bcs->inputstate |= INS_flag_hunt;
|
bcs->inputstate |= INS_flag_hunt;
|
||||||
|
|
||||||
/* submit all isochronous input URBs */
|
/* submit all isochronous input URBs */
|
||||||
|
@ -940,7 +940,8 @@ static int starturbs(struct bc_state *bcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
dump_urb(DEBUG_ISO, "Initial isoc read", urb);
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1045,7 +1046,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx)
|
||||||
|
|
||||||
/* compute frame length according to flow control */
|
/* compute frame length according to flow control */
|
||||||
ifd->length = BAS_NORMFRAME;
|
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",
|
gig_dbg(DEBUG_ISO, "%s: corrbytes=%d",
|
||||||
__func__, corrbytes);
|
__func__, corrbytes);
|
||||||
if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME)
|
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",
|
"%s: buffer busy at frame %d",
|
||||||
__func__, nframe);
|
__func__, nframe);
|
||||||
/* tasklet will be restarted from
|
/* tasklet will be restarted from
|
||||||
gigaset_send_skb() */
|
gigaset_isoc_send_skb() */
|
||||||
} else {
|
} else {
|
||||||
dev_err(ucx->bcs->cs->dev,
|
dev_err(ucx->bcs->cs->dev,
|
||||||
"%s: buffer error %d at frame %d\n",
|
"%s: buffer error %d at frame %d\n",
|
||||||
|
@ -1284,7 +1286,8 @@ static void read_iso_tasklet(unsigned long data)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* retrieve URB */
|
/* retrieve URB */
|
||||||
spin_lock_irqsave(&ubc->isoinlock, flags);
|
spin_lock_irqsave(&ubc->isoinlock, flags);
|
||||||
if (!(urb = ubc->isoindone)) {
|
urb = ubc->isoindone;
|
||||||
|
if (!urb) {
|
||||||
spin_unlock_irqrestore(&ubc->isoinlock, flags);
|
spin_unlock_irqrestore(&ubc->isoinlock, flags);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1371,7 +1374,7 @@ static void read_iso_tasklet(unsigned long data)
|
||||||
"isochronous read: %d data bytes missing\n",
|
"isochronous read: %d data bytes missing\n",
|
||||||
totleft);
|
totleft);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
/* URB processed, resubmit */
|
/* URB processed, resubmit */
|
||||||
for (frame = 0; frame < BAS_NUMFRAMES; frame++) {
|
for (frame = 0; frame < BAS_NUMFRAMES; frame++) {
|
||||||
urb->iso_frame_desc[frame].status = 0;
|
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;
|
ucs->dr_ctrl.wLength = 0;
|
||||||
usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
|
usb_fill_control_urb(ucs->urb_ctrl, ucs->udev,
|
||||||
usb_sndctrlpipe(ucs->udev, 0),
|
usb_sndctrlpipe(ucs->udev, 0),
|
||||||
(unsigned char*) &ucs->dr_ctrl, NULL, 0,
|
(unsigned char *) &ucs->dr_ctrl, NULL, 0,
|
||||||
write_ctrl_callback, ucs);
|
write_ctrl_callback, ucs);
|
||||||
ucs->retry_ctrl = 0;
|
ucs->retry_ctrl = 0;
|
||||||
ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC);
|
ret = usb_submit_urb(ucs->urb_ctrl, GFP_ATOMIC);
|
||||||
|
@ -1621,7 +1624,8 @@ static int gigaset_init_bchannel(struct bc_state *bcs)
|
||||||
return -EHOSTUNREACH;
|
return -EHOSTUNREACH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = starturbs(bcs)) < 0) {
|
ret = starturbs(bcs);
|
||||||
|
if (ret < 0) {
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"could not start isochronous I/O for channel B%d: %s\n",
|
"could not start isochronous I/O for channel B%d: %s\n",
|
||||||
bcs->channel + 1,
|
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;
|
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",
|
dev_err(cs->dev, "could not open channel B%d\n",
|
||||||
bcs->channel + 1);
|
bcs->channel + 1);
|
||||||
stopurbs(bcs->hw.bas);
|
stopurbs(bcs->hw.bas);
|
||||||
|
@ -1677,7 +1682,8 @@ static int gigaset_close_bchannel(struct bc_state *bcs)
|
||||||
|
|
||||||
/* channel running: tell device to close it */
|
/* channel running: tell device to close it */
|
||||||
req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL;
|
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",
|
dev_err(cs->dev, "closing channel B%d failed\n",
|
||||||
bcs->channel + 1);
|
bcs->channel + 1);
|
||||||
|
|
||||||
|
@ -1703,10 +1709,12 @@ static void complete_cb(struct cardstate *cs)
|
||||||
gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
|
gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD,
|
||||||
"write_command: sent %u bytes, %u left",
|
"write_command: sent %u bytes, %u left",
|
||||||
cs->curlen, cs->cmdbytes);
|
cs->curlen, cs->cmdbytes);
|
||||||
if ((cs->cmdbuf = cb->next) != NULL) {
|
if (cb->next != NULL) {
|
||||||
|
cs->cmdbuf = cb->next;
|
||||||
cs->cmdbuf->prev = NULL;
|
cs->cmdbuf->prev = NULL;
|
||||||
cs->curlen = cs->cmdbuf->len;
|
cs->curlen = cs->cmdbuf->len;
|
||||||
} else {
|
} else {
|
||||||
|
cs->cmdbuf = NULL;
|
||||||
cs->lastcmdbuf = NULL;
|
cs->lastcmdbuf = NULL;
|
||||||
cs->curlen = 0;
|
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);
|
ucs->dr_cmd_out.wLength = cpu_to_le16(len);
|
||||||
usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev,
|
usb_fill_control_urb(ucs->urb_cmd_out, ucs->udev,
|
||||||
usb_sndctrlpipe(ucs->udev, 0),
|
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);
|
write_command_callback, cs);
|
||||||
rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC);
|
rc = usb_submit_urb(ucs->urb_cmd_out, GFP_ATOMIC);
|
||||||
if (unlikely(rc)) {
|
if (unlikely(rc)) {
|
||||||
|
@ -1953,7 +1961,8 @@ static int gigaset_write_cmd(struct cardstate *cs,
|
||||||
|
|
||||||
if (len > IF_WRITEBUF)
|
if (len > IF_WRITEBUF)
|
||||||
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__);
|
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto notqueued;
|
goto notqueued;
|
||||||
|
@ -2100,14 +2109,15 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
||||||
}
|
}
|
||||||
ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL;
|
ubc->isooutdone = ubc->isooutfree = ubc->isooutovfl = NULL;
|
||||||
ubc->numsub = 0;
|
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");
|
pr_err("out of memory\n");
|
||||||
kfree(ubc);
|
kfree(ubc);
|
||||||
bcs->hw.bas = NULL;
|
bcs->hw.bas = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
tasklet_init(&ubc->sent_tasklet,
|
tasklet_init(&ubc->sent_tasklet,
|
||||||
&write_iso_tasklet, (unsigned long) bcs);
|
write_iso_tasklet, (unsigned long) bcs);
|
||||||
|
|
||||||
spin_lock_init(&ubc->isoinlock);
|
spin_lock_init(&ubc->isoinlock);
|
||||||
for (i = 0; i < BAS_INURBS; ++i)
|
for (i = 0; i < BAS_INURBS; ++i)
|
||||||
|
@ -2128,7 +2138,7 @@ static int gigaset_initbcshw(struct bc_state *bcs)
|
||||||
ubc->shared0s = 0;
|
ubc->shared0s = 0;
|
||||||
ubc->stolen0s = 0;
|
ubc->stolen0s = 0;
|
||||||
tasklet_init(&ubc->rcvd_tasklet,
|
tasklet_init(&ubc->rcvd_tasklet,
|
||||||
&read_iso_tasklet, (unsigned long) bcs);
|
read_iso_tasklet, (unsigned long) bcs);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2252,7 +2262,8 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||||
gig_dbg(DEBUG_ANY,
|
gig_dbg(DEBUG_ANY,
|
||||||
"%s: wrong alternate setting %d - trying to switch",
|
"%s: wrong alternate setting %d - trying to switch",
|
||||||
__func__, hostif->desc.bAlternateSetting);
|
__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, "
|
dev_warn(&udev->dev, "usb_set_interface failed, "
|
||||||
"device %d interface %d altsetting %d\n",
|
"device %d interface %d altsetting %d\n",
|
||||||
udev->devnum, hostif->desc.bInterfaceNumber,
|
udev->devnum, hostif->desc.bInterfaceNumber,
|
||||||
|
@ -2321,14 +2332,16 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||||
(endpoint->bEndpointAddress) & 0x0f),
|
(endpoint->bEndpointAddress) & 0x0f),
|
||||||
ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs,
|
ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs,
|
||||||
endpoint->bInterval);
|
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",
|
dev_err(cs->dev, "could not submit interrupt URB: %s\n",
|
||||||
get_usb_rcmsg(rc));
|
get_usb_rcmsg(rc));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tell the device that the driver is ready */
|
/* 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;
|
goto error;
|
||||||
|
|
||||||
/* tell common part that the device is ready */
|
/* tell common part that the device is ready */
|
||||||
|
@ -2524,9 +2537,10 @@ static int __init bas_gigaset_init(void)
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* allocate memory for our driver state and intialize it */
|
/* 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,
|
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||||
&gigops, THIS_MODULE)) == NULL)
|
&gigops, THIS_MODULE);
|
||||||
|
if (driver == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* register this driver with the USB subsystem */
|
/* 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;
|
int i, r;
|
||||||
|
|
||||||
cs->control_state = TIOCM_RTS; //FIXME
|
cs->control_state = TIOCM_RTS;
|
||||||
|
|
||||||
r = setflags(cs, TIOCM_DTR, 200);
|
r = setflags(cs, TIOCM_DTR, 200);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -132,10 +132,10 @@ int gigaset_enterconfigmode(struct cardstate *cs)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
dev_err(cs->dev, "error %d on setuartbits\n", -r);
|
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);
|
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)
|
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,
|
if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL,
|
||||||
at_state->timer_index, NULL)) {
|
at_state->timer_index, NULL))
|
||||||
//FIXME what should we do?
|
dev_err(at_state->cs->dev, "%s: out of memory\n",
|
||||||
}
|
__func__);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,6 +206,32 @@ int gigaset_get_channel(struct bc_state *bcs)
|
||||||
return 1;
|
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)
|
void gigaset_free_channel(struct bc_state *bcs)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -367,16 +392,15 @@ static void gigaset_freebcs(struct bc_state *bcs)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel);
|
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, "failed");
|
||||||
}
|
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
|
gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel);
|
||||||
clear_at_state(&bcs->at_state);
|
clear_at_state(&bcs->at_state);
|
||||||
gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel);
|
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) {
|
for (i = 0; i < AT_NUM; ++i) {
|
||||||
kfree(bcs->commands[i]);
|
kfree(bcs->commands[i]);
|
||||||
bcs->commands[i] = NULL;
|
bcs->commands[i] = NULL;
|
||||||
|
@ -463,6 +487,12 @@ void gigaset_freecs(struct cardstate *cs)
|
||||||
|
|
||||||
switch (cs->cs_init) {
|
switch (cs->cs_init) {
|
||||||
default:
|
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 */
|
/* clear device sysfs */
|
||||||
gigaset_free_dev_sysfs(cs);
|
gigaset_free_dev_sysfs(cs);
|
||||||
|
|
||||||
|
@ -471,28 +501,20 @@ void gigaset_freecs(struct cardstate *cs)
|
||||||
gig_dbg(DEBUG_INIT, "clearing hw");
|
gig_dbg(DEBUG_INIT, "clearing hw");
|
||||||
cs->ops->freecshw(cs);
|
cs->ops->freecshw(cs);
|
||||||
|
|
||||||
//FIXME cmdbuf
|
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 2: /* error in initcshw */
|
case 2: /* error in initcshw */
|
||||||
/* Deregister from LL */
|
/* Deregister from LL */
|
||||||
make_invalid(cs, VALID_ID);
|
make_invalid(cs, VALID_ID);
|
||||||
gig_dbg(DEBUG_INIT, "clearing iif");
|
gigaset_isdn_unregister(cs);
|
||||||
gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
|
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 1: /* error when regestering to LL */
|
case 1: /* error when registering to LL */
|
||||||
gig_dbg(DEBUG_INIT, "clearing at_state");
|
gig_dbg(DEBUG_INIT, "clearing at_state");
|
||||||
clear_at_state(&cs->at_state);
|
clear_at_state(&cs->at_state);
|
||||||
dealloc_at_states(cs);
|
dealloc_at_states(cs);
|
||||||
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 0: /* error in one call to initbcs */
|
case 0: /* error in basic setup */
|
||||||
for (i = 0; i < cs->channels; ++i) {
|
|
||||||
gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i);
|
|
||||||
gigaset_freebcs(cs->bcs + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
clear_events(cs);
|
clear_events(cs);
|
||||||
gig_dbg(DEBUG_INIT, "freeing inbuf");
|
gig_dbg(DEBUG_INIT, "freeing inbuf");
|
||||||
kfree(cs->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,
|
static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct cardstate *cs)
|
||||||
struct cardstate *cs, int inputstate)
|
|
||||||
/* inbuf->read must be allocated before! */
|
/* inbuf->read must be allocated before! */
|
||||||
{
|
{
|
||||||
inbuf->head = 0;
|
inbuf->head = 0;
|
||||||
inbuf->tail = 0;
|
inbuf->tail = 0;
|
||||||
inbuf->cs = cs;
|
inbuf->cs = cs;
|
||||||
inbuf->bcs = bcs; /*base driver: NULL*/
|
inbuf->inputstate = INS_command;
|
||||||
inbuf->rcvbuf = NULL;
|
|
||||||
inbuf->inputstate = inputstate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -599,7 +618,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
bcs->tx_skb = NULL; //FIXME -> hw part
|
bcs->tx_skb = NULL;
|
||||||
|
|
||||||
skb_queue_head_init(&bcs->squeue);
|
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->fcs = PPP_INITFCS;
|
||||||
bcs->inputstate = 0;
|
bcs->inputstate = 0;
|
||||||
if (cs->ignoreframes) {
|
if (cs->ignoreframes) {
|
||||||
bcs->inputstate |= INS_skip_frame;
|
|
||||||
bcs->skb = NULL;
|
bcs->skb = NULL;
|
||||||
} else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
} else {
|
||||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||||
else {
|
if (bcs->skb != NULL)
|
||||||
pr_err("out of memory\n");
|
skb_reserve(bcs->skb, cs->hw_hdr_len);
|
||||||
bcs->inputstate |= INS_skip_frame;
|
else
|
||||||
|
pr_err("out of memory\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
bcs->channel = channel;
|
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, " failed");
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel);
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -673,12 +692,13 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
||||||
int onechannel, int ignoreframes,
|
int onechannel, int ignoreframes,
|
||||||
int cidmode, const char *modulename)
|
int cidmode, const char *modulename)
|
||||||
{
|
{
|
||||||
struct cardstate *cs = NULL;
|
struct cardstate *cs;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "allocating cs");
|
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");
|
pr_err("maximum number of devices exceeded\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -707,7 +727,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
||||||
cs->ev_tail = 0;
|
cs->ev_tail = 0;
|
||||||
cs->ev_head = 0;
|
cs->ev_head = 0;
|
||||||
|
|
||||||
tasklet_init(&cs->event_tasklet, &gigaset_handle_event,
|
tasklet_init(&cs->event_tasklet, gigaset_handle_event,
|
||||||
(unsigned long) cs);
|
(unsigned long) cs);
|
||||||
cs->commands_pending = 0;
|
cs->commands_pending = 0;
|
||||||
cs->cur_at_seq = 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->mode = M_UNKNOWN;
|
||||||
cs->mstate = MS_UNINITIALIZED;
|
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;
|
++cs->cs_init;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "setting up at_state");
|
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;
|
cs->cbytes = 0;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "setting up inbuf");
|
gig_dbg(DEBUG_INIT, "setting up inbuf");
|
||||||
if (onechannel) { //FIXME distinction necessary?
|
gigaset_inbuf_init(cs->inbuf, cs);
|
||||||
gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command);
|
|
||||||
} else
|
|
||||||
gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command);
|
|
||||||
|
|
||||||
cs->connected = 0;
|
cs->connected = 0;
|
||||||
cs->isdn_up = 0;
|
cs->isdn_up = 0;
|
||||||
|
@ -758,7 +767,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
||||||
cs->cmdbytes = 0;
|
cs->cmdbytes = 0;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "setting up iif");
|
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");
|
pr_err("error registering ISDN device\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -777,6 +786,15 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
||||||
/* set up device sysfs */
|
/* set up device sysfs */
|
||||||
gigaset_init_dev_sysfs(cs);
|
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);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
cs->running = 1;
|
cs->running = 1;
|
||||||
spin_unlock_irqrestore(&cs->lock, flags);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
|
@ -824,9 +842,10 @@ void gigaset_bcs_reinit(struct bc_state *bcs)
|
||||||
bcs->chstate = 0;
|
bcs->chstate = 0;
|
||||||
|
|
||||||
bcs->ignore = cs->ignoreframes;
|
bcs->ignore = cs->ignoreframes;
|
||||||
if (bcs->ignore)
|
if (bcs->ignore) {
|
||||||
bcs->inputstate |= INS_skip_frame;
|
dev_kfree_skb(bcs->skb);
|
||||||
|
bcs->skb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cs->ops->reinitbcshw(bcs);
|
cs->ops->reinitbcshw(bcs);
|
||||||
}
|
}
|
||||||
|
@ -847,8 +866,6 @@ static void cleanup_cs(struct cardstate *cs)
|
||||||
free_strings(&cs->at_state);
|
free_strings(&cs->at_state);
|
||||||
gigaset_at_init(&cs->at_state, NULL, cs, 0);
|
gigaset_at_init(&cs->at_state, NULL, cs, 0);
|
||||||
|
|
||||||
kfree(cs->inbuf->rcvbuf);
|
|
||||||
cs->inbuf->rcvbuf = NULL;
|
|
||||||
cs->inbuf->inputstate = INS_command;
|
cs->inbuf->inputstate = INS_command;
|
||||||
cs->inbuf->head = 0;
|
cs->inbuf->head = 0;
|
||||||
cs->inbuf->tail = 0;
|
cs->inbuf->tail = 0;
|
||||||
|
@ -911,15 +928,13 @@ int gigaset_start(struct cardstate *cs)
|
||||||
cs->ops->baud_rate(cs, B115200);
|
cs->ops->baud_rate(cs, B115200);
|
||||||
cs->ops->set_line_ctrl(cs, CS8);
|
cs->ops->set_line_ctrl(cs, CS8);
|
||||||
cs->control_state = TIOCM_DTR|TIOCM_RTS;
|
cs->control_state = TIOCM_DTR|TIOCM_RTS;
|
||||||
} else {
|
|
||||||
//FIXME use some saved values?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cs->waiting = 1;
|
cs->waiting = 1;
|
||||||
|
|
||||||
if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
|
if (!gigaset_add_event(cs, &cs->at_state, EV_START, NULL, 0, NULL)) {
|
||||||
cs->waiting = 0;
|
cs->waiting = 0;
|
||||||
//FIXME what should we do?
|
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,7 +974,7 @@ int gigaset_shutdown(struct cardstate *cs)
|
||||||
cs->waiting = 1;
|
cs->waiting = 1;
|
||||||
|
|
||||||
if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) {
|
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;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -990,7 +1005,7 @@ void gigaset_stop(struct cardstate *cs)
|
||||||
cs->waiting = 1;
|
cs->waiting = 1;
|
||||||
|
|
||||||
if (!gigaset_add_event(cs, &cs->at_state, EV_STOP, NULL, 0, NULL)) {
|
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;
|
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 */
|
/* Possible ASCII responses */
|
||||||
#define RSP_OK 0
|
#define RSP_OK 0
|
||||||
//#define RSP_BUSY 1
|
#define RSP_BUSY 1
|
||||||
//#define RSP_CONNECT 2
|
#define RSP_CONNECT 2
|
||||||
#define RSP_ZGCI 3
|
#define RSP_ZGCI 3
|
||||||
#define RSP_RING 4
|
#define RSP_RING 4
|
||||||
#define RSP_ZAOC 5
|
#define RSP_ZAOC 5
|
||||||
|
@ -68,7 +68,6 @@
|
||||||
#define RSP_ZHLC (RSP_STR + STR_ZHLC)
|
#define RSP_ZHLC (RSP_STR + STR_ZHLC)
|
||||||
#define RSP_ERROR -1 /* ERROR */
|
#define RSP_ERROR -1 /* ERROR */
|
||||||
#define RSP_WRONG_CID -2 /* unknown cid in cmd */
|
#define RSP_WRONG_CID -2 /* unknown cid in cmd */
|
||||||
//#define RSP_EMPTY -3
|
|
||||||
#define RSP_UNKNOWN -4 /* unknown response */
|
#define RSP_UNKNOWN -4 /* unknown response */
|
||||||
#define RSP_FAIL -5 /* internal error */
|
#define RSP_FAIL -5 /* internal error */
|
||||||
#define RSP_INVAL -6 /* invalid response */
|
#define RSP_INVAL -6 /* invalid response */
|
||||||
|
@ -76,9 +75,9 @@
|
||||||
#define RSP_NONE -19
|
#define RSP_NONE -19
|
||||||
#define RSP_STRING -20
|
#define RSP_STRING -20
|
||||||
#define RSP_NULL -21
|
#define RSP_NULL -21
|
||||||
//#define RSP_RETRYFAIL -22
|
#define RSP_RETRYFAIL -22
|
||||||
//#define RSP_RETRY -23
|
#define RSP_RETRY -23
|
||||||
//#define RSP_SKIP -24
|
#define RSP_SKIP -24
|
||||||
#define RSP_INIT -27
|
#define RSP_INIT -27
|
||||||
#define RSP_ANY -26
|
#define RSP_ANY -26
|
||||||
#define RSP_LAST -28
|
#define RSP_LAST -28
|
||||||
|
@ -127,7 +126,6 @@
|
||||||
#define ACT_NOTIFY_BC_UP 39
|
#define ACT_NOTIFY_BC_UP 39
|
||||||
#define ACT_DIAL 40
|
#define ACT_DIAL 40
|
||||||
#define ACT_ACCEPT 41
|
#define ACT_ACCEPT 41
|
||||||
#define ACT_PROTO_L2 42
|
|
||||||
#define ACT_HUP 43
|
#define ACT_HUP 43
|
||||||
#define ACT_IF_LOCK 44
|
#define ACT_IF_LOCK 44
|
||||||
#define ACT_START 45
|
#define ACT_START 45
|
||||||
|
@ -159,229 +157,229 @@
|
||||||
#define SEQ_UMMODE 11
|
#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[] =
|
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 */
|
/* initialize device, set cid mode if possible */
|
||||||
//{RSP_INIT, -1, -1,100, 900, 0, {ACT_TEST}},
|
{RSP_INIT, -1, -1, SEQ_INIT, 100, 1, {ACT_TIMEOUT} },
|
||||||
//{RSP_ERROR, 900,900, -1, 0, 0, {ACT_FAILINIT}},
|
|
||||||
//{RSP_OK, 900,900, -1, 100, INIT_TIMEOUT,
|
|
||||||
// {ACT_TIMEOUT}},
|
|
||||||
|
|
||||||
{RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT,
|
{EV_TIMEOUT, 100, 100, -1, 101, 3, {0}, "Z\r"},
|
||||||
{ACT_TIMEOUT}}, /* wait until device is ready */
|
{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. */
|
{EV_TIMEOUT, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||||
{RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */
|
{RSP_ERROR, 101, 101, -1, 102, 5, {0}, "Z\r"},
|
||||||
|
|
||||||
{EV_TIMEOUT, 101,101, -1, 102, 5, {0}, "Z\r"}, /* timeout => try once again. */
|
{EV_TIMEOUT, 102, 102, -1, 108, 5, {ACT_SETDLE1},
|
||||||
{RSP_ERROR, 101,101, -1, 102, 5, {0}, "Z\r"}, /* error => try once again. */
|
"^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. */
|
{EV_TIMEOUT, 108, 108, -1, 105, 2, {ACT_SETDLE0,
|
||||||
{RSP_OK, 108,108, -1, 104,-1},
|
ACT_HUPMODEM,
|
||||||
{RSP_ZDLE, 104,104, 0, 103, 5, {0}, "Z\r"},
|
ACT_TIMEOUT} },
|
||||||
{EV_TIMEOUT, 104,104, -1, 0, 0, {ACT_FAILINIT}},
|
{EV_TIMEOUT, 105, 105, -1, 103, 5, {0}, "Z\r"},
|
||||||
{RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}},
|
|
||||||
|
|
||||||
{EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0,
|
{RSP_ERROR, 102, 102, -1, 107, 5, {0}, "^GETPRE\r"},
|
||||||
ACT_HUPMODEM,
|
{RSP_OK, 107, 107, -1, 0, 0, {ACT_CONFIGMODE} },
|
||||||
ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */
|
{RSP_ERROR, 107, 107, -1, 0, 0, {ACT_FAILINIT} },
|
||||||
{EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"},
|
{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_ERROR, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||||
{RSP_OK, 107,107, -1, 0, 0, {ACT_CONFIGMODE}},
|
{EV_TIMEOUT, 103, 103, -1, 0, 0, {ACT_FAILINIT} },
|
||||||
{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}},
|
{RSP_STRING, 120, 120, -1, 121, -1, {ACT_SETVER} },
|
||||||
{EV_TIMEOUT, 103,103, -1, 0, 0, {ACT_FAILINIT}},
|
|
||||||
|
|
||||||
{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}},
|
/* leave dle mode */
|
||||||
{RSP_ERROR, 120,121, -1, 0, 0, {ACT_FAILVER, ACT_INIT}},
|
{RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
||||||
{RSP_OK, 121,121, -1, 0, 0, {ACT_GOTVER, ACT_INIT}},
|
{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 */
|
/* enter dle mode */
|
||||||
{RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"},
|
{RSP_INIT, 0, 0, SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
||||||
{RSP_OK, 201,201, -1, 202,-1},
|
{RSP_OK, 251, 251, -1, 252, -1},
|
||||||
{RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}},
|
{RSP_ZDLE, 252, 252, 1, 0, 0, {ACT_DLE1} },
|
||||||
{RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}},
|
{RSP_ERROR, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||||
{RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
|
{EV_TIMEOUT, 250, 299, -1, 0, 0, {ACT_FAILDLE1} },
|
||||||
{EV_TIMEOUT, 200,249, -1, 0, 0, {ACT_FAILDLE0}},
|
|
||||||
|
|
||||||
/* enter dle mode */
|
/* incoming call */
|
||||||
{RSP_INIT, 0, 0,SEQ_DLE1, 251, 5, {0}, "^SDLE=1\r"},
|
{RSP_RING, -1, -1, -1, -1, -1, {ACT_RING} },
|
||||||
{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 */
|
/* get cid */
|
||||||
{RSP_RING, -1, -1, -1, -1,-1, {ACT_RING}},
|
{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 */
|
/* enter cid mode */
|
||||||
//{RSP_INIT, 0, 0,300, 901, 0, {ACT_TEST}},
|
{RSP_INIT, 0, 0, SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
||||||
//{RSP_ERROR, 901,901, -1, 0, 0, {ACT_FAILCID}},
|
{RSP_OK, 150, 150, -1, 0, 0, {ACT_CMODESET} },
|
||||||
//{RSP_OK, 901,901, -1, 301, 5, {0}, "^SGCI?\r"},
|
{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"},
|
/* leave cid mode */
|
||||||
{RSP_OK, 301,301, -1, 302,-1},
|
{RSP_INIT, 0, 0, SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
||||||
{RSP_ZGCI, 302,302, -1, 0, 0, {ACT_CID}},
|
{RSP_OK, 160, 160, -1, 0, 0, {ACT_UMODESET} },
|
||||||
{RSP_ERROR, 301,349, -1, 0, 0, {ACT_FAILCID}},
|
{RSP_ERROR, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||||
{EV_TIMEOUT, 301,349, -1, 0, 0, {ACT_FAILCID}},
|
{EV_TIMEOUT, 160, 160, -1, 0, 0, {ACT_FAILUMODE} },
|
||||||
|
|
||||||
/* enter cid mode */
|
/* abort getting cid */
|
||||||
{RSP_INIT, 0, 0,SEQ_CIDMODE, 150, 5, {0}, "^SGCI=1\r"},
|
{RSP_INIT, 0, 0, SEQ_NOCID, 0, 0, {ACT_ABORTCID} },
|
||||||
{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}},
|
|
||||||
|
|
||||||
/* leave cid mode */
|
/* reset */
|
||||||
//{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "^SGCI=0\r"},
|
{RSP_INIT, 0, 0, SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
||||||
{RSP_INIT, 0, 0,SEQ_UMMODE, 160, 5, {0}, "Z\r"},
|
{RSP_OK, 504, 504, -1, 0, 0, {ACT_SDOWN} },
|
||||||
{RSP_OK, 160,160, -1, 0, 0, {ACT_UMODESET}},
|
{RSP_ERROR, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||||
{RSP_ERROR, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
|
{EV_TIMEOUT, 501, 599, -1, 0, 0, {ACT_FAILSDOWN} },
|
||||||
{EV_TIMEOUT, 160,160, -1, 0, 0, {ACT_FAILUMODE}},
|
{RSP_NODEV, 501, 599, -1, 0, 0, {ACT_FAKESDOWN} },
|
||||||
|
|
||||||
/* abort getting cid */
|
{EV_PROC_CIDMODE, -1, -1, -1, -1, -1, {ACT_PROC_CIDMODE} },
|
||||||
{RSP_INIT, 0, 0,SEQ_NOCID, 0, 0, {ACT_ABORTCID}},
|
{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 */
|
/* misc. */
|
||||||
{RSP_INIT, 0, 0,SEQ_SHUTDOWN, 504, 5, {0}, "Z\r"},
|
{RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} },
|
||||||
{RSP_OK, 504,504, -1, 0, 0, {ACT_SDOWN}},
|
{RSP_ZCFGT, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_ERROR, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
|
{RSP_ZCFG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{EV_TIMEOUT, 501,599, -1, 0, 0, {ACT_FAILSDOWN}},
|
{RSP_ZLOG, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_NODEV, 501,599, -1, 0, 0, {ACT_FAKESDOWN}},
|
{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
|
{RSP_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||||
{EV_IF_LOCK, -1, -1, -1, -1,-1, {ACT_IF_LOCK}}, //FIXME
|
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{EV_IF_VER, -1, -1, -1, -1,-1, {ACT_IF_VER}}, //FIXME
|
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||||
{EV_START, -1, -1, -1, -1,-1, {ACT_START}}, //FIXME
|
{RSP_LAST}
|
||||||
{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}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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[] =
|
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 */
|
/* dial */
|
||||||
{EV_DIAL, -1, -1, -1, -1,-1, {ACT_DIAL}}, //FIXME
|
{EV_DIAL, -1, -1, -1, -1, -1, {ACT_DIAL} },
|
||||||
{RSP_INIT, 0, 0,SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC}},
|
{RSP_INIT, 0, 0, SEQ_DIAL, 601, 5, {ACT_CMD+AT_BC} },
|
||||||
{RSP_OK, 601,601, -1, 602, 5, {ACT_CMD+AT_HLC}},
|
{RSP_OK, 601, 601, -1, 602, 5, {ACT_CMD+AT_HLC} },
|
||||||
{RSP_NULL, 602,602, -1, 603, 5, {ACT_CMD+AT_PROTO}},
|
{RSP_NULL, 602, 602, -1, 603, 5, {ACT_CMD+AT_PROTO} },
|
||||||
{RSP_OK, 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, 603, 603, -1, 604, 5, {ACT_CMD+AT_TYPE} },
|
||||||
{RSP_OK, 604,604, -1, 605, 5, {ACT_CMD+AT_MSN}},
|
{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_CLIP} },
|
||||||
{RSP_NULL, 605,605, -1, 606, 5, {ACT_CMD+AT_ISO}},
|
{RSP_OK, 605, 605, -1, 606, 5, {ACT_CMD+AT_CLIP} },
|
||||||
{RSP_OK, 606,606, -1, 607, 5, {0}, "+VLS=17\r"},
|
{RSP_NULL, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} },
|
||||||
{RSP_OK, 607,607, -1, 608,-1},
|
{RSP_OK, 606, 606, -1, 607, 5, {ACT_CMD+AT_ISO} },
|
||||||
{RSP_ZSAU, 608,608,ZSAU_PROCEEDING, 609, 5, {ACT_CMD+AT_DIAL}},
|
{RSP_OK, 607, 607, -1, 608, 5, {0}, "+VLS=17\r"},
|
||||||
{RSP_OK, 609,609, -1, 650, 0, {ACT_DIALING}},
|
{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}},
|
{RSP_ERROR, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||||
{EV_TIMEOUT, 601,609, -1, 0, 0, {ACT_ABORTDIAL}},
|
{EV_TIMEOUT, 601, 610, -1, 0, 0, {ACT_ABORTDIAL} },
|
||||||
|
|
||||||
/* optional dialing responses */
|
/* optional dialing responses */
|
||||||
{EV_BC_OPEN, 650,650, -1, 651,-1},
|
{EV_BC_OPEN, 650, 650, -1, 651, -1},
|
||||||
{RSP_ZVLS, 608,651, 17, -1,-1, {ACT_DEBUG}},
|
{RSP_ZVLS, 609, 651, 17, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_ZCTP, 609,651, -1, -1,-1, {ACT_DEBUG}},
|
{RSP_ZCTP, 610, 651, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_ZCPN, 609,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}},
|
{RSP_ZSAU, 650, 651, ZSAU_CALL_DELIVERED, -1, -1, {ACT_DEBUG} },
|
||||||
|
|
||||||
/* connect */
|
/* connect */
|
||||||
{RSP_ZSAU, 650,650,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
|
{RSP_ZSAU, 650, 650, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||||
{RSP_ZSAU, 651,651,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
|
{RSP_ZSAU, 651, 651, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||||
ACT_NOTIFY_BC_UP}},
|
ACT_NOTIFY_BC_UP} },
|
||||||
{RSP_ZSAU, 750,750,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT}},
|
{RSP_ZSAU, 750, 750, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT} },
|
||||||
{RSP_ZSAU, 751,751,ZSAU_ACTIVE, 800,-1, {ACT_CONNECT,
|
{RSP_ZSAU, 751, 751, ZSAU_ACTIVE, 800, -1, {ACT_CONNECT,
|
||||||
ACT_NOTIFY_BC_UP}},
|
ACT_NOTIFY_BC_UP} },
|
||||||
{EV_BC_OPEN, 800,800, -1, 800,-1, {ACT_NOTIFY_BC_UP}},
|
{EV_BC_OPEN, 800, 800, -1, 800, -1, {ACT_NOTIFY_BC_UP} },
|
||||||
|
|
||||||
/* remote hangup */
|
/* remote hangup */
|
||||||
{RSP_ZSAU, 650,651,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT}},
|
{RSP_ZSAU, 650, 651, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEREJECT} },
|
||||||
{RSP_ZSAU, 750,751,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
|
{RSP_ZSAU, 750, 751, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||||
{RSP_ZSAU, 800,800,ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP}},
|
{RSP_ZSAU, 800, 800, ZSAU_DISCONNECT_IND, 0, 0, {ACT_REMOTEHUP} },
|
||||||
|
|
||||||
/* hangup */
|
/* hangup */
|
||||||
{EV_HUP, -1, -1, -1, -1,-1, {ACT_HUP}}, //FIXME
|
{EV_HUP, -1, -1, -1, -1, -1, {ACT_HUP} },
|
||||||
{RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1?
|
{RSP_INIT, -1, -1, SEQ_HUP, 401, 5, {0}, "+VLS=0\r"},
|
||||||
{RSP_OK, 401,401, -1, 402, 5},
|
{RSP_OK, 401, 401, -1, 402, 5},
|
||||||
{RSP_ZVLS, 402,402, 0, 403, 5},
|
{RSP_ZVLS, 402, 402, 0, 403, 5},
|
||||||
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
{RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
{RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} },
|
||||||
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
{RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} },
|
||||||
{RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}},
|
{RSP_ERROR, 401, 401, -1, 0, 0, {ACT_ABORTHUP} },
|
||||||
{EV_TIMEOUT, 401,403, -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 */
|
/* ring */
|
||||||
{RSP_ZBC, 700,700, -1, -1,-1, {0}},
|
{RSP_ZBC, 700, 700, -1, -1, -1, {0} },
|
||||||
{RSP_ZHLC, 700,700, -1, -1,-1, {0}},
|
{RSP_ZHLC, 700, 700, -1, -1, -1, {0} },
|
||||||
{RSP_NMBR, 700,700, -1, -1,-1, {0}},
|
{RSP_NMBR, 700, 700, -1, -1, -1, {0} },
|
||||||
{RSP_ZCPN, 700,700, -1, -1,-1, {0}},
|
{RSP_ZCPN, 700, 700, -1, -1, -1, {0} },
|
||||||
{RSP_ZCTP, 700,700, -1, -1,-1, {0}},
|
{RSP_ZCTP, 700, 700, -1, -1, -1, {0} },
|
||||||
{EV_TIMEOUT, 700,700, -1, 720,720, {ACT_ICALL}},
|
{EV_TIMEOUT, 700, 700, -1, 720, 720, {ACT_ICALL} },
|
||||||
{EV_BC_CLOSED,720,720, -1, 0,-1, {ACT_NOTIFY_BC_DOWN}},
|
{EV_BC_CLOSED, 720, 720, -1, 0, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||||
|
|
||||||
/*accept icall*/
|
/*accept icall*/
|
||||||
{EV_ACCEPT, -1, -1, -1, -1,-1, {ACT_ACCEPT}}, //FIXME
|
{EV_ACCEPT, -1, -1, -1, -1, -1, {ACT_ACCEPT} },
|
||||||
{RSP_INIT, 720,720,SEQ_ACCEPT, 721, 5, {ACT_CMD+AT_PROTO}},
|
{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, 721, 721, -1, 722, 5, {ACT_CMD+AT_ISO} },
|
||||||
{RSP_OK, 722,722, -1, 723, 5, {0}, "+VLS=17\r"}, /* set "Endgeraetemodus" */
|
{RSP_OK, 722, 722, -1, 723, 5, {0}, "+VLS=17\r"},
|
||||||
{RSP_OK, 723,723, -1, 724, 5, {0}},
|
{RSP_OK, 723, 723, -1, 724, 5, {0} },
|
||||||
{RSP_ZVLS, 724,724, 17, 750,50, {ACT_ACCEPTED}},
|
{RSP_ZVLS, 724, 724, 17, 750, 50, {ACT_ACCEPTED} },
|
||||||
{RSP_ERROR, 721,729, -1, 0, 0, {ACT_ABORTACCEPT}},
|
{RSP_ERROR, 721, 729, -1, 0, 0, {ACT_ABORTACCEPT} },
|
||||||
{EV_TIMEOUT, 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_NULL, 0, 0, {ACT_ABORTACCEPT} },
|
||||||
{RSP_ZSAU, 700,729,ZSAU_ACTIVE, 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}},
|
{RSP_ZSAU, 700, 729, ZSAU_DISCONNECT_IND, 0, 0, {ACT_ABORTACCEPT} },
|
||||||
|
|
||||||
{EV_BC_OPEN, 750,750, -1, 751,-1},
|
{EV_BC_OPEN, 750, 750, -1, 751, -1},
|
||||||
{EV_TIMEOUT, 750,751, -1, 0, 0, {ACT_CONNTIMEOUT}},
|
{EV_TIMEOUT, 750, 751, -1, 0, 0, {ACT_CONNTIMEOUT} },
|
||||||
|
|
||||||
/* B channel closed (general case) */
|
/* B channel closed (general case) */
|
||||||
{EV_BC_CLOSED, -1, -1, -1, -1,-1, {ACT_NOTIFY_BC_DOWN}}, //FIXME
|
{EV_BC_CLOSED, -1, -1, -1, -1, -1, {ACT_NOTIFY_BC_DOWN} },
|
||||||
|
|
||||||
/* misc. */
|
/* misc. */
|
||||||
{EV_PROTO_L2, -1, -1, -1, -1,-1, {ACT_PROTO_L2}}, //FIXME
|
{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_ZCAU, -1, -1, -1, -1, -1, {ACT_ZCAU} },
|
||||||
{RSP_ZCCR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
{RSP_NONE, -1, -1, -1, -1, -1, {ACT_DEBUG} },
|
||||||
{RSP_ZAOC, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
{RSP_ANY, -1, -1, -1, -1, -1, {ACT_WARN} },
|
||||||
{RSP_ZCSTR, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME
|
{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},
|
{"OK", RSP_OK, RT_NOTHING},
|
||||||
{"ERROR", RSP_ERROR, RT_NOTHING},
|
{"ERROR", RSP_ERROR, RT_NOTHING},
|
||||||
{"ZSAU", RSP_ZSAU, RT_ZSAU},
|
{"ZSAU", RSP_ZSAU, RT_ZSAU},
|
||||||
|
@ -405,7 +403,21 @@ static const struct resp_type_t resp_type[] =
|
||||||
{"ZLOG", RSP_ZLOG, RT_NOTHING},
|
{"ZLOG", RSP_ZLOG, RT_NOTHING},
|
||||||
{"ZABINFO", RSP_ZABINFO, RT_NOTHING},
|
{"ZABINFO", RSP_ZABINFO, RT_NOTHING},
|
||||||
{"ZSMLSTCHG", RSP_ZSMLSTCHG, 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)
|
if (cid < 1 || cid > 65535)
|
||||||
return -1; /* CID out of range */
|
return -1; /* CID out of range */
|
||||||
return cid;
|
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 params;
|
||||||
int i, j;
|
int i, j;
|
||||||
const struct resp_type_t *rt;
|
const struct resp_type_t *rt;
|
||||||
|
const struct zsau_resp_t *zr;
|
||||||
int curarg;
|
int curarg;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned next, tail, head;
|
unsigned next, tail, head;
|
||||||
|
@ -613,24 +625,14 @@ void gigaset_handle_modem_response(struct cardstate *cs)
|
||||||
event->parameter = ZSAU_NONE;
|
event->parameter = ZSAU_NONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!strcmp(argv[curarg], "OUTGOING_CALL_PROCEEDING"))
|
for (zr = zsau_resp; zr->str; ++zr)
|
||||||
event->parameter = ZSAU_OUTGOING_CALL_PROCEEDING;
|
if (!strcmp(argv[curarg], zr->str))
|
||||||
else if (!strcmp(argv[curarg], "CALL_DELIVERED"))
|
break;
|
||||||
event->parameter = ZSAU_CALL_DELIVERED;
|
event->parameter = zr->code;
|
||||||
else if (!strcmp(argv[curarg], "ACTIVE"))
|
if (!zr->str)
|
||||||
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;
|
|
||||||
dev_warn(cs->dev,
|
dev_warn(cs->dev,
|
||||||
"%s: unknown parameter %s after ZSAU\n",
|
"%s: unknown parameter %s after ZSAU\n",
|
||||||
__func__, argv[curarg]);
|
__func__, argv[curarg]);
|
||||||
}
|
|
||||||
++curarg;
|
++curarg;
|
||||||
break;
|
break;
|
||||||
case RT_STRING:
|
case RT_STRING:
|
||||||
|
@ -714,7 +716,7 @@ static void disconnect(struct at_state_t **at_state_p)
|
||||||
/* notify LL */
|
/* notify LL */
|
||||||
if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
|
if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
|
||||||
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 {
|
} else {
|
||||||
/* no B channel assigned: just deallocate */
|
/* no B channel assigned: just deallocate */
|
||||||
|
@ -872,12 +874,12 @@ static void bchannel_down(struct bc_state *bcs)
|
||||||
{
|
{
|
||||||
if (bcs->chstate & CHS_B_UP) {
|
if (bcs->chstate & CHS_B_UP) {
|
||||||
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)) {
|
if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) {
|
||||||
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);
|
gigaset_free_channel(bcs);
|
||||||
|
@ -894,15 +896,17 @@ static void bchannel_up(struct bc_state *bcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
bcs->chstate |= CHS_B_UP;
|
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 bc_state *bcs = at_state->bcs;
|
||||||
struct cardstate *cs = at_state->cs;
|
struct cardstate *cs = at_state->cs;
|
||||||
int retval;
|
char **commands = data;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
bcs->chstate |= CHS_NOTIFY_LL;
|
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);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
|
|
||||||
retval = gigaset_isdn_setup_dial(at_state, data);
|
for (i = 0; i < AT_NUM; ++i) {
|
||||||
if (retval != 0)
|
kfree(bcs->commands[i]);
|
||||||
goto error;
|
bcs->commands[i] = commands[i];
|
||||||
|
}
|
||||||
|
|
||||||
at_state->pending_commands |= PC_CID;
|
at_state->pending_commands |= PC_CID;
|
||||||
gig_dbg(DEBUG_CMD, "Scheduling 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;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
for (i = 0; i < AT_NUM; ++i) {
|
||||||
|
kfree(commands[i]);
|
||||||
|
commands[i] = NULL;
|
||||||
|
}
|
||||||
at_state->pending_commands |= PC_NOCID;
|
at_state->pending_commands |= PC_NOCID;
|
||||||
gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
|
gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID");
|
||||||
cs->commands_pending = 1;
|
cs->commands_pending = 1;
|
||||||
|
@ -933,20 +941,31 @@ error:
|
||||||
static void start_accept(struct at_state_t *at_state)
|
static void start_accept(struct at_state_t *at_state)
|
||||||
{
|
{
|
||||||
struct cardstate *cs = at_state->cs;
|
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) {
|
bcs->commands[AT_PROTO] = kmalloc(9, GFP_ATOMIC);
|
||||||
at_state->pending_commands |= PC_ACCEPT;
|
bcs->commands[AT_ISO] = kmalloc(9, GFP_ATOMIC);
|
||||||
gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT");
|
if (!bcs->commands[AT_PROTO] || !bcs->commands[AT_ISO]) {
|
||||||
cs->commands_pending = 1;
|
dev_err(at_state->cs->dev, "out of memory\n");
|
||||||
} else {
|
|
||||||
/* error reset */
|
/* error reset */
|
||||||
at_state->pending_commands |= PC_HUP;
|
at_state->pending_commands |= PC_HUP;
|
||||||
gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
|
gig_dbg(DEBUG_CMD, "Scheduling PC_HUP");
|
||||||
cs->commands_pending = 1;
|
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)
|
static void do_start(struct cardstate *cs)
|
||||||
|
@ -957,9 +976,7 @@ static void do_start(struct cardstate *cs)
|
||||||
schedule_init(cs, MS_INIT);
|
schedule_init(cs, MS_INIT);
|
||||||
|
|
||||||
cs->isdn_up = 1;
|
cs->isdn_up = 1;
|
||||||
gigaset_i4l_cmd(cs, ISDN_STAT_RUN);
|
gigaset_isdn_start(cs);
|
||||||
// FIXME: not in locked mode
|
|
||||||
// FIXME 2: only after init sequence
|
|
||||||
|
|
||||||
cs->waiting = 0;
|
cs->waiting = 0;
|
||||||
wake_up(&cs->waitqueue);
|
wake_up(&cs->waitqueue);
|
||||||
|
@ -975,7 +992,7 @@ static void finish_shutdown(struct cardstate *cs)
|
||||||
/* Tell the LL that the device is not available .. */
|
/* Tell the LL that the device is not available .. */
|
||||||
if (cs->isdn_up) {
|
if (cs->isdn_up) {
|
||||||
cs->isdn_up = 0;
|
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. */
|
/* The rest is done by cleanup_cs () in user mode. */
|
||||||
|
@ -1113,7 +1130,6 @@ static int do_lock(struct cardstate *cs)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MS_LOCKED:
|
case MS_LOCKED:
|
||||||
//retval = -EACCES;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -1276,7 +1292,7 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bcs->chstate |= CHS_D_UP;
|
bcs->chstate |= CHS_D_UP;
|
||||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
|
gigaset_isdn_connD(bcs);
|
||||||
cs->ops->init_bchannel(bcs);
|
cs->ops->init_bchannel(bcs);
|
||||||
break;
|
break;
|
||||||
case ACT_DLE1:
|
case ACT_DLE1:
|
||||||
|
@ -1284,7 +1300,7 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
bcs = cs->bcs + cs->curchannel;
|
bcs = cs->bcs + cs->curchannel;
|
||||||
|
|
||||||
bcs->chstate |= CHS_D_UP;
|
bcs->chstate |= CHS_D_UP;
|
||||||
gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN);
|
gigaset_isdn_connD(bcs);
|
||||||
cs->ops->init_bchannel(bcs);
|
cs->ops->init_bchannel(bcs);
|
||||||
break;
|
break;
|
||||||
case ACT_FAKEHUP:
|
case ACT_FAKEHUP:
|
||||||
|
@ -1369,7 +1385,7 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
cs->cur_at_seq = SEQ_NONE;
|
cs->cur_at_seq = SEQ_NONE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL processing */
|
case ACT_ABORTACCEPT: /* hangup/error/timeout during ICALL procssng */
|
||||||
disconnect(p_at_state);
|
disconnect(p_at_state);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1443,17 +1459,6 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
__func__, at_state->ConState);
|
__func__, at_state->ConState);
|
||||||
cs->cur_at_seq = SEQ_NONE;
|
cs->cur_at_seq = SEQ_NONE;
|
||||||
break;
|
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:
|
case ACT_DEBUG:
|
||||||
gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
|
gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d",
|
||||||
__func__, ev->type, at_state->ConState);
|
__func__, ev->type, at_state->ConState);
|
||||||
|
@ -1474,11 +1479,6 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
case ACT_ACCEPT:
|
case ACT_ACCEPT:
|
||||||
start_accept(at_state);
|
start_accept(at_state);
|
||||||
break;
|
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:
|
case ACT_HUP:
|
||||||
at_state->pending_commands |= PC_HUP;
|
at_state->pending_commands |= PC_HUP;
|
||||||
cs->commands_pending = 1;
|
cs->commands_pending = 1;
|
||||||
|
@ -1493,7 +1493,7 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
do_start(cs);
|
do_start(cs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* events from the interface */ // FIXME without ACT_xxxx?
|
/* events from the interface */
|
||||||
case ACT_IF_LOCK:
|
case ACT_IF_LOCK:
|
||||||
cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
|
cs->cmd_result = ev->parameter ? do_lock(cs) : do_unlock(cs);
|
||||||
cs->waiting = 0;
|
cs->waiting = 0;
|
||||||
|
@ -1512,7 +1512,7 @@ static void do_action(int action, struct cardstate *cs,
|
||||||
wake_up(&cs->waitqueue);
|
wake_up(&cs->waitqueue);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* events from the proc file system */ // FIXME without ACT_xxxx?
|
/* events from the proc file system */
|
||||||
case ACT_PROC_CIDMODE:
|
case ACT_PROC_CIDMODE:
|
||||||
spin_lock_irqsave(&cs->lock, flags);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
if (ev->parameter != cs->cidmode) {
|
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) {
|
for (curact = 0; curact < MAXACT; ++curact) {
|
||||||
/* The row tells us what we should do ..
|
/* 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)
|
if (!at_state)
|
||||||
break; /* may be freed after disconnect */
|
break; /* may be freed after disconnect */
|
||||||
}
|
}
|
||||||
|
@ -1661,13 +1662,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev)
|
||||||
|
|
||||||
if (genresp) {
|
if (genresp) {
|
||||||
spin_lock_irqsave(&cs->lock, flags);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
at_state->timer_expires = 0; //FIXME
|
at_state->timer_expires = 0;
|
||||||
at_state->timer_active = 0; //FIXME
|
at_state->timer_active = 0;
|
||||||
spin_unlock_irqrestore(&cs->lock, flags);
|
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 {
|
} else {
|
||||||
/* Send command to modem if not NULL... */
|
/* Send command to modem if not NULL... */
|
||||||
if (p_command/*rep->command*/) {
|
if (p_command) {
|
||||||
if (cs->connected)
|
if (cs->connected)
|
||||||
send_command(cs, p_command,
|
send_command(cs, p_command,
|
||||||
sendcid, cs->dle,
|
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);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
if (cs->at_state.pending_commands == PC_UMMODE
|
if (cs->at_state.pending_commands == PC_UMMODE
|
||||||
&& !cs->cidmode
|
&& !cs->cidmode
|
||||||
|
@ -1813,9 +1816,8 @@ static void process_command_flags(struct cardstate *cs)
|
||||||
|
|
||||||
if (cs->at_state.pending_commands & PC_INIT) {
|
if (cs->at_state.pending_commands & PC_INIT) {
|
||||||
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;
|
cs->inbuf->inputstate = INS_command;
|
||||||
//FIXME reset card state (or -> LOCK0)?
|
|
||||||
schedule_sequence(cs, &cs->at_state, SEQ_INIT);
|
schedule_sequence(cs, &cs->at_state, SEQ_INIT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/isdnif.h>
|
|
||||||
#include <linux/usb.h>
|
#include <linux/usb.h>
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
|
@ -35,12 +34,11 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
#define GIG_VERSION {0,5,0,0}
|
#define GIG_VERSION {0, 5, 0, 0}
|
||||||
#define GIG_COMPAT {0,4,0,0}
|
#define GIG_COMPAT {0, 4, 0, 0}
|
||||||
|
|
||||||
#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
|
#define MAX_REC_PARAMS 10 /* Max. number of params in response string */
|
||||||
#define MAX_RESP_SIZE 512 /* Max. size of a 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 */
|
#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 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)
|
#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_B1_FLOW_CONTROL 0x80
|
||||||
#define HD_B2_FLOW_CONTROL 0x81
|
#define HD_B2_FLOW_CONTROL 0x81
|
||||||
#define HD_RECEIVEATDATA_ACK (0x35) // 3070
|
#define HD_RECEIVEATDATA_ACK (0x35) /* 3070 */
|
||||||
// att: HD_RECEIVE>>AT<<DATA_ACK
|
#define HD_READY_SEND_ATDATA (0x36) /* 3070 */
|
||||||
#define HD_READY_SEND_ATDATA (0x36) // 3070
|
#define HD_OPEN_ATCHANNEL_ACK (0x37) /* 3070 */
|
||||||
#define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070
|
#define HD_CLOSE_ATCHANNEL_ACK (0x38) /* 3070 */
|
||||||
#define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070
|
#define HD_DEVICE_INIT_OK (0x11) /* ISurf USB + 3070 */
|
||||||
#define HD_DEVICE_INIT_OK (0x11) // ISurf USB + 3070
|
#define HD_OPEN_B1CHANNEL_ACK (0x51) /* ISurf USB + 3070 */
|
||||||
#define HD_OPEN_B1CHANNEL_ACK (0x51) // ISurf USB + 3070
|
#define HD_OPEN_B2CHANNEL_ACK (0x52) /* ISurf USB + 3070 */
|
||||||
#define HD_OPEN_B2CHANNEL_ACK (0x52) // ISurf USB + 3070
|
#define HD_CLOSE_B1CHANNEL_ACK (0x53) /* ISurf USB + 3070 */
|
||||||
#define HD_CLOSE_B1CHANNEL_ACK (0x53) // ISurf USB + 3070
|
#define HD_CLOSE_B2CHANNEL_ACK (0x54) /* ISurf USB + 3070 */
|
||||||
#define HD_CLOSE_B2CHANNEL_ACK (0x54) // ISurf USB + 3070
|
#define HD_SUSPEND_END (0x61) /* ISurf USB */
|
||||||
// Powermangment
|
#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) /* ISurf USB + 3070 */
|
||||||
#define HD_SUSPEND_END (0x61) // ISurf USB
|
|
||||||
// Configuration
|
|
||||||
#define HD_RESET_INTERRUPT_PIPE_ACK (0xFF) // ISurf USB + 3070
|
|
||||||
|
|
||||||
/* control requests 3070 */
|
/* control requests */
|
||||||
#define HD_OPEN_B1CHANNEL (0x23) // ISurf USB + 3070
|
#define HD_OPEN_B1CHANNEL (0x23) /* ISurf USB + 3070 */
|
||||||
#define HD_CLOSE_B1CHANNEL (0x24) // ISurf USB + 3070
|
#define HD_CLOSE_B1CHANNEL (0x24) /* ISurf USB + 3070 */
|
||||||
#define HD_OPEN_B2CHANNEL (0x25) // ISurf USB + 3070
|
#define HD_OPEN_B2CHANNEL (0x25) /* ISurf USB + 3070 */
|
||||||
#define HD_CLOSE_B2CHANNEL (0x26) // ISurf USB + 3070
|
#define HD_CLOSE_B2CHANNEL (0x26) /* ISurf USB + 3070 */
|
||||||
#define HD_RESET_INTERRUPT_PIPE (0x27) // ISurf USB + 3070
|
#define HD_RESET_INTERRUPT_PIPE (0x27) /* ISurf USB + 3070 */
|
||||||
#define HD_DEVICE_INIT_ACK (0x34) // ISurf USB + 3070
|
#define HD_DEVICE_INIT_ACK (0x34) /* ISurf USB + 3070 */
|
||||||
#define HD_WRITE_ATMESSAGE (0x12) // 3070
|
#define HD_WRITE_ATMESSAGE (0x12) /* 3070 */
|
||||||
#define HD_READ_ATMESSAGE (0x13) // 3070
|
#define HD_READ_ATMESSAGE (0x13) /* 3070 */
|
||||||
#define HD_OPEN_ATCHANNEL (0x28) // 3070
|
#define HD_OPEN_ATCHANNEL (0x28) /* 3070 */
|
||||||
#define HD_CLOSE_ATCHANNEL (0x29) // 3070
|
#define HD_CLOSE_ATCHANNEL (0x29) /* 3070 */
|
||||||
|
|
||||||
/* number of B channels supported by base driver */
|
/* number of B channels supported by base driver */
|
||||||
#define BAS_CHANNELS 2
|
#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_PROTO 4
|
||||||
#define AT_TYPE 5
|
#define AT_TYPE 5
|
||||||
#define AT_HLC 6
|
#define AT_HLC 6
|
||||||
#define AT_NUM 7
|
#define AT_CLIP 7
|
||||||
|
/* total number */
|
||||||
|
#define AT_NUM 8
|
||||||
|
|
||||||
/* variables in struct at_state_t */
|
/* variables in struct at_state_t */
|
||||||
#define VAR_ZSAU 0
|
#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_START -110
|
||||||
#define EV_STOP -111
|
#define EV_STOP -111
|
||||||
#define EV_IF_LOCK -112
|
#define EV_IF_LOCK -112
|
||||||
#define EV_PROTO_L2 -113
|
|
||||||
#define EV_ACCEPT -114
|
#define EV_ACCEPT -114
|
||||||
#define EV_DIAL -115
|
#define EV_DIAL -115
|
||||||
#define EV_HUP -116
|
#define EV_HUP -116
|
||||||
|
@ -224,12 +220,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
||||||
#define EV_BC_CLOSED -118
|
#define EV_BC_CLOSED -118
|
||||||
|
|
||||||
/* input state */
|
/* input state */
|
||||||
#define INS_command 0x0001
|
#define INS_command 0x0001 /* receiving messages (not payload data) */
|
||||||
#define INS_DLE_char 0x0002
|
#define INS_DLE_char 0x0002 /* DLE flag received (in DLE mode) */
|
||||||
#define INS_byte_stuff 0x0004
|
#define INS_byte_stuff 0x0004
|
||||||
#define INS_have_data 0x0008
|
#define INS_have_data 0x0008
|
||||||
#define INS_skip_frame 0x0010
|
#define INS_DLE_command 0x0020 /* DLE message start (<DLE> X) received */
|
||||||
#define INS_DLE_command 0x0020
|
|
||||||
#define INS_flag_hunt 0x0040
|
#define INS_flag_hunt 0x0040
|
||||||
|
|
||||||
/* channel state */
|
/* channel state */
|
||||||
|
@ -259,6 +254,11 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg,
|
||||||
#define SM_LOCKED 0
|
#define SM_LOCKED 0
|
||||||
#define SM_ISDN 1 /* default */
|
#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_ops;
|
||||||
struct gigaset_driver;
|
struct gigaset_driver;
|
||||||
|
|
||||||
|
@ -286,8 +286,6 @@ extern struct reply_t gigaset_tab_cid[];
|
||||||
extern struct reply_t gigaset_tab_nocid[];
|
extern struct reply_t gigaset_tab_nocid[];
|
||||||
|
|
||||||
struct inbuf_t {
|
struct inbuf_t {
|
||||||
unsigned char *rcvbuf; /* usb-gigaset receive buffer */
|
|
||||||
struct bc_state *bcs;
|
|
||||||
struct cardstate *cs;
|
struct cardstate *cs;
|
||||||
int inputstate;
|
int inputstate;
|
||||||
int head, tail;
|
int head, tail;
|
||||||
|
@ -359,12 +357,6 @@ struct at_state_t {
|
||||||
struct bc_state *bcs;
|
struct bc_state *bcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct resp_type_t {
|
|
||||||
unsigned char *response;
|
|
||||||
int resp_code; /* RSP_XXXX */
|
|
||||||
int type; /* RT_XXXX */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct event_t {
|
struct event_t {
|
||||||
int type;
|
int type;
|
||||||
void *ptr, *arg;
|
void *ptr, *arg;
|
||||||
|
@ -395,7 +387,7 @@ struct bc_state {
|
||||||
|
|
||||||
unsigned chstate; /* bitmap (CHS_*) */
|
unsigned chstate; /* bitmap (CHS_*) */
|
||||||
int ignore;
|
int ignore;
|
||||||
unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */
|
unsigned proto2; /* layer 2 protocol (L2_*) */
|
||||||
char *commands[AT_NUM]; /* see AT_XXXX */
|
char *commands[AT_NUM]; /* see AT_XXXX */
|
||||||
|
|
||||||
#ifdef CONFIG_GIGASET_DEBUG
|
#ifdef CONFIG_GIGASET_DEBUG
|
||||||
|
@ -410,6 +402,8 @@ struct bc_state {
|
||||||
struct usb_bc_state *usb; /* usb hardware driver (m105) */
|
struct usb_bc_state *usb; /* usb hardware driver (m105) */
|
||||||
struct bas_bc_state *bas; /* usb hardware driver (base) */
|
struct bas_bc_state *bas; /* usb hardware driver (base) */
|
||||||
} hw;
|
} hw;
|
||||||
|
|
||||||
|
void *ap; /* LL application structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cardstate {
|
struct cardstate {
|
||||||
|
@ -456,12 +450,13 @@ struct cardstate {
|
||||||
|
|
||||||
unsigned running; /* !=0 if events are handled */
|
unsigned running; /* !=0 if events are handled */
|
||||||
unsigned connected; /* !=0 if hardware is connected */
|
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;
|
unsigned cidmode;
|
||||||
|
|
||||||
int myid; /* id for communication with LL */
|
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 *tabnocid;
|
||||||
struct reply_t *tabcid;
|
struct reply_t *tabcid;
|
||||||
|
@ -476,8 +471,8 @@ struct cardstate {
|
||||||
|
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
int retry_count;
|
int retry_count;
|
||||||
int dle; /* !=0 if modem commands/responses are
|
int dle; /* !=0 if DLE mode is active
|
||||||
dle encoded */
|
(ZDLE=1 received -- M10x only) */
|
||||||
int cur_at_seq; /* sequence of AT commands being
|
int cur_at_seq; /* sequence of AT commands being
|
||||||
processed */
|
processed */
|
||||||
int curchannel; /* channel those commands are meant
|
int curchannel; /* channel those commands are meant
|
||||||
|
@ -616,7 +611,9 @@ struct gigaset_ops {
|
||||||
int (*baud_rate)(struct cardstate *cs, unsigned cflag);
|
int (*baud_rate)(struct cardstate *cs, unsigned cflag);
|
||||||
int (*set_line_ctrl)(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);
|
int (*send_skb)(struct bc_state *bcs, struct sk_buff *skb);
|
||||||
|
|
||||||
/* Called from ev-layer.c to process a block of data
|
/* 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:
|
/* Parser states for DLE-Event:
|
||||||
* <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "."
|
* <DLE-EVENT>: <DLE_FLAG> "X" <EVENT> <DLE_FLAG> "."
|
||||||
|
@ -638,8 +636,7 @@ struct gigaset_ops {
|
||||||
* Functions implemented in asyncdata.c
|
* Functions implemented in asyncdata.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 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 gigaset_skb_sent() should be called. */
|
|
||||||
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
||||||
|
|
||||||
/* Called from ev-layer.c to process a block of data
|
/* 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
|
* Functions implemented in isocdata.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 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 gigaset_skb_sent() should be called. */
|
|
||||||
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb);
|
||||||
|
|
||||||
/* Called from ev-layer.c to process a block of data
|
/* 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);
|
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 */
|
/* Called from common.c for setting up/shutting down with the ISDN subsystem */
|
||||||
int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid);
|
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_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 */
|
/* 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_icall(struct at_state_t *at_state);
|
||||||
int gigaset_isdn_setup_accept(struct at_state_t *at_state);
|
void gigaset_isdn_connD(struct bc_state *bcs);
|
||||||
int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data);
|
void gigaset_isdn_hupD(struct bc_state *bcs);
|
||||||
|
void gigaset_isdn_connB(struct bc_state *bcs);
|
||||||
void gigaset_i4l_cmd(struct cardstate *cs, int cmd);
|
void gigaset_isdn_hupB(struct bc_state *bcs);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===========================================================================
|
/* ===========================================================================
|
||||||
* Functions implemented in ev-layer.c
|
* 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,
|
void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs,
|
||||||
struct cardstate *cs, int cid);
|
struct cardstate *cs, int cid);
|
||||||
int gigaset_get_channel(struct bc_state *bcs);
|
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);
|
void gigaset_free_channel(struct bc_state *bcs);
|
||||||
int gigaset_get_channels(struct cardstate *cs);
|
int gigaset_get_channels(struct cardstate *cs);
|
||||||
void gigaset_free_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);
|
void *ptr, int parameter, void *arg);
|
||||||
|
|
||||||
/* Called on CONFIG1 command from frontend. */
|
/* 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 */
|
/* cs->lock must not be locked */
|
||||||
static inline void gigaset_schedule_event(struct cardstate *cs)
|
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 */
|
/* 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 */
|
/* append received bytes to inbuf */
|
||||||
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
|
int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src,
|
||||||
unsigned numbytes);
|
unsigned numbytes);
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "gigaset.h"
|
#include "gigaset.h"
|
||||||
|
#include <linux/isdnif.h>
|
||||||
|
|
||||||
|
#define HW_HDR_LEN 2 /* Header size used to store ack info */
|
||||||
|
|
||||||
/* == Handling of I4L IO =====================================================*/
|
/* == Handling of I4L IO =====================================================*/
|
||||||
|
|
||||||
|
@ -36,12 +39,12 @@
|
||||||
static int writebuf_from_LL(int driverID, int channel, int ack,
|
static int writebuf_from_LL(int driverID, int channel, int ack,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct cardstate *cs;
|
struct cardstate *cs = gigaset_get_cs_by_id(driverID);
|
||||||
struct bc_state *bcs;
|
struct bc_state *bcs;
|
||||||
|
unsigned char *ack_header;
|
||||||
unsigned len;
|
unsigned len;
|
||||||
unsigned skblen;
|
|
||||||
|
|
||||||
if (!(cs = gigaset_get_cs_by_id(driverID))) {
|
if (!cs) {
|
||||||
pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
|
pr_err("%s: invalid driver ID (%d)\n", __func__, driverID);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -75,11 +78,23 @@ static int writebuf_from_LL(int driverID, int channel, int ack,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
skblen = ack ? len : 0;
|
/* set up acknowledgement header */
|
||||||
skb->head[0] = skblen & 0xff;
|
if (skb_headroom(skb) < HW_HDR_LEN) {
|
||||||
skb->head[1] = skblen >> 8;
|
/* should never happen */
|
||||||
gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x",
|
dev_err(cs->dev, "%s: insufficient skb headroom\n", __func__);
|
||||||
len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]);
|
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 */
|
/* pass to device-specific module */
|
||||||
return cs->ops->send_skb(bcs, skb);
|
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)
|
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;
|
unsigned len;
|
||||||
isdn_ctrl response;
|
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",
|
dev_warn(bcs->cs->dev, "%s: skb->len==%d\n",
|
||||||
__func__, skb->len);
|
__func__, skb->len);
|
||||||
|
|
||||||
len = (unsigned char) skb->head[0] |
|
len = ack_header[0] + ((unsigned) ack_header[1] << 8);
|
||||||
(unsigned) (unsigned char) skb->head[1] << 8;
|
|
||||||
if (len) {
|
if (len) {
|
||||||
gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
|
gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)",
|
||||||
bcs->cs->myid, bcs->channel, len);
|
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.command = ISDN_STAT_BSENT;
|
||||||
response.arg = bcs->channel;
|
response.arg = bcs->channel;
|
||||||
response.parm.length = len;
|
response.parm.length = len;
|
||||||
bcs->cs->iif.statcallb(&response);
|
iif->statcallb(&response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(gigaset_skb_sent);
|
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
|
/* This function will be called by LL to send commands
|
||||||
* NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
|
* NOTE: LL ignores the returned value, for commands other than ISDN_CMD_IOCTL,
|
||||||
* so don't put too much effort into it.
|
* so don't put too much effort into it.
|
||||||
*/
|
*/
|
||||||
static int command_from_LL(isdn_ctrl *cntrl)
|
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;
|
struct bc_state *bcs;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
struct setup_parm *sp;
|
char **commands;
|
||||||
|
int ch;
|
||||||
|
int i;
|
||||||
|
size_t l;
|
||||||
|
|
||||||
gigaset_debugdrivers();
|
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);
|
pr_err("%s: invalid driver ID (%d)\n", __func__, cntrl->driver);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
ch = cntrl->arg & 0xff;
|
||||||
|
|
||||||
switch (cntrl->command) {
|
switch (cntrl->command) {
|
||||||
case ISDN_CMD_IOCTL:
|
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");
|
dev_warn(cs->dev, "ISDN_CMD_IOCTL not supported\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
case ISDN_CMD_DIAL:
|
case ISDN_CMD_DIAL:
|
||||||
gig_dbg(DEBUG_ANY,
|
gig_dbg(DEBUG_ANY,
|
||||||
"ISDN_CMD_DIAL (driver: %d, ch: %ld, "
|
"ISDN_CMD_DIAL (phone: %s, msn: %s, si1: %d, si2: %d)",
|
||||||
"phone: %s, ownmsn: %s, si1: %d, si2: %d)",
|
|
||||||
cntrl->driver, cntrl->arg,
|
|
||||||
cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
|
cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn,
|
||||||
cntrl->parm.setup.si1, cntrl->parm.setup.si2);
|
cntrl->parm.setup.si1, cntrl->parm.setup.si2);
|
||||||
|
|
||||||
if (cntrl->arg >= cs->channels) {
|
if (ch >= cs->channels) {
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_DIAL: invalid channel (%d)\n",
|
"ISDN_CMD_DIAL: invalid channel (%d)\n", ch);
|
||||||
(int) cntrl->arg);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
bcs = cs->bcs + ch;
|
||||||
bcs = cs->bcs + cntrl->arg;
|
|
||||||
|
|
||||||
if (!gigaset_get_channel(bcs)) {
|
if (!gigaset_get_channel(bcs)) {
|
||||||
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
|
dev_err(cs->dev, "ISDN_CMD_DIAL: channel not free\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp = kmalloc(sizeof *sp, GFP_ATOMIC);
|
commands = kzalloc(AT_NUM*(sizeof *commands), GFP_ATOMIC);
|
||||||
if (!sp) {
|
if (!commands) {
|
||||||
gigaset_free_channel(bcs);
|
gigaset_free_channel(bcs);
|
||||||
dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
|
dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
|
||||||
return -ENOMEM;
|
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)) {
|
bcs->at_state.seq_index, NULL)) {
|
||||||
//FIXME what should we do?
|
for (i = 0; i < AT_NUM; ++i)
|
||||||
kfree(sp);
|
kfree(commands[i]);
|
||||||
|
kfree(commands);
|
||||||
gigaset_free_channel(bcs);
|
gigaset_free_channel(bcs);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -186,115 +308,102 @@ static int command_from_LL(isdn_ctrl *cntrl)
|
||||||
gig_dbg(DEBUG_CMD, "scheduling DIAL");
|
gig_dbg(DEBUG_CMD, "scheduling DIAL");
|
||||||
gigaset_schedule_event(cs);
|
gigaset_schedule_event(cs);
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_ACCEPTD: //FIXME
|
case ISDN_CMD_ACCEPTD:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD");
|
if (ch >= cs->channels) {
|
||||||
|
|
||||||
if (cntrl->arg >= cs->channels) {
|
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_ACCEPTD: invalid channel (%d)\n",
|
"ISDN_CMD_ACCEPTD: invalid channel (%d)\n", ch);
|
||||||
(int) cntrl->arg);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
bcs = cs->bcs + ch;
|
||||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
|
if (!gigaset_add_event(cs, &bcs->at_state,
|
||||||
EV_ACCEPT, NULL, 0, NULL)) {
|
EV_ACCEPT, NULL, 0, NULL))
|
||||||
//FIXME what should we do?
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
|
gig_dbg(DEBUG_CMD, "scheduling ACCEPT");
|
||||||
gigaset_schedule_event(cs);
|
gigaset_schedule_event(cs);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_ACCEPTB:
|
case ISDN_CMD_ACCEPTB:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB");
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_HANGUP:
|
case ISDN_CMD_HANGUP:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)",
|
if (ch >= cs->channels) {
|
||||||
(int) cntrl->arg);
|
|
||||||
|
|
||||||
if (cntrl->arg >= cs->channels) {
|
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_HANGUP: invalid channel (%d)\n",
|
"ISDN_CMD_HANGUP: invalid channel (%d)\n", ch);
|
||||||
(int) cntrl->arg);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
bcs = cs->bcs + ch;
|
||||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state,
|
if (!gigaset_add_event(cs, &bcs->at_state,
|
||||||
EV_HUP, NULL, 0, NULL)) {
|
EV_HUP, NULL, 0, NULL))
|
||||||
//FIXME what should we do?
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
gig_dbg(DEBUG_CMD, "scheduling HUP");
|
gig_dbg(DEBUG_CMD, "scheduling HUP");
|
||||||
gigaset_schedule_event(cs);
|
gigaset_schedule_event(cs);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME
|
case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ");
|
dev_info(cs->dev, "ignoring ISDN_CMD_CLREAZ\n");
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME
|
case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */
|
||||||
gig_dbg(DEBUG_ANY,
|
dev_info(cs->dev, "ignoring ISDN_CMD_SETEAZ (%s)\n",
|
||||||
"ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)",
|
cntrl->parm.num);
|
||||||
cntrl->driver, cntrl->arg, cntrl->parm.num);
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_SETL2: /* Set L2 to given protocol */
|
case ISDN_CMD_SETL2: /* Set L2 to given protocol */
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)",
|
if (ch >= cs->channels) {
|
||||||
cntrl->arg & 0xff, (cntrl->arg >> 8));
|
|
||||||
|
|
||||||
if ((cntrl->arg & 0xff) >= cs->channels) {
|
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_SETL2: invalid channel (%d)\n",
|
"ISDN_CMD_SETL2: invalid channel (%d)\n", ch);
|
||||||
(int) cntrl->arg & 0xff);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
bcs = cs->bcs + ch;
|
||||||
if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state,
|
if (bcs->chstate & CHS_D_UP) {
|
||||||
EV_PROTO_L2, NULL, cntrl->arg >> 8,
|
dev_err(cs->dev,
|
||||||
NULL)) {
|
"ISDN_CMD_SETL2: channel active (%d)\n", ch);
|
||||||
//FIXME what should we do?
|
return -EINVAL;
|
||||||
return -ENOMEM;
|
}
|
||||||
|
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;
|
break;
|
||||||
case ISDN_CMD_SETL3: /* Set L3 to given protocol */
|
case ISDN_CMD_SETL3: /* Set L3 to given protocol */
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)",
|
if (ch >= cs->channels) {
|
||||||
cntrl->arg & 0xff, (cntrl->arg >> 8));
|
|
||||||
|
|
||||||
if ((cntrl->arg & 0xff) >= cs->channels) {
|
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_SETL3: invalid channel (%d)\n",
|
"ISDN_CMD_SETL3: invalid channel (%d)\n", ch);
|
||||||
(int) cntrl->arg & 0xff);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
|
if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) {
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_SETL3: invalid protocol %lu\n",
|
"ISDN_CMD_SETL3: unsupported protocol (%lu)\n",
|
||||||
cntrl->arg >> 8);
|
cntrl->arg >> 8);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_PROCEED:
|
case ISDN_CMD_PROCEED:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME
|
gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED");
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_ALERT:
|
case ISDN_CMD_ALERT:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME
|
gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT");
|
||||||
if (cntrl->arg >= cs->channels) {
|
if (cntrl->arg >= cs->channels) {
|
||||||
dev_err(cs->dev,
|
dev_err(cs->dev,
|
||||||
"ISDN_CMD_ALERT: invalid channel (%d)\n",
|
"ISDN_CMD_ALERT: invalid channel (%d)\n",
|
||||||
(int) cntrl->arg);
|
(int) cntrl->arg);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
//bcs = cs->bcs + cntrl->arg;
|
|
||||||
//bcs->proto2 = -1;
|
|
||||||
// FIXME
|
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_REDIR:
|
case ISDN_CMD_REDIR:
|
||||||
gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME
|
gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR");
|
||||||
break;
|
break;
|
||||||
case ISDN_CMD_PROT_IO:
|
case ISDN_CMD_PROT_IO:
|
||||||
gig_dbg(DEBUG_ANY, "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;
|
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;
|
isdn_ctrl command;
|
||||||
|
|
||||||
command.driver = cs->myid;
|
command.driver = cs->myid;
|
||||||
command.command = cmd;
|
command.command = cmd;
|
||||||
command.arg = 0;
|
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;
|
isdn_ctrl command;
|
||||||
|
|
||||||
command.driver = bcs->cs->myid;
|
command.driver = bcs->cs->myid;
|
||||||
command.command = cmd;
|
command.command = cmd;
|
||||||
command.arg = bcs->channel;
|
command.arg = bcs->channel;
|
||||||
bcs->cs->iif.statcallb(&command);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -482,13 +476,14 @@ int gigaset_isdn_icall(struct at_state_t *at_state)
|
||||||
{
|
{
|
||||||
struct cardstate *cs = at_state->cs;
|
struct cardstate *cs = at_state->cs;
|
||||||
struct bc_state *bcs = at_state->bcs;
|
struct bc_state *bcs = at_state->bcs;
|
||||||
|
isdn_if *iif = cs->iif;
|
||||||
isdn_ctrl response;
|
isdn_ctrl response;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* fill ICALL structure */
|
/* fill ICALL structure */
|
||||||
response.parm.setup.si1 = 0; /* default: unknown */
|
response.parm.setup.si1 = 0; /* default: unknown */
|
||||||
response.parm.setup.si2 = 0;
|
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;
|
response.parm.setup.plan = 0;
|
||||||
if (!at_state->str_var[STR_ZBC]) {
|
if (!at_state->str_var[STR_ZBC]) {
|
||||||
/* no BC (internal call): assume speech, A-law */
|
/* 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;
|
return ICALL_IGNORE;
|
||||||
}
|
}
|
||||||
if (at_state->str_var[STR_NMBR]) {
|
if (at_state->str_var[STR_NMBR]) {
|
||||||
strncpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
|
strlcpy(response.parm.setup.phone, at_state->str_var[STR_NMBR],
|
||||||
sizeof response.parm.setup.phone - 1);
|
sizeof response.parm.setup.phone);
|
||||||
response.parm.setup.phone[sizeof response.parm.setup.phone - 1] = 0;
|
|
||||||
} else
|
} else
|
||||||
response.parm.setup.phone[0] = 0;
|
response.parm.setup.phone[0] = 0;
|
||||||
if (at_state->str_var[STR_ZCPN]) {
|
if (at_state->str_var[STR_ZCPN]) {
|
||||||
strncpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
|
strlcpy(response.parm.setup.eazmsn, at_state->str_var[STR_ZCPN],
|
||||||
sizeof response.parm.setup.eazmsn - 1);
|
sizeof response.parm.setup.eazmsn);
|
||||||
response.parm.setup.eazmsn[sizeof response.parm.setup.eazmsn - 1] = 0;
|
|
||||||
} else
|
} else
|
||||||
response.parm.setup.eazmsn[0] = 0;
|
response.parm.setup.eazmsn[0] = 0;
|
||||||
|
|
||||||
if (!bcs) {
|
if (!bcs) {
|
||||||
dev_notice(cs->dev, "no channel for incoming call\n");
|
dev_notice(cs->dev, "no channel for incoming call\n");
|
||||||
response.command = ISDN_STAT_ICALLW;
|
response.command = ISDN_STAT_ICALLW;
|
||||||
response.arg = 0; //FIXME
|
response.arg = 0;
|
||||||
} else {
|
} else {
|
||||||
gig_dbg(DEBUG_CMD, "Sending ICALL");
|
gig_dbg(DEBUG_CMD, "Sending ICALL");
|
||||||
response.command = ISDN_STAT_ICALL;
|
response.command = ISDN_STAT_ICALL;
|
||||||
response.arg = bcs->channel; //FIXME
|
response.arg = bcs->channel;
|
||||||
}
|
}
|
||||||
response.driver = cs->myid;
|
response.driver = cs->myid;
|
||||||
retval = cs->iif.statcallb(&response);
|
retval = iif->statcallb(&response);
|
||||||
gig_dbg(DEBUG_CMD, "Response: %d", retval);
|
gig_dbg(DEBUG_CMD, "Response: %d", retval);
|
||||||
switch (retval) {
|
switch (retval) {
|
||||||
case 0: /* no takers */
|
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)
|
if (snprintf(iif->id, sizeof iif->id, "%s_%u", isdnid, cs->minor_index)
|
||||||
>= sizeof iif->id) {
|
>= sizeof iif->id) {
|
||||||
pr_err("ID too long: %s\n", isdnid);
|
pr_err("ID too long: %s\n", isdnid);
|
||||||
|
kfree(iif);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,9 +679,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid)
|
||||||
|
|
||||||
if (!register_isdn(iif)) {
|
if (!register_isdn(iif)) {
|
||||||
pr_err("register_isdn failed\n");
|
pr_err("register_isdn failed\n");
|
||||||
|
kfree(iif);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cs->iif = iif;
|
||||||
cs->myid = iif->channels; /* Set my device id */
|
cs->myid = iif->channels; /* Set my device id */
|
||||||
|
cs->hw_hdr_len = HW_HDR_LEN;
|
||||||
return 1;
|
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;
|
return -ENODEV;
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
tty->driver_data = cs;
|
tty->driver_data = cs;
|
||||||
|
|
||||||
++cs->open_count;
|
++cs->open_count;
|
||||||
|
@ -171,7 +171,7 @@ static int if_open(struct tty_struct *tty, struct file *filp)
|
||||||
spin_lock_irqsave(&cs->lock, flags);
|
spin_lock_irqsave(&cs->lock, flags);
|
||||||
cs->tty = tty;
|
cs->tty = tty;
|
||||||
spin_unlock_irqrestore(&cs->lock, flags);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
tty->low_latency = 1; //FIXME test
|
tty->low_latency = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&cs->mutex);
|
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);
|
gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd);
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (!cs->connected) {
|
if (!cs->connected) {
|
||||||
gig_dbg(DEBUG_IF, "not 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__);
|
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
// FIXME read from device?
|
|
||||||
retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
|
retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR);
|
||||||
|
|
||||||
mutex_unlock(&cs->mutex);
|
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);
|
cs->minor_index, __func__, set, clear);
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (!cs->connected) {
|
if (!cs->connected) {
|
||||||
gig_dbg(DEBUG_IF, "not 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__);
|
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (!cs->connected) {
|
if (!cs->connected) {
|
||||||
gig_dbg(DEBUG_IF, "not 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__);
|
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
if (!cs->connected) {
|
if (!cs->connected) {
|
||||||
gig_dbg(DEBUG_IF, "not 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 */
|
gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
|
||||||
else if (!cs->open_count)
|
else if (!cs->open_count)
|
||||||
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
||||||
else {
|
else
|
||||||
//FIXME
|
gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__);
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&cs->mutex);
|
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 */
|
gig_dbg(DEBUG_IF, "not connected"); /* nothing to do */
|
||||||
else if (!cs->open_count)
|
else if (!cs->open_count)
|
||||||
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
dev_warn(cs->dev, "%s: device not opened\n", __func__);
|
||||||
else {
|
else
|
||||||
//FIXME
|
gig_dbg(DEBUG_ANY, "%s: not implemented\n", __func__);
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&cs->mutex);
|
mutex_unlock(&cs->mutex);
|
||||||
}
|
}
|
||||||
|
@ -515,10 +512,9 @@ static void if_set_termios(struct tty_struct *tty, struct ktermios *old)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stolen from mct_u232.c
|
|
||||||
iflag = tty->termios->c_iflag;
|
iflag = tty->termios->c_iflag;
|
||||||
cflag = tty->termios->c_cflag;
|
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",
|
gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x",
|
||||||
cs->minor_index, iflag, cflag, old_cflag);
|
cs->minor_index, iflag, cflag, old_cflag);
|
||||||
|
|
||||||
|
@ -588,7 +584,7 @@ void gigaset_if_init(struct cardstate *cs)
|
||||||
if (!drv->have_tty)
|
if (!drv->have_tty)
|
||||||
return;
|
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);
|
mutex_lock(&cs->mutex);
|
||||||
cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
|
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;
|
struct tty_struct *tty;
|
||||||
|
|
||||||
spin_lock_irqsave(&cs->lock, flags);
|
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");
|
gig_dbg(DEBUG_ANY, "receive on closed device");
|
||||||
else {
|
else {
|
||||||
tty_buffer_request_room(tty, len);
|
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;
|
drv->have_tty = 0;
|
||||||
|
|
||||||
if ((drv->tty = alloc_tty_driver(minors)) == NULL)
|
drv->tty = tty = alloc_tty_driver(minors);
|
||||||
|
if (tty == NULL)
|
||||||
goto enomem;
|
goto enomem;
|
||||||
tty = drv->tty;
|
|
||||||
|
|
||||||
tty->magic = TTY_DRIVER_MAGIC,
|
tty->magic = TTY_DRIVER_MAGIC,
|
||||||
tty->major = GIG_MAJOR,
|
tty->major = GIG_MAJOR,
|
||||||
|
@ -676,8 +673,8 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname,
|
||||||
|
|
||||||
tty->owner = THIS_MODULE;
|
tty->owner = THIS_MODULE;
|
||||||
|
|
||||||
tty->init_termios = tty_std_termios; //FIXME
|
tty->init_termios = tty_std_termios;
|
||||||
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; //FIXME
|
tty->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||||
tty_set_operations(tty, &if_ops);
|
tty_set_operations(tty, &if_ops);
|
||||||
|
|
||||||
ret = tty_register_driver(tty);
|
ret = tty_register_driver(tty);
|
||||||
|
|
|
@ -41,7 +41,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
|
||||||
|
|
||||||
read = iwb->read;
|
read = iwb->read;
|
||||||
write = iwb->write;
|
write = iwb->write;
|
||||||
if ((freebytes = read - write) > 0) {
|
freebytes = read - write;
|
||||||
|
if (freebytes > 0) {
|
||||||
/* no wraparound: need padding space within regular area */
|
/* no wraparound: need padding space within regular area */
|
||||||
return freebytes - BAS_OUTBUFPAD;
|
return freebytes - BAS_OUTBUFPAD;
|
||||||
} else if (read < 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
|
/* start writing
|
||||||
* acquire the write semaphore
|
* acquire the write semaphore
|
||||||
* return true if acquired, false if busy
|
* 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
|
* bit 14..13 = number of bits added by stuffing
|
||||||
*/
|
*/
|
||||||
static const u16 stufftab[5 * 256] = {
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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:
|
* parameters:
|
||||||
* cin input byte
|
* cin input byte
|
||||||
* ones number of trailing '1' bits in result before this step
|
* 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:
|
* return value:
|
||||||
* number of trailing '1' bits in result after this step
|
* 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:
|
* parameters:
|
||||||
* in input buffer
|
* in input buffer
|
||||||
* count number of bytes 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:
|
* return value:
|
||||||
* position of end of packet in output buffer on success,
|
* position of end of packet in output buffer on success,
|
||||||
* -EAGAIN if write semaphore busy or buffer full
|
* -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);
|
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;
|
fcs ^= 0xffff;
|
||||||
ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
|
ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
|
||||||
ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 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:
|
* parameters:
|
||||||
* in input buffer
|
* in input buffer
|
||||||
* count number of bytes 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:
|
* return value:
|
||||||
* position of end of packet in output buffer on success,
|
* position of end of packet in output buffer on success,
|
||||||
* -EAGAIN if write semaphore busy or buffer full
|
* -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;
|
int result;
|
||||||
|
|
||||||
switch (bcs->proto2) {
|
switch (bcs->proto2) {
|
||||||
case ISDN_PROTO_L2_HDLC:
|
case L2_HDLC:
|
||||||
result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
|
result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
|
||||||
gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
|
gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
|
||||||
__func__, len, result);
|
__func__, len, result);
|
||||||
|
@ -542,8 +524,9 @@ static inline void hdlc_flush(struct bc_state *bcs)
|
||||||
if (likely(bcs->skb != NULL))
|
if (likely(bcs->skb != NULL))
|
||||||
skb_trim(bcs->skb, 0);
|
skb_trim(bcs->skb, 0);
|
||||||
else if (!bcs->ignore) {
|
else if (!bcs->ignore) {
|
||||||
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
bcs->skb = dev_alloc_skb(SBUFSIZE + bcs->cs->hw_hdr_len);
|
||||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
if (bcs->skb)
|
||||||
|
skb_reserve(bcs->skb, bcs->cs->hw_hdr_len);
|
||||||
else
|
else
|
||||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
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)
|
static inline void hdlc_done(struct bc_state *bcs)
|
||||||
{
|
{
|
||||||
|
struct cardstate *cs = bcs->cs;
|
||||||
struct sk_buff *procskb;
|
struct sk_buff *procskb;
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
if (unlikely(bcs->ignore)) {
|
if (unlikely(bcs->ignore)) {
|
||||||
bcs->ignore--;
|
bcs->ignore--;
|
||||||
hdlc_flush(bcs);
|
hdlc_flush(bcs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
procskb = bcs->skb;
|
||||||
if ((procskb = bcs->skb) == NULL) {
|
if (procskb == NULL) {
|
||||||
/* previous error */
|
/* previous error */
|
||||||
gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
|
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) {
|
} 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);
|
procskb->len);
|
||||||
bcs->hw.bas->runts++;
|
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) {
|
} else if (bcs->fcs != PPP_GOODFCS) {
|
||||||
dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
|
dev_notice(cs->dev, "frame check error (0x%04x)\n", bcs->fcs);
|
||||||
bcs->fcs);
|
|
||||||
bcs->hw.bas->fcserrs++;
|
bcs->hw.bas->fcserrs++;
|
||||||
gigaset_rcv_error(procskb, bcs->cs, bcs);
|
dev_kfree_skb_any(procskb);
|
||||||
|
gigaset_isdn_rcv_err(bcs);
|
||||||
} else {
|
} else {
|
||||||
procskb->len -= 2; /* subtract FCS */
|
len = procskb->len;
|
||||||
procskb->tail -= 2;
|
__skb_trim(procskb, len -= 2); /* subtract FCS */
|
||||||
gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
|
gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, len);
|
||||||
__func__, procskb->len);
|
|
||||||
dump_bytes(DEBUG_STREAM_DUMP,
|
dump_bytes(DEBUG_STREAM_DUMP,
|
||||||
"rcv data", procskb->data, procskb->len);
|
"rcv data", procskb->data, len);
|
||||||
bcs->hw.bas->goodbytes += procskb->len;
|
bcs->hw.bas->goodbytes += len;
|
||||||
gigaset_rcv_skb(procskb, bcs->cs, bcs);
|
gigaset_skb_rcvd(bcs, procskb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
|
bcs->skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
if (bcs->skb)
|
||||||
|
skb_reserve(bcs->skb, cs->hw_hdr_len);
|
||||||
else
|
else
|
||||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
dev_err(cs->dev, "could not allocate skb\n");
|
||||||
bcs->fcs = PPP_INITFCS;
|
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);
|
dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
|
||||||
bcs->hw.bas->alignerrs++;
|
bcs->hw.bas->alignerrs++;
|
||||||
gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
|
gigaset_isdn_rcv_err(bcs);
|
||||||
|
__skb_trim(bcs->skb, 0);
|
||||||
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");
|
|
||||||
bcs->fcs = PPP_INITFCS;
|
bcs->fcs = PPP_INITFCS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,10 +628,10 @@ static const unsigned char bitcounts[256] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* hdlc_unpack
|
/* hdlc_unpack
|
||||||
* perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation)
|
* perform HDLC frame processing (bit unstuffing, flag detection, FCS
|
||||||
* on a sequence of received data bytes (8 bits each, LSB first)
|
* 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
|
* pass on successfully received, complete frames as SKBs via gigaset_skb_rcvd
|
||||||
* notify of errors via gigaset_rcv_error
|
* notify of errors via gigaset_isdn_rcv_err
|
||||||
* tally frames, errors etc. in BC structure counters
|
* tally frames, errors etc. in BC structure counters
|
||||||
* parameters:
|
* parameters:
|
||||||
* src received data
|
* src received data
|
||||||
|
@ -665,9 +647,12 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
|
|
||||||
/* load previous state:
|
/* load previous state:
|
||||||
* inputstate = set of flag bits:
|
* inputstate = set of flag bits:
|
||||||
* - INS_flag_hunt: no complete opening flag received since connection setup or last abort
|
* - INS_flag_hunt: no complete opening flag received since connection
|
||||||
* - INS_have_data: at least one complete data byte received since last flag
|
* setup or last abort
|
||||||
* seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7)
|
* - 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)
|
* inbyte = accumulated partial data byte (if !INS_flag_hunt)
|
||||||
* inbits = number of valid bits in inbyte, starting at LSB (0..6)
|
* 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);
|
inbyte = c >> (lead1 + 1);
|
||||||
inbits = 7 - lead1;
|
inbits = 7 - lead1;
|
||||||
if (trail1 >= 8) {
|
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--;
|
inbits--;
|
||||||
/* correct the incorrectly handled cases individually */
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0xbe:
|
case 0xbe:
|
||||||
inbyte = 0x3f;
|
inbyte = 0x3f;
|
||||||
|
@ -729,13 +716,14 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
hdlc_flush(bcs);
|
hdlc_flush(bcs);
|
||||||
inputstate |= INS_flag_hunt;
|
inputstate |= INS_flag_hunt;
|
||||||
} else if (seqlen == 6) {
|
} 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) {
|
if (inbits > 7 - lead1) {
|
||||||
hdlc_frag(bcs, inbits + lead1 - 7);
|
hdlc_frag(bcs, inbits + lead1 - 7);
|
||||||
inputstate &= ~INS_have_data;
|
inputstate &= ~INS_have_data;
|
||||||
} else {
|
} else {
|
||||||
if (inbits < 7 - lead1)
|
if (inbits < 7 - lead1)
|
||||||
ubc->stolen0s ++;
|
ubc->stolen0s++;
|
||||||
if (inputstate & INS_have_data) {
|
if (inputstate & INS_have_data) {
|
||||||
hdlc_done(bcs);
|
hdlc_done(bcs);
|
||||||
inputstate &= ~INS_have_data;
|
inputstate &= ~INS_have_data;
|
||||||
|
@ -744,7 +732,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
|
|
||||||
if (c == PPP_FLAG) {
|
if (c == PPP_FLAG) {
|
||||||
/* complete flag, LSB overlaps preceding flag */
|
/* complete flag, LSB overlaps preceding flag */
|
||||||
ubc->shared0s ++;
|
ubc->shared0s++;
|
||||||
inbits = 0;
|
inbits = 0;
|
||||||
inbyte = 0;
|
inbyte = 0;
|
||||||
} else if (trail1 != 7) {
|
} else if (trail1 != 7) {
|
||||||
|
@ -752,9 +740,11 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
inbyte = c >> (lead1 + 1);
|
inbyte = c >> (lead1 + 1);
|
||||||
inbits = 7 - lead1;
|
inbits = 7 - lead1;
|
||||||
if (trail1 >= 8) {
|
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--;
|
inbits--;
|
||||||
/* correct the incorrectly handled cases individually */
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0xbe:
|
case 0xbe:
|
||||||
inbyte = 0x3f;
|
inbyte = 0x3f;
|
||||||
|
@ -762,7 +752,8 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* abort sequence follows, skb already empty anyway */
|
/* abort sequence follows,
|
||||||
|
* skb already empty anyway */
|
||||||
ubc->aborts++;
|
ubc->aborts++;
|
||||||
inputstate |= INS_flag_hunt;
|
inputstate |= INS_flag_hunt;
|
||||||
}
|
}
|
||||||
|
@ -787,14 +778,17 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
} else {
|
} else {
|
||||||
/* stuffed data */
|
/* stuffed data */
|
||||||
if (trail1 < 7) { /* => seqlen == 5 */
|
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;
|
unsigned char mask = (1 << lead1) - 1;
|
||||||
c = (c & mask) | ((c & ~mask) >> 1);
|
c = (c & mask) | ((c & ~mask) >> 1);
|
||||||
inbyte |= c << inbits;
|
inbyte |= c << inbits;
|
||||||
inbits += 7;
|
inbits += 7;
|
||||||
} else if (seqlen < 5) { /* trail1 >= 8 */
|
} else if (seqlen < 5) { /* trail1 >= 8 */
|
||||||
/* interior stuffing: omitting the MSB handles most cases */
|
/* interior stuffing:
|
||||||
/* correct the incorrectly handled cases individually */
|
* omitting the MSB handles most cases,
|
||||||
|
* correct the incorrectly handled
|
||||||
|
* cases individually */
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0xbe:
|
case 0xbe:
|
||||||
c = 0x7e;
|
c = 0x7e;
|
||||||
|
@ -804,8 +798,9 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
inbits += 7;
|
inbits += 7;
|
||||||
} else { /* seqlen == 5 && trail1 >= 8 */
|
} else { /* seqlen == 5 && trail1 >= 8 */
|
||||||
|
|
||||||
/* stuff bit at lead1 *and* interior stuffing */
|
/* stuff bit at lead1 *and* interior
|
||||||
switch (c) { /* unstuff individually */
|
* stuffing -- unstuff individually */
|
||||||
|
switch (c) {
|
||||||
case 0x7d:
|
case 0x7d:
|
||||||
c = 0x3f;
|
c = 0x3f;
|
||||||
break;
|
break;
|
||||||
|
@ -841,7 +836,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* trans_receive
|
/* 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
|
* invert bytes
|
||||||
* tally frames, errors etc. in BC structure counters
|
* tally frames, errors etc. in BC structure counters
|
||||||
* parameters:
|
* 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,
|
static inline void trans_receive(unsigned char *src, unsigned count,
|
||||||
struct bc_state *bcs)
|
struct bc_state *bcs)
|
||||||
{
|
{
|
||||||
|
struct cardstate *cs = bcs->cs;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int dobytes;
|
int dobytes;
|
||||||
unsigned char *dst;
|
unsigned char *dst;
|
||||||
|
@ -861,13 +857,14 @@ static inline void trans_receive(unsigned char *src, unsigned count,
|
||||||
hdlc_flush(bcs);
|
hdlc_flush(bcs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (unlikely((skb = bcs->skb) == NULL)) {
|
skb = bcs->skb;
|
||||||
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
|
if (unlikely(skb == NULL)) {
|
||||||
|
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
dev_err(bcs->cs->dev, "could not allocate skb\n");
|
dev_err(cs->dev, "could not allocate skb\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skb_reserve(skb, HW_HDR_LEN);
|
skb_reserve(skb, cs->hw_hdr_len);
|
||||||
}
|
}
|
||||||
bcs->hw.bas->goodbytes += skb->len;
|
bcs->hw.bas->goodbytes += skb->len;
|
||||||
dobytes = TRANSBUFSIZE - skb->len;
|
dobytes = TRANSBUFSIZE - skb->len;
|
||||||
|
@ -881,23 +878,24 @@ static inline void trans_receive(unsigned char *src, unsigned count,
|
||||||
if (dobytes == 0) {
|
if (dobytes == 0) {
|
||||||
dump_bytes(DEBUG_STREAM_DUMP,
|
dump_bytes(DEBUG_STREAM_DUMP,
|
||||||
"rcv data", skb->data, skb->len);
|
"rcv data", skb->data, skb->len);
|
||||||
gigaset_rcv_skb(skb, bcs->cs, bcs);
|
gigaset_skb_rcvd(bcs, skb);
|
||||||
bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
|
bcs->skb = skb =
|
||||||
|
dev_alloc_skb(SBUFSIZE + cs->hw_hdr_len);
|
||||||
if (!skb) {
|
if (!skb) {
|
||||||
dev_err(bcs->cs->dev,
|
dev_err(cs->dev, "could not allocate skb\n");
|
||||||
"could not allocate skb\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skb_reserve(bcs->skb, HW_HDR_LEN);
|
skb_reserve(skb, cs->hw_hdr_len);
|
||||||
dobytes = TRANSBUFSIZE;
|
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) {
|
switch (bcs->proto2) {
|
||||||
case ISDN_PROTO_L2_HDLC:
|
case L2_HDLC:
|
||||||
hdlc_unpack(src, count, bcs);
|
hdlc_unpack(src, count, bcs);
|
||||||
break;
|
break;
|
||||||
default: /* assume transparent */
|
default: /* assume transparent */
|
||||||
|
@ -981,8 +979,10 @@ void gigaset_isoc_input(struct inbuf_t *inbuf)
|
||||||
* @bcs: B channel descriptor structure.
|
* @bcs: B channel descriptor structure.
|
||||||
* @skb: data to send.
|
* @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.
|
* 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:
|
* Return value:
|
||||||
* number of bytes accepted for sending (skb->len) if ok,
|
* 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;
|
return -EINVAL;
|
||||||
|
|
||||||
if (mutex_lock_interruptible(&cs->mutex))
|
if (mutex_lock_interruptible(&cs->mutex))
|
||||||
return -ERESTARTSYS; // FIXME -EINTR?
|
return -ERESTARTSYS;
|
||||||
|
|
||||||
cs->waiting = 1;
|
cs->waiting = 1;
|
||||||
if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE,
|
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 cardstate *cs = (struct cardstate *) data;
|
||||||
struct bc_state *bcs;
|
struct bc_state *bcs;
|
||||||
|
struct sk_buff *nextskb;
|
||||||
int sent = 0;
|
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__);
|
gig_dbg(DEBUG_OUTPUT, "%s: no cardstate", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -179,9 +185,11 @@ static void gigaset_modem_fill(unsigned long data)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* no command to send; get skb */
|
/* 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 */
|
/* no skb either, nothing to do */
|
||||||
return;
|
return;
|
||||||
|
bcs->tx_skb = nextskb;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
|
gig_dbg(DEBUG_INTR, "Dequeued skb (Adr: %lx)",
|
||||||
(unsigned long) bcs->tx_skb);
|
(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
|
* number of bytes queued, or error code < 0
|
||||||
*/
|
*/
|
||||||
static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
|
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;
|
struct cmdbuf_t *cb;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
|
gigaset_dbg_buffer(cs->mstate != MS_LOCKED ?
|
||||||
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
|
DEBUG_TRANSCMD : DEBUG_LOCKCMD,
|
||||||
"CMD Transmit", len, buf);
|
"CMD Transmit", len, buf);
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return 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__);
|
dev_err(cs->dev, "%s: out of memory!\n", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -392,7 +401,6 @@ static void gigaset_device_release(struct device *dev)
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
|
||||||
/* adapted from platform_device_release() in drivers/base/platform.c */
|
/* adapted from platform_device_release() in drivers/base/platform.c */
|
||||||
//FIXME is this actually necessary?
|
|
||||||
kfree(dev->platform_data);
|
kfree(dev->platform_data);
|
||||||
kfree(pdev->resource);
|
kfree(pdev->resource);
|
||||||
}
|
}
|
||||||
|
@ -404,16 +412,20 @@ static void gigaset_device_release(struct device *dev)
|
||||||
static int gigaset_initcshw(struct cardstate *cs)
|
static int gigaset_initcshw(struct cardstate *cs)
|
||||||
{
|
{
|
||||||
int rc;
|
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");
|
pr_err("out of memory\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
cs->hw.ser = scs;
|
||||||
|
|
||||||
cs->hw.ser->dev.name = GIGASET_MODULENAME;
|
cs->hw.ser->dev.name = GIGASET_MODULENAME;
|
||||||
cs->hw.ser->dev.id = cs->minor_index;
|
cs->hw.ser->dev.id = cs->minor_index;
|
||||||
cs->hw.ser->dev.dev.release = gigaset_device_release;
|
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);
|
pr_err("error %d registering platform device\n", rc);
|
||||||
kfree(cs->hw.ser);
|
kfree(cs->hw.ser);
|
||||||
cs->hw.ser = NULL;
|
cs->hw.ser = NULL;
|
||||||
|
@ -422,7 +434,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
||||||
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
|
dev_set_drvdata(&cs->hw.ser->dev.dev, cs);
|
||||||
|
|
||||||
tasklet_init(&cs->write_tasklet,
|
tasklet_init(&cs->write_tasklet,
|
||||||
&gigaset_modem_fill, (unsigned long) cs);
|
gigaset_modem_fill, (unsigned long) cs);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,7 +446,8 @@ static int gigaset_initcshw(struct cardstate *cs)
|
||||||
* Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
|
* Called by "gigaset_start" and "gigaset_enterconfigmode" in common.c
|
||||||
* and by "if_lock" and "if_termios" in interface.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;
|
struct tty_struct *tty = cs->hw.ser->tty;
|
||||||
unsigned int set, clear;
|
unsigned int set, clear;
|
||||||
|
@ -520,8 +533,8 @@ gigaset_tty_open(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for our device state and intialize it */
|
/* allocate memory for our device state and intialize it */
|
||||||
if (!(cs = gigaset_initcs(driver, 1, 1, 0, cidmode,
|
cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME);
|
||||||
GIGASET_MODULENAME)))
|
if (!cs)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
cs->dev = &cs->hw.ser->dev.dev;
|
cs->dev = &cs->hw.ser->dev.dev;
|
||||||
|
@ -690,7 +703,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,
|
||||||
|
|
||||||
if (!cs)
|
if (!cs)
|
||||||
return;
|
return;
|
||||||
if (!(inbuf = cs->inbuf)) {
|
inbuf = cs->inbuf;
|
||||||
|
if (!inbuf) {
|
||||||
dev_err(cs->dev, "%s: no inbuf\n", __func__);
|
dev_err(cs->dev, "%s: no inbuf\n", __func__);
|
||||||
cs_put(cs);
|
cs_put(cs);
|
||||||
return;
|
return;
|
||||||
|
@ -770,18 +784,21 @@ static int __init ser_gigaset_init(void)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "%s", __func__);
|
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);
|
pr_err("error %d registering platform driver\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate memory for our driver state and intialize it */
|
/* 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,
|
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||||
&ops, THIS_MODULE)))
|
&ops, THIS_MODULE);
|
||||||
|
if (!driver)
|
||||||
goto error;
|
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);
|
pr_err("error %d registering line discipline\n", rc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -808,7 +825,8 @@ static void __exit ser_gigaset_exit(void)
|
||||||
driver = NULL;
|
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);
|
pr_err("error %d unregistering line discipline\n", rc);
|
||||||
|
|
||||||
platform_driver_unregister(&device_driver);
|
platform_driver_unregister(&device_driver);
|
||||||
|
|
|
@ -43,14 +43,14 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode");
|
||||||
#define GIGASET_MODULENAME "usb_gigaset"
|
#define GIGASET_MODULENAME "usb_gigaset"
|
||||||
#define GIGASET_DEVNAME "ttyGU"
|
#define GIGASET_DEVNAME "ttyGU"
|
||||||
|
|
||||||
#define IF_WRITEBUF 2000 //FIXME // WAKEUP_CHARS: 256
|
#define IF_WRITEBUF 2000 /* arbitrary limit */
|
||||||
|
|
||||||
/* Values for the Gigaset M105 Data */
|
/* Values for the Gigaset M105 Data */
|
||||||
#define USB_M105_VENDOR_ID 0x0681
|
#define USB_M105_VENDOR_ID 0x0681
|
||||||
#define USB_M105_PRODUCT_ID 0x0009
|
#define USB_M105_PRODUCT_ID 0x0009
|
||||||
|
|
||||||
/* table of devices that work with this driver */
|
/* 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) },
|
{ USB_DEVICE(USB_M105_VENDOR_ID, USB_M105_PRODUCT_ID) },
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
@ -97,8 +97,8 @@ MODULE_DEVICE_TABLE(usb, gigaset_table);
|
||||||
* 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13
|
* 41 19 -- -- -- -- 06 00 00 00 00 xx 11 13
|
||||||
* Used after every "configuration sequence" (RQ 12, RQs 01/03/13).
|
* Used after every "configuration sequence" (RQ 12, RQs 01/03/13).
|
||||||
* xx is usually 0x00 but was 0x7e before starting data transfer
|
* xx is usually 0x00 but was 0x7e before starting data transfer
|
||||||
* in unimodem mode. So, this might be an array of characters that need
|
* in unimodem mode. So, this might be an array of characters that
|
||||||
* special treatment ("commit all bufferd data"?), 11=^Q, 13=^S.
|
* 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
|
* Unimodem mode: use "modprobe ppp_async flag_time=0" as the device _needs_ two
|
||||||
* flags per packet.
|
* 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_resume(struct usb_interface *intf);
|
||||||
static int gigaset_pre_reset(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 */
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
static struct usb_driver gigaset_usb_driver = {
|
static struct usb_driver gigaset_usb_driver = {
|
||||||
|
@ -141,6 +141,7 @@ struct usb_cardstate {
|
||||||
struct urb *bulk_out_urb;
|
struct urb *bulk_out_urb;
|
||||||
|
|
||||||
/* Input buffer */
|
/* Input buffer */
|
||||||
|
unsigned char *rcvbuf;
|
||||||
int rcvbuf_size;
|
int rcvbuf_size;
|
||||||
struct urb *read_urb;
|
struct urb *read_urb;
|
||||||
__u8 int_in_endpointAddr;
|
__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);
|
val = tiocm_to_gigaset(new_state);
|
||||||
|
|
||||||
gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask);
|
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,
|
r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41,
|
||||||
(val & 0xff) | ((mask & 0xff) << 8), 0,
|
(val & 0xff) | ((mask & 0xff) << 8), 0,
|
||||||
NULL, 0, 2000 /* timeout? */);
|
NULL, 0, 2000 /* timeout? */);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
//..
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +219,6 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
|
||||||
cflag &= CBAUD;
|
cflag &= CBAUD;
|
||||||
|
|
||||||
switch (cflag) {
|
switch (cflag) {
|
||||||
//FIXME more values?
|
|
||||||
case B300: rate = 300; break;
|
case B300: rate = 300; break;
|
||||||
case B600: rate = 600; break;
|
case B600: rate = 600; break;
|
||||||
case B1200: rate = 1200; 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 */
|
/* set the number of stop bits */
|
||||||
if (cflag & CSTOPB) {
|
if (cflag & CSTOPB) {
|
||||||
if ((cflag & CSIZE) == CS5)
|
if ((cflag & CSIZE) == CS5)
|
||||||
val |= 1; /* 1.5 stop bits */ //FIXME is this okay?
|
val |= 1; /* 1.5 stop bits */
|
||||||
else
|
else
|
||||||
val |= 2; /* 2 stop bits */
|
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)
|
static int gigaset_init_bchannel(struct bc_state *bcs)
|
||||||
{
|
{
|
||||||
/* nothing to do for M10x */
|
/* nothing to do for M10x */
|
||||||
|
@ -344,7 +342,6 @@ static void gigaset_modem_fill(unsigned long data)
|
||||||
if (write_modem(cs) < 0) {
|
if (write_modem(cs) < 0) {
|
||||||
gig_dbg(DEBUG_OUTPUT,
|
gig_dbg(DEBUG_OUTPUT,
|
||||||
"modem_fill: write_modem failed");
|
"modem_fill: write_modem failed");
|
||||||
// FIXME should we tell the LL?
|
|
||||||
again = 1; /* no callback will be called! */
|
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)
|
static void gigaset_read_int_callback(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct inbuf_t *inbuf = urb->context;
|
struct cardstate *cs = urb->context;
|
||||||
struct cardstate *cs = inbuf->cs;
|
struct inbuf_t *inbuf = cs->inbuf;
|
||||||
int status = urb->status;
|
int status = urb->status;
|
||||||
int r;
|
int r;
|
||||||
unsigned numbytes;
|
unsigned numbytes;
|
||||||
|
@ -368,7 +365,7 @@ static void gigaset_read_int_callback(struct urb *urb)
|
||||||
numbytes = urb->actual_length;
|
numbytes = urb->actual_length;
|
||||||
|
|
||||||
if (numbytes) {
|
if (numbytes) {
|
||||||
src = inbuf->rcvbuf;
|
src = cs->hw.usb->rcvbuf;
|
||||||
if (unlikely(*src))
|
if (unlikely(*src))
|
||||||
dev_warn(cs->dev,
|
dev_warn(cs->dev,
|
||||||
"%s: There was no leading 0, but 0x%02x!\n",
|
"%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;
|
struct cmdbuf_t *tcb;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int count;
|
int count;
|
||||||
int status = -ENOENT; // FIXME
|
int status = -ENOENT;
|
||||||
struct usb_cardstate *ucs = cs->hw.usb;
|
struct usb_cardstate *ucs = cs->hw.usb;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -480,7 +477,9 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb)
|
||||||
ucs->busy = 1;
|
ucs->busy = 1;
|
||||||
|
|
||||||
spin_lock_irqsave(&cs->lock, flags);
|
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);
|
spin_unlock_irqrestore(&cs->lock, flags);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
|
@ -510,8 +509,8 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf,
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC);
|
||||||
if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) {
|
if (!cb) {
|
||||||
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
dev_err(cs->dev, "%s: out of memory\n", __func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -615,7 +614,7 @@ static int gigaset_initcshw(struct cardstate *cs)
|
||||||
ucs->bulk_out_urb = NULL;
|
ucs->bulk_out_urb = NULL;
|
||||||
ucs->read_urb = NULL;
|
ucs->read_urb = NULL;
|
||||||
tasklet_init(&cs->write_tasklet,
|
tasklet_init(&cs->write_tasklet,
|
||||||
&gigaset_modem_fill, (unsigned long) cs);
|
gigaset_modem_fill, (unsigned long) cs);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -637,9 +636,7 @@ static int write_modem(struct cardstate *cs)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy data to bulk out buffer and // FIXME copying not necessary
|
/* Copy data to bulk out buffer and transmit data */
|
||||||
* transmit data
|
|
||||||
*/
|
|
||||||
count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size);
|
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_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count);
|
||||||
skb_pull(bcs->tx_skb, count);
|
skb_pull(bcs->tx_skb, count);
|
||||||
|
@ -650,7 +647,8 @@ static int write_modem(struct cardstate *cs)
|
||||||
if (cs->connected) {
|
if (cs->connected) {
|
||||||
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
|
usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev,
|
||||||
usb_sndbulkpipe(ucs->udev,
|
usb_sndbulkpipe(ucs->udev,
|
||||||
ucs->bulk_out_endpointAddr & 0x0f),
|
ucs->bulk_out_endpointAddr &
|
||||||
|
0x0f),
|
||||||
ucs->bulk_out_buffer, count,
|
ucs->bulk_out_buffer, count,
|
||||||
gigaset_write_bulk_callback, cs);
|
gigaset_write_bulk_callback, cs);
|
||||||
ret = usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC);
|
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) {
|
if (!bcs->tx_skb->len) {
|
||||||
/* skb sent completely */
|
/* 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)!",
|
gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!",
|
||||||
(unsigned long) bcs->tx_skb);
|
(unsigned long) bcs->tx_skb);
|
||||||
|
@ -763,8 +761,8 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||||
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||||
ucs->rcvbuf_size = buffer_size;
|
ucs->rcvbuf_size = buffer_size;
|
||||||
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
|
ucs->int_in_endpointAddr = endpoint->bEndpointAddress;
|
||||||
cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
|
ucs->rcvbuf = kmalloc(buffer_size, GFP_KERNEL);
|
||||||
if (!cs->inbuf[0].rcvbuf) {
|
if (!ucs->rcvbuf) {
|
||||||
dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
|
dev_err(cs->dev, "Couldn't allocate rcvbuf\n");
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -773,9 +771,9 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||||
usb_fill_int_urb(ucs->read_urb, udev,
|
usb_fill_int_urb(ucs->read_urb, udev,
|
||||||
usb_rcvintpipe(udev,
|
usb_rcvintpipe(udev,
|
||||||
endpoint->bEndpointAddress & 0x0f),
|
endpoint->bEndpointAddress & 0x0f),
|
||||||
cs->inbuf[0].rcvbuf, buffer_size,
|
ucs->rcvbuf, buffer_size,
|
||||||
gigaset_read_int_callback,
|
gigaset_read_int_callback,
|
||||||
cs->inbuf + 0, endpoint->bInterval);
|
cs, endpoint->bInterval);
|
||||||
|
|
||||||
retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL);
|
retval = usb_submit_urb(ucs->read_urb, GFP_KERNEL);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -789,7 +787,7 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||||
|
|
||||||
if (!gigaset_start(cs)) {
|
if (!gigaset_start(cs)) {
|
||||||
tasklet_kill(&cs->write_tasklet);
|
tasklet_kill(&cs->write_tasklet);
|
||||||
retval = -ENODEV; //FIXME
|
retval = -ENODEV;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -798,11 +796,11 @@ error:
|
||||||
usb_kill_urb(ucs->read_urb);
|
usb_kill_urb(ucs->read_urb);
|
||||||
kfree(ucs->bulk_out_buffer);
|
kfree(ucs->bulk_out_buffer);
|
||||||
usb_free_urb(ucs->bulk_out_urb);
|
usb_free_urb(ucs->bulk_out_urb);
|
||||||
kfree(cs->inbuf[0].rcvbuf);
|
kfree(ucs->rcvbuf);
|
||||||
usb_free_urb(ucs->read_urb);
|
usb_free_urb(ucs->read_urb);
|
||||||
usb_set_intfdata(interface, NULL);
|
usb_set_intfdata(interface, NULL);
|
||||||
ucs->read_urb = ucs->bulk_out_urb = 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);
|
usb_put_dev(ucs->udev);
|
||||||
ucs->udev = NULL;
|
ucs->udev = NULL;
|
||||||
ucs->interface = NULL;
|
ucs->interface = NULL;
|
||||||
|
@ -831,10 +829,10 @@ static void gigaset_disconnect(struct usb_interface *interface)
|
||||||
|
|
||||||
kfree(ucs->bulk_out_buffer);
|
kfree(ucs->bulk_out_buffer);
|
||||||
usb_free_urb(ucs->bulk_out_urb);
|
usb_free_urb(ucs->bulk_out_urb);
|
||||||
kfree(cs->inbuf[0].rcvbuf);
|
kfree(ucs->rcvbuf);
|
||||||
usb_free_urb(ucs->read_urb);
|
usb_free_urb(ucs->read_urb);
|
||||||
ucs->read_urb = ucs->bulk_out_urb = 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);
|
usb_put_dev(ucs->udev);
|
||||||
ucs->interface = NULL;
|
ucs->interface = NULL;
|
||||||
|
@ -916,9 +914,10 @@ static int __init usb_gigaset_init(void)
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
/* allocate memory for our driver state and intialize it */
|
/* 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,
|
GIGASET_MODULENAME, GIGASET_DEVNAME,
|
||||||
&ops, THIS_MODULE)) == NULL)
|
&ops, THIS_MODULE);
|
||||||
|
if (driver == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* register this driver with the USB subsystem */
|
/* 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_AUTHOR("Karsten Keil");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_VERSION(SPEEDFAX_REV);
|
MODULE_VERSION(SPEEDFAX_REV);
|
||||||
|
MODULE_FIRMWARE("isdn/ISAR.BIN");
|
||||||
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
|
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
|
||||||
MODULE_PARM_DESC(debug, "Speedfax debug mask");
|
MODULE_PARM_DESC(debug, "Speedfax debug mask");
|
||||||
module_param(irqloops, uint, S_IRUGO | S_IWUSR);
|
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
|
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;
|
int err = -EPROTONOSUPPORT;
|
||||||
|
|
||||||
|
@ -808,8 +808,7 @@ mISDN_sock_create(struct net *net, struct socket *sock, int proto)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct
|
static const struct net_proto_family mISDN_sock_family_ops = {
|
||||||
net_proto_family mISDN_sock_family_ops = {
|
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.family = PF_ISDN,
|
.family = PF_ISDN,
|
||||||
.create = mISDN_sock_create,
|
.create = mISDN_sock_create,
|
||||||
|
|
|
@ -249,5 +249,6 @@ config EP93XX_PWM
|
||||||
source "drivers/misc/c2port/Kconfig"
|
source "drivers/misc/c2port/Kconfig"
|
||||||
source "drivers/misc/eeprom/Kconfig"
|
source "drivers/misc/eeprom/Kconfig"
|
||||||
source "drivers/misc/cb710/Kconfig"
|
source "drivers/misc/cb710/Kconfig"
|
||||||
|
source "drivers/misc/iwmc3200top/Kconfig"
|
||||||
|
|
||||||
endif # MISC_DEVICES
|
endif # MISC_DEVICES
|
||||||
|
|
|
@ -21,5 +21,6 @@ obj-$(CONFIG_HP_ILO) += hpilo.o
|
||||||
obj-$(CONFIG_ISL29003) += isl29003.o
|
obj-$(CONFIG_ISL29003) += isl29003.o
|
||||||
obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
|
obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
|
||||||
obj-$(CONFIG_C2PORT) += c2port/
|
obj-$(CONFIG_C2PORT) += c2port/
|
||||||
|
obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
|
||||||
obj-y += eeprom/
|
obj-y += eeprom/
|
||||||
obj-y += cb710/
|
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.
|
* for the Sager NP943 prefix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (station_addr[0] == 0x02 && station_addr[1] == 0x60
|
if (station_addr[0] == 0x02 && station_addr[1] == 0x60 &&
|
||||||
&& station_addr[2] == 0x8c)
|
station_addr[2] == 0x8c)
|
||||||
mname = "3c501";
|
mname = "3c501";
|
||||||
else if (station_addr[0] == 0x00 && station_addr[1] == 0x80
|
else if (station_addr[0] == 0x00 && station_addr[1] == 0x80 &&
|
||||||
&& station_addr[2] == 0xC8)
|
station_addr[2] == 0xC8)
|
||||||
mname = "NP943";
|
mname = "NP943";
|
||||||
else {
|
else {
|
||||||
release_region(ioaddr, EL1_IO_EXTENT);
|
release_region(ioaddr, EL1_IO_EXTENT);
|
||||||
|
@ -345,7 +345,7 @@ static int el_open(struct net_device *dev)
|
||||||
if (el_debug > 2)
|
if (el_debug > 2)
|
||||||
pr_debug("%s: Doing el_open()...\n", dev->name);
|
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)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
|
|
@ -214,8 +214,8 @@ el2_probe1(struct net_device *dev, int ioaddr)
|
||||||
iobase_reg = inb(ioaddr+0x403);
|
iobase_reg = inb(ioaddr+0x403);
|
||||||
membase_reg = inb(ioaddr+0x404);
|
membase_reg = inb(ioaddr+0x404);
|
||||||
/* ASIC location registers should be 0 or have only a single bit set. */
|
/* ASIC location registers should be 0 or have only a single bit set. */
|
||||||
if ( (iobase_reg & (iobase_reg - 1))
|
if ((iobase_reg & (iobase_reg - 1)) ||
|
||||||
|| (membase_reg & (membase_reg - 1))) {
|
(membase_reg & (membase_reg - 1))) {
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
goto out1;
|
goto out1;
|
||||||
}
|
}
|
||||||
|
@ -291,8 +291,8 @@ el2_probe1(struct net_device *dev, int ioaddr)
|
||||||
writel(0xba5eba5e, mem_base);
|
writel(0xba5eba5e, mem_base);
|
||||||
for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
|
for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
|
||||||
writel(test_val, mem_base + i);
|
writel(test_val, mem_base + i);
|
||||||
if (readl(mem_base) != 0xba5eba5e
|
if (readl(mem_base) != 0xba5eba5e ||
|
||||||
|| readl(mem_base + i) != test_val) {
|
readl(mem_base + i) != test_val) {
|
||||||
pr_warning("3c503: memory failure or memory address conflict.\n");
|
pr_warning("3c503: memory failure or memory address conflict.\n");
|
||||||
dev->mem_start = 0;
|
dev->mem_start = 0;
|
||||||
ei_status.name = "3c503-PIO";
|
ei_status.name = "3c503-PIO";
|
||||||
|
@ -397,9 +397,10 @@ el2_open(struct net_device *dev)
|
||||||
unsigned long cookie = probe_irq_on();
|
unsigned long cookie = probe_irq_on();
|
||||||
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
|
outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
|
||||||
outb_p(0x00, E33G_IDCFR);
|
outb_p(0x00, E33G_IDCFR);
|
||||||
if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */
|
if (*irqp == probe_irq_off(cookie) && /* It's a good IRQ line! */
|
||||||
&& ((retval = request_irq(dev->irq = *irqp,
|
((retval = request_irq(dev->irq = *irqp,
|
||||||
eip_interrupt, 0, dev->name, dev)) == 0))
|
eip_interrupt, 0,
|
||||||
|
dev->name, dev)) == 0))
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (retval != -EBUSY)
|
if (retval != -EBUSY)
|
||||||
|
|
|
@ -886,7 +886,7 @@ static int elp_open(struct net_device *dev)
|
||||||
/*
|
/*
|
||||||
* install our interrupt service routine
|
* 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);
|
pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -399,7 +399,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
|
||||||
|
|
||||||
irq = inb(ioaddr + IRQ_CONFIG) & 0x0f;
|
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) {
|
if (irqval) {
|
||||||
pr_cont("\n");
|
pr_cont("\n");
|
||||||
pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval);
|
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;
|
void __iomem *data_frame = lp->base + data_buffer_addr;
|
||||||
ushort pkt_len = readw(data_frame);
|
ushort pkt_len = readw(data_frame);
|
||||||
|
|
||||||
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 ||
|
||||||
|| (pkt_len & 0xC000) != 0xC000) {
|
(pkt_len & 0xC000) != 0xC000) {
|
||||||
pr_err("%s: Rx frame at %#x corrupted, "
|
pr_err("%s: Rx frame at %#x corrupted, "
|
||||||
"status %04x cmd %04x next %04x "
|
"status %04x cmd %04x next %04x "
|
||||||
"data-buf @%04x %04x.\n",
|
"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. */
|
This check is needed in order not to register them twice. */
|
||||||
for (i = 0; i < el3_cards; i++) {
|
for (i = 0; i < el3_cards; i++) {
|
||||||
struct el3_private *lp = netdev_priv(el3_devs[i]);
|
struct el3_private *lp = netdev_priv(el3_devs[i]);
|
||||||
if (lp->type == EL3_PNP
|
if (lp->type == EL3_PNP &&
|
||||||
&& !memcmp(phys_addr, el3_devs[i]->dev_addr,
|
!memcmp(phys_addr, el3_devs[i]->dev_addr,
|
||||||
ETH_ALEN)) {
|
ETH_ALEN)) {
|
||||||
if (el3_debug > 3)
|
if (el3_debug > 3)
|
||||||
pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
|
pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
|
||||||
phys_addr[0] & 0xff, phys_addr[0] >> 8,
|
phys_addr[0] & 0xff, phys_addr[0] >> 8,
|
||||||
|
@ -780,7 +780,7 @@ el3_open(struct net_device *dev)
|
||||||
outw(RxReset, ioaddr + EL3_CMD);
|
outw(RxReset, ioaddr + EL3_CMD);
|
||||||
outw(SetStatusEnb | 0x00, 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)
|
if (i)
|
||||||
return i;
|
return i;
|
||||||
|
|
||||||
|
@ -835,8 +835,8 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
#ifndef final_version
|
#ifndef final_version
|
||||||
{ /* Error-checking code, delete someday. */
|
{ /* Error-checking code, delete someday. */
|
||||||
ushort status = inw(ioaddr + EL3_STATUS);
|
ushort status = inw(ioaddr + EL3_STATUS);
|
||||||
if (status & 0x0001 /* IRQ line active, missed one. */
|
if (status & 0x0001 && /* IRQ line active, missed one. */
|
||||||
&& inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
|
inw(ioaddr + EL3_STATUS) & 1) { /* Make sure. */
|
||||||
pr_debug("%s: Missed interrupt, status then %04x now %04x"
|
pr_debug("%s: Missed interrupt, status then %04x now %04x"
|
||||||
" Tx %2.2x Rx %4.4x.\n", dev->name, status,
|
" Tx %2.2x Rx %4.4x.\n", dev->name, status,
|
||||||
inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_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. */
|
/* Use the now-standard shared IRQ implementation. */
|
||||||
if (vp->capabilities == 0x11c7) {
|
if (vp->capabilities == 0x11c7) {
|
||||||
/* Corkscrew: Cannot share ISA resources. */
|
/* Corkscrew: Cannot share ISA resources. */
|
||||||
if (dev->irq == 0
|
if (dev->irq == 0 ||
|
||||||
|| dev->dma == 0
|
dev->dma == 0 ||
|
||||||
|| request_irq(dev->irq, &corkscrew_interrupt, 0,
|
request_irq(dev->irq, corkscrew_interrupt, 0,
|
||||||
vp->product_name, dev)) return -EAGAIN;
|
vp->product_name, dev))
|
||||||
|
return -EAGAIN;
|
||||||
enable_dma(dev->dma);
|
enable_dma(dev->dma);
|
||||||
set_dma_mode(dev->dma, DMA_MODE_CASCADE);
|
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)) {
|
vp->product_name, dev)) {
|
||||||
return -EAGAIN;
|
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
|
/* Check if the packet is long enough to just accept without
|
||||||
copying to a properly sized skbuff. */
|
copying to a properly sized skbuff. */
|
||||||
if (pkt_len < rx_copybreak
|
if (pkt_len < rx_copybreak &&
|
||||||
&& (skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
|
(skb = dev_alloc_skb(pkt_len + 4)) != NULL) {
|
||||||
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
|
||||||
/* 'skb_put()' points to the start of sk_buff data area. */
|
/* 'skb_put()' points to the start of sk_buff data area. */
|
||||||
memcpy(skb_put(skb, pkt_len),
|
memcpy(skb_put(skb, pkt_len),
|
||||||
|
|
|
@ -288,7 +288,7 @@ static int elmc_open(struct net_device *dev)
|
||||||
|
|
||||||
elmc_id_attn586(); /* disable interrupts */
|
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);
|
dev->name, dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq);
|
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
|
* 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) {
|
if (err) {
|
||||||
release_region(dev->base_addr, MC32_IO_EXTENT);
|
release_region(dev->base_addr, MC32_IO_EXTENT);
|
||||||
pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq);
|
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 */
|
/* Try to save time by avoiding a copy on big frames */
|
||||||
|
|
||||||
if ((length > RX_COPYBREAK)
|
if ((length > RX_COPYBREAK) &&
|
||||||
&& ((newskb=dev_alloc_skb(1532)) != NULL))
|
((newskb=dev_alloc_skb(1532)) != NULL))
|
||||||
{
|
{
|
||||||
skb=lp->rx_ring[rx_ring_tail].skb;
|
skb=lp->rx_ring[rx_ring_tail].skb;
|
||||||
skb_put(skb, length);
|
skb_put(skb, length);
|
||||||
|
|
|
@ -1942,8 +1942,8 @@ vortex_error(struct net_device *dev, int status)
|
||||||
if (status & TxComplete) { /* Really "TxError" for us. */
|
if (status & TxComplete) { /* Really "TxError" for us. */
|
||||||
tx_status = ioread8(ioaddr + TxStatus);
|
tx_status = ioread8(ioaddr + TxStatus);
|
||||||
/* Presumably a tx-timeout. We must merely re-enable. */
|
/* Presumably a tx-timeout. We must merely re-enable. */
|
||||||
if (vortex_debug > 2
|
if (vortex_debug > 2 ||
|
||||||
|| (tx_status != 0x88 && vortex_debug > 0)) {
|
(tx_status != 0x88 && vortex_debug > 0)) {
|
||||||
pr_err("%s: Transmit error, Tx status register %2.2x.\n",
|
pr_err("%s: Transmit error, Tx status register %2.2x.\n",
|
||||||
dev->name, tx_status);
|
dev->name, tx_status);
|
||||||
if (tx_status == 0x82) {
|
if (tx_status == 0x82) {
|
||||||
|
@ -2560,7 +2560,7 @@ boomerang_rx(struct net_device *dev)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
entry = vp->dirty_rx % RX_RING_SIZE;
|
entry = vp->dirty_rx % RX_RING_SIZE;
|
||||||
if (vp->rx_skbuff[entry] == NULL) {
|
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) {
|
if (skb == NULL) {
|
||||||
static unsigned long last_jif;
|
static unsigned long last_jif;
|
||||||
if (time_after(jiffies, last_jif + 10 * HZ)) {
|
if (time_after(jiffies, last_jif + 10 * HZ)) {
|
||||||
|
@ -2572,7 +2572,6 @@ boomerang_rx(struct net_device *dev)
|
||||||
break; /* Bad news! */
|
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_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;
|
vp->rx_skbuff[entry] = skb;
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,14 +549,12 @@ rx_status_loop:
|
||||||
pr_debug("%s: rx slot %d status 0x%x len %d\n",
|
pr_debug("%s: rx slot %d status 0x%x len %d\n",
|
||||||
dev->name, rx_tail, status, len);
|
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) {
|
if (!new_skb) {
|
||||||
dev->stats.rx_dropped++;
|
dev->stats.rx_dropped++;
|
||||||
goto rx_next;
|
goto rx_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
skb_reserve(new_skb, NET_IP_ALIGN);
|
|
||||||
|
|
||||||
dma_unmap_single(&cp->pdev->dev, mapping,
|
dma_unmap_single(&cp->pdev->dev, mapping,
|
||||||
buflen, PCI_DMA_FROMDEVICE);
|
buflen, PCI_DMA_FROMDEVICE);
|
||||||
|
|
||||||
|
@ -911,8 +909,8 @@ static void __cp_set_rx_mode (struct net_device *dev)
|
||||||
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
||||||
AcceptAllPhys;
|
AcceptAllPhys;
|
||||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||||
} else if ((dev->mc_count > multicast_filter_limit)
|
} else if ((dev->mc_count > multicast_filter_limit) ||
|
||||||
|| (dev->flags & IFF_ALLMULTI)) {
|
(dev->flags & IFF_ALLMULTI)) {
|
||||||
/* Too many to filter perfectly -- accept all multicasts. */
|
/* Too many to filter perfectly -- accept all multicasts. */
|
||||||
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
||||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||||
|
@ -1057,12 +1055,10 @@ static int cp_refill_rx(struct cp_private *cp)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
dma_addr_t mapping;
|
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)
|
if (!skb)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
skb_reserve(skb, NET_IP_ALIGN);
|
|
||||||
|
|
||||||
mapping = dma_map_single(&cp->pdev->dev, skb->data,
|
mapping = dma_map_single(&cp->pdev->dev, skb->data,
|
||||||
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
|
||||||
cp->rx_skb[i] = skb;
|
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);
|
mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
|
||||||
|
|
||||||
if (!tp->mii.force_media && mii_lpa != 0xffff) {
|
if (!tp->mii.force_media && mii_lpa != 0xffff) {
|
||||||
int duplex = (mii_lpa & LPA_100FULL)
|
int duplex = ((mii_lpa & LPA_100FULL) ||
|
||||||
|| (mii_lpa & 0x01C0) == 0x0040;
|
(mii_lpa & 0x01C0) == 0x0040);
|
||||||
if (tp->mii.full_duplex != duplex) {
|
if (tp->mii.full_duplex != duplex) {
|
||||||
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 (RxBufAddr),
|
||||||
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
|
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
|
||||||
|
|
||||||
while (netif_running(dev) && received < budget
|
while (netif_running(dev) && received < budget &&
|
||||||
&& (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
|
(RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
|
||||||
u32 ring_offset = cur_rx % RX_BUF_LEN;
|
u32 ring_offset = cur_rx % RX_BUF_LEN;
|
||||||
u32 rx_status;
|
u32 rx_status;
|
||||||
unsigned int pkt_size;
|
unsigned int pkt_size;
|
||||||
|
@ -2004,9 +2004,8 @@ no_early_rx:
|
||||||
/* Malloc up new buffer, compatible with net-2e. */
|
/* Malloc up new buffer, compatible with net-2e. */
|
||||||
/* Omit the four octet CRC from the length. */
|
/* 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)) {
|
if (likely(skb)) {
|
||||||
skb_reserve (skb, NET_IP_ALIGN); /* 16 byte align the IP fields. */
|
|
||||||
#if RX_BUF_IDX == 3
|
#if RX_BUF_IDX == 3
|
||||||
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
|
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
|
||||||
#else
|
#else
|
||||||
|
@ -2522,8 +2521,8 @@ static void __set_rx_mode (struct net_device *dev)
|
||||||
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
|
||||||
AcceptAllPhys;
|
AcceptAllPhys;
|
||||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||||
} else if ((dev->mc_count > multicast_filter_limit)
|
} else if ((dev->mc_count > multicast_filter_limit) ||
|
||||||
|| (dev->flags & IFF_ALLMULTI)) {
|
(dev->flags & IFF_ALLMULTI)) {
|
||||||
/* Too many to filter perfectly -- accept all multicasts. */
|
/* Too many to filter perfectly -- accept all multicasts. */
|
||||||
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
|
||||||
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
mc_filter[1] = mc_filter[0] = 0xffffffff;
|
||||||
|
|
|
@ -1001,7 +1001,7 @@ config SMC911X
|
||||||
|
|
||||||
config SMSC911X
|
config SMSC911X
|
||||||
tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
|
tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
|
||||||
depends on ARM || SUPERH || BLACKFIN
|
depends on ARM || SUPERH || BLACKFIN || MIPS
|
||||||
select CRC32
|
select CRC32
|
||||||
select MII
|
select MII
|
||||||
select PHYLIB
|
select PHYLIB
|
||||||
|
@ -3235,7 +3235,7 @@ config VIRTIO_NET
|
||||||
|
|
||||||
config VMXNET3
|
config VMXNET3
|
||||||
tristate "VMware VMXNET3 ethernet driver"
|
tristate "VMware VMXNET3 ethernet driver"
|
||||||
depends on PCI && X86 && INET
|
depends on PCI && INET
|
||||||
help
|
help
|
||||||
This driver supports VMware's vmxnet3 virtual ethernet NIC.
|
This driver supports VMware's vmxnet3 virtual ethernet NIC.
|
||||||
To compile this driver as a module, choose M here: the
|
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. */
|
/* Reserve any actual interrupt. */
|
||||||
if (dev->irq) {
|
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)
|
if (retval)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue