forked from Minki/linux
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: (1623 commits) netxen: update copyright netxen: fix tx timeout recovery netxen: fix file firmware leak netxen: improve pci memory access netxen: change firmware write size tg3: Fix return ring size breakage netxen: build fix for INET=n cdc-phonet: autoconfigure Phonet address Phonet: back-end for autoconfigured addresses Phonet: fix netlink address dump error handling ipv6: Add IFA_F_DADFAILED flag net: Add DEVTYPE support for Ethernet based devices mv643xx_eth.c: remove unused txq_set_wrr() ucc_geth: Fix hangs after switching from full to half duplex ucc_geth: Rearrange some code to avoid forward declarations phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs drivers/net/phy: introduce missing kfree drivers/net/wan: introduce missing kfree net: force bridge module(s) to be GPL Subject: [PATCH] appletalk: Fix skb leak when ipddp interface is not loaded ... Fixed up trivial conflicts: - arch/x86/include/asm/socket.h converted to <asm-generic/socket.h> in the x86 tree. The generic header has the same new #define's, so that works out fine. - drivers/net/tun.c fix conflict between89f56d1e9
("tun: reuse struct sock fields") that switched over to using 'tun->socket.sk' instead of the redundantly available (and thus removed) 'tun->sk', and2b980dbd
("lsm: Add hooks to the TUN driver") which added a new 'tun->sk' use. Noted in 'next' by Stephen Rothwell.
This commit is contained in:
commit
d7e9660ad9
@ -82,6 +82,8 @@ block/
|
||||
- info on the Block I/O (BIO) layer.
|
||||
blockdev/
|
||||
- info on block devices & drivers
|
||||
btmrvl.txt
|
||||
- info on Marvell Bluetooth driver usage.
|
||||
cachetlb.txt
|
||||
- describes the cache/TLB flushing interfaces Linux uses.
|
||||
cdrom/
|
||||
|
119
Documentation/btmrvl.txt
Normal file
119
Documentation/btmrvl.txt
Normal file
@ -0,0 +1,119 @@
|
||||
=======================================================================
|
||||
README for btmrvl driver
|
||||
=======================================================================
|
||||
|
||||
|
||||
All commands are used via debugfs interface.
|
||||
|
||||
=====================
|
||||
Set/get driver configurations:
|
||||
|
||||
Path: /debug/btmrvl/config/
|
||||
|
||||
gpiogap=[n]
|
||||
hscfgcmd
|
||||
These commands are used to configure the host sleep parameters.
|
||||
bit 8:0 -- Gap
|
||||
bit 16:8 -- GPIO
|
||||
|
||||
where GPIO is the pin number of GPIO used to wake up the host.
|
||||
It could be any valid GPIO pin# (e.g. 0-7) or 0xff (SDIO interface
|
||||
wakeup will be used instead).
|
||||
|
||||
where Gap is the gap in milli seconds between wakeup signal and
|
||||
wakeup event, or 0xff for special host sleep setting.
|
||||
|
||||
Usage:
|
||||
# Use SDIO interface to wake up the host and set GAP to 0x80:
|
||||
echo 0xff80 > /debug/btmrvl/config/gpiogap
|
||||
echo 1 > /debug/btmrvl/config/hscfgcmd
|
||||
|
||||
# Use GPIO pin #3 to wake up the host and set GAP to 0xff:
|
||||
echo 0x03ff > /debug/btmrvl/config/gpiogap
|
||||
echo 1 > /debug/btmrvl/config/hscfgcmd
|
||||
|
||||
psmode=[n]
|
||||
pscmd
|
||||
These commands are used to enable/disable auto sleep mode
|
||||
|
||||
where the option is:
|
||||
1 -- Enable auto sleep mode
|
||||
0 -- Disable auto sleep mode
|
||||
|
||||
Usage:
|
||||
# Enable auto sleep mode
|
||||
echo 1 > /debug/btmrvl/config/psmode
|
||||
echo 1 > /debug/btmrvl/config/pscmd
|
||||
|
||||
# Disable auto sleep mode
|
||||
echo 0 > /debug/btmrvl/config/psmode
|
||||
echo 1 > /debug/btmrvl/config/pscmd
|
||||
|
||||
|
||||
hsmode=[n]
|
||||
hscmd
|
||||
These commands are used to enable host sleep or wake up firmware
|
||||
|
||||
where the option is:
|
||||
1 -- Enable host sleep
|
||||
0 -- Wake up firmware
|
||||
|
||||
Usage:
|
||||
# Enable host sleep
|
||||
echo 1 > /debug/btmrvl/config/hsmode
|
||||
echo 1 > /debug/btmrvl/config/hscmd
|
||||
|
||||
# Wake up firmware
|
||||
echo 0 > /debug/btmrvl/config/hsmode
|
||||
echo 1 > /debug/btmrvl/config/hscmd
|
||||
|
||||
|
||||
======================
|
||||
Get driver status:
|
||||
|
||||
Path: /debug/btmrvl/status/
|
||||
|
||||
Usage:
|
||||
cat /debug/btmrvl/status/<args>
|
||||
|
||||
where the args are:
|
||||
|
||||
curpsmode
|
||||
This command displays current auto sleep status.
|
||||
|
||||
psstate
|
||||
This command display the power save state.
|
||||
|
||||
hsstate
|
||||
This command display the host sleep state.
|
||||
|
||||
txdnldrdy
|
||||
This command displays the value of Tx download ready flag.
|
||||
|
||||
|
||||
=====================
|
||||
|
||||
Use hcitool to issue raw hci command, refer to hcitool manual
|
||||
|
||||
Usage: Hcitool cmd <ogf> <ocf> [Parameters]
|
||||
|
||||
Interface Control Command
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x01 0x00 --Enable All interface
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x01 0x01 --Enable Wlan interface
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x01 0x02 --Enable BT interface
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x00 0x00 --Disable All interface
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x00 0x01 --Disable Wlan interface
|
||||
hcitool cmd 0x3f 0x5b 0xf5 0x00 0x02 --Disable BT interface
|
||||
|
||||
=======================================================================
|
||||
|
||||
|
||||
SD8688 firmware:
|
||||
|
||||
/lib/firmware/sd8688_helper.bin
|
||||
/lib/firmware/sd8688.bin
|
||||
|
||||
|
||||
The images can be downloaded from:
|
||||
|
||||
git.infradead.org/users/dwmw2/linux-firmware.git/libertas/
|
@ -9,3 +9,8 @@ hostprogs-y := ucon
|
||||
always := $(hostprogs-y)
|
||||
|
||||
HOSTCFLAGS_ucon.o += -I$(objtree)/usr/include
|
||||
|
||||
all: modules
|
||||
|
||||
modules clean:
|
||||
$(MAKE) -C ../.. SUBDIRS=$(PWD) $@
|
||||
|
@ -19,6 +19,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "cn_test: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@ -27,18 +29,17 @@
|
||||
|
||||
#include <linux/connector.h>
|
||||
|
||||
static struct cb_id cn_test_id = { 0x123, 0x456 };
|
||||
static struct cb_id cn_test_id = { CN_NETLINK_USERS + 3, 0x456 };
|
||||
static char cn_test_name[] = "cn_test";
|
||||
static struct sock *nls;
|
||||
static struct timer_list cn_test_timer;
|
||||
|
||||
void cn_test_callback(void *data)
|
||||
static void cn_test_callback(struct cn_msg *msg)
|
||||
{
|
||||
struct cn_msg *msg = (struct cn_msg *)data;
|
||||
|
||||
printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
|
||||
__func__, jiffies, msg->id.idx, msg->id.val,
|
||||
msg->seq, msg->ack, msg->len, (char *)msg->data);
|
||||
pr_info("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s.\n",
|
||||
__func__, jiffies, msg->id.idx, msg->id.val,
|
||||
msg->seq, msg->ack, msg->len,
|
||||
msg->len ? (char *)msg->data : "");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -63,9 +64,7 @@ static int cn_test_want_notify(void)
|
||||
|
||||
skb = alloc_skb(size, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
printk(KERN_ERR "Failed to allocate new skb with size=%u.\n",
|
||||
size);
|
||||
|
||||
pr_err("failed to allocate new skb with size=%u\n", size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -114,12 +113,12 @@ static int cn_test_want_notify(void)
|
||||
//netlink_broadcast(nls, skb, 0, ctl->group, GFP_ATOMIC);
|
||||
netlink_unicast(nls, skb, 0, 0);
|
||||
|
||||
printk(KERN_INFO "Request was sent. Group=0x%x.\n", ctl->group);
|
||||
pr_info("request was sent: group=0x%x\n", ctl->group);
|
||||
|
||||
return 0;
|
||||
|
||||
nlmsg_failure:
|
||||
printk(KERN_ERR "Failed to send %u.%u\n", msg->seq, msg->ack);
|
||||
pr_err("failed to send %u.%u\n", msg->seq, msg->ack);
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -131,6 +130,8 @@ static void cn_test_timer_func(unsigned long __data)
|
||||
struct cn_msg *m;
|
||||
char data[32];
|
||||
|
||||
pr_debug("%s: timer fired with data %lu\n", __func__, __data);
|
||||
|
||||
m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
|
||||
if (m) {
|
||||
|
||||
@ -150,7 +151,7 @@ static void cn_test_timer_func(unsigned long __data)
|
||||
|
||||
cn_test_timer_counter++;
|
||||
|
||||
mod_timer(&cn_test_timer, jiffies + HZ);
|
||||
mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static int cn_test_init(void)
|
||||
@ -168,8 +169,10 @@ static int cn_test_init(void)
|
||||
}
|
||||
|
||||
setup_timer(&cn_test_timer, cn_test_timer_func, 0);
|
||||
cn_test_timer.expires = jiffies + HZ;
|
||||
add_timer(&cn_test_timer);
|
||||
mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
|
||||
|
||||
pr_info("initialized with id={%u.%u}\n",
|
||||
cn_test_id.idx, cn_test_id.val);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -5,10 +5,10 @@ Kernel Connector.
|
||||
Kernel connector - new netlink based userspace <-> kernel space easy
|
||||
to use communication module.
|
||||
|
||||
Connector driver adds possibility to connect various agents using
|
||||
netlink based network. One must register callback and
|
||||
identifier. When driver receives special netlink message with
|
||||
appropriate identifier, appropriate callback will be called.
|
||||
The Connector driver makes it easy to connect various agents using a
|
||||
netlink based network. One must register a callback and an identifier.
|
||||
When the driver receives a special netlink message with the appropriate
|
||||
identifier, the appropriate callback will be called.
|
||||
|
||||
From the userspace point of view it's quite straightforward:
|
||||
|
||||
@ -17,10 +17,10 @@ From the userspace point of view it's quite straightforward:
|
||||
send();
|
||||
recv();
|
||||
|
||||
But if kernelspace want to use full power of such connections, driver
|
||||
writer must create special sockets, must know about struct sk_buff
|
||||
handling... Connector allows any kernelspace agents to use netlink
|
||||
based networking for inter-process communication in a significantly
|
||||
But if kernelspace wants to use the full power of such connections, the
|
||||
driver writer must create special sockets, must know about struct sk_buff
|
||||
handling, etc... The Connector driver allows any kernelspace agents to use
|
||||
netlink based networking for inter-process communication in a significantly
|
||||
easier way:
|
||||
|
||||
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
|
||||
@ -32,15 +32,15 @@ struct cb_id
|
||||
__u32 val;
|
||||
};
|
||||
|
||||
idx and val are unique identifiers which must be registered in
|
||||
connector.h for in-kernel usage. void (*callback) (void *) - is a
|
||||
callback function which will be called when message with above idx.val
|
||||
will be received by connector core. Argument for that function must
|
||||
idx and val are unique identifiers which must be registered in the
|
||||
connector.h header for in-kernel usage. void (*callback) (void *) is a
|
||||
callback function which will be called when a message with above idx.val
|
||||
is received by the connector core. The argument for that function must
|
||||
be dereferenced to struct cn_msg *.
|
||||
|
||||
struct cn_msg
|
||||
{
|
||||
struct cb_id id;
|
||||
struct cb_id id;
|
||||
|
||||
__u32 seq;
|
||||
__u32 ack;
|
||||
@ -55,92 +55,95 @@ Connector interfaces.
|
||||
|
||||
int cn_add_callback(struct cb_id *id, char *name, void (*callback) (void *));
|
||||
|
||||
Registers new callback with connector core.
|
||||
Registers new callback with connector core.
|
||||
|
||||
struct cb_id *id - unique connector's user identifier.
|
||||
It must be registered in connector.h for legal in-kernel users.
|
||||
char *name - connector's callback symbolic name.
|
||||
void (*callback) (void *) - connector's callback.
|
||||
struct cb_id *id - unique connector's user identifier.
|
||||
It must be registered in connector.h for legal in-kernel users.
|
||||
char *name - connector's callback symbolic name.
|
||||
void (*callback) (void *) - connector's callback.
|
||||
Argument must be dereferenced to struct cn_msg *.
|
||||
|
||||
|
||||
void cn_del_callback(struct cb_id *id);
|
||||
|
||||
Unregisters new callback with connector core.
|
||||
Unregisters new callback with connector core.
|
||||
|
||||
struct cb_id *id - unique connector's user identifier.
|
||||
|
||||
struct cb_id *id - unique connector's user identifier.
|
||||
|
||||
int cn_netlink_send(struct cn_msg *msg, u32 __groups, int gfp_mask);
|
||||
|
||||
Sends message to the specified groups. It can be safely called from
|
||||
softirq context, but may silently fail under strong memory pressure.
|
||||
If there are no listeners for given group -ESRCH can be returned.
|
||||
Sends message to the specified groups. It can be safely called from
|
||||
softirq context, but may silently fail under strong memory pressure.
|
||||
If there are no listeners for given group -ESRCH can be returned.
|
||||
|
||||
struct cn_msg * - message header(with attached data).
|
||||
u32 __group - destination group.
|
||||
struct cn_msg * - message header(with attached data).
|
||||
u32 __group - destination group.
|
||||
If __group is zero, then appropriate group will
|
||||
be searched through all registered connector users,
|
||||
and message will be delivered to the group which was
|
||||
created for user with the same ID as in msg.
|
||||
If __group is not zero, then message will be delivered
|
||||
to the specified group.
|
||||
int gfp_mask - GFP mask.
|
||||
int gfp_mask - GFP mask.
|
||||
|
||||
Note: When registering new callback user, connector core assigns
|
||||
netlink group to the user which is equal to it's id.idx.
|
||||
Note: When registering new callback user, connector core assigns
|
||||
netlink group to the user which is equal to it's id.idx.
|
||||
|
||||
/*****************************************/
|
||||
Protocol description.
|
||||
/*****************************************/
|
||||
|
||||
Current offers transport layer with fixed header. Recommended
|
||||
protocol which uses such header is following:
|
||||
The current framework offers a transport layer with fixed headers. The
|
||||
recommended protocol which uses such a header is as following:
|
||||
|
||||
msg->seq and msg->ack are used to determine message genealogy. When
|
||||
someone sends message it puts there locally unique sequence and random
|
||||
acknowledge numbers. Sequence number may be copied into
|
||||
someone sends a message, they use a locally unique sequence and random
|
||||
acknowledge number. The sequence number may be copied into
|
||||
nlmsghdr->nlmsg_seq too.
|
||||
|
||||
Sequence number is incremented with each message to be sent.
|
||||
The sequence number is incremented with each message sent.
|
||||
|
||||
If we expect reply to our message, then sequence number in received
|
||||
message MUST be the same as in original message, and acknowledge
|
||||
number MUST be the same + 1.
|
||||
If you expect a reply to the message, then the sequence number in the
|
||||
received message MUST be the same as in the original message, and the
|
||||
acknowledge number MUST be the same + 1.
|
||||
|
||||
If we receive message and it's sequence number is not equal to one we
|
||||
are expecting, then it is new message. If we receive message and it's
|
||||
sequence number is the same as one we are expecting, but it's
|
||||
acknowledge is not equal acknowledge number in original message + 1,
|
||||
then it is new message.
|
||||
If we receive a message and its sequence number is not equal to one we
|
||||
are expecting, then it is a new message. If we receive a message and
|
||||
its sequence number is the same as one we are expecting, but its
|
||||
acknowledge is not equal to the acknowledge number in the original
|
||||
message + 1, then it is a new message.
|
||||
|
||||
Obviously, protocol header contains above id.
|
||||
Obviously, the protocol header contains the above id.
|
||||
|
||||
connector allows event notification in the following form: kernel
|
||||
The connector allows event notification in the following form: kernel
|
||||
driver or userspace process can ask connector to notify it when
|
||||
selected id's will be turned on or off(registered or unregistered it's
|
||||
callback). It is done by sending special command to connector
|
||||
driver(it also registers itself with id={-1, -1}).
|
||||
selected ids will be turned on or off (registered or unregistered its
|
||||
callback). It is done by sending a special command to the connector
|
||||
driver (it also registers itself with id={-1, -1}).
|
||||
|
||||
As example of usage Documentation/connector now contains cn_test.c -
|
||||
testing module which uses connector to request notification and to
|
||||
send messages.
|
||||
As example of this usage can be found in the cn_test.c module which
|
||||
uses the connector to request notification and to send messages.
|
||||
|
||||
/*****************************************/
|
||||
Reliability.
|
||||
/*****************************************/
|
||||
|
||||
Netlink itself is not reliable protocol, that means that messages can
|
||||
Netlink itself is not a reliable protocol. That means that messages can
|
||||
be lost due to memory pressure or process' receiving queue overflowed,
|
||||
so caller is warned must be prepared. That is why struct cn_msg [main
|
||||
connector's message header] contains u32 seq and u32 ack fields.
|
||||
so caller is warned that it must be prepared. That is why the struct
|
||||
cn_msg [main connector's message header] contains u32 seq and u32 ack
|
||||
fields.
|
||||
|
||||
/*****************************************/
|
||||
Userspace usage.
|
||||
/*****************************************/
|
||||
|
||||
2.6.14 has a new netlink socket implementation, which by default does not
|
||||
allow to send data to netlink groups other than 1.
|
||||
So, if to use netlink socket (for example using connector)
|
||||
with different group number userspace application must subscribe to
|
||||
that group. It can be achieved by following pseudocode:
|
||||
allow people to send data to netlink groups other than 1.
|
||||
So, if you wish to use a netlink socket (for example using connector)
|
||||
with a different group number, the userspace application must subscribe to
|
||||
that group first. It can be achieved by the following pseudocode:
|
||||
|
||||
s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
|
||||
|
||||
@ -160,8 +163,8 @@ if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
|
||||
}
|
||||
|
||||
Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket
|
||||
option. To drop multicast subscription one should call above socket option
|
||||
with NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
|
||||
option. To drop a multicast subscription, one should call the above socket
|
||||
option with the NETLINK_DROP_MEMBERSHIP parameter which is defined as 0.
|
||||
|
||||
2.6.14 netlink code only allows to select a group which is less or equal to
|
||||
the maximum group number, which is used at netlink_kernel_create() time.
|
||||
|
@ -30,18 +30,24 @@
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <linux/connector.h>
|
||||
|
||||
#define DEBUG
|
||||
#define NETLINK_CONNECTOR 11
|
||||
|
||||
/* Hopefully your userspace connector.h matches this kernel */
|
||||
#define CN_TEST_IDX CN_NETLINK_USERS + 3
|
||||
#define CN_TEST_VAL 0x456
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ulog(f, a...) fprintf(stdout, f, ##a)
|
||||
#else
|
||||
@ -83,6 +89,25 @@ static int netlink_send(int s, struct cn_msg *msg)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: ucon [options] [output file]\n"
|
||||
"\n"
|
||||
"\t-h\tthis help screen\n"
|
||||
"\t-s\tsend buffers to the test module\n"
|
||||
"\n"
|
||||
"The default behavior of ucon is to subscribe to the test module\n"
|
||||
"and wait for state messages. Any ones received are dumped to the\n"
|
||||
"specified output file (or stdout). The test module is assumed to\n"
|
||||
"have an id of {%u.%u}\n"
|
||||
"\n"
|
||||
"If you get no output, then verify the cn_test module id matches\n"
|
||||
"the expected id above.\n"
|
||||
, CN_TEST_IDX, CN_TEST_VAL
|
||||
);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int s;
|
||||
@ -94,17 +119,34 @@ int main(int argc, char *argv[])
|
||||
FILE *out;
|
||||
time_t tm;
|
||||
struct pollfd pfd;
|
||||
bool send_msgs = false;
|
||||
|
||||
if (argc < 2)
|
||||
out = stdout;
|
||||
else {
|
||||
out = fopen(argv[1], "a+");
|
||||
while ((s = getopt(argc, argv, "hs")) != -1) {
|
||||
switch (s) {
|
||||
case 's':
|
||||
send_msgs = true;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
|
||||
default:
|
||||
/* getopt() outputs an error for us */
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != optind) {
|
||||
out = fopen(argv[optind], "a+");
|
||||
if (!out) {
|
||||
ulog("Unable to open %s for writing: %s\n",
|
||||
argv[1], strerror(errno));
|
||||
out = stdout;
|
||||
}
|
||||
}
|
||||
} else
|
||||
out = stdout;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
@ -115,9 +157,11 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
l_local.nl_family = AF_NETLINK;
|
||||
l_local.nl_groups = 0x123; /* bitmask of requested groups */
|
||||
l_local.nl_groups = -1; /* bitmask of requested groups */
|
||||
l_local.nl_pid = 0;
|
||||
|
||||
ulog("subscribing to %u.%u\n", CN_TEST_IDX, CN_TEST_VAL);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
|
||||
perror("bind");
|
||||
close(s);
|
||||
@ -130,15 +174,15 @@ int main(int argc, char *argv[])
|
||||
setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on));
|
||||
}
|
||||
#endif
|
||||
if (0) {
|
||||
if (send_msgs) {
|
||||
int i, j;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
data = (struct cn_msg *)buf;
|
||||
|
||||
data->id.idx = 0x123;
|
||||
data->id.val = 0x456;
|
||||
data->id.idx = CN_TEST_IDX;
|
||||
data->id.val = CN_TEST_VAL;
|
||||
data->seq = seq++;
|
||||
data->ack = 0;
|
||||
data->len = 0;
|
||||
|
@ -6,6 +6,35 @@ be removed from this file.
|
||||
|
||||
---------------------------
|
||||
|
||||
What: PRISM54
|
||||
When: 2.6.34
|
||||
|
||||
Why: prism54 FullMAC PCI / Cardbus devices used to be supported only by the
|
||||
prism54 wireless driver. After Intersil stopped selling these
|
||||
devices in preference for the newer more flexible SoftMAC devices
|
||||
a SoftMAC device driver was required and prism54 did not support
|
||||
them. The p54pci driver now exists and has been present in the kernel for
|
||||
a while. This driver supports both SoftMAC devices and FullMAC devices.
|
||||
The main difference between these devices was the amount of memory which
|
||||
could be used for the firmware. The SoftMAC devices support a smaller
|
||||
amount of memory. Because of this the SoftMAC firmware fits into FullMAC
|
||||
devices's memory. p54pci supports not only PCI / Cardbus but also USB
|
||||
and SPI. Since p54pci supports all devices prism54 supports
|
||||
you will have a conflict. I'm not quite sure how distributions are
|
||||
handling this conflict right now. prism54 was kept around due to
|
||||
claims users may experience issues when using the SoftMAC driver.
|
||||
Time has passed users have not reported issues. If you use prism54
|
||||
and for whatever reason you cannot use p54pci please let us know!
|
||||
E-mail us at: linux-wireless@vger.kernel.org
|
||||
|
||||
For more information see the p54 wiki page:
|
||||
|
||||
http://wireless.kernel.org/en/users/Drivers/p54
|
||||
|
||||
Who: Luis R. Rodriguez <lrodriguez@atheros.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: IRQF_SAMPLE_RANDOM
|
||||
Check: IRQF_SAMPLE_RANDOM
|
||||
When: July 2009
|
||||
@ -217,31 +246,6 @@ Who: Thomas Gleixner <tglx@linutronix.de>
|
||||
---------------------------
|
||||
|
||||
What (Why):
|
||||
- include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
|
||||
(superseded by xt_TOS/xt_tos target & match)
|
||||
|
||||
- "forwarding" header files like ipt_mac.h in
|
||||
include/linux/netfilter_ipv4/ and include/linux/netfilter_ipv6/
|
||||
|
||||
- xt_CONNMARK match revision 0
|
||||
(superseded by xt_CONNMARK match revision 1)
|
||||
|
||||
- xt_MARK target revisions 0 and 1
|
||||
(superseded by xt_MARK match revision 2)
|
||||
|
||||
- xt_connmark match revision 0
|
||||
(superseded by xt_connmark match revision 1)
|
||||
|
||||
- xt_conntrack match revision 0
|
||||
(superseded by xt_conntrack match revision 1)
|
||||
|
||||
- xt_iprange match revision 0,
|
||||
include/linux/netfilter_ipv4/ipt_iprange.h
|
||||
(superseded by xt_iprange match revision 1)
|
||||
|
||||
- xt_mark match revision 0
|
||||
(superseded by xt_mark match revision 1)
|
||||
|
||||
- xt_recent: the old ipt_recent proc dir
|
||||
(superseded by /proc/net/xt_recent)
|
||||
|
||||
|
@ -1543,6 +1543,11 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
symbolic names: lapic and ioapic
|
||||
Example: nmi_watchdog=2 or nmi_watchdog=panic,lapic
|
||||
|
||||
netpoll.carrier_timeout=
|
||||
[NET] Specifies amount of time (in seconds) that
|
||||
netpoll should wait for a carrier. By default netpoll
|
||||
waits 4 seconds.
|
||||
|
||||
no387 [BUGS=X86-32] Tells the kernel to use the 387 maths
|
||||
emulation library even if a 387 maths coprocessor
|
||||
is present.
|
||||
|
@ -60,6 +60,8 @@ framerelay.txt
|
||||
- info on using Frame Relay/Data Link Connection Identifier (DLCI).
|
||||
generic_netlink.txt
|
||||
- info on Generic Netlink
|
||||
ieee802154.txt
|
||||
- Linux IEEE 802.15.4 implementation, API and drivers
|
||||
ip-sysctl.txt
|
||||
- /proc/sys/net/ipv4/* variables
|
||||
ip_dynaddr.txt
|
||||
|
@ -22,7 +22,7 @@ int sd = socket(PF_IEEE802154, SOCK_DGRAM, 0);
|
||||
.....
|
||||
|
||||
The address family, socket addresses etc. are defined in the
|
||||
include/net/ieee802154/af_ieee802154.h header or in the special header
|
||||
include/net/af_ieee802154.h header or in the special header
|
||||
in our userspace package (see either linux-zigbee sourceforge download page
|
||||
or git tree at git://linux-zigbee.git.sourceforge.net/gitroot/linux-zigbee).
|
||||
|
||||
@ -33,7 +33,7 @@ MLME - MAC Level Management
|
||||
============================
|
||||
|
||||
Most of IEEE 802.15.4 MLME interfaces are directly mapped on netlink commands.
|
||||
See the include/net/ieee802154/nl802154.h header. Our userspace tools package
|
||||
See the include/net/nl802154.h header. Our userspace tools package
|
||||
(see above) provides CLI configuration utility for radio interfaces and simple
|
||||
coordinator for IEEE 802.15.4 networks as an example users of MLME protocol.
|
||||
|
||||
@ -54,10 +54,14 @@ Those types of devices require different approach to be hooked into Linux kernel
|
||||
HardMAC
|
||||
=======
|
||||
|
||||
See the header include/net/ieee802154/netdevice.h. You have to implement Linux
|
||||
See the header include/net/ieee802154_netdev.h. You have to implement Linux
|
||||
net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
|
||||
code via plain sk_buffs. The control block of sk_buffs will contain additional
|
||||
info as described in the struct ieee802154_mac_cb.
|
||||
code via plain sk_buffs. On skb reception skb->cb must contain additional
|
||||
info as described in the struct ieee802154_mac_cb. During packet transmission
|
||||
the skb->cb is used to provide additional data to device's header_ops->create
|
||||
function. Be aware, that this data can be overriden later (when socket code
|
||||
submits skb to qdisc), so if you need something from that cb later, you should
|
||||
store info in the skb->data on your own.
|
||||
|
||||
To hook the MLME interface you have to populate the ml_priv field of your
|
||||
net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are
|
||||
@ -69,8 +73,8 @@ We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c
|
||||
SoftMAC
|
||||
=======
|
||||
|
||||
We are going to provide intermediate layer impelementing IEEE 802.15.4 MAC
|
||||
We are going to provide intermediate layer implementing IEEE 802.15.4 MAC
|
||||
in software. This is currently WIP.
|
||||
|
||||
See header include/net/ieee802154/mac802154.h and several drivers in
|
||||
drivers/ieee802154/
|
||||
See header include/net/mac802154.h and several drivers in drivers/ieee802154/.
|
||||
|
||||
|
@ -311,9 +311,12 @@ tcp_no_metrics_save - BOOLEAN
|
||||
connections.
|
||||
|
||||
tcp_orphan_retries - INTEGER
|
||||
How may times to retry before killing TCP connection, closed
|
||||
by our side. Default value 7 corresponds to ~50sec-16min
|
||||
depending on RTO. If you machine is loaded WEB server,
|
||||
This value influences the timeout of a locally closed TCP connection,
|
||||
when RTO retransmissions remain unacknowledged.
|
||||
See tcp_retries2 for more details.
|
||||
|
||||
The default value is 7.
|
||||
If your machine is a loaded WEB server,
|
||||
you should think about lowering this value, such sockets
|
||||
may consume significant resources. Cf. tcp_max_orphans.
|
||||
|
||||
@ -327,16 +330,28 @@ tcp_retrans_collapse - BOOLEAN
|
||||
certain TCP stacks.
|
||||
|
||||
tcp_retries1 - INTEGER
|
||||
How many times to retry before deciding that something is wrong
|
||||
and it is necessary to report this suspicion to network layer.
|
||||
Minimal RFC value is 3, it is default, which corresponds
|
||||
to ~3sec-8min depending on RTO.
|
||||
This value influences the time, after which TCP decides, that
|
||||
something is wrong due to unacknowledged RTO retransmissions,
|
||||
and reports this suspicion to the network layer.
|
||||
See tcp_retries2 for more details.
|
||||
|
||||
RFC 1122 recommends at least 3 retransmissions, which is the
|
||||
default.
|
||||
|
||||
tcp_retries2 - INTEGER
|
||||
How may times to retry before killing alive TCP connection.
|
||||
RFC1122 says that the limit should be longer than 100 sec.
|
||||
It is too small number. Default value 15 corresponds to ~13-30min
|
||||
depending on RTO.
|
||||
This value influences the timeout of an alive TCP connection,
|
||||
when RTO retransmissions remain unacknowledged.
|
||||
Given a value of N, a hypothetical TCP connection following
|
||||
exponential backoff with an initial RTO of TCP_RTO_MIN would
|
||||
retransmit N times before killing the connection at the (N+1)th RTO.
|
||||
|
||||
The default value of 15 yields a hypothetical timeout of 924.6
|
||||
seconds and is a lower bound for the effective timeout.
|
||||
TCP will effectively time out at the first RTO which exceeds the
|
||||
hypothetical timeout.
|
||||
|
||||
RFC 1122 recommends at least 100 seconds for the timeout,
|
||||
which corresponds to a value of at least 8.
|
||||
|
||||
tcp_rfc1337 - BOOLEAN
|
||||
If set, the TCP stack behaves conforming to RFC1337. If unset,
|
||||
@ -1282,6 +1297,16 @@ sctp_rmem - vector of 3 INTEGERs: min, default, max
|
||||
sctp_wmem - vector of 3 INTEGERs: min, default, max
|
||||
See tcp_wmem for a description.
|
||||
|
||||
addr_scope_policy - INTEGER
|
||||
Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
|
||||
|
||||
0 - Disable IPv4 address scoping
|
||||
1 - Enable IPv4 address scoping
|
||||
2 - Follow draft but allow IPv4 private addresses
|
||||
3 - Follow draft but allow IPv4 link local addresses
|
||||
|
||||
Default: 1
|
||||
|
||||
|
||||
/proc/sys/net/core/*
|
||||
dev_weight - INTEGER
|
||||
|
52
MAINTAINERS
52
MAINTAINERS
@ -876,6 +876,7 @@ M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
|
||||
M: Bob Copeland <me@bobcopeland.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ath5k-devel@lists.ath5k.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ath5k
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/ath/ath5k/
|
||||
|
||||
@ -887,6 +888,7 @@ M: Vasanthakumar Thiagarajan <vasanth@atheros.com>
|
||||
M: Senthil Balasubramanian <senthilkumar@atheros.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ath9k-devel@lists.ath9k.org
|
||||
W: http://wireless.kernel.org/en/users/Drivers/ath9k
|
||||
S: Supported
|
||||
F: drivers/net/wireless/ath/ath9k/
|
||||
|
||||
@ -2660,25 +2662,21 @@ F: drivers/net/ixgbe/
|
||||
|
||||
INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: James Ketrenos <jketreno@linux.intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw2100-devel@lists.sourceforge.net
|
||||
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
|
||||
W: http://ipw2100.sourceforge.net
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: Documentation/networking/README.ipw2100
|
||||
F: drivers/net/wireless/ipw2x00/ipw2100.*
|
||||
|
||||
INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: James Ketrenos <jketreno@linux.intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw2100-devel@lists.sourceforge.net
|
||||
W: http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
|
||||
W: http://ipw2200.sourceforge.net
|
||||
S: Supported
|
||||
S: Odd Fixes
|
||||
F: Documentation/networking/README.ipw2200
|
||||
F: drivers/net/wireless/ipw2x00/ipw2200.*
|
||||
|
||||
@ -2695,8 +2693,8 @@ F: include/linux/wimax/i2400m.h
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Zhu Yi <yi.zhu@intel.com>
|
||||
M: Reinette Chatre <reinette.chatre@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
L: ipw3945-devel@lists.sourceforge.net
|
||||
W: http://intellinuxwireless.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
|
||||
S: Supported
|
||||
@ -3279,6 +3277,12 @@ S: Supported
|
||||
F: drivers/net/mv643xx_eth.*
|
||||
F: include/linux/mv643xx.h
|
||||
|
||||
MARVELL MWL8K WIRELESS DRIVER
|
||||
M: Lennert Buytenhek <buytenh@marvell.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/wireless/mwl8k.c
|
||||
|
||||
MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
|
||||
M: Nicolas Pitre <nico@cam.org>
|
||||
S: Maintained
|
||||
@ -3591,9 +3595,12 @@ M: "John W. Linville" <linville@tuxdriver.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
|
||||
S: Maintained
|
||||
F: net/mac80211/
|
||||
F: net/rfkill/
|
||||
F: net/wireless/
|
||||
F: include/net/ieee80211*
|
||||
F: include/linux/wireless.h
|
||||
F: drivers/net/wireless/
|
||||
|
||||
NETWORKING DRIVERS
|
||||
L: netdev@vger.kernel.org
|
||||
@ -4299,7 +4306,7 @@ L: linux-wireless@vger.kernel.org
|
||||
W: http://linuxwireless.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/rtl818*
|
||||
F: drivers/net/wireless/rtl818x/rtl8180*
|
||||
|
||||
RTL8187 WIRELESS DRIVER
|
||||
M: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
|
||||
@ -4526,9 +4533,10 @@ S: Supported
|
||||
F: drivers/net/benet/
|
||||
|
||||
SFC NETWORK DRIVER
|
||||
P: Steve Hodgson
|
||||
P: Ben Hutchings
|
||||
M: Robert Stonehouse <linux-net-drivers@solarflare.com>
|
||||
M: Solarflare linux maintainers <linux-net-drivers@solarflare.com>
|
||||
M: Steve Hodgson <shodgson@solarflare.com>
|
||||
M: Ben Hutchings <bhutchings@solarflare.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/net/sfc/
|
||||
|
||||
@ -5578,6 +5586,24 @@ M: Miloslav Trmac <mitr@volny.cz>
|
||||
S: Maintained
|
||||
F: drivers/input/misc/wistron_btns.c
|
||||
|
||||
WL1251 WIRELESS DRIVER
|
||||
P: Kalle Valo
|
||||
M: kalle.valo@nokia.com
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/wl12xx/*
|
||||
X: drivers/net/wireless/wl12xx/wl1271*
|
||||
|
||||
WL1271 WIRELESS DRIVER
|
||||
M: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
F: drivers/net/wireless/wl12xx/wl1271*
|
||||
|
||||
WL3501 WIRELESS PCMCIA CARD DRIVER
|
||||
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
|
@ -32,6 +32,8 @@
|
||||
#define SO_RCVTIMEO 0x1012
|
||||
#define SO_SNDTIMEO 0x1013
|
||||
#define SO_ACCEPTCONN 0x1014
|
||||
#define SO_PROTOCOL 0x1028
|
||||
#define SO_DOMAIN 0x1029
|
||||
|
||||
/* linux-specific, might as well be the same as on i386 */
|
||||
#define SO_NO_CHECK 11
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -416,6 +416,7 @@ static struct clocksource clocksource_ixp4xx = {
|
||||
};
|
||||
|
||||
unsigned long ixp4xx_timer_freq = FREQ;
|
||||
EXPORT_SYMBOL(ixp4xx_timer_freq);
|
||||
static int __init ixp4xx_clocksource_init(void)
|
||||
{
|
||||
clocksource_ixp4xx.mult =
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* __ASM_AVR32_SOCKET_H */
|
||||
|
@ -59,6 +59,9 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
||||
|
@ -57,5 +57,8 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -412,7 +412,7 @@ simeth_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
*/
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static inline struct sk_buff *
|
||||
|
@ -66,4 +66,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_IA64_SOCKET_H */
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_M32R_SOCKET_H */
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <linux/leds.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phy_fixed.h>
|
||||
|
||||
#include <asm/addrspace.h>
|
||||
#include <asm/mach-ar7/ar7.h>
|
||||
@ -208,6 +210,12 @@ static struct physmap_flash_data physmap_flash_data = {
|
||||
.width = 2,
|
||||
};
|
||||
|
||||
static struct fixed_phy_status fixed_phy_status __initdata = {
|
||||
.link = 1,
|
||||
.speed = 100,
|
||||
.duplex = 1,
|
||||
};
|
||||
|
||||
static struct plat_cpmac_data cpmac_low_data = {
|
||||
.reset_bit = 17,
|
||||
.power_bit = 20,
|
||||
@ -530,6 +538,9 @@ static int __init ar7_register_devices(void)
|
||||
}
|
||||
|
||||
if (ar7_has_high_cpmac()) {
|
||||
res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
|
||||
if (res && res != -ENODEV)
|
||||
return res;
|
||||
cpmac_get_mac(1, cpmac_high_data.dev_addr);
|
||||
res = platform_device_register(&cpmac_high);
|
||||
if (res)
|
||||
@ -538,6 +549,10 @@ static int __init ar7_register_devices(void)
|
||||
cpmac_low_data.phy_mask = 0xffffffff;
|
||||
}
|
||||
|
||||
res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
|
||||
if (res && res != -ENODEV)
|
||||
return res;
|
||||
|
||||
cpmac_get_mac(0, cpmac_low_data.dev_addr);
|
||||
res = platform_device_register(&cpmac_low);
|
||||
if (res)
|
||||
|
@ -42,6 +42,8 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
|
||||
#define SO_SNDTIMEO 0x1005 /* send timeout */
|
||||
#define SO_RCVTIMEO 0x1006 /* receive timeout */
|
||||
#define SO_ACCEPTCONN 0x1009
|
||||
#define SO_PROTOCOL 0x1028 /* protocol type */
|
||||
#define SO_DOMAIN 0x1029 /* domain/socket family */
|
||||
|
||||
/* linux-specific, might as well be the same as on i386 */
|
||||
#define SO_NO_CHECK 11
|
||||
|
@ -164,7 +164,7 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_connect
|
||||
PTR sys_accept
|
||||
PTR sys_sendto
|
||||
PTR sys_recvfrom
|
||||
PTR compat_sys_recvfrom
|
||||
PTR compat_sys_sendmsg /* 6045 */
|
||||
PTR compat_sys_recvmsg
|
||||
PTR sys_shutdown
|
||||
|
@ -378,8 +378,8 @@ sys_call_table:
|
||||
PTR sys_getsockname
|
||||
PTR sys_getsockopt
|
||||
PTR sys_listen
|
||||
PTR sys_recv /* 4175 */
|
||||
PTR sys_recvfrom
|
||||
PTR compat_sys_recv /* 4175 */
|
||||
PTR compat_sys_recvfrom
|
||||
PTR compat_sys_recvmsg
|
||||
PTR sys_send
|
||||
PTR compat_sys_sendmsg
|
||||
|
@ -57,4 +57,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -24,6 +24,8 @@
|
||||
#define SO_RCVTIMEO 0x1006
|
||||
#define SO_ERROR 0x1007
|
||||
#define SO_TYPE 0x1008
|
||||
#define SO_PROTOCOL 0x1028
|
||||
#define SO_DOMAIN 0x1029
|
||||
#define SO_PEERNAME 0x2000
|
||||
|
||||
#define SO_NO_CHECK 0x400b
|
||||
|
@ -154,6 +154,7 @@ int qe_get_snum(void);
|
||||
void qe_put_snum(u8 snum);
|
||||
unsigned int qe_get_num_of_risc(void);
|
||||
unsigned int qe_get_num_of_snums(void);
|
||||
int qe_alive_during_sleep(void);
|
||||
|
||||
/* we actually use cpm_muram implementation, define this for convenience */
|
||||
#define qe_muram_init cpm_muram_init
|
||||
|
@ -64,4 +64,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_POWERPC_SOCKET_H */
|
||||
|
@ -65,6 +65,19 @@ static unsigned int qe_num_of_snum;
|
||||
|
||||
static phys_addr_t qebase = -1;
|
||||
|
||||
int qe_alive_during_sleep(void)
|
||||
{
|
||||
static int ret = -1;
|
||||
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
ret = !of_find_compatible_node(NULL, NULL, "fsl,mpc8569-pmc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_alive_during_sleep);
|
||||
|
||||
phys_addr_t get_qe_base(void)
|
||||
{
|
||||
struct device_node *qe;
|
||||
|
@ -65,4 +65,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _ASM_SOCKET_H */
|
||||
|
@ -6,6 +6,9 @@ enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
|
||||
struct sh_eth_plat_data {
|
||||
int phy;
|
||||
int edmac_endian;
|
||||
|
||||
unsigned no_ether_link:1;
|
||||
unsigned ether_link_active_low:1;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,9 @@
|
||||
#define SO_RCVBUFFORCE 0x100b
|
||||
#define SO_ERROR 0x1007
|
||||
#define SO_TYPE 0x1008
|
||||
#define SO_PROTOCOL 0x1028
|
||||
#define SO_DOMAIN 0x1029
|
||||
|
||||
|
||||
/* Linux specific, keep the same. */
|
||||
#define SO_NO_CHECK 0x000b
|
||||
|
@ -121,7 +121,7 @@ SIGN2(sys32_syslog, sys_syslog, %o0, %o2)
|
||||
SIGN1(sys32_umask, sys_umask, %o0)
|
||||
SIGN3(sys32_tgkill, sys_tgkill, %o0, %o1, %o2)
|
||||
SIGN1(sys32_sendto, sys_sendto, %o0)
|
||||
SIGN1(sys32_recvfrom, sys_recvfrom, %o0)
|
||||
SIGN1(sys32_recvfrom, compat_sys_recvfrom, %o0)
|
||||
SIGN3(sys32_socket, sys_socket, %o0, %o1, %o2)
|
||||
SIGN2(sys32_connect, sys_connect, %o0, %o2)
|
||||
SIGN2(sys32_bind, sys_bind, %o0, %o2)
|
||||
|
@ -245,7 +245,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static void uml_net_set_multicast_list(struct net_device *dev)
|
||||
@ -285,7 +285,7 @@ static void uml_net_get_drvinfo(struct net_device *dev,
|
||||
strcpy(info->version, "42");
|
||||
}
|
||||
|
||||
static struct ethtool_ops uml_net_ethtool_ops = {
|
||||
static const struct ethtool_ops uml_net_ethtool_ops = {
|
||||
.get_drvinfo = uml_net_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
@ -68,4 +68,7 @@
|
||||
#define SO_TIMESTAMPING 37
|
||||
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||
|
||||
#define SO_PROTOCOL 38
|
||||
#define SO_DOMAIN 39
|
||||
|
||||
#endif /* _XTENSA_SOCKET_H */
|
||||
|
@ -545,7 +545,7 @@ static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
spin_unlock_irqrestore(&lp->lock, flags);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -641,7 +641,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
|
||||
pre = 1;
|
||||
break;
|
||||
case round_nearest:
|
||||
pre = (br+(c<<div)/2)/(c<<div);
|
||||
pre = DIV_ROUND_CLOSEST(br, c<<div);
|
||||
// but p must be non-zero
|
||||
if (!pre)
|
||||
pre = 1;
|
||||
@ -671,7 +671,7 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r,
|
||||
pre = DIV_ROUND_UP(br, c<<div);
|
||||
break;
|
||||
case round_nearest:
|
||||
pre = (br+(c<<div)/2)/(c<<div);
|
||||
pre = DIV_ROUND_CLOSEST(br, c<<div);
|
||||
break;
|
||||
default: /* round_up */
|
||||
pre = br/(c<<div);
|
||||
|
@ -372,7 +372,7 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
|
||||
}
|
||||
|
||||
snr = next_string(skb);
|
||||
if (!str)
|
||||
if (!snr)
|
||||
return -EIO;
|
||||
attn = next_string(skb);
|
||||
if (!attn)
|
||||
|
@ -170,5 +170,30 @@ config BT_HCIVHCI
|
||||
Say Y here to compile support for virtual HCI devices into the
|
||||
kernel or say M to compile it as module (hci_vhci).
|
||||
|
||||
config BT_MRVL
|
||||
tristate "Marvell Bluetooth driver support"
|
||||
help
|
||||
The core driver to support Marvell Bluetooth devices.
|
||||
|
||||
This driver is required if you want to support
|
||||
Marvell Bluetooth devices, such as 8688.
|
||||
|
||||
Say Y here to compile Marvell Bluetooth driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
||||
config BT_MRVL_SDIO
|
||||
tristate "Marvell BT-over-SDIO driver"
|
||||
depends on BT_MRVL && MMC
|
||||
select FW_LOADER
|
||||
help
|
||||
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
||||
|
||||
This driver is required if you want to use Marvell Bluetooth
|
||||
devices with SDIO interface. Currently only SD8688 chipset is
|
||||
supported.
|
||||
|
||||
Say Y here to compile support for Marvell BT-over-SDIO driver
|
||||
into the kernel or say M to compile it as module.
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -15,6 +15,12 @@ obj-$(CONFIG_BT_HCIBTUART) += btuart_cs.o
|
||||
obj-$(CONFIG_BT_HCIBTUSB) += btusb.o
|
||||
obj-$(CONFIG_BT_HCIBTSDIO) += btsdio.o
|
||||
|
||||
obj-$(CONFIG_BT_MRVL) += btmrvl.o
|
||||
obj-$(CONFIG_BT_MRVL_SDIO) += btmrvl_sdio.o
|
||||
|
||||
btmrvl-y := btmrvl_main.o
|
||||
btmrvl-$(CONFIG_DEBUG_FS) += btmrvl_debugfs.o
|
||||
|
||||
hci_uart-y := hci_ldisc.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
|
||||
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
|
||||
|
432
drivers/bluetooth/btmrvl_debugfs.c
Normal file
432
drivers/bluetooth/btmrvl_debugfs.c
Normal file
@ -0,0 +1,432 @@
|
||||
/**
|
||||
* Marvell Bluetooth driver: debugfs related functions
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
**/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "btmrvl_drv.h"
|
||||
|
||||
struct btmrvl_debugfs_data {
|
||||
struct dentry *root_dir, *config_dir, *status_dir;
|
||||
|
||||
/* config */
|
||||
struct dentry *drvdbg;
|
||||
struct dentry *psmode;
|
||||
struct dentry *pscmd;
|
||||
struct dentry *hsmode;
|
||||
struct dentry *hscmd;
|
||||
struct dentry *gpiogap;
|
||||
struct dentry *hscfgcmd;
|
||||
|
||||
/* status */
|
||||
struct dentry *curpsmode;
|
||||
struct dentry *hsstate;
|
||||
struct dentry *psstate;
|
||||
struct dentry *txdnldready;
|
||||
};
|
||||
|
||||
static int btmrvl_open_generic(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_hscfgcmd_write(struct file *file,
|
||||
const char __user *ubuf, size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 10, &result);
|
||||
|
||||
priv->btmrvl_dev.hscfgcmd = result;
|
||||
|
||||
if (priv->btmrvl_dev.hscfgcmd) {
|
||||
btmrvl_prepare_command(priv);
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_hscfgcmd_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
|
||||
priv->btmrvl_dev.hscfgcmd);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_hscfgcmd_fops = {
|
||||
.read = btmrvl_hscfgcmd_read,
|
||||
.write = btmrvl_hscfgcmd_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 10, &result);
|
||||
|
||||
priv->btmrvl_dev.psmode = result;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_psmode_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
|
||||
priv->btmrvl_dev.psmode);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_psmode_fops = {
|
||||
.read = btmrvl_psmode_read,
|
||||
.write = btmrvl_psmode_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 10, &result);
|
||||
|
||||
priv->btmrvl_dev.pscmd = result;
|
||||
|
||||
if (priv->btmrvl_dev.pscmd) {
|
||||
btmrvl_prepare_command(priv);
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
}
|
||||
|
||||
return count;
|
||||
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_pscmd_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.pscmd);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_pscmd_fops = {
|
||||
.read = btmrvl_pscmd_read,
|
||||
.write = btmrvl_pscmd_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 16, &result);
|
||||
|
||||
priv->btmrvl_dev.gpio_gap = result;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_gpiogap_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "0x%x\n",
|
||||
priv->btmrvl_dev.gpio_gap);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_gpiogap_fops = {
|
||||
.read = btmrvl_gpiogap_read,
|
||||
.write = btmrvl_gpiogap_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = (struct btmrvl_private *) file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 10, &result);
|
||||
|
||||
priv->btmrvl_dev.hscmd = result;
|
||||
if (priv->btmrvl_dev.hscmd) {
|
||||
btmrvl_prepare_command(priv);
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_hscmd_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hscmd);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_hscmd_fops = {
|
||||
.read = btmrvl_hscmd_read,
|
||||
.write = btmrvl_hscmd_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
long result, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtol(buf, 10, &result);
|
||||
|
||||
priv->btmrvl_dev.hsmode = result;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t btmrvl_hsmode_read(struct file *file, char __user * userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->btmrvl_dev.hsmode);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_hsmode_fops = {
|
||||
.read = btmrvl_hsmode_read,
|
||||
.write = btmrvl_hsmode_write,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_curpsmode_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->psmode);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_curpsmode_fops = {
|
||||
.read = btmrvl_curpsmode_read,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_psstate_read(struct file *file, char __user * userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->ps_state);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_psstate_fops = {
|
||||
.read = btmrvl_psstate_read,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_hsstate_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n", priv->adapter->hs_state);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_hsstate_fops = {
|
||||
.read = btmrvl_hsstate_read,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_txdnldready_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, sizeof(buf) - 1, "%d\n",
|
||||
priv->btmrvl_dev.tx_dnld_rdy);
|
||||
|
||||
return simple_read_from_buffer(userbuf, count, ppos, buf, ret);
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_txdnldready_fops = {
|
||||
.read = btmrvl_txdnldready_read,
|
||||
.open = btmrvl_open_generic,
|
||||
};
|
||||
|
||||
void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hdev->driver_data;
|
||||
struct btmrvl_debugfs_data *dbg;
|
||||
|
||||
dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
|
||||
priv->debugfs_data = dbg;
|
||||
|
||||
if (!dbg) {
|
||||
BT_ERR("Can not allocate memory for btmrvl_debugfs_data.");
|
||||
return;
|
||||
}
|
||||
|
||||
dbg->root_dir = debugfs_create_dir("btmrvl", NULL);
|
||||
|
||||
dbg->config_dir = debugfs_create_dir("config", dbg->root_dir);
|
||||
|
||||
dbg->psmode = debugfs_create_file("psmode", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_psmode_fops);
|
||||
dbg->pscmd = debugfs_create_file("pscmd", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_pscmd_fops);
|
||||
dbg->gpiogap = debugfs_create_file("gpiogap", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_gpiogap_fops);
|
||||
dbg->hsmode = debugfs_create_file("hsmode", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_hsmode_fops);
|
||||
dbg->hscmd = debugfs_create_file("hscmd", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_hscmd_fops);
|
||||
dbg->hscfgcmd = debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
||||
hdev->driver_data, &btmrvl_hscfgcmd_fops);
|
||||
|
||||
dbg->status_dir = debugfs_create_dir("status", dbg->root_dir);
|
||||
dbg->curpsmode = debugfs_create_file("curpsmode", 0444,
|
||||
dbg->status_dir,
|
||||
hdev->driver_data,
|
||||
&btmrvl_curpsmode_fops);
|
||||
dbg->psstate = debugfs_create_file("psstate", 0444, dbg->status_dir,
|
||||
hdev->driver_data, &btmrvl_psstate_fops);
|
||||
dbg->hsstate = debugfs_create_file("hsstate", 0444, dbg->status_dir,
|
||||
hdev->driver_data, &btmrvl_hsstate_fops);
|
||||
dbg->txdnldready = debugfs_create_file("txdnldready", 0444,
|
||||
dbg->status_dir,
|
||||
hdev->driver_data,
|
||||
&btmrvl_txdnldready_fops);
|
||||
}
|
||||
|
||||
void btmrvl_debugfs_remove(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hdev->driver_data;
|
||||
struct btmrvl_debugfs_data *dbg = priv->debugfs_data;
|
||||
|
||||
if (!dbg)
|
||||
return;
|
||||
|
||||
debugfs_remove(dbg->psmode);
|
||||
debugfs_remove(dbg->pscmd);
|
||||
debugfs_remove(dbg->gpiogap);
|
||||
debugfs_remove(dbg->hsmode);
|
||||
debugfs_remove(dbg->hscmd);
|
||||
debugfs_remove(dbg->hscfgcmd);
|
||||
debugfs_remove(dbg->config_dir);
|
||||
|
||||
debugfs_remove(dbg->curpsmode);
|
||||
debugfs_remove(dbg->psstate);
|
||||
debugfs_remove(dbg->hsstate);
|
||||
debugfs_remove(dbg->txdnldready);
|
||||
debugfs_remove(dbg->status_dir);
|
||||
|
||||
debugfs_remove(dbg->root_dir);
|
||||
|
||||
kfree(dbg);
|
||||
}
|
139
drivers/bluetooth/btmrvl_drv.h
Normal file
139
drivers/bluetooth/btmrvl_drv.h
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Marvell Bluetooth driver: global definitions & declarations
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
#define BTM_HEADER_LEN 4
|
||||
#define BTM_UPLD_SIZE 2312
|
||||
|
||||
/* Time to wait until Host Sleep state change in millisecond */
|
||||
#define WAIT_UNTIL_HS_STATE_CHANGED 5000
|
||||
/* Time to wait for command response in millisecond */
|
||||
#define WAIT_UNTIL_CMD_RESP 5000
|
||||
|
||||
struct btmrvl_thread {
|
||||
struct task_struct *task;
|
||||
wait_queue_head_t wait_q;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
struct btmrvl_device {
|
||||
void *card;
|
||||
struct hci_dev *hcidev;
|
||||
|
||||
u8 tx_dnld_rdy;
|
||||
|
||||
u8 psmode;
|
||||
u8 pscmd;
|
||||
u8 hsmode;
|
||||
u8 hscmd;
|
||||
|
||||
/* Low byte is gap, high byte is GPIO */
|
||||
u16 gpio_gap;
|
||||
|
||||
u8 hscfgcmd;
|
||||
u8 sendcmdflag;
|
||||
};
|
||||
|
||||
struct btmrvl_adapter {
|
||||
u32 int_count;
|
||||
struct sk_buff_head tx_queue;
|
||||
u8 psmode;
|
||||
u8 ps_state;
|
||||
u8 hs_state;
|
||||
u8 wakeup_tries;
|
||||
wait_queue_head_t cmd_wait_q;
|
||||
u8 cmd_complete;
|
||||
};
|
||||
|
||||
struct btmrvl_private {
|
||||
struct btmrvl_device btmrvl_dev;
|
||||
struct btmrvl_adapter *adapter;
|
||||
struct btmrvl_thread main_thread;
|
||||
int (*hw_host_to_card) (struct btmrvl_private *priv,
|
||||
u8 *payload, u16 nb);
|
||||
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
|
||||
spinlock_t driver_lock; /* spinlock used by driver */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void *debugfs_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MRVL_VENDOR_PKT 0xFE
|
||||
|
||||
/* Bluetooth commands */
|
||||
#define BT_CMD_AUTO_SLEEP_MODE 0x23
|
||||
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
|
||||
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
|
||||
#define BT_CMD_MODULE_CFG_REQ 0x5B
|
||||
|
||||
/* Sub-commands: Module Bringup/Shutdown Request */
|
||||
#define MODULE_BRINGUP_REQ 0xF1
|
||||
#define MODULE_SHUTDOWN_REQ 0xF2
|
||||
|
||||
#define BT_EVENT_POWER_STATE 0x20
|
||||
|
||||
/* Bluetooth Power States */
|
||||
#define BT_PS_ENABLE 0x02
|
||||
#define BT_PS_DISABLE 0x03
|
||||
#define BT_PS_SLEEP 0x01
|
||||
|
||||
#define OGF 0x3F
|
||||
|
||||
/* Host Sleep states */
|
||||
#define HS_ACTIVATED 0x01
|
||||
#define HS_DEACTIVATED 0x00
|
||||
|
||||
/* Power Save modes */
|
||||
#define PS_SLEEP 0x01
|
||||
#define PS_AWAKE 0x00
|
||||
|
||||
struct btmrvl_cmd {
|
||||
__le16 ocf_ogf;
|
||||
u8 length;
|
||||
u8 data[4];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct btmrvl_event {
|
||||
u8 ec; /* event counter */
|
||||
u8 length;
|
||||
u8 data[4];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Prototype of global function */
|
||||
|
||||
struct btmrvl_private *btmrvl_add_card(void *card);
|
||||
int btmrvl_remove_card(struct btmrvl_private *priv);
|
||||
|
||||
void btmrvl_interrupt(struct btmrvl_private *priv);
|
||||
|
||||
void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
|
||||
|
||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd);
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void btmrvl_debugfs_init(struct hci_dev *hdev);
|
||||
void btmrvl_debugfs_remove(struct hci_dev *hdev);
|
||||
#endif
|
624
drivers/bluetooth/btmrvl_main.c
Normal file
624
drivers/bluetooth/btmrvl_main.c
Normal file
@ -0,0 +1,624 @@
|
||||
/**
|
||||
* Marvell Bluetooth driver
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
**/
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#include "btmrvl_drv.h"
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
/*
|
||||
* This function is called by interface specific interrupt handler.
|
||||
* It updates Power Save & Host Sleep states, and wakes up the main
|
||||
* thread.
|
||||
*/
|
||||
void btmrvl_interrupt(struct btmrvl_private *priv)
|
||||
{
|
||||
priv->adapter->ps_state = PS_AWAKE;
|
||||
|
||||
priv->adapter->wakeup_tries = 0;
|
||||
|
||||
priv->adapter->int_count++;
|
||||
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_interrupt);
|
||||
|
||||
void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_event_hdr *hdr = (void *) skb->data;
|
||||
struct hci_ev_cmd_complete *ec;
|
||||
u16 opcode, ocf;
|
||||
|
||||
if (hdr->evt == HCI_EV_CMD_COMPLETE) {
|
||||
ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
|
||||
opcode = __le16_to_cpu(ec->opcode);
|
||||
ocf = hci_opcode_ocf(opcode);
|
||||
if (ocf == BT_CMD_MODULE_CFG_REQ &&
|
||||
priv->btmrvl_dev.sendcmdflag) {
|
||||
priv->btmrvl_dev.sendcmdflag = false;
|
||||
priv->adapter->cmd_complete = true;
|
||||
wake_up_interruptible(&priv->adapter->cmd_wait_q);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_check_evtpkt);
|
||||
|
||||
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct btmrvl_adapter *adapter = priv->adapter;
|
||||
struct btmrvl_event *event;
|
||||
u8 ret = 0;
|
||||
|
||||
event = (struct btmrvl_event *) skb->data;
|
||||
if (event->ec != 0xff) {
|
||||
BT_DBG("Not Marvell Event=%x", event->ec);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (event->data[0]) {
|
||||
case BT_CMD_AUTO_SLEEP_MODE:
|
||||
if (!event->data[2]) {
|
||||
if (event->data[1] == BT_PS_ENABLE)
|
||||
adapter->psmode = 1;
|
||||
else
|
||||
adapter->psmode = 0;
|
||||
BT_DBG("PS Mode:%s",
|
||||
(adapter->psmode) ? "Enable" : "Disable");
|
||||
} else {
|
||||
BT_DBG("PS Mode command failed");
|
||||
}
|
||||
break;
|
||||
|
||||
case BT_CMD_HOST_SLEEP_CONFIG:
|
||||
if (!event->data[3])
|
||||
BT_DBG("gpio=%x, gap=%x", event->data[1],
|
||||
event->data[2]);
|
||||
else
|
||||
BT_DBG("HSCFG command failed");
|
||||
break;
|
||||
|
||||
case BT_CMD_HOST_SLEEP_ENABLE:
|
||||
if (!event->data[1]) {
|
||||
adapter->hs_state = HS_ACTIVATED;
|
||||
if (adapter->psmode)
|
||||
adapter->ps_state = PS_SLEEP;
|
||||
wake_up_interruptible(&adapter->cmd_wait_q);
|
||||
BT_DBG("HS ACTIVATED!");
|
||||
} else {
|
||||
BT_DBG("HS Enable failed");
|
||||
}
|
||||
break;
|
||||
|
||||
case BT_CMD_MODULE_CFG_REQ:
|
||||
if (priv->btmrvl_dev.sendcmdflag &&
|
||||
event->data[1] == MODULE_BRINGUP_REQ) {
|
||||
BT_DBG("EVENT:%s", (event->data[2]) ?
|
||||
"Bring-up failed" : "Bring-up succeed");
|
||||
} else if (priv->btmrvl_dev.sendcmdflag &&
|
||||
event->data[1] == MODULE_SHUTDOWN_REQ) {
|
||||
BT_DBG("EVENT:%s", (event->data[2]) ?
|
||||
"Shutdown failed" : "Shutdown succeed");
|
||||
} else {
|
||||
BT_DBG("BT_CMD_MODULE_CFG_REQ resp for APP");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
break;
|
||||
|
||||
case BT_EVENT_POWER_STATE:
|
||||
if (event->data[1] == BT_PS_SLEEP)
|
||||
adapter->ps_state = PS_SLEEP;
|
||||
BT_DBG("EVENT:%s",
|
||||
(adapter->ps_state) ? "PS_SLEEP" : "PS_AWAKE");
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("Unknown Event=%d", event->data[0]);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (!ret)
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_process_event);
|
||||
|
||||
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
int ret = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_MODULE_CFG_REQ));
|
||||
cmd->length = 1;
|
||||
cmd->data[0] = subcmd;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
priv->btmrvl_dev.sendcmdflag = true;
|
||||
|
||||
priv->adapter->cmd_complete = false;
|
||||
|
||||
BT_DBG("Queue module cfg Command");
|
||||
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
|
||||
if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
|
||||
priv->adapter->cmd_complete,
|
||||
msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
|
||||
ret = -ETIMEDOUT;
|
||||
BT_ERR("module_cfg_cmd(%x): timeout: %d",
|
||||
subcmd, priv->btmrvl_dev.sendcmdflag);
|
||||
}
|
||||
|
||||
BT_DBG("module cfg Command done");
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
|
||||
|
||||
static int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct btmrvl_cmd *cmd;
|
||||
int ret = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_ENABLE));
|
||||
cmd->length = 0;
|
||||
|
||||
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 hs enable Command");
|
||||
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
|
||||
if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
|
||||
priv->adapter->hs_state,
|
||||
msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED))) {
|
||||
ret = -ETIMEDOUT;
|
||||
BT_ERR("timeout: %d, %d,%d", priv->adapter->hs_state,
|
||||
priv->adapter->ps_state,
|
||||
priv->adapter->wakeup_tries);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct btmrvl_cmd *cmd;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->btmrvl_dev.hscfgcmd) {
|
||||
priv->btmrvl_dev.hscfgcmd = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG));
|
||||
cmd->length = 2;
|
||||
cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8;
|
||||
cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff);
|
||||
|
||||
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 HSCFG Command, gpio=0x%x, gap=0x%x",
|
||||
cmd->data[0], cmd->data[1]);
|
||||
}
|
||||
|
||||
if (priv->btmrvl_dev.pscmd) {
|
||||
priv->btmrvl_dev.pscmd = 0;
|
||||
|
||||
skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd));
|
||||
cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_AUTO_SLEEP_MODE));
|
||||
cmd->length = 1;
|
||||
|
||||
if (priv->btmrvl_dev.psmode)
|
||||
cmd->data[0] = BT_PS_ENABLE;
|
||||
else
|
||||
cmd->data[0] = BT_PS_DISABLE;
|
||||
|
||||
bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
|
||||
|
||||
skb->dev = (void *) priv->btmrvl_dev.hcidev;
|
||||
skb_queue_head(&priv->adapter->tx_queue, skb);
|
||||
|
||||
BT_DBG("Queue PSMODE Command:%d", cmd->data[0]);
|
||||
}
|
||||
|
||||
if (priv->btmrvl_dev.hscmd) {
|
||||
priv->btmrvl_dev.hscmd = 0;
|
||||
|
||||
if (priv->btmrvl_dev.hsmode) {
|
||||
ret = btmrvl_enable_hs(priv);
|
||||
} else {
|
||||
ret = priv->hw_wakeup_firmware(priv);
|
||||
priv->adapter->hs_state = HS_DEACTIVATED;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!skb || !skb->data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!skb->len || ((skb->len + BTM_HEADER_LEN) > BTM_UPLD_SIZE)) {
|
||||
BT_ERR("Tx Error: Bad skb length %d : %d",
|
||||
skb->len, BTM_UPLD_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb_headroom(skb) < BTM_HEADER_LEN) {
|
||||
struct sk_buff *tmp = skb;
|
||||
|
||||
skb = skb_realloc_headroom(skb, BTM_HEADER_LEN);
|
||||
if (!skb) {
|
||||
BT_ERR("Tx Error: realloc_headroom failed %d",
|
||||
BTM_HEADER_LEN);
|
||||
skb = tmp;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
kfree_skb(tmp);
|
||||
}
|
||||
|
||||
skb_push(skb, BTM_HEADER_LEN);
|
||||
|
||||
/* header type: byte[3]
|
||||
* HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor
|
||||
* header length: byte[2][1][0]
|
||||
*/
|
||||
|
||||
skb->data[0] = (skb->len & 0x0000ff);
|
||||
skb->data[1] = (skb->len & 0x00ff00) >> 8;
|
||||
skb->data[2] = (skb->len & 0xff0000) >> 16;
|
||||
skb->data[3] = bt_cb(skb)->pkt_type;
|
||||
|
||||
if (priv->hw_host_to_card)
|
||||
ret = priv->hw_host_to_card(priv, skb->data, skb->len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void btmrvl_init_adapter(struct btmrvl_private *priv)
|
||||
{
|
||||
skb_queue_head_init(&priv->adapter->tx_queue);
|
||||
|
||||
priv->adapter->ps_state = PS_AWAKE;
|
||||
|
||||
init_waitqueue_head(&priv->adapter->cmd_wait_q);
|
||||
}
|
||||
|
||||
static void btmrvl_free_adapter(struct btmrvl_private *priv)
|
||||
{
|
||||
skb_queue_purge(&priv->adapter->tx_queue);
|
||||
|
||||
kfree(priv->adapter);
|
||||
|
||||
priv->adapter = NULL;
|
||||
}
|
||||
|
||||
static int btmrvl_ioctl(struct hci_dev *hdev,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
static void btmrvl_destruct(struct hci_dev *hdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int btmrvl_send_frame(struct sk_buff *skb)
|
||||
{
|
||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||
struct btmrvl_private *priv = NULL;
|
||||
|
||||
BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len);
|
||||
|
||||
if (!hdev || !hdev->driver_data) {
|
||||
BT_ERR("Frame for unknown HCI device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = (struct btmrvl_private *) hdev->driver_data;
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
|
||||
BT_ERR("Failed testing HCI_RUNING, flags=%lx", hdev->flags);
|
||||
print_hex_dump_bytes("data: ", DUMP_PREFIX_OFFSET,
|
||||
skb->data, skb->len);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
switch (bt_cb(skb)->pkt_type) {
|
||||
case HCI_COMMAND_PKT:
|
||||
hdev->stat.cmd_tx++;
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
hdev->stat.acl_tx++;
|
||||
break;
|
||||
|
||||
case HCI_SCODATA_PKT:
|
||||
hdev->stat.sco_tx++;
|
||||
break;
|
||||
}
|
||||
|
||||
skb_queue_tail(&priv->adapter->tx_queue, skb);
|
||||
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmrvl_flush(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hdev->driver_data;
|
||||
|
||||
skb_queue_purge(&priv->adapter->tx_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmrvl_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hdev->driver_data;
|
||||
|
||||
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
|
||||
skb_queue_purge(&priv->adapter->tx_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmrvl_open(struct hci_dev *hdev)
|
||||
{
|
||||
set_bit(HCI_RUNNING, &hdev->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the event generated by firmware, rx data
|
||||
* received from firmware, and tx data sent from kernel.
|
||||
*/
|
||||
static int btmrvl_service_main_thread(void *data)
|
||||
{
|
||||
struct btmrvl_thread *thread = data;
|
||||
struct btmrvl_private *priv = thread->priv;
|
||||
struct btmrvl_adapter *adapter = priv->adapter;
|
||||
wait_queue_t wait;
|
||||
struct sk_buff *skb;
|
||||
ulong flags;
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
|
||||
current->flags |= PF_NOFREEZE;
|
||||
|
||||
for (;;) {
|
||||
add_wait_queue(&thread->wait_q, &wait);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (adapter->wakeup_tries ||
|
||||
((!adapter->int_count) &&
|
||||
(!priv->btmrvl_dev.tx_dnld_rdy ||
|
||||
skb_queue_empty(&adapter->tx_queue)))) {
|
||||
BT_DBG("main_thread is sleeping...");
|
||||
schedule();
|
||||
}
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
remove_wait_queue(&thread->wait_q, &wait);
|
||||
|
||||
BT_DBG("main_thread woke up");
|
||||
|
||||
if (kthread_should_stop()) {
|
||||
BT_DBG("main_thread: break from main thread");
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (adapter->int_count) {
|
||||
adapter->int_count = 0;
|
||||
} else if (adapter->ps_state == PS_SLEEP &&
|
||||
!skb_queue_empty(&adapter->tx_queue)) {
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
adapter->wakeup_tries++;
|
||||
priv->hw_wakeup_firmware(priv);
|
||||
continue;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
if (adapter->ps_state == PS_SLEEP)
|
||||
continue;
|
||||
|
||||
if (!priv->btmrvl_dev.tx_dnld_rdy)
|
||||
continue;
|
||||
|
||||
skb = skb_dequeue(&adapter->tx_queue);
|
||||
if (skb) {
|
||||
if (btmrvl_tx_pkt(priv, skb))
|
||||
priv->btmrvl_dev.hcidev->stat.err_tx++;
|
||||
else
|
||||
priv->btmrvl_dev.hcidev->stat.byte_tx += skb->len;
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct btmrvl_private *btmrvl_add_card(void *card)
|
||||
{
|
||||
struct hci_dev *hdev = NULL;
|
||||
struct btmrvl_private *priv;
|
||||
int ret;
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
BT_ERR("Can not allocate priv");
|
||||
goto err_priv;
|
||||
}
|
||||
|
||||
priv->adapter = kzalloc(sizeof(*priv->adapter), GFP_KERNEL);
|
||||
if (!priv->adapter) {
|
||||
BT_ERR("Allocate buffer for btmrvl_adapter failed!");
|
||||
goto err_adapter;
|
||||
}
|
||||
|
||||
btmrvl_init_adapter(priv);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
BT_ERR("Can not allocate HCI device");
|
||||
goto err_hdev;
|
||||
}
|
||||
|
||||
BT_DBG("Starting kthread...");
|
||||
priv->main_thread.priv = priv;
|
||||
spin_lock_init(&priv->driver_lock);
|
||||
|
||||
init_waitqueue_head(&priv->main_thread.wait_q);
|
||||
priv->main_thread.task = kthread_run(btmrvl_service_main_thread,
|
||||
&priv->main_thread, "btmrvl_main_service");
|
||||
|
||||
priv->btmrvl_dev.hcidev = hdev;
|
||||
priv->btmrvl_dev.card = card;
|
||||
|
||||
hdev->driver_data = priv;
|
||||
|
||||
priv->btmrvl_dev.tx_dnld_rdy = true;
|
||||
|
||||
hdev->type = HCI_SDIO;
|
||||
hdev->open = btmrvl_open;
|
||||
hdev->close = btmrvl_close;
|
||||
hdev->flush = btmrvl_flush;
|
||||
hdev->send = btmrvl_send_frame;
|
||||
hdev->destruct = btmrvl_destruct;
|
||||
hdev->ioctl = btmrvl_ioctl;
|
||||
hdev->owner = THIS_MODULE;
|
||||
|
||||
ret = hci_register_dev(hdev);
|
||||
if (ret < 0) {
|
||||
BT_ERR("Can not register HCI device");
|
||||
goto err_hci_register_dev;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
btmrvl_debugfs_init(hdev);
|
||||
#endif
|
||||
|
||||
return priv;
|
||||
|
||||
err_hci_register_dev:
|
||||
/* Stop the thread servicing the interrupts */
|
||||
kthread_stop(priv->main_thread.task);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
|
||||
err_hdev:
|
||||
btmrvl_free_adapter(priv);
|
||||
|
||||
err_adapter:
|
||||
kfree(priv);
|
||||
|
||||
err_priv:
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_add_card);
|
||||
|
||||
int btmrvl_remove_card(struct btmrvl_private *priv)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
|
||||
hdev = priv->btmrvl_dev.hcidev;
|
||||
|
||||
wake_up_interruptible(&priv->adapter->cmd_wait_q);
|
||||
|
||||
kthread_stop(priv->main_thread.task);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
btmrvl_debugfs_remove(hdev);
|
||||
#endif
|
||||
|
||||
hci_unregister_dev(hdev);
|
||||
|
||||
hci_free_dev(hdev);
|
||||
|
||||
priv->btmrvl_dev.hcidev = NULL;
|
||||
|
||||
btmrvl_free_adapter(priv);
|
||||
|
||||
kfree(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_remove_card);
|
||||
|
||||
MODULE_AUTHOR("Marvell International Ltd.");
|
||||
MODULE_DESCRIPTION("Marvell Bluetooth driver ver " VERSION);
|
||||
MODULE_VERSION(VERSION);
|
||||
MODULE_LICENSE("GPL v2");
|
1003
drivers/bluetooth/btmrvl_sdio.c
Normal file
1003
drivers/bluetooth/btmrvl_sdio.c
Normal file
File diff suppressed because it is too large
Load Diff
108
drivers/bluetooth/btmrvl_sdio.h
Normal file
108
drivers/bluetooth/btmrvl_sdio.h
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Marvell BT-over-SDIO driver: SDIO interface related definitions
|
||||
*
|
||||
* Copyright (C) 2009, Marvell International Ltd.
|
||||
*
|
||||
* This software file (the "File") is distributed by Marvell International
|
||||
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
|
||||
* (the "License"). You may use, redistribute and/or modify this File in
|
||||
* accordance with the terms and conditions of the License, a copy of which
|
||||
* is available by writing to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
|
||||
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
*
|
||||
*
|
||||
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
|
||||
* this warranty disclaimer.
|
||||
*
|
||||
**/
|
||||
|
||||
#define SDIO_HEADER_LEN 4
|
||||
|
||||
/* SD block size can not bigger than 64 due to buf size limit in firmware */
|
||||
/* define SD block size for data Tx/Rx */
|
||||
#define SDIO_BLOCK_SIZE 64
|
||||
|
||||
/* Number of blocks for firmware transfer */
|
||||
#define FIRMWARE_TRANSFER_NBLOCK 2
|
||||
|
||||
/* This is for firmware specific length */
|
||||
#define FW_EXTRA_LEN 36
|
||||
|
||||
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
|
||||
|
||||
#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
|
||||
(HCI_MAX_FRAME_SIZE + FW_EXTRA_LEN)
|
||||
|
||||
#define ALLOC_BUF_SIZE (((max_t (int, MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
|
||||
MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
|
||||
+ SDIO_BLOCK_SIZE - 1) / SDIO_BLOCK_SIZE) \
|
||||
* SDIO_BLOCK_SIZE)
|
||||
|
||||
/* The number of times to try when polling for status */
|
||||
#define MAX_POLL_TRIES 100
|
||||
|
||||
/* Max retry number of CMD53 write */
|
||||
#define MAX_WRITE_IOMEM_RETRY 2
|
||||
|
||||
/* Host Control Registers */
|
||||
#define IO_PORT_0_REG 0x00
|
||||
#define IO_PORT_1_REG 0x01
|
||||
#define IO_PORT_2_REG 0x02
|
||||
|
||||
#define CONFIG_REG 0x03
|
||||
#define HOST_POWER_UP BIT(1)
|
||||
#define HOST_CMD53_FIN BIT(2)
|
||||
|
||||
#define HOST_INT_MASK_REG 0x04
|
||||
#define HIM_DISABLE 0xff
|
||||
#define HIM_ENABLE (BIT(0) | BIT(1))
|
||||
|
||||
#define HOST_INTSTATUS_REG 0x05
|
||||
#define UP_LD_HOST_INT_STATUS BIT(0)
|
||||
#define DN_LD_HOST_INT_STATUS BIT(1)
|
||||
|
||||
/* Card Control Registers */
|
||||
#define SQ_READ_BASE_ADDRESS_A0_REG 0x10
|
||||
#define SQ_READ_BASE_ADDRESS_A1_REG 0x11
|
||||
|
||||
#define CARD_STATUS_REG 0x20
|
||||
#define DN_LD_CARD_RDY BIT(0)
|
||||
#define CARD_IO_READY BIT(3)
|
||||
|
||||
#define CARD_FW_STATUS0_REG 0x40
|
||||
#define CARD_FW_STATUS1_REG 0x41
|
||||
#define FIRMWARE_READY 0xfedc
|
||||
|
||||
#define CARD_RX_LEN_REG 0x42
|
||||
#define CARD_RX_UNIT_REG 0x43
|
||||
|
||||
|
||||
struct btmrvl_sdio_card {
|
||||
struct sdio_func *func;
|
||||
u32 ioport;
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
u8 rx_unit;
|
||||
struct btmrvl_private *priv;
|
||||
};
|
||||
|
||||
struct btmrvl_sdio_device {
|
||||
const char *helper;
|
||||
const char *firmware;
|
||||
};
|
||||
|
||||
|
||||
/* Platform specific DMA alignment */
|
||||
#define BTSDIO_DMA_ALIGN 8
|
||||
|
||||
/* Macros for Data Alignment : size */
|
||||
#define ALIGN_SZ(p, a) \
|
||||
(((p) + ((a) - 1)) & ~((a) - 1))
|
||||
|
||||
/* Macros for Data Alignment : address */
|
||||
#define ALIGN_ADDR(p, a) \
|
||||
((((unsigned long)(p)) + (((unsigned long)(a)) - 1)) & \
|
||||
~(((unsigned long)(a)) - 1))
|
@ -35,7 +35,7 @@
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
|
||||
#define VERSION "0.5"
|
||||
#define VERSION "0.6"
|
||||
|
||||
static int ignore_dga;
|
||||
static int ignore_csr;
|
||||
@ -145,6 +145,7 @@ static struct usb_device_id blacklist_table[] = {
|
||||
#define BTUSB_INTR_RUNNING 0
|
||||
#define BTUSB_BULK_RUNNING 1
|
||||
#define BTUSB_ISOC_RUNNING 2
|
||||
#define BTUSB_SUSPENDING 3
|
||||
|
||||
struct btusb_data {
|
||||
struct hci_dev *hdev;
|
||||
@ -157,11 +158,15 @@ struct btusb_data {
|
||||
unsigned long flags;
|
||||
|
||||
struct work_struct work;
|
||||
struct work_struct waker;
|
||||
|
||||
struct usb_anchor tx_anchor;
|
||||
struct usb_anchor intr_anchor;
|
||||
struct usb_anchor bulk_anchor;
|
||||
struct usb_anchor isoc_anchor;
|
||||
struct usb_anchor deferred;
|
||||
int tx_in_flight;
|
||||
spinlock_t txlock;
|
||||
|
||||
struct usb_endpoint_descriptor *intr_ep;
|
||||
struct usb_endpoint_descriptor *bulk_tx_ep;
|
||||
@ -174,8 +179,23 @@ struct btusb_data {
|
||||
unsigned int sco_num;
|
||||
int isoc_altsetting;
|
||||
int suspend_count;
|
||||
int did_iso_resume:1;
|
||||
};
|
||||
|
||||
static int inc_tx(struct btusb_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
int rv;
|
||||
|
||||
spin_lock_irqsave(&data->txlock, flags);
|
||||
rv = test_bit(BTUSB_SUSPENDING, &data->flags);
|
||||
if (!rv)
|
||||
data->tx_in_flight++;
|
||||
spin_unlock_irqrestore(&data->txlock, flags);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void btusb_intr_complete(struct urb *urb)
|
||||
{
|
||||
struct hci_dev *hdev = urb->context;
|
||||
@ -202,6 +222,7 @@ static void btusb_intr_complete(struct urb *urb)
|
||||
if (!test_bit(BTUSB_INTR_RUNNING, &data->flags))
|
||||
return;
|
||||
|
||||
usb_mark_last_busy(data->udev);
|
||||
usb_anchor_urb(urb, &data->intr_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
@ -301,7 +322,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||
struct urb *urb;
|
||||
unsigned char *buf;
|
||||
unsigned int pipe;
|
||||
int err, size;
|
||||
int err, size = HCI_MAX_FRAME_SIZE;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
@ -312,8 +333,6 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||
if (!urb)
|
||||
return -ENOMEM;
|
||||
|
||||
size = le16_to_cpu(data->bulk_rx_ep->wMaxPacketSize);
|
||||
|
||||
buf = kmalloc(size, mem_flags);
|
||||
if (!buf) {
|
||||
usb_free_urb(urb);
|
||||
@ -327,6 +346,7 @@ static int btusb_submit_bulk_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||
|
||||
urb->transfer_flags |= URB_FREE_BUFFER;
|
||||
|
||||
usb_mark_last_busy(data->udev);
|
||||
usb_anchor_urb(urb, &data->bulk_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, mem_flags);
|
||||
@ -462,6 +482,33 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
|
||||
}
|
||||
|
||||
static void btusb_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
|
||||
BT_DBG("%s urb %p status %d count %d", hdev->name,
|
||||
urb, urb->status, urb->actual_length);
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
goto done;
|
||||
|
||||
if (!urb->status)
|
||||
hdev->stat.byte_tx += urb->transfer_buffer_length;
|
||||
else
|
||||
hdev->stat.err_tx++;
|
||||
|
||||
done:
|
||||
spin_lock(&data->txlock);
|
||||
data->tx_in_flight--;
|
||||
spin_unlock(&data->txlock);
|
||||
|
||||
kfree(urb->setup_packet);
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void btusb_isoc_tx_complete(struct urb *urb)
|
||||
{
|
||||
struct sk_buff *skb = urb->context;
|
||||
struct hci_dev *hdev = (struct hci_dev *) skb->dev;
|
||||
@ -490,11 +537,17 @@ static int btusb_open(struct hci_dev *hdev)
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
data->intf->needs_remote_wakeup = 1;
|
||||
|
||||
if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
if (test_and_set_bit(BTUSB_INTR_RUNNING, &data->flags))
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
err = btusb_submit_intr_urb(hdev, GFP_KERNEL);
|
||||
if (err < 0)
|
||||
@ -509,17 +562,28 @@ static int btusb_open(struct hci_dev *hdev)
|
||||
set_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
btusb_submit_bulk_urb(hdev, GFP_KERNEL);
|
||||
|
||||
done:
|
||||
usb_autopm_put_interface(data->intf);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
clear_bit(HCI_RUNNING, &hdev->flags);
|
||||
usb_autopm_put_interface(data->intf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void btusb_stop_traffic(struct btusb_data *data)
|
||||
{
|
||||
usb_kill_anchored_urbs(&data->intr_anchor);
|
||||
usb_kill_anchored_urbs(&data->bulk_anchor);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
}
|
||||
|
||||
static int btusb_close(struct hci_dev *hdev)
|
||||
{
|
||||
struct btusb_data *data = hdev->driver_data;
|
||||
int err;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
@ -529,13 +593,16 @@ static int btusb_close(struct hci_dev *hdev)
|
||||
cancel_work_sync(&data->work);
|
||||
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->bulk_anchor);
|
||||
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->intr_anchor);
|
||||
|
||||
btusb_stop_traffic(data);
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err < 0)
|
||||
return 0;
|
||||
|
||||
data->intf->needs_remote_wakeup = 0;
|
||||
usb_autopm_put_interface(data->intf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -622,7 +689,7 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
urb->dev = data->udev;
|
||||
urb->pipe = pipe;
|
||||
urb->context = skb;
|
||||
urb->complete = btusb_tx_complete;
|
||||
urb->complete = btusb_isoc_tx_complete;
|
||||
urb->interval = data->isoc_tx_ep->bInterval;
|
||||
|
||||
urb->transfer_flags = URB_ISO_ASAP;
|
||||
@ -633,12 +700,21 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
|
||||
|
||||
hdev->stat.sco_tx++;
|
||||
break;
|
||||
goto skip_waking;
|
||||
|
||||
default:
|
||||
return -EILSEQ;
|
||||
}
|
||||
|
||||
err = inc_tx(data);
|
||||
if (err) {
|
||||
usb_anchor_urb(urb, &data->deferred);
|
||||
schedule_work(&data->waker);
|
||||
err = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
skip_waking:
|
||||
usb_anchor_urb(urb, &data->tx_anchor);
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
@ -646,10 +722,13 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
BT_ERR("%s urb %p submission failed", hdev->name, urb);
|
||||
kfree(urb->setup_packet);
|
||||
usb_unanchor_urb(urb);
|
||||
} else {
|
||||
usb_mark_last_busy(data->udev);
|
||||
}
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -721,8 +800,19 @@ static void btusb_work(struct work_struct *work)
|
||||
{
|
||||
struct btusb_data *data = container_of(work, struct btusb_data, work);
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
int err;
|
||||
|
||||
if (hdev->conn_hash.sco_num > 0) {
|
||||
if (!data->did_iso_resume) {
|
||||
err = usb_autopm_get_interface(data->isoc);
|
||||
if (err < 0) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
data->did_iso_resume = 1;
|
||||
}
|
||||
if (data->isoc_altsetting != 2) {
|
||||
clear_bit(BTUSB_ISOC_RUNNING, &data->flags);
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
@ -742,9 +832,25 @@ static void btusb_work(struct work_struct *work)
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
|
||||
__set_isoc_interface(hdev, 0);
|
||||
if (data->did_iso_resume) {
|
||||
data->did_iso_resume = 0;
|
||||
usb_autopm_put_interface(data->isoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void btusb_waker(struct work_struct *work)
|
||||
{
|
||||
struct btusb_data *data = container_of(work, struct btusb_data, waker);
|
||||
int err;
|
||||
|
||||
err = usb_autopm_get_interface(data->intf);
|
||||
if (err < 0)
|
||||
return;
|
||||
|
||||
usb_autopm_put_interface(data->intf);
|
||||
}
|
||||
|
||||
static int btusb_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
@ -814,11 +920,14 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
spin_lock_init(&data->lock);
|
||||
|
||||
INIT_WORK(&data->work, btusb_work);
|
||||
INIT_WORK(&data->waker, btusb_waker);
|
||||
spin_lock_init(&data->txlock);
|
||||
|
||||
init_usb_anchor(&data->tx_anchor);
|
||||
init_usb_anchor(&data->intr_anchor);
|
||||
init_usb_anchor(&data->bulk_anchor);
|
||||
init_usb_anchor(&data->isoc_anchor);
|
||||
init_usb_anchor(&data->deferred);
|
||||
|
||||
hdev = hci_alloc_dev();
|
||||
if (!hdev) {
|
||||
@ -943,6 +1052,7 @@ static void btusb_disconnect(struct usb_interface *intf)
|
||||
hci_free_dev(hdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
{
|
||||
struct btusb_data *data = usb_get_intfdata(intf);
|
||||
@ -952,22 +1062,44 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
if (data->suspend_count++)
|
||||
return 0;
|
||||
|
||||
spin_lock_irq(&data->txlock);
|
||||
if (!(interface_to_usbdev(intf)->auto_pm && data->tx_in_flight)) {
|
||||
set_bit(BTUSB_SUSPENDING, &data->flags);
|
||||
spin_unlock_irq(&data->txlock);
|
||||
} else {
|
||||
spin_unlock_irq(&data->txlock);
|
||||
data->suspend_count--;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
cancel_work_sync(&data->work);
|
||||
|
||||
btusb_stop_traffic(data);
|
||||
usb_kill_anchored_urbs(&data->tx_anchor);
|
||||
|
||||
usb_kill_anchored_urbs(&data->isoc_anchor);
|
||||
usb_kill_anchored_urbs(&data->bulk_anchor);
|
||||
usb_kill_anchored_urbs(&data->intr_anchor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void play_deferred(struct btusb_data *data)
|
||||
{
|
||||
struct urb *urb;
|
||||
int err;
|
||||
|
||||
while ((urb = usb_get_from_anchor(&data->deferred))) {
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (err < 0)
|
||||
break;
|
||||
|
||||
data->tx_in_flight++;
|
||||
}
|
||||
usb_scuttle_anchored_urbs(&data->deferred);
|
||||
}
|
||||
|
||||
static int btusb_resume(struct usb_interface *intf)
|
||||
{
|
||||
struct btusb_data *data = usb_get_intfdata(intf);
|
||||
struct hci_dev *hdev = data->hdev;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
BT_DBG("intf %p", intf);
|
||||
|
||||
@ -975,13 +1107,13 @@ static int btusb_resume(struct usb_interface *intf)
|
||||
return 0;
|
||||
|
||||
if (!test_bit(HCI_RUNNING, &hdev->flags))
|
||||
return 0;
|
||||
goto done;
|
||||
|
||||
if (test_bit(BTUSB_INTR_RUNNING, &data->flags)) {
|
||||
err = btusb_submit_intr_urb(hdev, GFP_NOIO);
|
||||
if (err < 0) {
|
||||
clear_bit(BTUSB_INTR_RUNNING, &data->flags);
|
||||
return err;
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
@ -989,9 +1121,10 @@ static int btusb_resume(struct usb_interface *intf)
|
||||
err = btusb_submit_bulk_urb(hdev, GFP_NOIO);
|
||||
if (err < 0) {
|
||||
clear_bit(BTUSB_BULK_RUNNING, &data->flags);
|
||||
return err;
|
||||
} else
|
||||
btusb_submit_bulk_urb(hdev, GFP_NOIO);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
btusb_submit_bulk_urb(hdev, GFP_NOIO);
|
||||
}
|
||||
|
||||
if (test_bit(BTUSB_ISOC_RUNNING, &data->flags)) {
|
||||
@ -1001,16 +1134,35 @@ static int btusb_resume(struct usb_interface *intf)
|
||||
btusb_submit_isoc_urb(hdev, GFP_NOIO);
|
||||
}
|
||||
|
||||
spin_lock_irq(&data->txlock);
|
||||
play_deferred(data);
|
||||
clear_bit(BTUSB_SUSPENDING, &data->flags);
|
||||
spin_unlock_irq(&data->txlock);
|
||||
schedule_work(&data->work);
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
usb_scuttle_anchored_urbs(&data->deferred);
|
||||
done:
|
||||
spin_lock_irq(&data->txlock);
|
||||
clear_bit(BTUSB_SUSPENDING, &data->flags);
|
||||
spin_unlock_irq(&data->txlock);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct usb_driver btusb_driver = {
|
||||
.name = "btusb",
|
||||
.probe = btusb_probe,
|
||||
.disconnect = btusb_disconnect,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = btusb_suspend,
|
||||
.resume = btusb_resume,
|
||||
#endif
|
||||
.id_table = btusb_table,
|
||||
.supports_autosuspend = 1,
|
||||
};
|
||||
|
||||
static int __init btusb_init(void)
|
||||
|
@ -373,8 +373,9 @@ static void bcsp_pkt_cull(struct bcsp_struct *bcsp)
|
||||
|
||||
i = 0;
|
||||
skb_queue_walk_safe(&bcsp->unack, skb, tmp) {
|
||||
if (i++ >= pkts_to_be_removed)
|
||||
if (i >= pkts_to_be_removed)
|
||||
break;
|
||||
i++;
|
||||
|
||||
__skb_unlink(skb, &bcsp->unack);
|
||||
kfree_skb(skb);
|
||||
|
@ -4005,10 +4005,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
|
||||
*
|
||||
* skb socket buffer containing HDLC frame
|
||||
* dev pointer to network device structure
|
||||
*
|
||||
* returns 0 if success, otherwise error code
|
||||
*/
|
||||
static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
MGSLPC_INFO *info = dev_to_port(dev);
|
||||
unsigned long flags;
|
||||
@ -4043,7 +4042,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7697,10 +7697,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
|
||||
*
|
||||
* skb socket buffer containing HDLC frame
|
||||
* dev pointer to network device structure
|
||||
*
|
||||
* returns 0 if success, otherwise error code
|
||||
*/
|
||||
static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct mgsl_struct *info = dev_to_port(dev);
|
||||
unsigned long flags;
|
||||
@ -7731,7 +7730,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
usc_start_transmitter(info);
|
||||
spin_unlock_irqrestore(&info->irq_spinlock,flags);
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1497,10 +1497,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
|
||||
*
|
||||
* skb socket buffer containing HDLC frame
|
||||
* dev pointer to network device structure
|
||||
*
|
||||
* returns 0 if success, otherwise error code
|
||||
*/
|
||||
static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct slgt_info *info = dev_to_port(dev);
|
||||
unsigned long flags;
|
||||
@ -1529,7 +1528,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
update_tx_timer(info);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1608,10 +1608,9 @@ static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
|
||||
*
|
||||
* skb socket buffer containing HDLC frame
|
||||
* dev pointer to network device structure
|
||||
*
|
||||
* returns 0 if success, otherwise error code
|
||||
*/
|
||||
static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
SLMP_INFO *info = dev_to_port(dev);
|
||||
unsigned long flags;
|
||||
@ -1642,7 +1641,7 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
tx_start(info);
|
||||
spin_unlock_irqrestore(&info->lock,flags);
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -202,9 +202,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
|
||||
* cn_proc_mcast_ctl
|
||||
* @data: message sent from userspace via the connector
|
||||
*/
|
||||
static void cn_proc_mcast_ctl(void *data)
|
||||
static void cn_proc_mcast_ctl(struct cn_msg *msg)
|
||||
{
|
||||
struct cn_msg *msg = data;
|
||||
enum proc_cn_mcast_op *mc_op = NULL;
|
||||
int err = 0;
|
||||
|
||||
|
@ -87,7 +87,9 @@ void cn_queue_wrapper(struct work_struct *work)
|
||||
kfree(d->free);
|
||||
}
|
||||
|
||||
static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *))
|
||||
static struct cn_callback_entry *
|
||||
cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
|
||||
void (*callback)(struct cn_msg *))
|
||||
{
|
||||
struct cn_callback_entry *cbq;
|
||||
|
||||
@ -120,7 +122,8 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
|
||||
return ((i1->idx == i2->idx) && (i1->val == i2->val));
|
||||
}
|
||||
|
||||
int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *))
|
||||
int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
|
||||
void (*callback)(struct cn_msg *))
|
||||
{
|
||||
struct cn_callback_entry *cbq, *__cbq;
|
||||
int found = 0;
|
||||
|
@ -269,7 +269,8 @@ static void cn_notify(struct cb_id *id, u32 notify_event)
|
||||
*
|
||||
* May sleep.
|
||||
*/
|
||||
int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *))
|
||||
int cn_add_callback(struct cb_id *id, char *name,
|
||||
void (*callback)(struct cn_msg *))
|
||||
{
|
||||
int err;
|
||||
struct cn_dev *dev = &cdev;
|
||||
@ -351,9 +352,8 @@ static int cn_ctl_msg_equals(struct cn_ctl_msg *m1, struct cn_ctl_msg *m2)
|
||||
*
|
||||
* Used for notification of a request's processing.
|
||||
*/
|
||||
static void cn_callback(void *data)
|
||||
static void cn_callback(struct cn_msg *msg)
|
||||
{
|
||||
struct cn_msg *msg = data;
|
||||
struct cn_ctl_msg *ctl;
|
||||
struct cn_ctl_entry *ent;
|
||||
u32 size;
|
||||
|
@ -663,8 +663,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
||||
if (netif_queue_stopped(net))
|
||||
netif_wake_queue(net);
|
||||
|
||||
net->last_rx = jiffies;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1188,7 +1186,7 @@ static int fwnet_stop(struct net_device *net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
||||
static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
||||
{
|
||||
struct fwnet_header hdr_buf;
|
||||
struct fwnet_device *dev = netdev_priv(net);
|
||||
@ -1342,7 +1340,7 @@ static void fwnet_get_drvinfo(struct net_device *net,
|
||||
strcpy(info->bus_info, "ieee1394");
|
||||
}
|
||||
|
||||
static struct ethtool_ops fwnet_ethtool_ops = {
|
||||
static const struct ethtool_ops fwnet_ethtool_ops = {
|
||||
.get_drvinfo = fwnet_get_drvinfo,
|
||||
};
|
||||
|
||||
|
@ -169,10 +169,11 @@ static int ether1394_header_cache(const struct neighbour *neigh,
|
||||
static void ether1394_header_cache_update(struct hh_cache *hh,
|
||||
const struct net_device *dev,
|
||||
const unsigned char *haddr);
|
||||
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
|
||||
static netdev_tx_t ether1394_tx(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
static void ether1394_iso(struct hpsb_iso *iso);
|
||||
|
||||
static struct ethtool_ops ethtool_ops;
|
||||
static const struct ethtool_ops ethtool_ops;
|
||||
|
||||
static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
|
||||
quadlet_t *data, u64 addr, size_t len, u16 flags);
|
||||
@ -1300,7 +1301,6 @@ static void ether1394_iso(struct hpsb_iso *iso)
|
||||
|
||||
hpsb_iso_recv_release_packets(iso, i);
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
@ -1555,7 +1555,8 @@ static void ether1394_complete_cb(void *__ptask)
|
||||
}
|
||||
|
||||
/* Transmit a packet (called by kernel) */
|
||||
static int ether1394_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t ether1394_tx(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct eth1394hdr hdr_buf;
|
||||
struct eth1394_priv *priv = netdev_priv(dev);
|
||||
@ -1694,14 +1695,6 @@ fail:
|
||||
dev->stats.tx_errors++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/*
|
||||
* FIXME: According to a patch from 2003-02-26, "returning non-zero
|
||||
* causes serious problems" here, allegedly. Before that patch,
|
||||
* -ERRNO was returned which is not appropriate under Linux 2.6.
|
||||
* Perhaps more needs to be done? Stop the queue in serious
|
||||
* conditions and restart it elsewhere?
|
||||
*/
|
||||
/* return NETDEV_TX_BUSY; */
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
@ -1712,7 +1705,7 @@ static void ether1394_get_drvinfo(struct net_device *dev,
|
||||
strcpy(info->bus_info, "ieee1394"); /* FIXME provide more detail? */
|
||||
}
|
||||
|
||||
static struct ethtool_ops ethtool_ops = {
|
||||
static const struct ethtool_ops ethtool_ops = {
|
||||
.get_drvinfo = ether1394_get_drvinfo
|
||||
};
|
||||
|
||||
|
@ -26,11 +26,23 @@
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
|
||||
#include <net/ieee802154/af_ieee802154.h>
|
||||
#include <net/ieee802154/netdevice.h>
|
||||
#include <net/ieee802154/mac_def.h>
|
||||
#include <net/ieee802154/nl802154.h>
|
||||
#include <net/af_ieee802154.h>
|
||||
#include <net/ieee802154_netdev.h>
|
||||
#include <net/ieee802154.h>
|
||||
#include <net/nl802154.h>
|
||||
#include <net/wpan-phy.h>
|
||||
|
||||
struct wpan_phy *net_to_phy(struct net_device *dev)
|
||||
{
|
||||
return container_of(dev->dev.parent, struct wpan_phy, dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_get_pan_id - Retrieve the PAN ID of the device.
|
||||
* @dev: The network device to retrieve the PAN of.
|
||||
*
|
||||
* Return the ID of the PAN from the PIB.
|
||||
*/
|
||||
static u16 fake_get_pan_id(struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
@ -38,6 +50,14 @@ static u16 fake_get_pan_id(struct net_device *dev)
|
||||
return 0xeba1;
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_get_short_addr - Retrieve the short address of the device.
|
||||
* @dev: The network device to retrieve the short address of.
|
||||
*
|
||||
* Returns the IEEE 802.15.4 short-form address cached for this
|
||||
* device. If the device has not yet had a short address assigned
|
||||
* then this should return 0xFFFF to indicate a lack of association.
|
||||
*/
|
||||
static u16 fake_get_short_addr(struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
@ -45,6 +65,19 @@ static u16 fake_get_short_addr(struct net_device *dev)
|
||||
return 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_get_dsn - Retrieve the DSN of the device.
|
||||
* @dev: The network device to retrieve the DSN for.
|
||||
*
|
||||
* Returns the IEEE 802.15.4 DSN for the network device.
|
||||
* The DSN is the sequence number which will be added to each
|
||||
* packet or MAC command frame by the MAC during transmission.
|
||||
*
|
||||
* DSN means 'Data Sequence Number'.
|
||||
*
|
||||
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||
* document.
|
||||
*/
|
||||
static u8 fake_get_dsn(struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
@ -52,6 +85,19 @@ static u8 fake_get_dsn(struct net_device *dev)
|
||||
return 0x00; /* DSN are implemented in HW, so return just 0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_get_bsn - Retrieve the BSN of the device.
|
||||
* @dev: The network device to retrieve the BSN for.
|
||||
*
|
||||
* Returns the IEEE 802.15.4 BSN for the network device.
|
||||
* The BSN is the sequence number which will be added to each
|
||||
* beacon frame sent by the MAC.
|
||||
*
|
||||
* BSN means 'Beacon Sequence Number'.
|
||||
*
|
||||
* Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
|
||||
* document.
|
||||
*/
|
||||
static u8 fake_get_bsn(struct net_device *dev)
|
||||
{
|
||||
BUG_ON(dev->type != ARPHRD_IEEE802154);
|
||||
@ -59,40 +105,130 @@ static u8 fake_get_bsn(struct net_device *dev)
|
||||
return 0x00; /* BSN are implemented in HW, so return just 0 */
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_assoc_req - Make an association request to the HW.
|
||||
* @dev: The network device which we are associating to a network.
|
||||
* @addr: The coordinator with which we wish to associate.
|
||||
* @channel: The channel on which to associate.
|
||||
* @cap: The capability information field to use in the association.
|
||||
*
|
||||
* Start an association with a coordinator. The coordinator's address
|
||||
* and PAN ID can be found in @addr.
|
||||
*
|
||||
* Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE
|
||||
* 802.15.4-2006 document.
|
||||
*/
|
||||
static int fake_assoc_req(struct net_device *dev,
|
||||
struct ieee802154_addr *addr, u8 channel, u8 cap)
|
||||
struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
|
||||
mutex_lock(&phy->pib_lock);
|
||||
phy->current_channel = channel;
|
||||
phy->current_page = page;
|
||||
mutex_unlock(&phy->pib_lock);
|
||||
|
||||
/* We simply emulate it here */
|
||||
return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
|
||||
IEEE802154_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_assoc_resp - Send an association response to a device.
|
||||
* @dev: The network device on which to send the response.
|
||||
* @addr: The address of the device to respond to.
|
||||
* @short_addr: The assigned short address for the device (if any).
|
||||
* @status: The result of the association request.
|
||||
*
|
||||
* Queue the association response of the coordinator to another
|
||||
* device's attempt to associate with the network which we
|
||||
* coordinate. This is then added to the indirect-send queue to be
|
||||
* transmitted to the end device when it polls for data.
|
||||
*
|
||||
* Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE
|
||||
* 802.15.4-2006 document.
|
||||
*/
|
||||
static int fake_assoc_resp(struct net_device *dev,
|
||||
struct ieee802154_addr *addr, u16 short_addr, u8 status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_disassoc_req - Disassociate a device from a network.
|
||||
* @dev: The network device on which we're disassociating a device.
|
||||
* @addr: The device to disassociate from the network.
|
||||
* @reason: The reason to give to the device for being disassociated.
|
||||
*
|
||||
* This sends a disassociation notification to the device being
|
||||
* disassociated from the network.
|
||||
*
|
||||
* Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006
|
||||
* document, with the reason described in 7.3.3.2.
|
||||
*/
|
||||
static int fake_disassoc_req(struct net_device *dev,
|
||||
struct ieee802154_addr *addr, u8 reason)
|
||||
{
|
||||
return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_start_req - Start an IEEE 802.15.4 PAN.
|
||||
* @dev: The network device on which to start the PAN.
|
||||
* @addr: The coordinator address to use when starting the PAN.
|
||||
* @channel: The channel on which to start the PAN.
|
||||
* @bcn_ord: Beacon order.
|
||||
* @sf_ord: Superframe order.
|
||||
* @pan_coord: Whether or not we are the PAN coordinator or just
|
||||
* requesting a realignment perhaps?
|
||||
* @blx: Battery Life Extension feature bitfield.
|
||||
* @coord_realign: Something to realign something else.
|
||||
*
|
||||
* If pan_coord is non-zero then this starts a network with the
|
||||
* provided parameters, otherwise it attempts a coordinator
|
||||
* realignment of the stated network instead.
|
||||
*
|
||||
* Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
|
||||
* document, with 7.3.8 describing coordinator realignment.
|
||||
*/
|
||||
static int fake_start_req(struct net_device *dev, struct ieee802154_addr *addr,
|
||||
u8 channel,
|
||||
u8 channel, u8 page,
|
||||
u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
|
||||
u8 coord_realign)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
|
||||
mutex_lock(&phy->pib_lock);
|
||||
phy->current_channel = channel;
|
||||
phy->current_page = page;
|
||||
mutex_unlock(&phy->pib_lock);
|
||||
|
||||
/* We don't emulate beacons here at all, so START should fail */
|
||||
ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fake_scan_req - Start a channel scan.
|
||||
* @dev: The network device on which to perform a channel scan.
|
||||
* @type: The type of scan to perform.
|
||||
* @channels: The channel bitmask to scan.
|
||||
* @duration: How long to spend on each channel.
|
||||
*
|
||||
* This starts either a passive (energy) scan or an active (PAN) scan
|
||||
* on the channels indicated in the @channels bitmask. The duration of
|
||||
* the scan is measured in terms of superframe duration. Specifically,
|
||||
* the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each
|
||||
* channel.
|
||||
*
|
||||
* Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document.
|
||||
*/
|
||||
static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
|
||||
u8 duration)
|
||||
u8 page, u8 duration)
|
||||
{
|
||||
u8 edl[27] = {};
|
||||
return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
|
||||
channels,
|
||||
channels, page,
|
||||
type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
|
||||
}
|
||||
|
||||
@ -121,7 +257,8 @@ static int ieee802154_fake_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee802154_fake_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
skb->iif = dev->ifindex;
|
||||
skb->dev = dev;
|
||||
@ -132,7 +269,7 @@ static int ieee802154_fake_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
/* FIXME: do hardware work here ... */
|
||||
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -174,6 +311,14 @@ static const struct net_device_ops fake_ops = {
|
||||
.ndo_set_mac_address = ieee802154_fake_mac_addr,
|
||||
};
|
||||
|
||||
static void ieee802154_fake_destruct(struct net_device *dev)
|
||||
{
|
||||
struct wpan_phy *phy = net_to_phy(dev);
|
||||
|
||||
wpan_phy_unregister(phy);
|
||||
free_netdev(dev);
|
||||
wpan_phy_free(phy);
|
||||
}
|
||||
|
||||
static void ieee802154_fake_setup(struct net_device *dev)
|
||||
{
|
||||
@ -186,22 +331,34 @@ static void ieee802154_fake_setup(struct net_device *dev)
|
||||
dev->type = ARPHRD_IEEE802154;
|
||||
dev->flags = IFF_NOARP | IFF_BROADCAST;
|
||||
dev->watchdog_timeo = 0;
|
||||
dev->destructor = ieee802154_fake_destruct;
|
||||
}
|
||||
|
||||
|
||||
static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *dev =
|
||||
alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup);
|
||||
struct net_device *dev;
|
||||
struct wpan_phy *phy = wpan_phy_alloc(0);
|
||||
int err;
|
||||
|
||||
if (!dev)
|
||||
if (!phy)
|
||||
return -ENOMEM;
|
||||
|
||||
dev = alloc_netdev(0, "hardwpan%d", ieee802154_fake_setup);
|
||||
if (!dev) {
|
||||
wpan_phy_free(phy);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
phy->dev.platform_data = dev;
|
||||
|
||||
memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
|
||||
dev->addr_len);
|
||||
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
|
||||
|
||||
phy->channels_supported = (1 << 27) - 1;
|
||||
phy->transmit_power = 0xbf;
|
||||
|
||||
dev->netdev_ops = &fake_ops;
|
||||
dev->ml_priv = &fake_mlme;
|
||||
|
||||
@ -215,15 +372,18 @@ static int __devinit ieee802154fake_probe(struct platform_device *pdev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
SET_NETDEV_DEV(dev, &pdev->dev);
|
||||
SET_NETDEV_DEV(dev, &phy->dev);
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
err = wpan_phy_register(&pdev->dev, phy);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
|
||||
dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
|
||||
return 0;
|
||||
|
||||
@ -236,7 +396,6 @@ static int __devexit ieee802154fake_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct net_device *dev = platform_get_drvdata(pdev);
|
||||
unregister_netdev(dev);
|
||||
free_netdev(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -526,7 +526,6 @@ static void c2_rx_interrupt(struct net_device *netdev)
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
netdev->last_rx = jiffies;
|
||||
netdev->stats.rx_packets++;
|
||||
netdev->stats.rx_bytes += buflen;
|
||||
}
|
||||
|
@ -2743,7 +2743,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
|
||||
}
|
||||
|
||||
skip_rx_indicate0:
|
||||
nesvnic->netdev->last_rx = jiffies;
|
||||
;
|
||||
/* nesvnic->netstats.rx_packets++; */
|
||||
/* nesvnic->netstats.rx_bytes += rx_pkt_size; */
|
||||
}
|
||||
|
@ -1508,7 +1508,7 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
|
||||
}
|
||||
|
||||
|
||||
static struct ethtool_ops nes_ethtool_ops = {
|
||||
static const struct ethtool_ops nes_ethtool_ops = {
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_settings = nes_netdev_get_settings,
|
||||
.set_settings = nes_netdev_set_settings,
|
||||
|
@ -662,7 +662,6 @@ copied:
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, IPOIB_ENCAP_LEN);
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
++dev->stats.rx_packets;
|
||||
dev->stats.rx_bytes += skb->len;
|
||||
|
||||
|
@ -276,7 +276,6 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
|
||||
skb_reset_mac_header(skb);
|
||||
skb_pull(skb, IPOIB_ENCAP_LEN);
|
||||
|
||||
dev->last_rx = jiffies;
|
||||
++dev->stats.rx_packets;
|
||||
dev->stats.rx_bytes += skb->len;
|
||||
|
||||
|
@ -21,8 +21,6 @@ menuconfig ISDN
|
||||
|
||||
if ISDN
|
||||
|
||||
source "drivers/isdn/mISDN/Kconfig"
|
||||
|
||||
menuconfig ISDN_I4L
|
||||
tristate "Old ISDN4Linux (deprecated)"
|
||||
---help---
|
||||
@ -41,9 +39,9 @@ menuconfig ISDN_I4L
|
||||
It is still available, though, for use with adapters that are not
|
||||
supported by the new CAPI subsystem yet.
|
||||
|
||||
if ISDN_I4L
|
||||
source "drivers/isdn/mISDN/Kconfig"
|
||||
|
||||
source "drivers/isdn/i4l/Kconfig"
|
||||
endif
|
||||
|
||||
menuconfig ISDN_CAPI
|
||||
tristate "CAPI 2.0 subsystem"
|
||||
|
@ -78,7 +78,6 @@ static actcapi_msgdsc valid_msg[] = {
|
||||
#endif
|
||||
{{ 0x00, 0x00}, NULL},
|
||||
};
|
||||
#define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc))
|
||||
#define num_valid_imsg 27 /* MANUFACTURER_IND */
|
||||
|
||||
/*
|
||||
@ -1025,7 +1024,7 @@ actcapi_debug_msg(struct sk_buff *skb, int direction)
|
||||
#ifdef DEBUG_DUMP_SKB
|
||||
dump_skb(skb);
|
||||
#endif
|
||||
for (i = 0; i < num_valid_msg; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
|
||||
if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
|
||||
(msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
|
||||
descr = valid_msg[i].description;
|
||||
|
@ -23,7 +23,6 @@ static unsigned short act2000_isa_ports[] =
|
||||
0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380,
|
||||
0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60,
|
||||
};
|
||||
#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short))
|
||||
|
||||
static act2000_card *cards = (act2000_card *) NULL;
|
||||
|
||||
@ -686,21 +685,21 @@ act2000_addcard(int bus, int port, int irq, char *id)
|
||||
* This may result in more than one card detected.
|
||||
*/
|
||||
switch (bus) {
|
||||
case ACT2000_BUS_ISA:
|
||||
for (i = 0; i < ISA_NRPORTS; i++)
|
||||
if (act2000_isa_detect(act2000_isa_ports[i])) {
|
||||
printk(KERN_INFO
|
||||
"act2000: Detected ISA card at port 0x%x\n",
|
||||
act2000_isa_ports[i]);
|
||||
act2000_alloccard(bus, act2000_isa_ports[i], irq, id);
|
||||
}
|
||||
break;
|
||||
case ACT2000_BUS_MCA:
|
||||
case ACT2000_BUS_PCMCIA:
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"act2000: addcard: Invalid BUS type %d\n",
|
||||
bus);
|
||||
case ACT2000_BUS_ISA:
|
||||
for (i = 0; i < ARRAY_SIZE(act2000_isa_ports); i++)
|
||||
if (act2000_isa_detect(act2000_isa_ports[i])) {
|
||||
printk(KERN_INFO "act2000: Detected "
|
||||
"ISA card at port 0x%x\n",
|
||||
act2000_isa_ports[i]);
|
||||
act2000_alloccard(bus,
|
||||
act2000_isa_ports[i], irq, id);
|
||||
}
|
||||
break;
|
||||
case ACT2000_BUS_MCA:
|
||||
case ACT2000_BUS_PCMCIA:
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"act2000: addcard: Invalid BUS type %d\n", bus);
|
||||
}
|
||||
}
|
||||
if (!cards)
|
||||
|
@ -551,9 +551,7 @@ word api_put(APPL * appl, CAPI_MSG * msg)
|
||||
dbug(1,dprintf("com=%x",msg->header.command));
|
||||
|
||||
for(j=0;j<MAX_MSG_PARMS+1;j++) msg_parms[j].length = 0;
|
||||
for(i=0, ret = _BAD_MSG;
|
||||
i<(sizeof(ftable)/sizeof(struct _ftable));
|
||||
i++) {
|
||||
for(i=0, ret = _BAD_MSG; i < ARRAY_SIZE(ftable); i++) {
|
||||
|
||||
if(ftable[i].command==msg->header.command) {
|
||||
/* break loop if the message is correct, otherwise continue scan */
|
||||
|
@ -149,8 +149,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a)
|
||||
diva_os_xdi_adapter_t *diva_current;
|
||||
diva_os_xdi_adapter_t *adapter_list[4];
|
||||
PISDN_ADAPTER Slave;
|
||||
unsigned long bar_length[sizeof(_4bri_bar_length) /
|
||||
sizeof(_4bri_bar_length[0])];
|
||||
unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
|
||||
int v2 = _4bri_is_rev_2_card(a->CardOrdinal);
|
||||
int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT;
|
||||
int factor = (tasks == 1) ? 1 : 2;
|
||||
|
@ -39,3 +39,54 @@ config MISDN_HFCUSB
|
||||
Enable support for USB ISDN TAs with Cologne Chip AG's
|
||||
HFC-S USB ISDN Controller
|
||||
|
||||
config MISDN_AVMFRITZ
|
||||
tristate "Support for AVM FRITZ!CARD PCI"
|
||||
depends on MISDN
|
||||
depends on PCI
|
||||
select MISDN_IPAC
|
||||
help
|
||||
Enable support for AVMs FRITZ!CARD PCI cards
|
||||
|
||||
config MISDN_SPEEDFAX
|
||||
tristate "Support for Sedlbauer Speedfax+"
|
||||
depends on MISDN
|
||||
depends on PCI
|
||||
select MISDN_IPAC
|
||||
select MISDN_ISAR
|
||||
help
|
||||
Enable support for Sedlbauer Speedfax+.
|
||||
|
||||
config MISDN_INFINEON
|
||||
tristate "Support for cards with Infineon chipset"
|
||||
depends on MISDN
|
||||
depends on PCI
|
||||
select MISDN_IPAC
|
||||
help
|
||||
Enable support for cards with ISAC + HSCX, IPAC or IPAC-SX
|
||||
chip from Infineon (former manufacturer Siemens).
|
||||
|
||||
config MISDN_W6692
|
||||
tristate "Support for cards with Winbond 6692"
|
||||
depends on MISDN
|
||||
depends on PCI
|
||||
help
|
||||
Enable support for Winbond 6692 PCI chip based cards.
|
||||
|
||||
config MISDN_NETJET
|
||||
tristate "Support for NETJet cards"
|
||||
depends on MISDN
|
||||
depends on PCI
|
||||
select MISDN_IPAC
|
||||
select ISDN_HDLC
|
||||
help
|
||||
Enable support for Traverse Technologies NETJet PCI cards.
|
||||
|
||||
|
||||
config MISDN_IPAC
|
||||
tristate
|
||||
depends on MISDN
|
||||
|
||||
config MISDN_ISAR
|
||||
tristate
|
||||
depends on MISDN
|
||||
|
||||
|
@ -6,3 +6,11 @@
|
||||
obj-$(CONFIG_MISDN_HFCPCI) += hfcpci.o
|
||||
obj-$(CONFIG_MISDN_HFCMULTI) += hfcmulti.o
|
||||
obj-$(CONFIG_MISDN_HFCUSB) += hfcsusb.o
|
||||
obj-$(CONFIG_MISDN_AVMFRITZ) += avmfritz.o
|
||||
obj-$(CONFIG_MISDN_SPEEDFAX) += speedfax.o
|
||||
obj-$(CONFIG_MISDN_INFINEON) += mISDNinfineon.o
|
||||
obj-$(CONFIG_MISDN_W6692) += w6692.o
|
||||
obj-$(CONFIG_MISDN_NETJET) += netjet.o
|
||||
# chip modules
|
||||
obj-$(CONFIG_MISDN_IPAC) += mISDNipac.o
|
||||
obj-$(CONFIG_MISDN_ISAR) += mISDNisar.o
|
||||
|
1152
drivers/isdn/hardware/mISDN/avmfritz.c
Normal file
1152
drivers/isdn/hardware/mISDN/avmfritz.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -3416,22 +3416,8 @@ deactivate_bchannel(struct bchannel *bch)
|
||||
u_long flags;
|
||||
|
||||
spin_lock_irqsave(&hc->lock, flags);
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
|
||||
dev_kfree_skb(bch->next_skb);
|
||||
bch->next_skb = NULL;
|
||||
}
|
||||
if (bch->tx_skb) {
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
bch->tx_skb = NULL;
|
||||
}
|
||||
bch->tx_idx = 0;
|
||||
if (bch->rx_skb) {
|
||||
dev_kfree_skb(bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
}
|
||||
mISDN_clear_bchannel(bch);
|
||||
hc->chan[bch->slot].coeff_count = 0;
|
||||
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
hc->chan[bch->slot].rx_off = 0;
|
||||
hc->chan[bch->slot].conf = -1;
|
||||
mode_hfcmulti(hc, bch->slot, ISDN_P_NONE, -1, 0, -1, 0);
|
||||
@ -5384,9 +5370,10 @@ hfcmulti_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
ent->device == PCI_DEVICE_ID_CCD_HFC8S ||
|
||||
ent->device == PCI_DEVICE_ID_CCD_HFCE1)) {
|
||||
printk(KERN_ERR
|
||||
"Unknown HFC multiport controller (vendor:%x device:%x "
|
||||
"subvendor:%x subdevice:%x)\n", ent->vendor, ent->device,
|
||||
ent->subvendor, ent->subdevice);
|
||||
"Unknown HFC multiport controller (vendor:%04x device:%04x "
|
||||
"subvendor:%04x subdevice:%04x)\n", pdev->vendor,
|
||||
pdev->device, pdev->subsystem_vendor,
|
||||
pdev->subsystem_device);
|
||||
printk(KERN_ERR
|
||||
"Please contact the driver maintainer for support.\n");
|
||||
return -ENODEV;
|
||||
|
@ -1522,22 +1522,8 @@ deactivate_bchannel(struct bchannel *bch)
|
||||
u_long flags;
|
||||
|
||||
spin_lock_irqsave(&hc->lock, flags);
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
|
||||
dev_kfree_skb(bch->next_skb);
|
||||
bch->next_skb = NULL;
|
||||
}
|
||||
if (bch->tx_skb) {
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
bch->tx_skb = NULL;
|
||||
}
|
||||
bch->tx_idx = 0;
|
||||
if (bch->rx_skb) {
|
||||
dev_kfree_skb(bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
}
|
||||
mISDN_clear_bchannel(bch);
|
||||
mode_hfcpci(bch, bch->nr, ISDN_P_NONE);
|
||||
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
spin_unlock_irqrestore(&hc->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -1809,21 +1809,7 @@ deactivate_bchannel(struct bchannel *bch)
|
||||
hw->name, __func__, bch->nr);
|
||||
|
||||
spin_lock_irqsave(&hw->lock, flags);
|
||||
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
|
||||
dev_kfree_skb(bch->next_skb);
|
||||
bch->next_skb = NULL;
|
||||
}
|
||||
if (bch->tx_skb) {
|
||||
dev_kfree_skb(bch->tx_skb);
|
||||
bch->tx_skb = NULL;
|
||||
}
|
||||
bch->tx_idx = 0;
|
||||
if (bch->rx_skb) {
|
||||
dev_kfree_skb(bch->rx_skb);
|
||||
bch->rx_skb = NULL;
|
||||
}
|
||||
clear_bit(FLG_ACTIVE, &bch->Flags);
|
||||
clear_bit(FLG_TX_BUSY, &bch->Flags);
|
||||
mISDN_clear_bchannel(bch);
|
||||
spin_unlock_irqrestore(&hw->lock, flags);
|
||||
hfcsusb_setup_bch(bch, ISDN_P_NONE);
|
||||
hfcsusb_stop_endpoint(hw, bch->nr);
|
||||
|
109
drivers/isdn/hardware/mISDN/iohelper.h
Normal file
109
drivers/isdn/hardware/mISDN/iohelper.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* iohelper.h
|
||||
* helper for define functions to access ISDN hardware
|
||||
* supported are memory mapped IO
|
||||
* indirect port IO (one port for address, one for data)
|
||||
*
|
||||
* Author Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _IOHELPER_H
|
||||
#define _IOHELPER_H
|
||||
|
||||
typedef u8 (read_reg_func)(void *hwp, u8 offset);
|
||||
typedef void (write_reg_func)(void *hwp, u8 offset, u8 value);
|
||||
typedef void (fifo_func)(void *hwp, u8 offset, u8 *datap, int size);
|
||||
|
||||
struct _ioport {
|
||||
u32 port;
|
||||
u32 ale;
|
||||
};
|
||||
|
||||
#define IOFUNC_IO(name, hws, ap) \
|
||||
static u8 Read##name##_IO(void *p, u8 off) {\
|
||||
struct hws *hw = p;\
|
||||
return inb(hw->ap.port + off);\
|
||||
} \
|
||||
static void Write##name##_IO(void *p, u8 off, u8 val) {\
|
||||
struct hws *hw = p;\
|
||||
outb(val, hw->ap.port + off);\
|
||||
} \
|
||||
static void ReadFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
insb(hw->ap.port + off, dp, size);\
|
||||
} \
|
||||
static void WriteFiFo##name##_IO(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
outsb(hw->ap.port + off, dp, size);\
|
||||
}
|
||||
|
||||
#define IOFUNC_IND(name, hws, ap) \
|
||||
static u8 Read##name##_IND(void *p, u8 off) {\
|
||||
struct hws *hw = p;\
|
||||
outb(off, hw->ap.ale);\
|
||||
return inb(hw->ap.port);\
|
||||
} \
|
||||
static void Write##name##_IND(void *p, u8 off, u8 val) {\
|
||||
struct hws *hw = p;\
|
||||
outb(off, hw->ap.ale);\
|
||||
outb(val, hw->ap.port);\
|
||||
} \
|
||||
static void ReadFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
outb(off, hw->ap.ale);\
|
||||
insb(hw->ap.port, dp, size);\
|
||||
} \
|
||||
static void WriteFiFo##name##_IND(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
outb(off, hw->ap.ale);\
|
||||
outsb(hw->ap.port, dp, size);\
|
||||
}
|
||||
|
||||
#define IOFUNC_MEMIO(name, hws, typ, adr) \
|
||||
static u8 Read##name##_MIO(void *p, u8 off) {\
|
||||
struct hws *hw = p;\
|
||||
return readb(((typ *)hw->adr) + off);\
|
||||
} \
|
||||
static void Write##name##_MIO(void *p, u8 off, u8 val) {\
|
||||
struct hws *hw = p;\
|
||||
writeb(val, ((typ *)hw->adr) + off);\
|
||||
} \
|
||||
static void ReadFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
while (size--)\
|
||||
*dp++ = readb(((typ *)hw->adr) + off);\
|
||||
} \
|
||||
static void WriteFiFo##name##_MIO(void *p, u8 off, u8 *dp, int size) {\
|
||||
struct hws *hw = p;\
|
||||
while (size--)\
|
||||
writeb(*dp++, ((typ *)hw->adr) + off);\
|
||||
}
|
||||
|
||||
#define ASSIGN_FUNC(typ, name, dest) do {\
|
||||
dest.read_reg = &Read##name##_##typ;\
|
||||
dest.write_reg = &Write##name##_##typ;\
|
||||
dest.read_fifo = &ReadFiFo##name##_##typ;\
|
||||
dest.write_fifo = &WriteFiFo##name##_##typ;\
|
||||
} while (0)
|
||||
#define ASSIGN_FUNC_IPAC(typ, target) do {\
|
||||
ASSIGN_FUNC(typ, ISAC, target.isac);\
|
||||
ASSIGN_FUNC(typ, IPAC, target);\
|
||||
} while (0)
|
||||
|
||||
#endif
|
405
drivers/isdn/hardware/mISDN/ipac.h
Normal file
405
drivers/isdn/hardware/mISDN/ipac.h
Normal file
@ -0,0 +1,405 @@
|
||||
/*
|
||||
*
|
||||
* ipac.h Defines for the Infineon (former Siemens) ISDN
|
||||
* chip series
|
||||
*
|
||||
* Author Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iohelper.h"
|
||||
|
||||
struct isac_hw {
|
||||
struct dchannel dch;
|
||||
u32 type;
|
||||
u32 off; /* offset to isac regs */
|
||||
char *name;
|
||||
spinlock_t *hwlock; /* lock HW acccess */
|
||||
read_reg_func *read_reg;
|
||||
write_reg_func *write_reg;
|
||||
fifo_func *read_fifo;
|
||||
fifo_func *write_fifo;
|
||||
int (*monitor)(void *, u32, u8 *, int);
|
||||
void (*release)(struct isac_hw *);
|
||||
int (*init)(struct isac_hw *);
|
||||
int (*ctrl)(struct isac_hw *, u32, u_long);
|
||||
int (*open)(struct isac_hw *, struct channel_req *);
|
||||
u8 *mon_tx;
|
||||
u8 *mon_rx;
|
||||
int mon_txp;
|
||||
int mon_txc;
|
||||
int mon_rxp;
|
||||
struct arcofi_msg *arcofi_list;
|
||||
struct timer_list arcofitimer;
|
||||
wait_queue_head_t arcofi_wait;
|
||||
u8 arcofi_bc;
|
||||
u8 arcofi_state;
|
||||
u8 mocr;
|
||||
u8 adf2;
|
||||
u8 state;
|
||||
};
|
||||
|
||||
struct ipac_hw;
|
||||
|
||||
struct hscx_hw {
|
||||
struct bchannel bch;
|
||||
struct ipac_hw *ip;
|
||||
u8 fifo_size;
|
||||
u8 off; /* offset to ICA or ICB */
|
||||
u8 slot;
|
||||
char log[64];
|
||||
};
|
||||
|
||||
struct ipac_hw {
|
||||
struct isac_hw isac;
|
||||
struct hscx_hw hscx[2];
|
||||
char *name;
|
||||
void *hw;
|
||||
spinlock_t *hwlock; /* lock HW acccess */
|
||||
struct module *owner;
|
||||
u32 type;
|
||||
read_reg_func *read_reg;
|
||||
write_reg_func *write_reg;
|
||||
fifo_func *read_fifo;
|
||||
fifo_func *write_fifo;
|
||||
void (*release)(struct ipac_hw *);
|
||||
int (*init)(struct ipac_hw *);
|
||||
int (*ctrl)(struct ipac_hw *, u32, u_long);
|
||||
u8 conf;
|
||||
};
|
||||
|
||||
#define IPAC_TYPE_ISAC 0x0010
|
||||
#define IPAC_TYPE_IPAC 0x0020
|
||||
#define IPAC_TYPE_ISACX 0x0040
|
||||
#define IPAC_TYPE_IPACX 0x0080
|
||||
#define IPAC_TYPE_HSCX 0x0100
|
||||
|
||||
#define ISAC_USE_ARCOFI 0x1000
|
||||
|
||||
/* Monitor functions */
|
||||
#define MONITOR_RX_0 0x1000
|
||||
#define MONITOR_RX_1 0x1001
|
||||
#define MONITOR_TX_0 0x2000
|
||||
#define MONITOR_TX_1 0x2001
|
||||
|
||||
/* All registers original Siemens Spec */
|
||||
/* IPAC/ISAC registers */
|
||||
#define ISAC_MASK 0x20
|
||||
#define ISAC_ISTA 0x20
|
||||
#define ISAC_STAR 0x21
|
||||
#define ISAC_CMDR 0x21
|
||||
#define ISAC_EXIR 0x24
|
||||
#define ISAC_ADF2 0x39
|
||||
#define ISAC_SPCR 0x30
|
||||
#define ISAC_ADF1 0x38
|
||||
#define ISAC_CIR0 0x31
|
||||
#define ISAC_CIX0 0x31
|
||||
#define ISAC_CIR1 0x33
|
||||
#define ISAC_CIX1 0x33
|
||||
#define ISAC_STCR 0x37
|
||||
#define ISAC_MODE 0x22
|
||||
#define ISAC_RSTA 0x27
|
||||
#define ISAC_RBCL 0x25
|
||||
#define ISAC_RBCH 0x2A
|
||||
#define ISAC_TIMR 0x23
|
||||
#define ISAC_SQXR 0x3b
|
||||
#define ISAC_SQRR 0x3b
|
||||
#define ISAC_MOSR 0x3a
|
||||
#define ISAC_MOCR 0x3a
|
||||
#define ISAC_MOR0 0x32
|
||||
#define ISAC_MOX0 0x32
|
||||
#define ISAC_MOR1 0x34
|
||||
#define ISAC_MOX1 0x34
|
||||
|
||||
#define ISAC_RBCH_XAC 0x80
|
||||
|
||||
#define IPAC_D_TIN2 0x01
|
||||
|
||||
/* IPAC/HSCX */
|
||||
#define IPAC_ISTAB 0x20 /* RD */
|
||||
#define IPAC_MASKB 0x20 /* WR */
|
||||
#define IPAC_STARB 0x21 /* RD */
|
||||
#define IPAC_CMDRB 0x21 /* WR */
|
||||
#define IPAC_MODEB 0x22 /* R/W */
|
||||
#define IPAC_EXIRB 0x24 /* RD */
|
||||
#define IPAC_RBCLB 0x25 /* RD */
|
||||
#define IPAC_RAH1 0x26 /* WR */
|
||||
#define IPAC_RAH2 0x27 /* WR */
|
||||
#define IPAC_RSTAB 0x27 /* RD */
|
||||
#define IPAC_RAL1 0x28 /* R/W */
|
||||
#define IPAC_RAL2 0x29 /* WR */
|
||||
#define IPAC_RHCRB 0x29 /* RD */
|
||||
#define IPAC_XBCL 0x2A /* WR */
|
||||
#define IPAC_CCR2 0x2C /* R/W */
|
||||
#define IPAC_RBCHB 0x2D /* RD */
|
||||
#define IPAC_XBCH 0x2D /* WR */
|
||||
#define HSCX_VSTR 0x2E /* RD */
|
||||
#define IPAC_RLCR 0x2E /* WR */
|
||||
#define IPAC_CCR1 0x2F /* R/W */
|
||||
#define IPAC_TSAX 0x30 /* WR */
|
||||
#define IPAC_TSAR 0x31 /* WR */
|
||||
#define IPAC_XCCR 0x32 /* WR */
|
||||
#define IPAC_RCCR 0x33 /* WR */
|
||||
|
||||
/* IPAC_ISTAB/IPAC_MASKB bits */
|
||||
#define IPAC_B_XPR 0x10
|
||||
#define IPAC_B_RPF 0x40
|
||||
#define IPAC_B_RME 0x80
|
||||
#define IPAC_B_ON 0x2F
|
||||
|
||||
/* IPAC_EXIRB bits */
|
||||
#define IPAC_B_RFS 0x04
|
||||
#define IPAC_B_RFO 0x10
|
||||
#define IPAC_B_XDU 0x40
|
||||
#define IPAC_B_XMR 0x80
|
||||
|
||||
/* IPAC special registers */
|
||||
#define IPAC_CONF 0xC0 /* R/W */
|
||||
#define IPAC_ISTA 0xC1 /* RD */
|
||||
#define IPAC_MASK 0xC1 /* WR */
|
||||
#define IPAC_ID 0xC2 /* RD */
|
||||
#define IPAC_ACFG 0xC3 /* R/W */
|
||||
#define IPAC_AOE 0xC4 /* R/W */
|
||||
#define IPAC_ARX 0xC5 /* RD */
|
||||
#define IPAC_ATX 0xC5 /* WR */
|
||||
#define IPAC_PITA1 0xC6 /* R/W */
|
||||
#define IPAC_PITA2 0xC7 /* R/W */
|
||||
#define IPAC_POTA1 0xC8 /* R/W */
|
||||
#define IPAC_POTA2 0xC9 /* R/W */
|
||||
#define IPAC_PCFG 0xCA /* R/W */
|
||||
#define IPAC_SCFG 0xCB /* R/W */
|
||||
#define IPAC_TIMR2 0xCC /* R/W */
|
||||
|
||||
/* IPAC_ISTA/_MASK bits */
|
||||
#define IPAC__EXB 0x01
|
||||
#define IPAC__ICB 0x02
|
||||
#define IPAC__EXA 0x04
|
||||
#define IPAC__ICA 0x08
|
||||
#define IPAC__EXD 0x10
|
||||
#define IPAC__ICD 0x20
|
||||
#define IPAC__INT0 0x40
|
||||
#define IPAC__INT1 0x80
|
||||
#define IPAC__ON 0xC0
|
||||
|
||||
/* HSCX ISTA/MASK bits */
|
||||
#define HSCX__EXB 0x01
|
||||
#define HSCX__EXA 0x02
|
||||
#define HSCX__ICA 0x04
|
||||
|
||||
/* ISAC/ISACX/IPAC/IPACX L1 commands */
|
||||
#define ISAC_CMD_TIM 0x0
|
||||
#define ISAC_CMD_RS 0x1
|
||||
#define ISAC_CMD_SCZ 0x4
|
||||
#define ISAC_CMD_SSZ 0x2
|
||||
#define ISAC_CMD_AR8 0x8
|
||||
#define ISAC_CMD_AR10 0x9
|
||||
#define ISAC_CMD_ARL 0xA
|
||||
#define ISAC_CMD_DUI 0xF
|
||||
|
||||
/* ISAC/ISACX/IPAC/IPACX L1 indications */
|
||||
#define ISAC_IND_RS 0x1
|
||||
#define ISAC_IND_PU 0x7
|
||||
#define ISAC_IND_DR 0x0
|
||||
#define ISAC_IND_SD 0x2
|
||||
#define ISAC_IND_DIS 0x3
|
||||
#define ISAC_IND_EI 0x6
|
||||
#define ISAC_IND_RSY 0x4
|
||||
#define ISAC_IND_ARD 0x8
|
||||
#define ISAC_IND_TI 0xA
|
||||
#define ISAC_IND_ATI 0xB
|
||||
#define ISAC_IND_AI8 0xC
|
||||
#define ISAC_IND_AI10 0xD
|
||||
#define ISAC_IND_DID 0xF
|
||||
|
||||
/* the new ISACX / IPACX */
|
||||
/* D-channel registers */
|
||||
#define ISACX_RFIFOD 0x00 /* RD */
|
||||
#define ISACX_XFIFOD 0x00 /* WR */
|
||||
#define ISACX_ISTAD 0x20 /* RD */
|
||||
#define ISACX_MASKD 0x20 /* WR */
|
||||
#define ISACX_STARD 0x21 /* RD */
|
||||
#define ISACX_CMDRD 0x21 /* WR */
|
||||
#define ISACX_MODED 0x22 /* R/W */
|
||||
#define ISACX_EXMD1 0x23 /* R/W */
|
||||
#define ISACX_TIMR1 0x24 /* R/W */
|
||||
#define ISACX_SAP1 0x25 /* WR */
|
||||
#define ISACX_SAP2 0x26 /* WR */
|
||||
#define ISACX_RBCLD 0x26 /* RD */
|
||||
#define ISACX_RBCHD 0x27 /* RD */
|
||||
#define ISACX_TEI1 0x27 /* WR */
|
||||
#define ISACX_TEI2 0x28 /* WR */
|
||||
#define ISACX_RSTAD 0x28 /* RD */
|
||||
#define ISACX_TMD 0x29 /* R/W */
|
||||
#define ISACX_CIR0 0x2E /* RD */
|
||||
#define ISACX_CIX0 0x2E /* WR */
|
||||
#define ISACX_CIR1 0x2F /* RD */
|
||||
#define ISACX_CIX1 0x2F /* WR */
|
||||
|
||||
/* Transceiver registers */
|
||||
#define ISACX_TR_CONF0 0x30 /* R/W */
|
||||
#define ISACX_TR_CONF1 0x31 /* R/W */
|
||||
#define ISACX_TR_CONF2 0x32 /* R/W */
|
||||
#define ISACX_TR_STA 0x33 /* RD */
|
||||
#define ISACX_TR_CMD 0x34 /* R/W */
|
||||
#define ISACX_SQRR1 0x35 /* RD */
|
||||
#define ISACX_SQXR1 0x35 /* WR */
|
||||
#define ISACX_SQRR2 0x36 /* RD */
|
||||
#define ISACX_SQXR2 0x36 /* WR */
|
||||
#define ISACX_SQRR3 0x37 /* RD */
|
||||
#define ISACX_SQXR3 0x37 /* WR */
|
||||
#define ISACX_ISTATR 0x38 /* RD */
|
||||
#define ISACX_MASKTR 0x39 /* R/W */
|
||||
#define ISACX_TR_MODE 0x3A /* R/W */
|
||||
#define ISACX_ACFG1 0x3C /* R/W */
|
||||
#define ISACX_ACFG2 0x3D /* R/W */
|
||||
#define ISACX_AOE 0x3E /* R/W */
|
||||
#define ISACX_ARX 0x3F /* RD */
|
||||
#define ISACX_ATX 0x3F /* WR */
|
||||
|
||||
/* IOM: Timeslot, DPS, CDA */
|
||||
#define ISACX_CDA10 0x40 /* R/W */
|
||||
#define ISACX_CDA11 0x41 /* R/W */
|
||||
#define ISACX_CDA20 0x42 /* R/W */
|
||||
#define ISACX_CDA21 0x43 /* R/W */
|
||||
#define ISACX_CDA_TSDP10 0x44 /* R/W */
|
||||
#define ISACX_CDA_TSDP11 0x45 /* R/W */
|
||||
#define ISACX_CDA_TSDP20 0x46 /* R/W */
|
||||
#define ISACX_CDA_TSDP21 0x47 /* R/W */
|
||||
#define ISACX_BCHA_TSDP_BC1 0x48 /* R/W */
|
||||
#define ISACX_BCHA_TSDP_BC2 0x49 /* R/W */
|
||||
#define ISACX_BCHB_TSDP_BC1 0x4A /* R/W */
|
||||
#define ISACX_BCHB_TSDP_BC2 0x4B /* R/W */
|
||||
#define ISACX_TR_TSDP_BC1 0x4C /* R/W */
|
||||
#define ISACX_TR_TSDP_BC2 0x4D /* R/W */
|
||||
#define ISACX_CDA1_CR 0x4E /* R/W */
|
||||
#define ISACX_CDA2_CR 0x4F /* R/W */
|
||||
|
||||
/* IOM: Contol, Sync transfer, Monitor */
|
||||
#define ISACX_TR_CR 0x50 /* R/W */
|
||||
#define ISACX_TRC_CR 0x50 /* R/W */
|
||||
#define ISACX_BCHA_CR 0x51 /* R/W */
|
||||
#define ISACX_BCHB_CR 0x52 /* R/W */
|
||||
#define ISACX_DCI_CR 0x53 /* R/W */
|
||||
#define ISACX_DCIC_CR 0x53 /* R/W */
|
||||
#define ISACX_MON_CR 0x54 /* R/W */
|
||||
#define ISACX_SDS1_CR 0x55 /* R/W */
|
||||
#define ISACX_SDS2_CR 0x56 /* R/W */
|
||||
#define ISACX_IOM_CR 0x57 /* R/W */
|
||||
#define ISACX_STI 0x58 /* RD */
|
||||
#define ISACX_ASTI 0x58 /* WR */
|
||||
#define ISACX_MSTI 0x59 /* R/W */
|
||||
#define ISACX_SDS_CONF 0x5A /* R/W */
|
||||
#define ISACX_MCDA 0x5B /* RD */
|
||||
#define ISACX_MOR 0x5C /* RD */
|
||||
#define ISACX_MOX 0x5C /* WR */
|
||||
#define ISACX_MOSR 0x5D /* RD */
|
||||
#define ISACX_MOCR 0x5E /* R/W */
|
||||
#define ISACX_MSTA 0x5F /* RD */
|
||||
#define ISACX_MCONF 0x5F /* WR */
|
||||
|
||||
/* Interrupt and general registers */
|
||||
#define ISACX_ISTA 0x60 /* RD */
|
||||
#define ISACX_MASK 0x60 /* WR */
|
||||
#define ISACX_AUXI 0x61 /* RD */
|
||||
#define ISACX_AUXM 0x61 /* WR */
|
||||
#define ISACX_MODE1 0x62 /* R/W */
|
||||
#define ISACX_MODE2 0x63 /* R/W */
|
||||
#define ISACX_ID 0x64 /* RD */
|
||||
#define ISACX_SRES 0x64 /* WR */
|
||||
#define ISACX_TIMR2 0x65 /* R/W */
|
||||
|
||||
/* Register Bits */
|
||||
/* ISACX/IPACX _ISTAD (R) and _MASKD (W) */
|
||||
#define ISACX_D_XDU 0x04
|
||||
#define ISACX_D_XMR 0x08
|
||||
#define ISACX_D_XPR 0x10
|
||||
#define ISACX_D_RFO 0x20
|
||||
#define ISACX_D_RPF 0x40
|
||||
#define ISACX_D_RME 0x80
|
||||
|
||||
/* ISACX/IPACX _ISTA (R) and _MASK (W) */
|
||||
#define ISACX__ICD 0x01
|
||||
#define ISACX__MOS 0x02
|
||||
#define ISACX__TRAN 0x04
|
||||
#define ISACX__AUX 0x08
|
||||
#define ISACX__CIC 0x10
|
||||
#define ISACX__ST 0x20
|
||||
#define IPACX__ICB 0x40
|
||||
#define IPACX__ICA 0x80
|
||||
#define IPACX__ON 0x2C
|
||||
|
||||
/* ISACX/IPACX _CMDRD (W) */
|
||||
#define ISACX_CMDRD_XRES 0x01
|
||||
#define ISACX_CMDRD_XME 0x02
|
||||
#define ISACX_CMDRD_XTF 0x08
|
||||
#define ISACX_CMDRD_STI 0x10
|
||||
#define ISACX_CMDRD_RRES 0x40
|
||||
#define ISACX_CMDRD_RMC 0x80
|
||||
|
||||
/* ISACX/IPACX _RSTAD (R) */
|
||||
#define ISACX_RSTAD_TA 0x01
|
||||
#define ISACX_RSTAD_CR 0x02
|
||||
#define ISACX_RSTAD_SA0 0x04
|
||||
#define ISACX_RSTAD_SA1 0x08
|
||||
#define ISACX_RSTAD_RAB 0x10
|
||||
#define ISACX_RSTAD_CRC 0x20
|
||||
#define ISACX_RSTAD_RDO 0x40
|
||||
#define ISACX_RSTAD_VFR 0x80
|
||||
|
||||
/* ISACX/IPACX _CIR0 (R) */
|
||||
#define ISACX_CIR0_BAS 0x01
|
||||
#define ISACX_CIR0_SG 0x08
|
||||
#define ISACX_CIR0_CIC1 0x08
|
||||
#define ISACX_CIR0_CIC0 0x08
|
||||
|
||||
/* B-channel registers */
|
||||
#define IPACX_OFF_ICA 0x70
|
||||
#define IPACX_OFF_ICB 0x80
|
||||
|
||||
/* ICA: IPACX_OFF_ICA + Reg ICB: IPACX_OFF_ICB + Reg */
|
||||
|
||||
#define IPACX_ISTAB 0x00 /* RD */
|
||||
#define IPACX_MASKB 0x00 /* WR */
|
||||
#define IPACX_STARB 0x01 /* RD */
|
||||
#define IPACX_CMDRB 0x01 /* WR */
|
||||
#define IPACX_MODEB 0x02 /* R/W */
|
||||
#define IPACX_EXMB 0x03 /* R/W */
|
||||
#define IPACX_RAH1 0x05 /* WR */
|
||||
#define IPACX_RAH2 0x06 /* WR */
|
||||
#define IPACX_RBCLB 0x06 /* RD */
|
||||
#define IPACX_RBCHB 0x07 /* RD */
|
||||
#define IPACX_RAL1 0x07 /* WR */
|
||||
#define IPACX_RAL2 0x08 /* WR */
|
||||
#define IPACX_RSTAB 0x08 /* RD */
|
||||
#define IPACX_TMB 0x09 /* R/W */
|
||||
#define IPACX_RFIFOB 0x0A /* RD */
|
||||
#define IPACX_XFIFOB 0x0A /* WR */
|
||||
|
||||
/* IPACX_ISTAB / IPACX_MASKB bits */
|
||||
#define IPACX_B_XDU 0x04
|
||||
#define IPACX_B_XPR 0x10
|
||||
#define IPACX_B_RFO 0x20
|
||||
#define IPACX_B_RPF 0x40
|
||||
#define IPACX_B_RME 0x80
|
||||
|
||||
#define IPACX_B_ON 0x0B
|
||||
|
||||
extern int mISDNisac_init(struct isac_hw *, void *);
|
||||
extern irqreturn_t mISDNisac_irq(struct isac_hw *, u8);
|
||||
extern u32 mISDNipac_init(struct ipac_hw *, void *);
|
||||
extern irqreturn_t mISDNipac_irq(struct ipac_hw *, int);
|
269
drivers/isdn/hardware/mISDN/isar.h
Normal file
269
drivers/isdn/hardware/mISDN/isar.h
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
*
|
||||
* isar.h ISAR (Siemens PSB 7110) specific defines
|
||||
*
|
||||
* Author Karsten Keil (keil@isdn4linux.de)
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iohelper.h"
|
||||
|
||||
struct isar_hw;
|
||||
|
||||
struct isar_ch {
|
||||
struct bchannel bch;
|
||||
struct isar_hw *is;
|
||||
struct timer_list ftimer;
|
||||
u8 nr;
|
||||
u8 dpath;
|
||||
u8 mml;
|
||||
u8 state;
|
||||
u8 cmd;
|
||||
u8 mod;
|
||||
u8 newcmd;
|
||||
u8 newmod;
|
||||
u8 try_mod;
|
||||
u8 conmsg[16];
|
||||
};
|
||||
|
||||
struct isar_hw {
|
||||
struct isar_ch ch[2];
|
||||
void *hw;
|
||||
spinlock_t *hwlock; /* lock HW acccess */
|
||||
char *name;
|
||||
struct module *owner;
|
||||
read_reg_func *read_reg;
|
||||
write_reg_func *write_reg;
|
||||
fifo_func *read_fifo;
|
||||
fifo_func *write_fifo;
|
||||
int (*ctrl)(void *, u32, u_long);
|
||||
void (*release)(struct isar_hw *);
|
||||
int (*init)(struct isar_hw *);
|
||||
int (*open)(struct isar_hw *, struct channel_req *);
|
||||
int (*firmware)(struct isar_hw *, const u8 *, int);
|
||||
unsigned long Flags;
|
||||
int version;
|
||||
u8 bstat;
|
||||
u8 iis;
|
||||
u8 cmsb;
|
||||
u8 clsb;
|
||||
u8 buf[256];
|
||||
u8 log[256];
|
||||
};
|
||||
|
||||
#define ISAR_IRQMSK 0x04
|
||||
#define ISAR_IRQSTA 0x04
|
||||
#define ISAR_IRQBIT 0x75
|
||||
#define ISAR_CTRL_H 0x61
|
||||
#define ISAR_CTRL_L 0x60
|
||||
#define ISAR_IIS 0x58
|
||||
#define ISAR_IIA 0x58
|
||||
#define ISAR_HIS 0x50
|
||||
#define ISAR_HIA 0x50
|
||||
#define ISAR_MBOX 0x4c
|
||||
#define ISAR_WADR 0x4a
|
||||
#define ISAR_RADR 0x48
|
||||
|
||||
#define ISAR_HIS_VNR 0x14
|
||||
#define ISAR_HIS_DKEY 0x02
|
||||
#define ISAR_HIS_FIRM 0x1e
|
||||
#define ISAR_HIS_STDSP 0x08
|
||||
#define ISAR_HIS_DIAG 0x05
|
||||
#define ISAR_HIS_P0CFG 0x3c
|
||||
#define ISAR_HIS_P12CFG 0x24
|
||||
#define ISAR_HIS_SARTCFG 0x25
|
||||
#define ISAR_HIS_PUMPCFG 0x26
|
||||
#define ISAR_HIS_PUMPCTRL 0x2a
|
||||
#define ISAR_HIS_IOM2CFG 0x27
|
||||
#define ISAR_HIS_IOM2REQ 0x07
|
||||
#define ISAR_HIS_IOM2CTRL 0x2b
|
||||
#define ISAR_HIS_BSTREQ 0x0c
|
||||
#define ISAR_HIS_PSTREQ 0x0e
|
||||
#define ISAR_HIS_SDATA 0x20
|
||||
#define ISAR_HIS_DPS1 0x40
|
||||
#define ISAR_HIS_DPS2 0x80
|
||||
#define SET_DPS(x) ((x<<6) & 0xc0)
|
||||
|
||||
#define ISAR_IIS_MSCMSD 0x3f
|
||||
#define ISAR_IIS_VNR 0x15
|
||||
#define ISAR_IIS_DKEY 0x03
|
||||
#define ISAR_IIS_FIRM 0x1f
|
||||
#define ISAR_IIS_STDSP 0x09
|
||||
#define ISAR_IIS_DIAG 0x25
|
||||
#define ISAR_IIS_GSTEV 0x00
|
||||
#define ISAR_IIS_BSTEV 0x28
|
||||
#define ISAR_IIS_BSTRSP 0x2c
|
||||
#define ISAR_IIS_PSTRSP 0x2e
|
||||
#define ISAR_IIS_PSTEV 0x2a
|
||||
#define ISAR_IIS_IOM2RSP 0x27
|
||||
#define ISAR_IIS_RDATA 0x20
|
||||
#define ISAR_IIS_INVMSG 0x3f
|
||||
|
||||
#define ISAR_CTRL_SWVER 0x10
|
||||
#define ISAR_CTRL_STST 0x40
|
||||
|
||||
#define ISAR_MSG_HWVER 0x20
|
||||
|
||||
#define ISAR_DP1_USE 1
|
||||
#define ISAR_DP2_USE 2
|
||||
#define ISAR_RATE_REQ 3
|
||||
|
||||
#define PMOD_DISABLE 0
|
||||
#define PMOD_FAX 1
|
||||
#define PMOD_DATAMODEM 2
|
||||
#define PMOD_HALFDUPLEX 3
|
||||
#define PMOD_V110 4
|
||||
#define PMOD_DTMF 5
|
||||
#define PMOD_DTMF_TRANS 6
|
||||
#define PMOD_BYPASS 7
|
||||
|
||||
#define PCTRL_ORIG 0x80
|
||||
#define PV32P2_V23R 0x40
|
||||
#define PV32P2_V22A 0x20
|
||||
#define PV32P2_V22B 0x10
|
||||
#define PV32P2_V22C 0x08
|
||||
#define PV32P2_V21 0x02
|
||||
#define PV32P2_BEL 0x01
|
||||
|
||||
/* LSB MSB in ISAR doc wrong !!! Arghhh */
|
||||
#define PV32P3_AMOD 0x80
|
||||
#define PV32P3_V32B 0x02
|
||||
#define PV32P3_V23B 0x01
|
||||
#define PV32P4_48 0x11
|
||||
#define PV32P5_48 0x05
|
||||
#define PV32P4_UT48 0x11
|
||||
#define PV32P5_UT48 0x0d
|
||||
#define PV32P4_96 0x11
|
||||
#define PV32P5_96 0x03
|
||||
#define PV32P4_UT96 0x11
|
||||
#define PV32P5_UT96 0x0f
|
||||
#define PV32P4_B96 0x91
|
||||
#define PV32P5_B96 0x0b
|
||||
#define PV32P4_UTB96 0xd1
|
||||
#define PV32P5_UTB96 0x0f
|
||||
#define PV32P4_120 0xb1
|
||||
#define PV32P5_120 0x09
|
||||
#define PV32P4_UT120 0xf1
|
||||
#define PV32P5_UT120 0x0f
|
||||
#define PV32P4_144 0x99
|
||||
#define PV32P5_144 0x09
|
||||
#define PV32P4_UT144 0xf9
|
||||
#define PV32P5_UT144 0x0f
|
||||
#define PV32P6_CTN 0x01
|
||||
#define PV32P6_ATN 0x02
|
||||
|
||||
#define PFAXP2_CTN 0x01
|
||||
#define PFAXP2_ATN 0x04
|
||||
|
||||
#define PSEV_10MS_TIMER 0x02
|
||||
#define PSEV_CON_ON 0x18
|
||||
#define PSEV_CON_OFF 0x19
|
||||
#define PSEV_V24_OFF 0x20
|
||||
#define PSEV_CTS_ON 0x21
|
||||
#define PSEV_CTS_OFF 0x22
|
||||
#define PSEV_DCD_ON 0x23
|
||||
#define PSEV_DCD_OFF 0x24
|
||||
#define PSEV_DSR_ON 0x25
|
||||
#define PSEV_DSR_OFF 0x26
|
||||
#define PSEV_REM_RET 0xcc
|
||||
#define PSEV_REM_REN 0xcd
|
||||
#define PSEV_GSTN_CLR 0xd4
|
||||
|
||||
#define PSEV_RSP_READY 0xbc
|
||||
#define PSEV_LINE_TX_H 0xb3
|
||||
#define PSEV_LINE_TX_B 0xb2
|
||||
#define PSEV_LINE_RX_H 0xb1
|
||||
#define PSEV_LINE_RX_B 0xb0
|
||||
#define PSEV_RSP_CONN 0xb5
|
||||
#define PSEV_RSP_DISC 0xb7
|
||||
#define PSEV_RSP_FCERR 0xb9
|
||||
#define PSEV_RSP_SILDET 0xbe
|
||||
#define PSEV_RSP_SILOFF 0xab
|
||||
#define PSEV_FLAGS_DET 0xba
|
||||
|
||||
#define PCTRL_CMD_TDTMF 0x5a
|
||||
|
||||
#define PCTRL_CMD_FTH 0xa7
|
||||
#define PCTRL_CMD_FRH 0xa5
|
||||
#define PCTRL_CMD_FTM 0xa8
|
||||
#define PCTRL_CMD_FRM 0xa6
|
||||
#define PCTRL_CMD_SILON 0xac
|
||||
#define PCTRL_CMD_CONT 0xa2
|
||||
#define PCTRL_CMD_ESC 0xa4
|
||||
#define PCTRL_CMD_SILOFF 0xab
|
||||
#define PCTRL_CMD_HALT 0xa9
|
||||
|
||||
#define PCTRL_LOC_RET 0xcf
|
||||
#define PCTRL_LOC_REN 0xce
|
||||
|
||||
#define SMODE_DISABLE 0
|
||||
#define SMODE_V14 2
|
||||
#define SMODE_HDLC 3
|
||||
#define SMODE_BINARY 4
|
||||
#define SMODE_FSK_V14 5
|
||||
|
||||
#define SCTRL_HDMC_BOTH 0x00
|
||||
#define SCTRL_HDMC_DTX 0x80
|
||||
#define SCTRL_HDMC_DRX 0x40
|
||||
#define S_P1_OVSP 0x40
|
||||
#define S_P1_SNP 0x20
|
||||
#define S_P1_EOP 0x10
|
||||
#define S_P1_EDP 0x08
|
||||
#define S_P1_NSB 0x04
|
||||
#define S_P1_CHS_8 0x03
|
||||
#define S_P1_CHS_7 0x02
|
||||
#define S_P1_CHS_6 0x01
|
||||
#define S_P1_CHS_5 0x00
|
||||
|
||||
#define S_P2_BFT_DEF 0x10
|
||||
|
||||
#define IOM_CTRL_ENA 0x80
|
||||
#define IOM_CTRL_NOPCM 0x00
|
||||
#define IOM_CTRL_ALAW 0x02
|
||||
#define IOM_CTRL_ULAW 0x04
|
||||
#define IOM_CTRL_RCV 0x01
|
||||
|
||||
#define IOM_P1_TXD 0x10
|
||||
|
||||
#define HDLC_FED 0x40
|
||||
#define HDLC_FSD 0x20
|
||||
#define HDLC_FST 0x20
|
||||
#define HDLC_ERROR 0x1c
|
||||
#define HDLC_ERR_FAD 0x10
|
||||
#define HDLC_ERR_RER 0x08
|
||||
#define HDLC_ERR_CER 0x04
|
||||
#define SART_NMD 0x01
|
||||
|
||||
#define BSTAT_RDM0 0x1
|
||||
#define BSTAT_RDM1 0x2
|
||||
#define BSTAT_RDM2 0x4
|
||||
#define BSTAT_RDM3 0x8
|
||||
#define BSTEV_TBO 0x1f
|
||||
#define BSTEV_RBO 0x2f
|
||||
|
||||
/* FAX State Machine */
|
||||
#define STFAX_NULL 0
|
||||
#define STFAX_READY 1
|
||||
#define STFAX_LINE 2
|
||||
#define STFAX_CONT 3
|
||||
#define STFAX_ACTIV 4
|
||||
#define STFAX_ESCAPE 5
|
||||
#define STFAX_SILDET 6
|
||||
|
||||
extern u32 mISDNisar_init(struct isar_hw *, void *);
|
||||
extern void mISDNisar_irq(struct isar_hw *);
|
1178
drivers/isdn/hardware/mISDN/mISDNinfineon.c
Normal file
1178
drivers/isdn/hardware/mISDN/mISDNinfineon.c
Normal file
File diff suppressed because it is too large
Load Diff
1655
drivers/isdn/hardware/mISDN/mISDNipac.c
Normal file
1655
drivers/isdn/hardware/mISDN/mISDNipac.c
Normal file
File diff suppressed because it is too large
Load Diff
1726
drivers/isdn/hardware/mISDN/mISDNisar.c
Normal file
1726
drivers/isdn/hardware/mISDN/mISDNisar.c
Normal file
File diff suppressed because it is too large
Load Diff
1156
drivers/isdn/hardware/mISDN/netjet.c
Normal file
1156
drivers/isdn/hardware/mISDN/netjet.c
Normal file
File diff suppressed because it is too large
Load Diff
58
drivers/isdn/hardware/mISDN/netjet.h
Normal file
58
drivers/isdn/hardware/mISDN/netjet.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* NETjet common header file
|
||||
*
|
||||
* Author Karsten Keil
|
||||
* based on work of Matt Henderson and Daniel Potts,
|
||||
* Traverse Technologies P/L www.traverse.com.au
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define NJ_CTRL 0x00
|
||||
#define NJ_DMACTRL 0x01
|
||||
#define NJ_AUXCTRL 0x02
|
||||
#define NJ_AUXDATA 0x03
|
||||
#define NJ_IRQMASK0 0x04
|
||||
#define NJ_IRQMASK1 0x05
|
||||
#define NJ_IRQSTAT0 0x06
|
||||
#define NJ_IRQSTAT1 0x07
|
||||
#define NJ_DMA_READ_START 0x08
|
||||
#define NJ_DMA_READ_IRQ 0x0c
|
||||
#define NJ_DMA_READ_END 0x10
|
||||
#define NJ_DMA_READ_ADR 0x14
|
||||
#define NJ_DMA_WRITE_START 0x18
|
||||
#define NJ_DMA_WRITE_IRQ 0x1c
|
||||
#define NJ_DMA_WRITE_END 0x20
|
||||
#define NJ_DMA_WRITE_ADR 0x24
|
||||
#define NJ_PULSE_CNT 0x28
|
||||
|
||||
#define NJ_ISAC_OFF 0xc0
|
||||
#define NJ_ISACIRQ 0x10
|
||||
|
||||
#define NJ_IRQM0_RD_MASK 0x03
|
||||
#define NJ_IRQM0_RD_IRQ 0x01
|
||||
#define NJ_IRQM0_RD_END 0x02
|
||||
#define NJ_IRQM0_WR_MASK 0x0c
|
||||
#define NJ_IRQM0_WR_IRQ 0x04
|
||||
#define NJ_IRQM0_WR_END 0x08
|
||||
|
||||
/* one page here is no need to be smaller */
|
||||
#define NJ_DMA_SIZE 4096
|
||||
/* 2 * 64 byte is a compromise between IRQ count and latency */
|
||||
#define NJ_DMA_RXSIZE 128 /* 2 * 64 */
|
||||
#define NJ_DMA_TXSIZE 128 /* 2 * 64 */
|
||||
|
526
drivers/isdn/hardware/mISDN/speedfax.c
Normal file
526
drivers/isdn/hardware/mISDN/speedfax.c
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* speedfax.c low level stuff for Sedlbauer Speedfax+ cards
|
||||
* based on the ISAR DSP
|
||||
* Thanks to Sedlbauer AG for informations and HW
|
||||
*
|
||||
* Author Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mISDNhw.h>
|
||||
#include <linux/firmware.h>
|
||||
#include "ipac.h"
|
||||
#include "isar.h"
|
||||
|
||||
#define SPEEDFAX_REV "2.0"
|
||||
|
||||
#define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51
|
||||
#define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54
|
||||
#define PCI_SUB_ID_SEDLBAUER 0x01
|
||||
|
||||
#define SFAX_PCI_ADDR 0xc8
|
||||
#define SFAX_PCI_ISAC 0xd0
|
||||
#define SFAX_PCI_ISAR 0xe0
|
||||
|
||||
/* TIGER 100 Registers */
|
||||
|
||||
#define TIGER_RESET_ADDR 0x00
|
||||
#define TIGER_EXTERN_RESET_ON 0x01
|
||||
#define TIGER_EXTERN_RESET_OFF 0x00
|
||||
#define TIGER_AUX_CTRL 0x02
|
||||
#define TIGER_AUX_DATA 0x03
|
||||
#define TIGER_AUX_IRQMASK 0x05
|
||||
#define TIGER_AUX_STATUS 0x07
|
||||
|
||||
/* Tiger AUX BITs */
|
||||
#define SFAX_AUX_IOMASK 0xdd /* 1 and 5 are inputs */
|
||||
#define SFAX_ISAR_RESET_BIT_OFF 0x00
|
||||
#define SFAX_ISAR_RESET_BIT_ON 0x01
|
||||
#define SFAX_TIGER_IRQ_BIT 0x02
|
||||
#define SFAX_LED1_BIT 0x08
|
||||
#define SFAX_LED2_BIT 0x10
|
||||
|
||||
#define SFAX_PCI_RESET_ON (SFAX_ISAR_RESET_BIT_ON)
|
||||
#define SFAX_PCI_RESET_OFF (SFAX_LED1_BIT | SFAX_LED2_BIT)
|
||||
|
||||
static int sfax_cnt;
|
||||
static u32 debug;
|
||||
static u32 irqloops = 4;
|
||||
|
||||
struct sfax_hw {
|
||||
struct list_head list;
|
||||
struct pci_dev *pdev;
|
||||
char name[MISDN_MAX_IDLEN];
|
||||
u32 irq;
|
||||
u32 irqcnt;
|
||||
u32 cfg;
|
||||
struct _ioport p_isac;
|
||||
struct _ioport p_isar;
|
||||
u8 aux_data;
|
||||
spinlock_t lock; /* HW access lock */
|
||||
struct isac_hw isac;
|
||||
struct isar_hw isar;
|
||||
};
|
||||
|
||||
static LIST_HEAD(Cards);
|
||||
static DEFINE_RWLOCK(card_lock); /* protect Cards */
|
||||
|
||||
static void
|
||||
_set_debug(struct sfax_hw *card)
|
||||
{
|
||||
card->isac.dch.debug = debug;
|
||||
card->isar.ch[0].bch.debug = debug;
|
||||
card->isar.ch[1].bch.debug = debug;
|
||||
}
|
||||
|
||||
static int
|
||||
set_debug(const char *val, struct kernel_param *kp)
|
||||
{
|
||||
int ret;
|
||||
struct sfax_hw *card;
|
||||
|
||||
ret = param_set_uint(val, kp);
|
||||
if (!ret) {
|
||||
read_lock(&card_lock);
|
||||
list_for_each_entry(card, &Cards, list)
|
||||
_set_debug(card);
|
||||
read_unlock(&card_lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Karsten Keil");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_VERSION(SPEEDFAX_REV);
|
||||
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Speedfax debug mask");
|
||||
module_param(irqloops, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(irqloops, "Speedfax maximal irqloops (default 4)");
|
||||
|
||||
IOFUNC_IND(ISAC, sfax_hw, p_isac)
|
||||
IOFUNC_IND(ISAR, sfax_hw, p_isar)
|
||||
|
||||
static irqreturn_t
|
||||
speedfax_irq(int intno, void *dev_id)
|
||||
{
|
||||
struct sfax_hw *sf = dev_id;
|
||||
u8 val;
|
||||
int cnt = irqloops;
|
||||
|
||||
spin_lock(&sf->lock);
|
||||
val = inb(sf->cfg + TIGER_AUX_STATUS);
|
||||
if (val & SFAX_TIGER_IRQ_BIT) { /* for us or shared ? */
|
||||
spin_unlock(&sf->lock);
|
||||
return IRQ_NONE; /* shared */
|
||||
}
|
||||
sf->irqcnt++;
|
||||
val = ReadISAR_IND(sf, ISAR_IRQBIT);
|
||||
Start_ISAR:
|
||||
if (val & ISAR_IRQSTA)
|
||||
mISDNisar_irq(&sf->isar);
|
||||
val = ReadISAC_IND(sf, ISAC_ISTA);
|
||||
if (val)
|
||||
mISDNisac_irq(&sf->isac, val);
|
||||
val = ReadISAR_IND(sf, ISAR_IRQBIT);
|
||||
if ((val & ISAR_IRQSTA) && cnt--)
|
||||
goto Start_ISAR;
|
||||
if (cnt < irqloops)
|
||||
pr_debug("%s: %d irqloops cpu%d\n", sf->name,
|
||||
irqloops - cnt, smp_processor_id());
|
||||
if (irqloops && !cnt)
|
||||
pr_notice("%s: %d IRQ LOOP cpu%d\n", sf->name,
|
||||
irqloops, smp_processor_id());
|
||||
spin_unlock(&sf->lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void
|
||||
enable_hwirq(struct sfax_hw *sf)
|
||||
{
|
||||
WriteISAC_IND(sf, ISAC_MASK, 0);
|
||||
WriteISAR_IND(sf, ISAR_IRQBIT, ISAR_IRQMSK);
|
||||
outb(SFAX_TIGER_IRQ_BIT, sf->cfg + TIGER_AUX_IRQMASK);
|
||||
}
|
||||
|
||||
static void
|
||||
disable_hwirq(struct sfax_hw *sf)
|
||||
{
|
||||
WriteISAC_IND(sf, ISAC_MASK, 0xFF);
|
||||
WriteISAR_IND(sf, ISAR_IRQBIT, 0);
|
||||
outb(0, sf->cfg + TIGER_AUX_IRQMASK);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_speedfax(struct sfax_hw *sf)
|
||||
{
|
||||
|
||||
pr_debug("%s: resetting card\n", sf->name);
|
||||
outb(TIGER_EXTERN_RESET_ON, sf->cfg + TIGER_RESET_ADDR);
|
||||
outb(SFAX_PCI_RESET_ON, sf->cfg + TIGER_AUX_DATA);
|
||||
mdelay(1);
|
||||
outb(TIGER_EXTERN_RESET_OFF, sf->cfg + TIGER_RESET_ADDR);
|
||||
sf->aux_data = SFAX_PCI_RESET_OFF;
|
||||
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
static int
|
||||
sfax_ctrl(struct sfax_hw *sf, u32 cmd, u_long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case HW_RESET_REQ:
|
||||
reset_speedfax(sf);
|
||||
break;
|
||||
case HW_ACTIVATE_IND:
|
||||
if (arg & 1)
|
||||
sf->aux_data &= ~SFAX_LED1_BIT;
|
||||
if (arg & 2)
|
||||
sf->aux_data &= ~SFAX_LED2_BIT;
|
||||
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
|
||||
break;
|
||||
case HW_DEACT_IND:
|
||||
if (arg & 1)
|
||||
sf->aux_data |= SFAX_LED1_BIT;
|
||||
if (arg & 2)
|
||||
sf->aux_data |= SFAX_LED2_BIT;
|
||||
outb(sf->aux_data, sf->cfg + TIGER_AUX_DATA);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: %s unknown command %x %lx\n",
|
||||
sf->name, __func__, cmd, arg);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
channel_ctrl(struct sfax_hw *sf, struct mISDN_ctrl_req *cq)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (cq->op) {
|
||||
case MISDN_CTRL_GETOP:
|
||||
cq->op = MISDN_CTRL_LOOP;
|
||||
break;
|
||||
case MISDN_CTRL_LOOP:
|
||||
/* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */
|
||||
if (cq->channel < 0 || cq->channel > 3) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
ret = sf->isac.ctrl(&sf->isac, HW_TESTLOOP, cq->channel);
|
||||
break;
|
||||
default:
|
||||
pr_info("%s: unknown Op %x\n", sf->name, cq->op);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
sfax_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
|
||||
{
|
||||
struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D);
|
||||
struct dchannel *dch = container_of(dev, struct dchannel, dev);
|
||||
struct sfax_hw *sf = dch->hw;
|
||||
struct channel_req *rq;
|
||||
int err = 0;
|
||||
|
||||
pr_debug("%s: cmd:%x %p\n", sf->name, cmd, arg);
|
||||
switch (cmd) {
|
||||
case OPEN_CHANNEL:
|
||||
rq = arg;
|
||||
if (rq->protocol == ISDN_P_TE_S0)
|
||||
err = sf->isac.open(&sf->isac, rq);
|
||||
else
|
||||
err = sf->isar.open(&sf->isar, rq);
|
||||
if (err)
|
||||
break;
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
pr_info("%s: cannot get module\n", sf->name);
|
||||
break;
|
||||
case CLOSE_CHANNEL:
|
||||
pr_debug("%s: dev(%d) close from %p\n", sf->name,
|
||||
dch->dev.id, __builtin_return_address(0));
|
||||
module_put(THIS_MODULE);
|
||||
break;
|
||||
case CONTROL_CHANNEL:
|
||||
err = channel_ctrl(sf, arg);
|
||||
break;
|
||||
default:
|
||||
pr_debug("%s: unknown command %x\n", sf->name, cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
init_card(struct sfax_hw *sf)
|
||||
{
|
||||
int ret, cnt = 3;
|
||||
u_long flags;
|
||||
|
||||
ret = request_irq(sf->irq, speedfax_irq, IRQF_SHARED, sf->name, sf);
|
||||
if (ret) {
|
||||
pr_info("%s: couldn't get interrupt %d\n", sf->name, sf->irq);
|
||||
return ret;
|
||||
}
|
||||
while (cnt--) {
|
||||
spin_lock_irqsave(&sf->lock, flags);
|
||||
ret = sf->isac.init(&sf->isac);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&sf->lock, flags);
|
||||
pr_info("%s: ISAC init failed with %d\n",
|
||||
sf->name, ret);
|
||||
break;
|
||||
}
|
||||
enable_hwirq(sf);
|
||||
/* RESET Receiver and Transmitter */
|
||||
WriteISAC_IND(sf, ISAC_CMDR, 0x41);
|
||||
spin_unlock_irqrestore(&sf->lock, flags);
|
||||
msleep_interruptible(10);
|
||||
if (debug & DEBUG_HW)
|
||||
pr_notice("%s: IRQ %d count %d\n", sf->name,
|
||||
sf->irq, sf->irqcnt);
|
||||
if (!sf->irqcnt) {
|
||||
pr_info("%s: IRQ(%d) got no requests during init %d\n",
|
||||
sf->name, sf->irq, 3 - cnt);
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
free_irq(sf->irq, sf);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
static int __devinit
|
||||
setup_speedfax(struct sfax_hw *sf)
|
||||
{
|
||||
u_long flags;
|
||||
|
||||
if (!request_region(sf->cfg, 256, sf->name)) {
|
||||
pr_info("mISDN: %s config port %x-%x already in use\n",
|
||||
sf->name, sf->cfg, sf->cfg + 255);
|
||||
return -EIO;
|
||||
}
|
||||
outb(0xff, sf->cfg);
|
||||
outb(0, sf->cfg);
|
||||
outb(0xdd, sf->cfg + TIGER_AUX_CTRL);
|
||||
outb(0, sf->cfg + TIGER_AUX_IRQMASK);
|
||||
|
||||
sf->isac.type = IPAC_TYPE_ISAC;
|
||||
sf->p_isac.ale = sf->cfg + SFAX_PCI_ADDR;
|
||||
sf->p_isac.port = sf->cfg + SFAX_PCI_ISAC;
|
||||
sf->p_isar.ale = sf->cfg + SFAX_PCI_ADDR;
|
||||
sf->p_isar.port = sf->cfg + SFAX_PCI_ISAR;
|
||||
ASSIGN_FUNC(IND, ISAC, sf->isac);
|
||||
ASSIGN_FUNC(IND, ISAR, sf->isar);
|
||||
spin_lock_irqsave(&sf->lock, flags);
|
||||
reset_speedfax(sf);
|
||||
disable_hwirq(sf);
|
||||
spin_unlock_irqrestore(&sf->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
release_card(struct sfax_hw *card) {
|
||||
u_long flags;
|
||||
|
||||
spin_lock_irqsave(&card->lock, flags);
|
||||
disable_hwirq(card);
|
||||
spin_unlock_irqrestore(&card->lock, flags);
|
||||
card->isac.release(&card->isac);
|
||||
free_irq(card->irq, card);
|
||||
card->isar.release(&card->isar);
|
||||
mISDN_unregister_device(&card->isac.dch.dev);
|
||||
release_region(card->cfg, 256);
|
||||
pci_disable_device(card->pdev);
|
||||
pci_set_drvdata(card->pdev, NULL);
|
||||
write_lock_irqsave(&card_lock, flags);
|
||||
list_del(&card->list);
|
||||
write_unlock_irqrestore(&card_lock, flags);
|
||||
kfree(card);
|
||||
sfax_cnt--;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
setup_instance(struct sfax_hw *card)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
int i, err;
|
||||
u_long flags;
|
||||
|
||||
snprintf(card->name, MISDN_MAX_IDLEN - 1, "Speedfax.%d", sfax_cnt + 1);
|
||||
write_lock_irqsave(&card_lock, flags);
|
||||
list_add_tail(&card->list, &Cards);
|
||||
write_unlock_irqrestore(&card_lock, flags);
|
||||
_set_debug(card);
|
||||
spin_lock_init(&card->lock);
|
||||
card->isac.hwlock = &card->lock;
|
||||
card->isar.hwlock = &card->lock;
|
||||
card->isar.ctrl = (void *)&sfax_ctrl;
|
||||
card->isac.name = card->name;
|
||||
card->isar.name = card->name;
|
||||
card->isar.owner = THIS_MODULE;
|
||||
|
||||
err = request_firmware(&firmware, "isdn/ISAR.BIN", &card->pdev->dev);
|
||||
if (err < 0) {
|
||||
pr_info("%s: firmware request failed %d\n",
|
||||
card->name, err);
|
||||
goto error_fw;
|
||||
}
|
||||
if (debug & DEBUG_HW)
|
||||
pr_notice("%s: got firmware %zu bytes\n",
|
||||
card->name, firmware->size);
|
||||
|
||||
mISDNisac_init(&card->isac, card);
|
||||
|
||||
card->isac.dch.dev.D.ctrl = sfax_dctrl;
|
||||
card->isac.dch.dev.Bprotocols =
|
||||
mISDNisar_init(&card->isar, card);
|
||||
for (i = 0; i < 2; i++) {
|
||||
set_channelmap(i + 1, card->isac.dch.dev.channelmap);
|
||||
list_add(&card->isar.ch[i].bch.ch.list,
|
||||
&card->isac.dch.dev.bchannels);
|
||||
}
|
||||
|
||||
err = setup_speedfax(card);
|
||||
if (err)
|
||||
goto error_setup;
|
||||
err = card->isar.init(&card->isar);
|
||||
if (err)
|
||||
goto error;
|
||||
err = mISDN_register_device(&card->isac.dch.dev,
|
||||
&card->pdev->dev, card->name);
|
||||
if (err)
|
||||
goto error;
|
||||
err = init_card(card);
|
||||
if (err)
|
||||
goto error_init;
|
||||
err = card->isar.firmware(&card->isar, firmware->data, firmware->size);
|
||||
if (!err) {
|
||||
release_firmware(firmware);
|
||||
sfax_cnt++;
|
||||
pr_notice("SpeedFax %d cards installed\n", sfax_cnt);
|
||||
return 0;
|
||||
}
|
||||
disable_hwirq(card);
|
||||
free_irq(card->irq, card);
|
||||
error_init:
|
||||
mISDN_unregister_device(&card->isac.dch.dev);
|
||||
error:
|
||||
release_region(card->cfg, 256);
|
||||
error_setup:
|
||||
card->isac.release(&card->isac);
|
||||
card->isar.release(&card->isar);
|
||||
release_firmware(firmware);
|
||||
error_fw:
|
||||
pci_disable_device(card->pdev);
|
||||
write_lock_irqsave(&card_lock, flags);
|
||||
list_del(&card->list);
|
||||
write_unlock_irqrestore(&card_lock, flags);
|
||||
kfree(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
sfaxpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
struct sfax_hw *card = kzalloc(sizeof(struct sfax_hw), GFP_KERNEL);
|
||||
|
||||
if (!card) {
|
||||
pr_info("No memory for Speedfax+ PCI\n");
|
||||
return err;
|
||||
}
|
||||
card->pdev = pdev;
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
kfree(card);
|
||||
return err;
|
||||
}
|
||||
|
||||
pr_notice("mISDN: Speedfax found adapter %s at %s\n",
|
||||
(char *)ent->driver_data, pci_name(pdev));
|
||||
|
||||
card->cfg = pci_resource_start(pdev, 0);
|
||||
card->irq = pdev->irq;
|
||||
pci_set_drvdata(pdev, card);
|
||||
err = setup_instance(card);
|
||||
if (err)
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit
|
||||
sfax_remove_pci(struct pci_dev *pdev)
|
||||
{
|
||||
struct sfax_hw *card = pci_get_drvdata(pdev);
|
||||
|
||||
if (card)
|
||||
release_card(card);
|
||||
else
|
||||
pr_debug("%s: drvdata allready removed\n", __func__);
|
||||
}
|
||||
|
||||
static struct pci_device_id sfaxpci_ids[] __devinitdata = {
|
||||
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
|
||||
PCI_SUBVENDOR_SPEEDFAX_PYRAMID, PCI_SUB_ID_SEDLBAUER,
|
||||
0, 0, (unsigned long) "Pyramid Speedfax + PCI"
|
||||
},
|
||||
{ PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
|
||||
PCI_SUBVENDOR_SPEEDFAX_PCI, PCI_SUB_ID_SEDLBAUER,
|
||||
0, 0, (unsigned long) "Sedlbauer Speedfax + PCI"
|
||||
},
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, sfaxpci_ids);
|
||||
|
||||
static struct pci_driver sfaxpci_driver = {
|
||||
.name = "speedfax+ pci",
|
||||
.probe = sfaxpci_probe,
|
||||
.remove = __devexit_p(sfax_remove_pci),
|
||||
.id_table = sfaxpci_ids,
|
||||
};
|
||||
|
||||
static int __init
|
||||
Speedfax_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
pr_notice("Sedlbauer Speedfax+ Driver Rev. %s\n",
|
||||
SPEEDFAX_REV);
|
||||
err = pci_register_driver(&sfaxpci_driver);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
Speedfax_cleanup(void)
|
||||
{
|
||||
pci_unregister_driver(&sfaxpci_driver);
|
||||
}
|
||||
|
||||
module_init(Speedfax_init);
|
||||
module_exit(Speedfax_cleanup);
|
1440
drivers/isdn/hardware/mISDN/w6692.c
Normal file
1440
drivers/isdn/hardware/mISDN/w6692.c
Normal file
File diff suppressed because it is too large
Load Diff
190
drivers/isdn/hardware/mISDN/w6692.h
Normal file
190
drivers/isdn/hardware/mISDN/w6692.h
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Winbond W6692 specific defines
|
||||
*
|
||||
* Author Karsten Keil <keil@isdn4linux.de>
|
||||
* based on the w6692 I4L driver from Petr Novak <petr.novak@i.cz>
|
||||
*
|
||||
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Specifications of W6692 registers */
|
||||
|
||||
#define W_D_RFIFO 0x00 /* R */
|
||||
#define W_D_XFIFO 0x04 /* W */
|
||||
#define W_D_CMDR 0x08 /* W */
|
||||
#define W_D_MODE 0x0c /* R/W */
|
||||
#define W_D_TIMR 0x10 /* R/W */
|
||||
#define W_ISTA 0x14 /* R_clr */
|
||||
#define W_IMASK 0x18 /* R/W */
|
||||
#define W_D_EXIR 0x1c /* R_clr */
|
||||
#define W_D_EXIM 0x20 /* R/W */
|
||||
#define W_D_STAR 0x24 /* R */
|
||||
#define W_D_RSTA 0x28 /* R */
|
||||
#define W_D_SAM 0x2c /* R/W */
|
||||
#define W_D_SAP1 0x30 /* R/W */
|
||||
#define W_D_SAP2 0x34 /* R/W */
|
||||
#define W_D_TAM 0x38 /* R/W */
|
||||
#define W_D_TEI1 0x3c /* R/W */
|
||||
#define W_D_TEI2 0x40 /* R/W */
|
||||
#define W_D_RBCH 0x44 /* R */
|
||||
#define W_D_RBCL 0x48 /* R */
|
||||
#define W_TIMR2 0x4c /* W */
|
||||
#define W_L1_RC 0x50 /* R/W */
|
||||
#define W_D_CTL 0x54 /* R/W */
|
||||
#define W_CIR 0x58 /* R */
|
||||
#define W_CIX 0x5c /* W */
|
||||
#define W_SQR 0x60 /* R */
|
||||
#define W_SQX 0x64 /* W */
|
||||
#define W_PCTL 0x68 /* R/W */
|
||||
#define W_MOR 0x6c /* R */
|
||||
#define W_MOX 0x70 /* R/W */
|
||||
#define W_MOSR 0x74 /* R_clr */
|
||||
#define W_MOCR 0x78 /* R/W */
|
||||
#define W_GCR 0x7c /* R/W */
|
||||
|
||||
#define W_B_RFIFO 0x80 /* R */
|
||||
#define W_B_XFIFO 0x84 /* W */
|
||||
#define W_B_CMDR 0x88 /* W */
|
||||
#define W_B_MODE 0x8c /* R/W */
|
||||
#define W_B_EXIR 0x90 /* R_clr */
|
||||
#define W_B_EXIM 0x94 /* R/W */
|
||||
#define W_B_STAR 0x98 /* R */
|
||||
#define W_B_ADM1 0x9c /* R/W */
|
||||
#define W_B_ADM2 0xa0 /* R/W */
|
||||
#define W_B_ADR1 0xa4 /* R/W */
|
||||
#define W_B_ADR2 0xa8 /* R/W */
|
||||
#define W_B_RBCL 0xac /* R */
|
||||
#define W_B_RBCH 0xb0 /* R */
|
||||
|
||||
#define W_XADDR 0xf4 /* R/W */
|
||||
#define W_XDATA 0xf8 /* R/W */
|
||||
#define W_EPCTL 0xfc /* W */
|
||||
|
||||
/* W6692 register bits */
|
||||
|
||||
#define W_D_CMDR_XRST 0x01
|
||||
#define W_D_CMDR_XME 0x02
|
||||
#define W_D_CMDR_XMS 0x08
|
||||
#define W_D_CMDR_STT 0x10
|
||||
#define W_D_CMDR_RRST 0x40
|
||||
#define W_D_CMDR_RACK 0x80
|
||||
|
||||
#define W_D_MODE_RLP 0x01
|
||||
#define W_D_MODE_DLP 0x02
|
||||
#define W_D_MODE_MFD 0x04
|
||||
#define W_D_MODE_TEE 0x08
|
||||
#define W_D_MODE_TMS 0x10
|
||||
#define W_D_MODE_RACT 0x40
|
||||
#define W_D_MODE_MMS 0x80
|
||||
|
||||
#define W_INT_B2_EXI 0x01
|
||||
#define W_INT_B1_EXI 0x02
|
||||
#define W_INT_D_EXI 0x04
|
||||
#define W_INT_XINT0 0x08
|
||||
#define W_INT_XINT1 0x10
|
||||
#define W_INT_D_XFR 0x20
|
||||
#define W_INT_D_RME 0x40
|
||||
#define W_INT_D_RMR 0x80
|
||||
|
||||
#define W_D_EXI_WEXP 0x01
|
||||
#define W_D_EXI_TEXP 0x02
|
||||
#define W_D_EXI_ISC 0x04
|
||||
#define W_D_EXI_MOC 0x08
|
||||
#define W_D_EXI_TIN2 0x10
|
||||
#define W_D_EXI_XCOL 0x20
|
||||
#define W_D_EXI_XDUN 0x40
|
||||
#define W_D_EXI_RDOV 0x80
|
||||
|
||||
#define W_D_STAR_DRDY 0x10
|
||||
#define W_D_STAR_XBZ 0x20
|
||||
#define W_D_STAR_XDOW 0x80
|
||||
|
||||
#define W_D_RSTA_RMB 0x10
|
||||
#define W_D_RSTA_CRCE 0x20
|
||||
#define W_D_RSTA_RDOV 0x40
|
||||
|
||||
#define W_D_CTL_SRST 0x20
|
||||
|
||||
#define W_CIR_SCC 0x80
|
||||
#define W_CIR_ICC 0x40
|
||||
#define W_CIR_COD_MASK 0x0f
|
||||
|
||||
#define W_PCTL_PCX 0x01
|
||||
#define W_PCTL_XMODE 0x02
|
||||
#define W_PCTL_OE0 0x04
|
||||
#define W_PCTL_OE1 0x08
|
||||
#define W_PCTL_OE2 0x10
|
||||
#define W_PCTL_OE3 0x20
|
||||
#define W_PCTL_OE4 0x40
|
||||
#define W_PCTL_OE5 0x80
|
||||
|
||||
#define W_B_CMDR_XRST 0x01
|
||||
#define W_B_CMDR_XME 0x02
|
||||
#define W_B_CMDR_XMS 0x04
|
||||
#define W_B_CMDR_RACT 0x20
|
||||
#define W_B_CMDR_RRST 0x40
|
||||
#define W_B_CMDR_RACK 0x80
|
||||
|
||||
#define W_B_MODE_FTS0 0x01
|
||||
#define W_B_MODE_FTS1 0x02
|
||||
#define W_B_MODE_SW56 0x04
|
||||
#define W_B_MODE_BSW0 0x08
|
||||
#define W_B_MODE_BSW1 0x10
|
||||
#define W_B_MODE_EPCM 0x20
|
||||
#define W_B_MODE_ITF 0x40
|
||||
#define W_B_MODE_MMS 0x80
|
||||
|
||||
#define W_B_EXI_XDUN 0x01
|
||||
#define W_B_EXI_XFR 0x02
|
||||
#define W_B_EXI_RDOV 0x10
|
||||
#define W_B_EXI_RME 0x20
|
||||
#define W_B_EXI_RMR 0x40
|
||||
|
||||
#define W_B_STAR_XBZ 0x01
|
||||
#define W_B_STAR_XDOW 0x04
|
||||
#define W_B_STAR_RMB 0x10
|
||||
#define W_B_STAR_CRCE 0x20
|
||||
#define W_B_STAR_RDOV 0x40
|
||||
|
||||
#define W_B_RBCH_LOV 0x20
|
||||
|
||||
/* W6692 Layer1 commands */
|
||||
|
||||
#define W_L1CMD_ECK 0x00
|
||||
#define W_L1CMD_RST 0x01
|
||||
#define W_L1CMD_SCP 0x04
|
||||
#define W_L1CMD_SSP 0x02
|
||||
#define W_L1CMD_AR8 0x08
|
||||
#define W_L1CMD_AR10 0x09
|
||||
#define W_L1CMD_EAL 0x0a
|
||||
#define W_L1CMD_DRC 0x0f
|
||||
|
||||
/* W6692 Layer1 indications */
|
||||
|
||||
#define W_L1IND_CE 0x07
|
||||
#define W_L1IND_DRD 0x00
|
||||
#define W_L1IND_LD 0x04
|
||||
#define W_L1IND_ARD 0x08
|
||||
#define W_L1IND_TI 0x0a
|
||||
#define W_L1IND_ATI 0x0b
|
||||
#define W_L1IND_AI8 0x0c
|
||||
#define W_L1IND_AI10 0x0d
|
||||
#define W_L1IND_CD 0x0f
|
||||
|
||||
/* FIFO thresholds */
|
||||
#define W_D_FIFO_THRESH 64
|
||||
#define W_B_FIFO_THRESH 64
|
@ -391,6 +391,7 @@ comment "HiSax sub driver modules"
|
||||
config HISAX_ST5481
|
||||
tristate "ST5481 USB ISDN modem (EXPERIMENTAL)"
|
||||
depends on USB && EXPERIMENTAL
|
||||
select ISDN_HDLC
|
||||
select CRC_CCITT
|
||||
select BITREVERSE
|
||||
help
|
||||
@ -418,11 +419,6 @@ config HISAX_FRITZ_PCIPNP
|
||||
(the latter also needs you to select "ISA Plug and Play support"
|
||||
from the menu "Plug and Play configuration")
|
||||
|
||||
config HISAX_HDLC
|
||||
bool
|
||||
depends on HISAX_ST5481
|
||||
default y
|
||||
|
||||
config HISAX_AVM_A1_PCMCIA
|
||||
bool
|
||||
depends on HISAX_AVM_A1_CS
|
||||
|
@ -16,10 +16,6 @@ obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o
|
||||
obj-$(CONFIG_HISAX_HFC4S8S) += hfc4s8s_l1.o
|
||||
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o
|
||||
|
||||
ifdef CONFIG_HISAX_HDLC
|
||||
obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o
|
||||
endif
|
||||
|
||||
# Multipart objects.
|
||||
|
||||
hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \
|
||||
|
@ -238,8 +238,6 @@ Amd7930_bh(struct work_struct *work)
|
||||
container_of(work, struct IsdnCardState, tqueue);
|
||||
struct PStack *stptr;
|
||||
|
||||
if (!cs)
|
||||
return;
|
||||
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
|
||||
if (cs->debug)
|
||||
debugl1(cs, "Amd7930: bh, D-Channel Busy cleared");
|
||||
|
@ -833,8 +833,6 @@ static struct FsmNode fnlist[] __initdata =
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
|
||||
|
||||
int __init
|
||||
CallcNew(void)
|
||||
{
|
||||
@ -842,7 +840,7 @@ CallcNew(void)
|
||||
callcfsm.event_count = EVENT_COUNT;
|
||||
callcfsm.strEvent = strEvent;
|
||||
callcfsm.strState = strState;
|
||||
return FsmNew(&callcfsm, fnlist, FNCOUNT);
|
||||
return FsmNew(&callcfsm, fnlist, ARRAY_SIZE(fnlist));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1506,8 +1506,6 @@ hfcpci_bh(struct work_struct *work)
|
||||
u_long flags;
|
||||
// struct PStack *stptr;
|
||||
|
||||
if (!cs)
|
||||
return;
|
||||
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
|
||||
if (!cs->hw.hfcpci.nt_mode)
|
||||
switch (cs->dc.hfcpci.ph_state) {
|
||||
|
@ -1255,8 +1255,6 @@ hfcsx_bh(struct work_struct *work)
|
||||
container_of(work, struct IsdnCardState, tqueue);
|
||||
u_long flags;
|
||||
|
||||
if (!cs)
|
||||
return;
|
||||
if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
|
||||
if (!cs->hw.hfcsx.nt_mode)
|
||||
switch (cs->dc.hfcsx.ph_state) {
|
||||
|
@ -83,8 +83,6 @@ icc_bh(struct work_struct *work)
|
||||
container_of(work, struct IsdnCardState, tqueue);
|
||||
struct PStack *stptr;
|
||||
|
||||
if (!cs)
|
||||
return;
|
||||
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
|
||||
if (cs->debug)
|
||||
debugl1(cs, "D-Channel Busy cleared");
|
||||
|
@ -86,8 +86,6 @@ isac_bh(struct work_struct *work)
|
||||
container_of(work, struct IsdnCardState, tqueue);
|
||||
struct PStack *stptr;
|
||||
|
||||
if (!cs)
|
||||
return;
|
||||
if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
|
||||
if (cs->debug)
|
||||
debugl1(cs, "D-Channel Busy cleared");
|
||||
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* isdnhdlc.h -- General purpose ISDN HDLC decoder.
|
||||
*
|
||||
* Implementation of a HDLC decoder/encoder in software.
|
||||
* Neccessary because some ISDN devices don't have HDLC
|
||||
* controllers. Also included: a bit reversal table.
|
||||
*
|
||||
*Copyright (C) 2002 Wolfgang Mües <wolfgang@iksw-muees.de>
|
||||
* 2001 Frode Isaksen <fisaksen@bewan.com>
|
||||
* 2001 Kai Germaschewski <kai.germaschewski@gmx.de>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ISDNHDLC_H__
|
||||
#define __ISDNHDLC_H__
|
||||
|
||||
struct isdnhdlc_vars {
|
||||
int bit_shift;
|
||||
int hdlc_bits1;
|
||||
int data_bits;
|
||||
int ffbit_shift; // encoding only
|
||||
int state;
|
||||
int dstpos;
|
||||
|
||||
unsigned short crc;
|
||||
|
||||
unsigned char cbin;
|
||||
unsigned char shift_reg;
|
||||
unsigned char ffvalue;
|
||||
|
||||
unsigned int data_received:1; // set if transferring data
|
||||
unsigned int dchannel:1; // set if D channel (send idle instead of flags)
|
||||
unsigned int do_adapt56:1; // set if 56K adaptation
|
||||
unsigned int do_closing:1; // set if in closing phase (need to send CRC + flag
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
The return value from isdnhdlc_decode is
|
||||
the frame length, 0 if no complete frame was decoded,
|
||||
or a negative error number
|
||||
*/
|
||||
#define HDLC_FRAMING_ERROR 1
|
||||
#define HDLC_CRC_ERROR 2
|
||||
#define HDLC_LENGTH_ERROR 3
|
||||
|
||||
extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56);
|
||||
|
||||
extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
|
||||
unsigned char *dst, int dsize);
|
||||
|
||||
extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56);
|
||||
|
||||
extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
|
||||
unsigned char *dst,int dsize);
|
||||
|
||||
#endif /* __ISDNHDLC_H__ */
|
@ -647,8 +647,6 @@ static struct FsmNode L1SFnList[] __initdata =
|
||||
{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
|
||||
};
|
||||
|
||||
#define L1S_FN_COUNT (sizeof(L1SFnList)/sizeof(struct FsmNode))
|
||||
|
||||
#ifdef HISAX_UINTERFACE
|
||||
static void
|
||||
l1_deact_req_u(struct FsmInst *fi, int event, void *arg)
|
||||
@ -706,8 +704,6 @@ static struct FsmNode L1UFnList[] __initdata =
|
||||
{ST_L1_RESET, EV_TIMER_DEACT, l1_timer_deact},
|
||||
};
|
||||
|
||||
#define L1U_FN_COUNT (sizeof(L1UFnList)/sizeof(struct FsmNode))
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
@ -754,8 +750,6 @@ static struct FsmNode L1BFnList[] __initdata =
|
||||
{ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
|
||||
};
|
||||
|
||||
#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
|
||||
|
||||
int __init
|
||||
Isdnl1New(void)
|
||||
{
|
||||
@ -765,7 +759,7 @@ Isdnl1New(void)
|
||||
l1fsm_s.event_count = L1_EVENT_COUNT;
|
||||
l1fsm_s.strEvent = strL1Event;
|
||||
l1fsm_s.strState = strL1SState;
|
||||
retval = FsmNew(&l1fsm_s, L1SFnList, L1S_FN_COUNT);
|
||||
retval = FsmNew(&l1fsm_s, L1SFnList, ARRAY_SIZE(L1SFnList));
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
@ -773,7 +767,7 @@ Isdnl1New(void)
|
||||
l1fsm_b.event_count = L1_EVENT_COUNT;
|
||||
l1fsm_b.strEvent = strL1Event;
|
||||
l1fsm_b.strState = strL1BState;
|
||||
retval = FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
|
||||
retval = FsmNew(&l1fsm_b, L1BFnList, ARRAY_SIZE(L1BFnList));
|
||||
if (retval) {
|
||||
FsmFree(&l1fsm_s);
|
||||
return retval;
|
||||
@ -783,7 +777,7 @@ Isdnl1New(void)
|
||||
l1fsm_u.event_count = L1_EVENT_COUNT;
|
||||
l1fsm_u.strEvent = strL1Event;
|
||||
l1fsm_u.strState = strL1UState;
|
||||
retval = FsmNew(&l1fsm_u, L1UFnList, L1U_FN_COUNT);
|
||||
retval = FsmNew(&l1fsm_u, L1UFnList, ARRAY_SIZE(L1UFnList));
|
||||
if (retval) {
|
||||
FsmFree(&l1fsm_s);
|
||||
FsmFree(&l1fsm_b);
|
||||
|
@ -1623,8 +1623,6 @@ static struct FsmNode L2FnList[] __initdata =
|
||||
{ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da},
|
||||
};
|
||||
|
||||
#define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode))
|
||||
|
||||
static void
|
||||
isdnl2_l1l2(struct PStack *st, int pr, void *arg)
|
||||
{
|
||||
@ -1836,7 +1834,7 @@ Isdnl2New(void)
|
||||
l2fsm.event_count = L2_EVENT_COUNT;
|
||||
l2fsm.strEvent = strL2Event;
|
||||
l2fsm.strState = strL2State;
|
||||
return FsmNew(&l2fsm, L2FnList, L2_FN_COUNT);
|
||||
return FsmNew(&l2fsm, L2FnList, ARRAY_SIZE(L2FnList));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -543,8 +543,6 @@ static struct FsmNode L3FnList[] __initdata =
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
|
||||
|
||||
void
|
||||
l3_msg(struct PStack *st, int pr, void *arg)
|
||||
{
|
||||
@ -587,7 +585,7 @@ Isdnl3New(void)
|
||||
l3fsm.event_count = L3_EVENT_COUNT;
|
||||
l3fsm.strEvent = strL3Event;
|
||||
l3fsm.strState = strL3State;
|
||||
return FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
|
||||
return FsmNew(&l3fsm, L3FnList, ARRAY_SIZE(L3FnList));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -698,9 +698,6 @@ static struct stateentry downstl[] =
|
||||
CC_T308_2, l3_1tr6_t308_2},
|
||||
};
|
||||
|
||||
#define DOWNSTL_LEN \
|
||||
(sizeof(downstl) / sizeof(struct stateentry))
|
||||
|
||||
static struct stateentry datastln1[] =
|
||||
{
|
||||
{SBIT(0),
|
||||
@ -735,9 +732,6 @@ static struct stateentry datastln1[] =
|
||||
MT_N1_REL_ACK, l3_1tr6_rel_ack}
|
||||
};
|
||||
|
||||
#define DATASTLN1_LEN \
|
||||
(sizeof(datastln1) / sizeof(struct stateentry))
|
||||
|
||||
static struct stateentry manstatelist[] =
|
||||
{
|
||||
{SBIT(2),
|
||||
@ -746,8 +740,6 @@ static struct stateentry manstatelist[] =
|
||||
DL_RELEASE | INDICATION, l3_1tr6_dl_release},
|
||||
};
|
||||
|
||||
#define MANSLLEN \
|
||||
(sizeof(manstatelist) / sizeof(struct stateentry))
|
||||
/* *INDENT-ON* */
|
||||
|
||||
static void
|
||||
@ -840,11 +832,11 @@ up1tr6(struct PStack *st, int pr, void *arg)
|
||||
mt = MT_N1_INVALID;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < DATASTLN1_LEN; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(datastln1); i++)
|
||||
if ((mt == datastln1[i].primitive) &&
|
||||
((1 << proc->state) & datastln1[i].state))
|
||||
break;
|
||||
if (i == DATASTLN1_LEN) {
|
||||
if (i == ARRAY_SIZE(datastln1)) {
|
||||
dev_kfree_skb(skb);
|
||||
if (st->l3.debug & L3_DEB_STATE) {
|
||||
sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
|
||||
@ -892,11 +884,11 @@ down1tr6(struct PStack *st, int pr, void *arg)
|
||||
proc = arg;
|
||||
}
|
||||
|
||||
for (i = 0; i < DOWNSTL_LEN; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(downstl); i++)
|
||||
if ((pr == downstl[i].primitive) &&
|
||||
((1 << proc->state) & downstl[i].state))
|
||||
break;
|
||||
if (i == DOWNSTL_LEN) {
|
||||
if (i == ARRAY_SIZE(downstl)) {
|
||||
if (st->l3.debug & L3_DEB_STATE) {
|
||||
sprintf(tmp, "down1tr6 state %d prim %d unhandled",
|
||||
proc->state, pr);
|
||||
@ -922,11 +914,11 @@ man1tr6(struct PStack *st, int pr, void *arg)
|
||||
printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < MANSLLEN; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(manstatelist); i++)
|
||||
if ((pr == manstatelist[i].primitive) &&
|
||||
((1 << proc->state) & manstatelist[i].state))
|
||||
break;
|
||||
if (i == MANSLLEN) {
|
||||
if (i == ARRAY_SIZE(manstatelist)) {
|
||||
if (st->l3.debug & L3_DEB_STATE) {
|
||||
l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
|
||||
proc->callref & 0x7f, proc->state, pr);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user