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/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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");
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
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);
|
||||
|
|
|
@ -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
|
|
@ -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);
|
|
@ -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 *);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
||||
|
|
@ -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);
|
File diff suppressed because it is too large
Load Diff
|
@ -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