Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4bcb7d97
Commit
4bcb7d97
authored
May 25, 2003
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge redhat.com:/garz/repo/linus-2.5
into redhat.com:/garz/repo/irda-2.5
parents
dc2f9764
2fab8e81
Changes
36
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
3652 additions
and
642 deletions
+3652
-642
drivers/net/irda/Kconfig
drivers/net/irda/Kconfig
+17
-4
drivers/net/irda/Makefile
drivers/net/irda/Makefile
+5
-4
drivers/net/irda/ali-ircc.c
drivers/net/irda/ali-ircc.c
+4
-0
drivers/net/irda/donauboe.c
drivers/net/irda/donauboe.c
+3
-1
drivers/net/irda/irport.c
drivers/net/irda/irport.c
+288
-192
drivers/net/irda/irtty-sir.c
drivers/net/irda/irtty-sir.c
+2
-7
drivers/net/irda/nsc-ircc.c
drivers/net/irda/nsc-ircc.c
+4
-0
drivers/net/irda/sir_kthread.c
drivers/net/irda/sir_kthread.c
+7
-0
drivers/net/irda/smc-ircc.c
drivers/net/irda/smc-ircc.c
+8
-4
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/smsc-ircc2.c
+2441
-0
drivers/net/irda/smsc-ircc2.h
drivers/net/irda/smsc-ircc2.h
+194
-0
drivers/net/irda/smsc-sio.h
drivers/net/irda/smsc-sio.h
+100
-0
drivers/net/irda/w83977af_ir.c
drivers/net/irda/w83977af_ir.c
+2
-0
include/net/irda/iriap.h
include/net/irda/iriap.h
+1
-1
include/net/irda/irlmp_event.h
include/net/irda/irlmp_event.h
+0
-20
include/net/irda/irport.h
include/net/irda/irport.h
+1
-0
net/irda/af_irda.c
net/irda/af_irda.c
+9
-4
net/irda/ircomm/ircomm_core.c
net/irda/ircomm/ircomm_core.c
+18
-18
net/irda/ircomm/ircomm_event.c
net/irda/ircomm/ircomm_event.c
+1
-9
net/irda/ircomm/ircomm_lmp.c
net/irda/ircomm/ircomm_lmp.c
+42
-14
net/irda/ircomm/ircomm_ttp.c
net/irda/ircomm/ircomm_ttp.c
+43
-10
net/irda/ircomm/ircomm_tty.c
net/irda/ircomm/ircomm_tty.c
+15
-6
net/irda/ircomm/ircomm_tty_attach.c
net/irda/ircomm/ircomm_tty_attach.c
+12
-10
net/irda/iriap.c
net/irda/iriap.c
+71
-65
net/irda/iriap_event.c
net/irda/iriap_event.c
+18
-17
net/irda/irlan/irlan_eth.c
net/irda/irlan/irlan_eth.c
+1
-1
net/irda/irlap.c
net/irda/irlap.c
+8
-8
net/irda/irlap_event.c
net/irda/irlap_event.c
+6
-1
net/irda/irlap_frame.c
net/irda/irlap_frame.c
+100
-85
net/irda/irlmp.c
net/irda/irlmp.c
+112
-59
net/irda/irlmp_event.c
net/irda/irlmp_event.c
+18
-23
net/irda/irlmp_frame.c
net/irda/irlmp_frame.c
+5
-18
net/irda/irnet/irnet.h
net/irda/irnet/irnet.h
+6
-0
net/irda/irnet/irnet_irda.c
net/irda/irnet/irnet_irda.c
+15
-15
net/irda/irnet/irnet_ppp.c
net/irda/irnet/irnet_ppp.c
+1
-1
net/irda/irttp.c
net/irda/irttp.c
+74
-45
No files found.
drivers/net/irda/Kconfig
View file @
4bcb7d97
...
...
@@ -289,16 +289,29 @@ config TOSHIBA_FIR
<file:Documentation/modules.txt>.
The module will be called donauboe.
config SMC_IRCC_
FIR
tristate "SMC IrCC (EXPERIMENTAL)"
config SMC_IRCC_
OLD
tristate "SMC IrCC (
old driver) (
EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA
help
Say Y here if you want to build support for the SMC Infrared
Communications Controller. It is used in the Fujitsu Lifebook 635t
and Sony PCG-505TX. If you want to compile it as a module, say M
here and read <file:Documentation/modules.txt>. The module will be
and Sony PCG-505TX. This driver is obsolete, will no more be
maintained and will be removed in favor of the new driver.
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. The module will be
called smc-ircc.
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA
help
Say Y here if you want to build support for the SMC Infrared
Communications Controller. It is used in a wide variety of
laptops (Fujitsu, Sony, Compaq and some Toshiba).
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. The module will be
called smsc-ircc2.o.
config ALI_FIR
tristate "ALi M5123 FIR (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA
...
...
drivers/net/irda/Makefile
View file @
4bcb7d97
...
...
@@ -15,13 +15,14 @@ obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
obj-$(CONFIG_SA1100_FIR)
+=
sa1100_ir.o
obj-$(CONFIG_TOSHIBA_OLD)
+=
toshoboe.o
obj-$(CONFIG_TOSHIBA_FIR)
+=
donauboe.o
obj-$(CONFIG_SMC_IRCC_FIR)
+=
smc-ircc.o irport.o
obj-$(CONFIG_SMC_IRCC_OLD)
+=
smc-ircc.o irport.o
obj-$(CONFIG_SMC_IRCC_FIR)
+=
smsc-ircc2.o
obj-$(CONFIG_ALI_FIR)
+=
ali-ircc.o
obj-$(CONFIG_VLSI_FIR)
+=
vlsi_ir.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_OLD)
+=
esi.o
obj-$(CONFIG_TEKRAM_OLD)
+=
tekram.o
obj-$(CONFIG_ACTISYS_OLD)
+=
actisys.o
obj-$(CONFIG_ESI_
DONGLE_
OLD)
+=
esi.o
obj-$(CONFIG_TEKRAM_
DONGLE_
OLD)
+=
tekram.o
obj-$(CONFIG_ACTISYS_
DONGLE_
OLD)
+=
actisys.o
obj-$(CONFIG_GIRBIL_DONGLE)
+=
girbil.o
obj-$(CONFIG_LITELINK_DONGLE)
+=
litelink.o
obj-$(CONFIG_OLD_BELKIN_DONGLE)
+=
old_belkin.o
...
...
drivers/net/irda/ali-ircc.c
View file @
4bcb7d97
...
...
@@ -1451,6 +1451,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check for empty frame */
if
(
!
skb
->
len
)
{
ali_ircc_change_speed
(
self
,
speed
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -1560,6 +1561,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Restore bank register */
switch_bank
(
iobase
,
BANK0
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
@@ -1974,6 +1976,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check for empty frame */
if
(
!
skb
->
len
)
{
ali_ircc_change_speed
(
self
,
speed
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -1993,6 +1996,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Turn on transmit finished interrupt. Will fire immediately! */
outb
(
UART_IER_THRI
,
iobase
+
UART_IER
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
drivers/net/irda/donauboe.c
View file @
4bcb7d97
...
...
@@ -1051,7 +1051,9 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
toshoboe_checkstuck
(
self
);
/* Check if we need to change the speed */
dev
->
trans_start
=
jiffies
;
/* Check if we need to change the speed */
/* But not now. Wait after transmission if mtt not required */
speed
=
irda_get_next_speed
(
skb
);
if
((
speed
!=
self
->
io
.
speed
)
&&
(
speed
!=
-
1
))
...
...
drivers/net/irda/irport.c
View file @
4bcb7d97
...
...
@@ -11,6 +11,7 @@
* Sources: serial.c by Linus Torvalds
*
* Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -48,6 +49,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/rtnetlink.h>
#include <asm/system.h>
...
...
@@ -72,14 +74,14 @@ static unsigned int qos_mtt_bits = 0x03;
static
struct
irport_cb
*
dev_self
[]
=
{
NULL
,
NULL
,
NULL
,
NULL
};
static
char
*
driver_name
=
"irport"
;
static
void
irport_write_wakeup
(
struct
irport_cb
*
self
);
static
int
irport_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
);
static
void
irport_receive
(
struct
irport_cb
*
self
);
static
inline
void
irport_write_wakeup
(
struct
irport_cb
*
self
);
static
in
line
in
t
irport_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
);
static
inline
void
irport_receive
(
struct
irport_cb
*
self
);
static
int
irport_net_init
(
struct
net_device
*
dev
);
static
int
irport_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
int
irport_is_receiving
(
struct
irport_cb
*
self
);
static
in
line
in
t
irport_is_receiving
(
struct
irport_cb
*
self
);
static
int
irport_set_dtr_rts
(
struct
net_device
*
dev
,
int
dtr
,
int
rts
);
static
int
irport_raw_write
(
struct
net_device
*
dev
,
__u8
*
buf
,
int
len
);
static
struct
net_device_stats
*
irport_net_get_stats
(
struct
net_device
*
dev
);
...
...
@@ -169,7 +171,7 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self
->
io
.
sir_base
=
iobase
;
self
->
io
.
sir_ext
=
IO_EXTENT
;
self
->
io
.
irq
=
irq
;
self
->
io
.
fifo_size
=
16
;
self
->
io
.
fifo_size
=
16
;
/* 16550A and compatible */
/* Initialize QoS for this device */
irda_init_max_qos_capabilies
(
&
self
->
qos
);
...
...
@@ -181,39 +183,47 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
irda_qos_bits_to_value
(
&
self
->
qos
);
self
->
flags
=
IFF_SIR
|
IFF_PIO
;
self
->
mode
=
IRDA_IRLAP
;
/* Bootstrap ZeroCopy Rx */
self
->
rx_buff
.
truesize
=
IRDA_SKB_MAX_MTU
;
self
->
rx_buff
.
skb
=
__dev_alloc_skb
(
self
->
rx_buff
.
truesize
,
GFP_KERNEL
);
if
(
self
->
rx_buff
.
skb
==
NULL
)
return
NULL
;
skb_reserve
(
self
->
rx_buff
.
skb
,
1
);
self
->
rx_buff
.
head
=
self
->
rx_buff
.
skb
->
data
;
/* No need to memset the buffer, unless you are really pedantic */
/* Finish setup the Rx buffer descriptor */
self
->
rx_buff
.
in_frame
=
FALSE
;
self
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
/* Specify how much memory we want */
self
->
rx_buff
.
truesize
=
4000
;
self
->
tx_buff
.
truesize
=
4000
;
/* Allocate memory if needed */
if
(
self
->
rx_buff
.
truesize
>
0
)
{
self
->
rx_buff
.
head
=
(
__u8
*
)
kmalloc
(
self
->
rx_buff
.
truesize
,
GFP_KERNEL
);
if
(
self
->
rx_buff
.
head
==
NULL
)
return
NULL
;
memset
(
self
->
rx_buff
.
head
,
0
,
self
->
rx_buff
.
truesize
);
}
if
(
self
->
tx_buff
.
truesize
>
0
)
{
self
->
tx_buff
.
head
=
(
__u8
*
)
kmalloc
(
self
->
tx_buff
.
truesize
,
GFP_KERNEL
);
if
(
self
->
tx_buff
.
head
==
NULL
)
{
kfree
(
self
->
rx_buff
.
head
);
kfree_skb
(
self
->
rx_buff
.
skb
);
self
->
rx_buff
.
skb
=
NULL
;
self
->
rx_buff
.
head
=
NULL
;
return
NULL
;
}
memset
(
self
->
tx_buff
.
head
,
0
,
self
->
tx_buff
.
truesize
);
}
self
->
rx_buff
.
in_frame
=
FALSE
;
self
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
self
->
mode
=
IRDA_IRLAP
;
if
(
!
(
dev
=
dev_alloc
(
"irda%d"
,
&
err
)))
{
ERROR
(
"%s(), dev_alloc() failed!
\n
"
,
__FUNCTION__
);
return
NULL
;
}
self
->
netdev
=
dev
;
/* Keep track of module usage */
SET_MODULE_OWNER
(
dev
);
/* May be overridden by piggyback drivers */
dev
->
priv
=
(
void
*
)
self
;
...
...
@@ -241,7 +251,8 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
ERROR
(
"%s(), register_netdev() failed!
\n
"
,
__FUNCTION__
);
return
NULL
;
}
MESSAGE
(
"IrDA: Registered device %s
\n
"
,
dev
->
name
);
MESSAGE
(
"IrDA: Registered device %s (irport io=0x%X irq=%d)
\n
"
,
dev
->
name
,
iobase
,
irq
);
return
self
;
}
...
...
@@ -270,8 +281,9 @@ int irport_close(struct irport_cb *self)
if
(
self
->
tx_buff
.
head
)
kfree
(
self
->
tx_buff
.
head
);
if
(
self
->
rx_buff
.
head
)
kfree
(
self
->
rx_buff
.
head
);
if
(
self
->
rx_buff
.
skb
)
kfree_skb
(
self
->
rx_buff
.
skb
);
self
->
rx_buff
.
skb
=
NULL
;
/* Remove ourselves */
dev_self
[
self
->
index
]
=
NULL
;
...
...
@@ -306,6 +318,9 @@ void irport_stop(struct irport_cb *self)
/* We can't lock, we may be called from a FIR driver - Jean II */
/* We are not transmitting any more */
self
->
transmitting
=
0
;
/* Reset UART */
outb
(
0
,
iobase
+
UART_MCR
);
...
...
@@ -326,6 +341,33 @@ int irport_probe(int iobase)
return
0
;
}
/*
* Function irport_get_fcr (speed)
*
* Compute value of fcr
*
*/
static
inline
unsigned
int
irport_get_fcr
(
__u32
speed
)
{
unsigned
int
fcr
;
/* FIFO control reg */
/* Enable fifos */
fcr
=
UART_FCR_ENABLE_FIFO
;
/*
* Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
* about this timeout since it will always be fast enough.
*/
if
(
speed
<
38400
)
fcr
|=
UART_FCR_TRIGGER_1
;
else
//fcr |= UART_FCR_TRIGGER_14;
fcr
|=
UART_FCR_TRIGGER_8
;
return
(
fcr
);
}
/*
* Function irport_change_speed (self, speed)
*
...
...
@@ -337,11 +379,12 @@ void irport_change_speed(void *priv, __u32 speed)
{
struct
irport_cb
*
self
=
(
struct
irport_cb
*
)
priv
;
int
iobase
;
int
fcr
;
/* FIFO control reg */
int
lcr
;
/* Line control reg */
unsigned
int
fcr
;
/* FIFO control reg */
unsigned
int
lcr
;
/* Line control reg */
int
divisor
;
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
speed
!=
0
,
return
;);
IRDA_DEBUG
(
1
,
"%s(), Setting speed to: %d - iobase=%#x
\n
"
,
__FUNCTION__
,
speed
,
self
->
io
.
sir_base
);
...
...
@@ -358,18 +401,9 @@ void irport_change_speed(void *priv, __u32 speed)
divisor
=
SPEED_MAX
/
speed
;
fcr
=
UART_FCR_ENABLE_FIFO
;
/* Get proper fifo configuration */
fcr
=
irport_get_fcr
(
speed
);
/*
* Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
* about this timeout since it will always be fast enough.
*/
if
(
self
->
io
.
speed
<
38400
)
fcr
|=
UART_FCR_TRIGGER_1
;
else
fcr
|=
UART_FCR_TRIGGER_14
;
/* IrDA ports use 8N1 */
lcr
=
UART_LCR_WLEN8
;
...
...
@@ -380,7 +414,7 @@ void irport_change_speed(void *priv, __u32 speed)
outb
(
fcr
,
iobase
+
UART_FCR
);
/* Enable FIFO's */
/* Turn on interrups */
/* This will generate a fata interrupt storm.
/* This will generate a fata
l
interrupt storm.
* People calling us will do that properly - Jean II */
//outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
}
...
...
@@ -467,8 +501,8 @@ int __irport_change_speed(struct irda_task *task)
irda_task_next_state
(
task
,
IRDA_TASK_DONE
);
ret
=
-
1
;
break
;
}
/* Put stuff in the sate we found them - Jean II */
}
/* Put stuff in the s
t
ate we found them - Jean II */
if
(
wasunlocked
)
{
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
}
...
...
@@ -476,98 +510,6 @@ int __irport_change_speed(struct irda_task *task)
return
ret
;
}
/*
* Function irport_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*
*/
static
void
irport_write_wakeup
(
struct
irport_cb
*
self
)
{
int
actual
=
0
;
int
iobase
;
int
fcr
;
ASSERT
(
self
!=
NULL
,
return
;);
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
iobase
=
self
->
io
.
sir_base
;
/* Finished with frame? */
if
(
self
->
tx_buff
.
len
>
0
)
{
/* Write data left in transmit buffer */
actual
=
irport_write
(
iobase
,
self
->
io
.
fifo_size
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
);
self
->
tx_buff
.
data
+=
actual
;
self
->
tx_buff
.
len
-=
actual
;
/* Turn on transmit finished interrupt. */
outb
(
UART_IER_THRI
,
iobase
+
UART_IER
);
}
else
{
/*
* Now serial buffer is almost free & we can start
* transmission of another packet. But first we must check
* if we need to change the speed of the hardware
*/
if
(
self
->
new_speed
)
{
IRDA_DEBUG
(
5
,
"%s(), Changing speed!
\n
"
,
__FUNCTION__
);
irda_task_execute
(
self
,
__irport_change_speed
,
irport_change_speed_complete
,
NULL
,
(
void
*
)
self
->
new_speed
);
self
->
new_speed
=
0
;
IRDA_DEBUG
(
5
,
"%s(), Speed changed!
\n
"
,
__FUNCTION__
);
}
else
{
/* Tell network layer that we want more frames */
netif_wake_queue
(
self
->
netdev
);
}
self
->
stats
.
tx_packets
++
;
/*
* Reset Rx FIFO to make sure that all reflected transmit data
* is discarded. This is needed for half duplex operation
*/
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_CLEAR_RCVR
;
if
(
self
->
io
.
speed
<
38400
)
fcr
|=
UART_FCR_TRIGGER_1
;
else
fcr
|=
UART_FCR_TRIGGER_14
;
outb
(
fcr
,
iobase
+
UART_FCR
);
/* Turn on receive interrupts */
outb
(
UART_IER_RDI
,
iobase
+
UART_IER
);
}
}
/*
* Function irport_write (driver)
*
* Fill Tx FIFO with transmit data
*
*/
static
int
irport_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
)
{
int
actual
=
0
;
/* Tx FIFO should be empty! */
if
(
!
(
inb
(
iobase
+
UART_LSR
)
&
UART_LSR_THRE
))
{
IRDA_DEBUG
(
0
,
"%s(), failed, fifo not empty!
\n
"
,
__FUNCTION__
);
return
0
;
}
/* Fill FIFO with current frame */
while
((
fifo_size
--
>
0
)
&&
(
actual
<
len
))
{
/* Transmit next byte */
outb
(
buf
[
actual
],
iobase
+
UART_TX
);
actual
++
;
}
return
actual
;
}
/*
* Function irport_change_speed_complete (task)
*
...
...
@@ -604,23 +546,79 @@ static void irport_timeout(struct net_device *dev)
{
struct
irport_cb
*
self
;
int
iobase
;
int
iir
,
lsr
;
unsigned
long
flags
;
self
=
(
struct
irport_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
;);
iobase
=
self
->
io
.
sir_base
;
WARNING
(
"%s: transmit timed out
\n
"
,
dev
->
name
);
WARNING
(
"%s: transmit timed out, jiffies = %ld, trans_start = %ld
\n
"
,
dev
->
name
,
jiffies
,
dev
->
trans_start
);
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Debug what's happening... */
/* Get interrupt status */
lsr
=
inb
(
iobase
+
UART_LSR
);
/* Read interrupt register */
iir
=
inb
(
iobase
+
UART_IIR
);
IRDA_DEBUG
(
0
,
"%s(), iir=%02x, lsr=%02x, iobase=%#x
\n
"
,
__FUNCTION__
,
iir
,
lsr
,
iobase
);
IRDA_DEBUG
(
0
,
"%s(), transmitting=%d, remain=%d, done=%d
\n
"
,
__FUNCTION__
,
self
->
transmitting
,
self
->
tx_buff
.
len
,
self
->
tx_buff
.
data
-
self
->
tx_buff
.
head
);
/* Now, restart the port */
irport_start
(
self
);
self
->
change_speed
(
self
->
priv
,
self
->
io
.
speed
);
/* This will re-enable irqs */
outb
(
/*UART_IER_RLSI|*/
UART_IER_RDI
/*|UART_IER_THRI*/
,
iobase
+
UART_IER
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev
->
trans_start
=
jiffies
;
netif_wake_queue
(
dev
);
}
/*
* Function irport_wait_hw_transmitter_finish ()
*
* Wait for the real end of HW transmission
*
* The UART is a strict FIFO, and we get called only when we have finished
* pushing data to the FIFO, so the maximum amount of time we must wait
* is only for the FIFO to drain out.
*
* We use a simple calibrated loop. We may need to adjust the loop
* delay (udelay) to balance I/O traffic and latency. And we also need to
* adjust the maximum timeout.
* It would probably be better to wait for the proper interrupt,
* but it doesn't seem to be available.
*
* We can't use jiffies or kernel timers because :
* 1) We are called from the interrupt handler, which disable softirqs,
* so jiffies won't be increased
* 2) Jiffies granularity is usually very coarse (10ms), and we don't
* want to wait that long to detect stuck hardware.
* Jean II
*/
static
void
irport_wait_hw_transmitter_finish
(
struct
irport_cb
*
self
)
{
int
iobase
;
int
count
=
1000
;
/* 1 ms */
iobase
=
self
->
io
.
sir_base
;
/* Calibrated busy loop */
while
((
count
--
>
0
)
&&
!
(
inb
(
iobase
+
UART_LSR
)
&
UART_LSR_TEMT
))
udelay
(
1
);
if
(
count
==
0
)
IRDA_DEBUG
(
0
,
"%s(): stuck transmitter
\n
"
,
__FUNCTION__
);
}
/*
* Function irport_hard_start_xmit (struct sk_buff *skb, struct net_device *dev)
*
...
...
@@ -645,8 +643,8 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
iobase
=
self
->
io
.
sir_base
;
netif_stop_queue
(
dev
);
/* Make sure tests
*
& speed change are atomic */
/* Make sure tests & speed change are atomic */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Check if we need to change the speed */
...
...
@@ -654,10 +652,21 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
if
((
speed
!=
self
->
io
.
speed
)
&&
(
speed
!=
-
1
))
{
/* Check for empty frame */
if
(
!
skb
->
len
)
{
/*
* We send frames one by one in SIR mode (no
* pipelining), so at this point, if we were sending
* a previous frame, we just received the interrupt
* telling us it is finished (UART_IIR_THRI).
* Therefore, waiting for the transmitter to really
* finish draining the fifo won't take too long.
* And the interrupt handler is not expected to run.
* - Jean II */
irport_wait_hw_transmitter_finish
(
self
);
/* Better go there already locked - Jean II */
irda_task_execute
(
self
,
__irport_change_speed
,
irport_change_speed_complete
,
NULL
,
(
void
*
)
speed
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -674,9 +683,13 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self
->
stats
.
tx_bytes
+=
self
->
tx_buff
.
len
;
/* We are transmitting */
self
->
transmitting
=
1
;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb
(
UART_IER_THRI
,
iobase
+
UART_IER
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
@@ -684,13 +697,101 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
return
0
;
}
/*
* Function irport_write (driver)
*
* Fill Tx FIFO with transmit data
*
* Called only from irport_write_wakeup()
*/
static
inline
int
irport_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
)
{
int
actual
=
0
;
/* Fill FIFO with current frame */
while
((
actual
<
fifo_size
)
&&
(
actual
<
len
))
{
/* Transmit next byte */
outb
(
buf
[
actual
],
iobase
+
UART_TX
);
actual
++
;
}
return
actual
;
}
/*
* Function irport_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*
* Called only from irport_interrupt()
* Make sure this function is *not* called while we are receiving,
* otherwise we will reset fifo and loose data :-(
*/
static
inline
void
irport_write_wakeup
(
struct
irport_cb
*
self
)
{
int
actual
=
0
;
int
iobase
;
unsigned
int
fcr
;
ASSERT
(
self
!=
NULL
,
return
;);
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
iobase
=
self
->
io
.
sir_base
;
/* Finished with frame? */
if
(
self
->
tx_buff
.
len
>
0
)
{
/* Write data left in transmit buffer */
actual
=
irport_write
(
iobase
,
self
->
io
.
fifo_size
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
);
self
->
tx_buff
.
data
+=
actual
;
self
->
tx_buff
.
len
-=
actual
;
}
else
{
/*
* Now serial buffer is almost free & we can start
* transmission of another packet. But first we must check
* if we need to change the speed of the hardware
*/
if
(
self
->
new_speed
)
{
irport_wait_hw_transmitter_finish
(
self
);
irda_task_execute
(
self
,
__irport_change_speed
,
irport_change_speed_complete
,
NULL
,
(
void
*
)
self
->
new_speed
);
self
->
new_speed
=
0
;
}
else
{
/* Tell network layer that we want more frames */
netif_wake_queue
(
self
->
netdev
);
}
self
->
stats
.
tx_packets
++
;
/*
* Reset Rx FIFO to make sure that all reflected transmit data
* is discarded. This is needed for half duplex operation
*/
fcr
=
irport_get_fcr
(
self
->
io
.
speed
);
fcr
|=
UART_FCR_CLEAR_RCVR
;
outb
(
fcr
,
iobase
+
UART_FCR
);
/* Finished transmitting */
self
->
transmitting
=
0
;
/* Turn on receive interrupts */
outb
(
UART_IER_RDI
,
iobase
+
UART_IER
);
IRDA_DEBUG
(
1
,
"%s() : finished Tx
\n
"
,
__FUNCTION__
);
}
}
/*
* Function irport_receive (self)
*
* Receive one frame from the infrared port
*
* Called only from irport_interrupt()
*/
static
void
irport_receive
(
struct
irport_cb
*
self
)
static
inline
void
irport_receive
(
struct
irport_cb
*
self
)
{
int
boguscount
=
0
;
int
iobase
;
...
...
@@ -739,40 +840,51 @@ irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
iobase
=
self
->
io
.
sir_base
;
iir
=
inb
(
iobase
+
UART_IIR
)
&
UART_IIR_ID
;
while
(
iir
)
{
handled
=
1
;
/* Cut'n'paste interrupt routine from serial.c
* This version try to minimise latency and I/O operations.
* Simplified and modified to enforce half duplex operation.
* - Jean II */
/* Clear interrupt */
/* Check status even is iir reg is cleared, more robust and
* eliminate a read on the I/O bus - Jean II */
do
{
/* Get interrupt status ; Clear interrupt */
lsr
=
inb
(
iobase
+
UART_LSR
);
/* Are we receiving or transmitting ? */
if
(
!
self
->
transmitting
)
{
/* Received something ? */
if
(
lsr
&
UART_LSR_DR
)
irport_receive
(
self
);
}
else
{
/* Room in Tx fifo ? */
if
(
lsr
&
(
UART_LSR_THRE
|
UART_LSR_TEMT
))
irport_write_wakeup
(
self
);
}
IRDA_DEBUG
(
4
,
"%s(), iir=%02x, lsr=%02x, iobase=%#x
\n
"
,
__FUNCTION__
,
iir
,
lsr
,
iobase
);
/* A bit hackish, but working as expected... Jean II */
if
(
lsr
&
(
UART_LSR_THRE
|
UART_LSR_TEMT
|
UART_LSR_DR
))
handled
=
1
;
switch
(
iir
)
{
case
UART_IIR_RLSI
:
IRDA_DEBUG
(
2
,
"%s(), RLSI
\n
"
,
__FUNCTION__
);
break
;
case
UART_IIR_RDI
:
/* Receive interrupt */
irport_receive
(
self
);
break
;
case
UART_IIR_THRI
:
if
(
lsr
&
UART_LSR_THRE
)
/* Transmitter ready for data */
irport_write_wakeup
(
self
);
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), unhandled IIR=%#x
\n
"
,
__FUNCTION__
,
iir
);
break
;
}
/* Make sure we don't stay here too long */
if
(
boguscount
++
>
100
)
/* Make sure we don't stay here to long */
if
(
boguscount
++
>
10
)
{
WARNING
(
"%s() irq handler looping : lsr=%02x
\n
"
,
__FUNCTION__
,
lsr
);
break
;
}
/* Read interrupt register */
iir
=
inb
(
iobase
+
UART_IIR
);
/* Enable this debug only when no other options and at low
* bit rates, otherwise it may cause Rx overruns (lsr=63).
* - Jean II */
IRDA_DEBUG
(
6
,
"%s(), iir=%02x, lsr=%02x, iobase=%#x
\n
"
,
__FUNCTION__
,
iir
,
lsr
,
iobase
);
/* As long as interrupt pending... */
}
while
((
iir
&
UART_IIR_NO_INT
)
==
0
);
iir
=
inb
(
iobase
+
UART_IIR
)
&
UART_IIR_ID
;
}
spin_unlock
(
&
self
->
lock
);
return
IRQ_RETVAL
(
handled
);
}
...
...
@@ -800,8 +912,8 @@ int irport_net_open(struct net_device *dev)
char
hwname
[
16
];
unsigned
long
flags
;
IRDA_DEBUG
(
1
,
"%s()
\n
"
,
__FUNCTION__
);
IRDA_DEBUG
(
2
,
"%s()
\n
"
,
__FUNCTION__
);
ASSERT
(
dev
!=
NULL
,
return
-
1
;);
self
=
(
struct
irport_cb
*
)
dev
->
priv
;
...
...
@@ -815,7 +927,12 @@ int irport_net_open(struct net_device *dev)
}
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Init uart */
irport_start
(
self
);
/* Set 9600 bauds per default, including at the dongle */
irda_task_execute
(
self
,
__irport_change_speed
,
irport_change_speed_complete
,
NULL
,
(
void
*
)
9600
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
...
...
@@ -828,12 +945,9 @@ int irport_net_open(struct net_device *dev)
*/
self
->
irlap
=
irlap_open
(
dev
,
&
self
->
qos
,
hwname
);
/* FIXME: change speed of dongle */
/* Ready to play! */
netif_start_queue
(
dev
);
MOD_INC_USE_COUNT
;
return
0
;
}
...
...
@@ -873,40 +987,16 @@ int irport_net_close(struct net_device *dev)
free_irq
(
self
->
io
.
irq
,
dev
);
MOD_DEC_USE_COUNT
;
return
0
;
}
/*
* Function irport_wait_until_sent (self)
*
* Delay exectution until finished transmitting
*
*/
#if 0
void irport_wait_until_sent(struct irport_cb *self)
{
int iobase;
iobase = self->io.sir_base;
/* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
IRDA_DEBUG(2, "%s(), waiting!\n", __FUNCTION__);
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(60));
}
}
#endif
/*
* Function irport_is_receiving (self)
*
* Returns true is we are currently receiving data
*
*/
static
int
irport_is_receiving
(
struct
irport_cb
*
self
)
static
in
line
in
t
irport_is_receiving
(
struct
irport_cb
*
self
)
{
return
(
self
->
rx_buff
.
state
!=
OUTSIDE_FRAME
);
}
...
...
@@ -998,6 +1088,12 @@ static int irport_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
break
;
}
/* Locking :
* irda_device_dongle_init() can't be locked.
* irda_task_execute() doesn't need to be locked.
* Jean II
*/
/* Initialize dongle */
dongle
=
irda_device_dongle_init
(
dev
,
irq
->
ifr_dongle
);
if
(
!
dongle
)
...
...
drivers/net/irda/irtty-sir.c
View file @
4bcb7d97
...
...
@@ -504,10 +504,7 @@ static int irtty_open(struct tty_struct *tty)
struct
sirtty_cb
*
priv
;
int
ret
=
0
;
/* unfortunately, there's no tty_ldisc->owner field
* so there is some window for SMP race with rmmod
*/
MOD_INC_USE_COUNT
;
/* Module stuff handled via irda_ldisc.owner - Jean II */
/* First make sure we're not already connected. */
if
(
tty
->
disc_data
!=
NULL
)
{
...
...
@@ -569,7 +566,6 @@ static int irtty_open(struct tty_struct *tty)
out_put:
sirdev_put_instance
(
dev
);
out:
MOD_DEC_USE_COUNT
;
return
ret
;
}
...
...
@@ -614,8 +610,6 @@ static void irtty_close(struct tty_struct *tty)
tty
->
driver
->
stop
(
tty
);
kfree
(
priv
);
MOD_DEC_USE_COUNT
;
}
/* ------------------------------------------------------- */
...
...
@@ -633,6 +627,7 @@ static struct tty_ldisc irda_ldisc = {
.
receive_buf
=
irtty_receive_buf
,
.
receive_room
=
irtty_receive_room
,
.
write_wakeup
=
irtty_write_wakeup
,
.
owner
=
THIS_MODULE
,
};
/* ------------------------------------------------------- */
...
...
drivers/net/irda/nsc-ircc.c
View file @
4bcb7d97
...
...
@@ -1096,6 +1096,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
* to make sure packets gets through the
* proper xmit handler - Jean II */
}
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -1120,6 +1121,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
/* Restore bank register */
outb
(
bank
,
iobase
+
BSR
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
@@ -1164,6 +1166,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
* the speed change has been done.
* Jean II */
}
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -1250,6 +1253,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
/* Restore bank register */
outb
(
bank
,
iobase
+
BSR
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
drivers/net/irda/sir_kthread.c
View file @
4bcb7d97
...
...
@@ -151,6 +151,13 @@ static int irda_thread(void *startup)
while
(
irda_rq_queue
.
thread
!=
NULL
)
{
/* We use TASK_INTERRUPTIBLE, rather than
* TASK_UNINTERRUPTIBLE. Andrew Morton made this
* change ; he told me that it is safe, because "signal
* blocking is now handled in daemonize()", he added
* that the problem is that "uninterruptible sleep
* contributes to load average", making user worry.
* Jean II */
set_task_state
(
current
,
TASK_INTERRUPTIBLE
);
add_wait_queue
(
&
irda_rq_queue
.
kick
,
&
wait
);
if
(
list_empty
(
&
irda_rq_queue
.
request_list
))
...
...
drivers/net/irda/smc-ircc.c
View file @
4bcb7d97
...
...
@@ -529,6 +529,9 @@ static int __init ircc_open(unsigned int fir_base, unsigned int sir_base)
irport
->
priv
=
self
;
/* Keep track of module usage */
SET_MODULE_OWNER
(
self
->
netdev
);
/* Initialize IO */
self
->
io
=
&
irport
->
io
;
self
->
io
->
fir_base
=
fir_base
;
...
...
@@ -747,6 +750,7 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check for empty frame */
if
(
!
skb
->
len
)
{
ircc_change_speed
(
self
,
speed
);
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
irport
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
...
...
@@ -776,6 +780,7 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Transmit frame */
ircc_dma_xmit
(
self
,
iobase
,
0
);
}
dev
->
trans_start
=
jiffies
;
spin_unlock_irqrestore
(
&
self
->
irport
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
...
...
@@ -1090,8 +1095,6 @@ static int ircc_net_open(struct net_device *dev)
WARNING
(
"%s(), unable to allocate DMA=%d
\n
"
,
__FUNCTION__
,
self
->
io
->
dma
);
return
-
EAGAIN
;
}
MOD_INC_USE_COUNT
;
return
0
;
}
...
...
@@ -1124,8 +1127,6 @@ static int ircc_net_close(struct net_device *dev)
free_dma
(
self
->
io
->
dma
);
MOD_DEC_USE_COUNT
;
return
0
;
}
...
...
@@ -1187,6 +1188,9 @@ static int __exit ircc_close(struct ircc_cb *self)
iobase
=
self
->
irport
->
io
.
fir_base
;
if
(
self
->
pmdev
)
pm_unregister
(
self
->
pmdev
);
/* This will destroy irport */
irport_close
(
self
->
irport
);
...
...
drivers/net/irda/smsc-ircc2.c
0 → 100644
View file @
4bcb7d97
/*********************************************************************
* $Id: smsc-ircc2.c,v 1.19.2.5 2002/10/27 11:34:26 dip Exp $
*
* Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Daniele Peri (peri@csai.unipa.it)
* Created at:
* Modified at:
* Modified by:
*
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
* Copyright (c) 2002 Jean Tourrilhes
*
*
* Based on smc-ircc.c:
*
* Copyright (c) 2001 Stefani Seibold
* Copyright (c) 1999-2001 Dag Brattli
* Copyright (c) 1998-1999 Thomas Davis,
*
* and irport.c:
*
* Copyright (c) 1997, 1998, 1999-2000 Dag Brattli, All Rights Reserved.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/serial_reg.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#include "smsc-ircc2.h"
#include "smsc-sio.h"
/* Types */
struct
smsc_transceiver
{
char
*
name
;
void
(
*
set_for_speed
)(
int
fir_base
,
u32
speed
);
int
(
*
probe
)(
int
fir_base
);
};
typedef
struct
smsc_transceiver
smsc_transceiver_t
;
#if 0
struct smc_chip {
char *name;
u16 flags;
u8 devid;
u8 rev;
};
typedef struct smc_chip smc_chip_t;
#endif
struct
smsc_chip
{
char
*
name
;
#if 0
u8 type;
#endif
u16
flags
;
u8
devid
;
u8
rev
;
};
typedef
struct
smsc_chip
smsc_chip_t
;
struct
smsc_chip_address
{
unsigned
int
cfg_base
;
unsigned
int
type
;
};
typedef
struct
smsc_chip_address
smsc_chip_address_t
;
/* Private data for each instance */
struct
smsc_ircc_cb
{
struct
net_device
*
netdev
;
/* Yes! we are some kind of netdevice */
struct
net_device_stats
stats
;
struct
irlap_cb
*
irlap
;
/* The link layer we are binded to */
chipio_t
io
;
/* IrDA controller information */
iobuff_t
tx_buff
;
/* Transmit buffer */
iobuff_t
rx_buff
;
/* Receive buffer */
struct
qos_info
qos
;
/* QoS capabilities for this device */
spinlock_t
lock
;
/* For serializing operations */
__u32
new_speed
;
__u32
flags
;
/* Interface flags */
int
tx_buff_offsets
[
10
];
/* Offsets between frames in tx_buff */
int
tx_len
;
/* Number of frames in tx_buff */
int
transceiver
;
struct
pm_dev
*
pmdev
;
};
/* Constants */
static
const
char
*
driver_name
=
"smsc-ircc2"
;
#define DIM(x) (sizeof(x)/(sizeof(*(x))))
#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600
#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1
#define SMSC_IRCC2_C_NET_TIMEOUT 0
#define SMSC_IRCC2_C_SIR_STOP 0
/* Prototypes */
static
int
smsc_ircc_open
(
unsigned
int
firbase
,
unsigned
int
sirbase
,
u8
dma
,
u8
irq
);
static
int
smsc_ircc_present
(
unsigned
int
fir_base
,
unsigned
int
sir_base
);
static
int
smsc_ircc_setup_io
(
struct
smsc_ircc_cb
*
self
,
unsigned
int
fir_base
,
unsigned
int
sir_base
,
u8
dma
,
u8
irq
);
static
int
smsc_ircc_setup_buffers
(
struct
smsc_ircc_cb
*
self
);
static
void
smsc_ircc_setup_qos
(
struct
smsc_ircc_cb
*
self
);
static
int
smsc_ircc_setup_netdev
(
struct
smsc_ircc_cb
*
self
);
static
void
smsc_ircc_init_chip
(
struct
smsc_ircc_cb
*
self
);
static
int
__exit
smsc_ircc_close
(
struct
smsc_ircc_cb
*
self
);
static
int
smsc_ircc_dma_receive
(
struct
smsc_ircc_cb
*
self
,
int
iobase
);
static
void
smsc_ircc_dma_receive_complete
(
struct
smsc_ircc_cb
*
self
,
int
iobase
);
static
void
smsc_ircc_sir_receive
(
struct
smsc_ircc_cb
*
self
);
static
int
smsc_ircc_hard_xmit_sir
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
int
smsc_ircc_hard_xmit_fir
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
void
smsc_ircc_dma_xmit
(
struct
smsc_ircc_cb
*
self
,
int
iobase
,
int
bofs
);
static
void
smsc_ircc_dma_xmit_complete
(
struct
smsc_ircc_cb
*
self
,
int
iobase
);
static
void
smsc_ircc_change_speed
(
void
*
priv
,
u32
speed
);
static
void
smsc_ircc_set_sir_speed
(
void
*
priv
,
u32
speed
);
static
irqreturn_t
smsc_ircc_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
smsc_ircc_interrupt_sir
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
);
static
void
smsc_ircc_sir_start
(
struct
smsc_ircc_cb
*
self
);
#if SMSC_IRCC2_C_SIR_STOP
static
void
smsc_ircc_sir_stop
(
struct
smsc_ircc_cb
*
self
);
#endif
static
void
smsc_ircc_sir_write_wakeup
(
struct
smsc_ircc_cb
*
self
);
static
int
smsc_ircc_sir_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
);
static
int
smsc_ircc_net_init
(
struct
net_device
*
dev
);
static
int
smsc_ircc_net_open
(
struct
net_device
*
dev
);
static
int
smsc_ircc_net_close
(
struct
net_device
*
dev
);
static
int
smsc_ircc_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
#if SMSC_IRCC2_C_NET_TIMEOUT
static
void
smsc_ircc_timeout
(
struct
net_device
*
dev
);
#endif
static
struct
net_device_stats
*
smsc_ircc_net_get_stats
(
struct
net_device
*
dev
);
static
int
smsc_ircc_pmproc
(
struct
pm_dev
*
dev
,
pm_request_t
rqst
,
void
*
data
);
static
int
smsc_ircc_is_receiving
(
struct
smsc_ircc_cb
*
self
);
static
void
smsc_ircc_probe_transceiver
(
struct
smsc_ircc_cb
*
self
);
static
void
smsc_ircc_set_transceiver_for_speed
(
struct
smsc_ircc_cb
*
self
,
u32
speed
);
static
void
smsc_ircc_sir_wait_hw_transmitter_finish
(
struct
smsc_ircc_cb
*
self
);
/* Probing */
static
int
__init
smsc_ircc_look_for_chips
(
void
);
static
const
smsc_chip_t
*
__init
smsc_ircc_probe
(
unsigned
short
cfg_base
,
u8
reg
,
const
smsc_chip_t
*
chip
,
char
*
type
);
static
int
__init
smsc_superio_flat
(
const
smsc_chip_t
*
chips
,
unsigned
short
cfg_base
,
char
*
type
);
static
int
__init
smsc_superio_paged
(
const
smsc_chip_t
*
chips
,
unsigned
short
cfg_base
,
char
*
type
);
static
int
__init
smsc_superio_fdc
(
unsigned
short
cfg_base
);
static
int
__init
smsc_superio_lpc
(
unsigned
short
cfg_base
);
/* Transceivers specific functions */
static
void
smsc_ircc_set_transceiver_toshiba_sat1800
(
int
fir_base
,
u32
speed
);
static
int
smsc_ircc_probe_transceiver_toshiba_sat1800
(
int
fir_base
);
static
void
smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select
(
int
fir_base
,
u32
speed
);
static
int
smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select
(
int
fir_base
);
static
void
smsc_ircc_set_transceiver_smsc_ircc_atc
(
int
fir_base
,
u32
speed
);
static
int
smsc_ircc_probe_transceiver_smsc_ircc_atc
(
int
fir_base
);
/* Power Management */
static
void
smsc_ircc_suspend
(
struct
smsc_ircc_cb
*
self
);
static
void
smsc_ircc_wakeup
(
struct
smsc_ircc_cb
*
self
);
static
int
smsc_ircc_pmproc
(
struct
pm_dev
*
dev
,
pm_request_t
rqst
,
void
*
data
);
/* Transceivers for SMSC-ircc */
smsc_transceiver_t
smsc_transceivers
[]
=
{
{
"Toshiba Satellite 1800 (GP data pin select)"
,
smsc_ircc_set_transceiver_toshiba_sat1800
,
smsc_ircc_probe_transceiver_toshiba_sat1800
},
{
"Fast pin select"
,
smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select
,
smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select
},
{
"ATC IRMode"
,
smsc_ircc_set_transceiver_smsc_ircc_atc
,
smsc_ircc_probe_transceiver_smsc_ircc_atc
},
{
NULL
,
NULL
}
};
#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (DIM(smsc_transceivers)-1)
/* SMC SuperIO chipsets definitions */
#define KEY55_1 0
/* SuperIO Configuration mode with Key <0x55> */
#define KEY55_2 1
/* SuperIO Configuration mode with Key <0x55,0x55> */
#define NoIRDA 2
/* SuperIO Chip has no IRDA Port */
#define SIR 0
/* SuperIO Chip has only slow IRDA */
#define FIR 4
/* SuperIO Chip has fast IRDA */
#define SERx4 8
/* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */
static
smsc_chip_t
__initdata
fdc_chips_flat
[]
=
{
/* Base address 0x3f0 or 0x370 */
{
"37C44"
,
KEY55_1
|
NoIRDA
,
0x00
,
0x00
},
/* This chip cannot be detected */
{
"37C665GT"
,
KEY55_2
|
NoIRDA
,
0x65
,
0x01
},
{
"37C665GT"
,
KEY55_2
|
NoIRDA
,
0x66
,
0x01
},
{
"37C669"
,
KEY55_2
|
SIR
|
SERx4
,
0x03
,
0x02
},
{
"37C669"
,
KEY55_2
|
SIR
|
SERx4
,
0x04
,
0x02
},
/* ID? */
{
"37C78"
,
KEY55_2
|
NoIRDA
,
0x78
,
0x00
},
{
"37N769"
,
KEY55_1
|
FIR
|
SERx4
,
0x28
,
0x00
},
{
"37N869"
,
KEY55_1
|
FIR
|
SERx4
,
0x29
,
0x00
},
{
NULL
}
};
static
smsc_chip_t
__initdata
fdc_chips_paged
[]
=
{
/* Base address 0x3f0 or 0x370 */
{
"37B72X"
,
KEY55_1
|
SIR
|
SERx4
,
0x4c
,
0x00
},
{
"37B77X"
,
KEY55_1
|
SIR
|
SERx4
,
0x43
,
0x00
},
{
"37B78X"
,
KEY55_1
|
SIR
|
SERx4
,
0x44
,
0x00
},
{
"37B80X"
,
KEY55_1
|
SIR
|
SERx4
,
0x42
,
0x00
},
{
"37C67X"
,
KEY55_1
|
FIR
|
SERx4
,
0x40
,
0x00
},
{
"37C93X"
,
KEY55_2
|
SIR
|
SERx4
,
0x02
,
0x01
},
{
"37C93XAPM"
,
KEY55_1
|
SIR
|
SERx4
,
0x30
,
0x01
},
{
"37C93XFR"
,
KEY55_2
|
FIR
|
SERx4
,
0x03
,
0x01
},
{
"37M707"
,
KEY55_1
|
SIR
|
SERx4
,
0x42
,
0x00
},
{
"37M81X"
,
KEY55_1
|
SIR
|
SERx4
,
0x4d
,
0x00
},
{
"37N958FR"
,
KEY55_1
|
FIR
|
SERx4
,
0x09
,
0x04
},
{
"37N971"
,
KEY55_1
|
FIR
|
SERx4
,
0x0a
,
0x00
},
{
"37N972"
,
KEY55_1
|
FIR
|
SERx4
,
0x0b
,
0x00
},
{
NULL
}
};
static
smsc_chip_t
__initdata
lpc_chips_flat
[]
=
{
/* Base address 0x2E or 0x4E */
{
"47N227"
,
KEY55_1
|
FIR
|
SERx4
,
0x5a
,
0x00
},
{
"47N267"
,
KEY55_1
|
FIR
|
SERx4
,
0x5e
,
0x00
},
{
NULL
}
};
static
smsc_chip_t
__initdata
lpc_chips_paged
[]
=
{
/* Base address 0x2E or 0x4E */
{
"47B27X"
,
KEY55_1
|
SIR
|
SERx4
,
0x51
,
0x00
},
{
"47B37X"
,
KEY55_1
|
SIR
|
SERx4
,
0x52
,
0x00
},
{
"47M10X"
,
KEY55_1
|
SIR
|
SERx4
,
0x59
,
0x00
},
{
"47M120"
,
KEY55_1
|
NoIRDA
|
SERx4
,
0x5c
,
0x00
},
{
"47M13X"
,
KEY55_1
|
SIR
|
SERx4
,
0x59
,
0x00
},
{
"47M14X"
,
KEY55_1
|
SIR
|
SERx4
,
0x5f
,
0x00
},
{
"47N252"
,
KEY55_1
|
FIR
|
SERx4
,
0x0e
,
0x00
},
{
"47S42X"
,
KEY55_1
|
SIR
|
SERx4
,
0x57
,
0x00
},
{
NULL
}
};
#define SMSCSIO_TYPE_FDC 1
#define SMSCSIO_TYPE_LPC 2
#define SMSCSIO_TYPE_FLAT 4
#define SMSCSIO_TYPE_PAGED 8
static
smsc_chip_address_t
__initdata
possible_addresses
[]
=
{
{
0x3f0
,
SMSCSIO_TYPE_FDC
|
SMSCSIO_TYPE_FLAT
|
SMSCSIO_TYPE_PAGED
},
{
0x370
,
SMSCSIO_TYPE_FDC
|
SMSCSIO_TYPE_FLAT
|
SMSCSIO_TYPE_PAGED
},
{
0xe0
,
SMSCSIO_TYPE_FDC
|
SMSCSIO_TYPE_FLAT
|
SMSCSIO_TYPE_PAGED
},
{
0x2e
,
SMSCSIO_TYPE_LPC
|
SMSCSIO_TYPE_FLAT
|
SMSCSIO_TYPE_PAGED
},
{
0x4e
,
SMSCSIO_TYPE_LPC
|
SMSCSIO_TYPE_FLAT
|
SMSCSIO_TYPE_PAGED
},
{
0
,
0
}
};
/* Globals */
static
struct
smsc_ircc_cb
*
dev_self
[]
=
{
NULL
,
NULL
};
static
int
ircc_irq
=
255
;
static
int
ircc_dma
=
255
;
static
int
ircc_fir
=
0
;
static
int
ircc_sir
=
0
;
static
int
ircc_cfg
=
0
;
static
int
ircc_transceiver
=
0
;
static
unsigned
short
dev_count
=
0
;
static
inline
void
register_bank
(
int
iobase
,
int
bank
)
{
outb
(((
inb
(
iobase
+
IRCC_MASTER
)
&
0xf0
)
|
(
bank
&
0x07
)),
iobase
+
IRCC_MASTER
);
}
/*******************************************************************************
*
*
* SMSC-ircc stuff
*
*
*******************************************************************************/
/*
* Function smsc_ircc_init ()
*
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
int
__init
smsc_ircc_init
(
void
)
{
int
ret
=-
ENODEV
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
dev_count
=
0
;
if
((
ircc_fir
>
0
)
&&
(
ircc_sir
>
0
))
{
MESSAGE
(
" Overriding FIR address 0x%04x
\n
"
,
ircc_fir
);
MESSAGE
(
" Overriding SIR address 0x%04x
\n
"
,
ircc_sir
);
if
(
smsc_ircc_open
(
ircc_fir
,
ircc_sir
,
ircc_dma
,
ircc_irq
)
==
0
)
return
0
;
return
-
ENODEV
;
}
/* try user provided configuration register base address */
if
(
ircc_cfg
>
0
)
{
MESSAGE
(
" Overriding configuration address 0x%04x
\n
"
,
ircc_cfg
);
if
(
!
smsc_superio_fdc
(
ircc_cfg
))
ret
=
0
;
if
(
!
smsc_superio_lpc
(
ircc_cfg
))
ret
=
0
;
}
if
(
smsc_ircc_look_for_chips
()
>
0
)
ret
=
0
;
return
ret
;
}
/*
* Function smsc_ircc_open (firbase, sirbase, dma, irq)
*
* Try to open driver instance
*
*/
static
int
__init
smsc_ircc_open
(
unsigned
int
fir_base
,
unsigned
int
sir_base
,
u8
dma
,
u8
irq
)
{
struct
smsc_ircc_cb
*
self
;
int
err
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
err
=
smsc_ircc_present
(
fir_base
,
sir_base
);
if
(
err
)
return
-
ENODEV
;
if
(
dev_count
>
DIM
(
dev_self
))
{
WARNING
(
"%s(), too many devices!
\n
"
,
__FUNCTION__
);
return
-
ENOMEM
;
}
/*
* Allocate new instance of the driver
*/
self
=
kmalloc
(
sizeof
(
struct
smsc_ircc_cb
),
GFP_KERNEL
);
if
(
self
==
NULL
)
{
ERROR
(
"%s, Can't allocate memory for control block!
\n
"
,
driver_name
);
return
-
ENOMEM
;
}
memset
(
self
,
0
,
sizeof
(
struct
smsc_ircc_cb
));
/* Need to store self somewhere */
dev_self
[
dev_count
++
]
=
self
;
spin_lock_init
(
&
self
->
lock
);
err
=
smsc_ircc_setup_buffers
(
self
);
if
(
err
)
return
err
;
err
=
smsc_ircc_setup_io
(
self
,
fir_base
,
sir_base
,
dma
,
irq
);
if
(
err
)
return
err
;
smsc_ircc_setup_qos
(
self
);
self
->
flags
=
IFF_FIR
|
IFF_MIR
|
IFF_SIR
|
IFF_DMA
|
IFF_PIO
;
smsc_ircc_init_chip
(
self
);
if
(
ircc_transceiver
>
0
&&
ircc_transceiver
<
SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS
)
self
->
transceiver
=
ircc_transceiver
;
else
smsc_ircc_probe_transceiver
(
self
);
err
=
smsc_ircc_setup_netdev
(
self
);
if
(
err
)
return
err
;
self
->
pmdev
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_IRDA
,
smsc_ircc_pmproc
);
if
(
self
->
pmdev
)
self
->
pmdev
->
data
=
self
;
return
0
;
}
/*
* Function smsc_ircc_present(fir_base, sir_base)
*
* Check the smsc-ircc chip presence
*
*/
static
int
smsc_ircc_present
(
unsigned
int
fir_base
,
unsigned
int
sir_base
)
{
unsigned
char
low
,
high
,
chip
,
config
,
dma
,
irq
,
version
;
if
(
check_region
(
fir_base
,
SMSC_IRCC2_FIR_CHIP_IO_EXTENT
)
<
0
)
{
WARNING
(
"%s: can't get fir_base of 0x%03x
\n
"
,
__FUNCTION__
,
fir_base
);
return
-
ENODEV
;
}
#if POSSIBLE_USED_BY_SERIAL_DRIVER
if
(
check_region
(
sir_base
,
SMSC_IRCC2_SIR_CHIP_IO_EXTENT
)
<
0
)
{
WARNING
(
"%s: can't get sir_base of 0x%03x
\n
"
,
__FUNCTION__
,
sir_base
);
return
-
ENODEV
;
}
#endif
register_bank
(
fir_base
,
3
);
high
=
inb
(
fir_base
+
IRCC_ID_HIGH
);
low
=
inb
(
fir_base
+
IRCC_ID_LOW
);
chip
=
inb
(
fir_base
+
IRCC_CHIP_ID
);
version
=
inb
(
fir_base
+
IRCC_VERSION
);
config
=
inb
(
fir_base
+
IRCC_INTERFACE
);
dma
=
config
&
IRCC_INTERFACE_DMA_MASK
;
irq
=
(
config
&
IRCC_INTERFACE_IRQ_MASK
)
>>
4
;
if
(
high
!=
0x10
||
low
!=
0xb8
||
(
chip
!=
0xf1
&&
chip
!=
0xf2
))
{
WARNING
(
"%s(), addr 0x%04x - no device found!
\n
"
,
__FUNCTION__
,
fir_base
);
return
-
ENODEV
;
}
MESSAGE
(
"SMsC IrDA Controller found
\n
IrCC version %d.%d, "
"firport 0x%03x, sirport 0x%03x dma=%d, irq=%d
\n
"
,
chip
&
0x0f
,
version
,
fir_base
,
sir_base
,
dma
,
irq
);
return
0
;
}
/*
* Function smsc_ircc_setup_buffers(self)
*
* Setup RX/TX buffers
*
*/
static
int
smsc_ircc_setup_buffers
(
struct
smsc_ircc_cb
*
self
)
{
self
->
rx_buff
.
truesize
=
SMSC_IRCC2_RX_BUFF_TRUESIZE
;
self
->
tx_buff
.
truesize
=
SMSC_IRCC2_TX_BUFF_TRUESIZE
;
self
->
rx_buff
.
head
=
(
u8
*
)
kmalloc
(
self
->
rx_buff
.
truesize
,
GFP_KERNEL
|
GFP_DMA
);
if
(
self
->
rx_buff
.
head
==
NULL
)
{
ERROR
(
"%s, Can't allocate memory for receive buffer!
\n
"
,
driver_name
);
kfree
(
self
);
return
-
ENOMEM
;
}
self
->
tx_buff
.
head
=
(
u8
*
)
kmalloc
(
self
->
tx_buff
.
truesize
,
GFP_KERNEL
|
GFP_DMA
);
if
(
self
->
tx_buff
.
head
==
NULL
)
{
ERROR
(
"%s, Can't allocate memory for transmit buffer!
\n
"
,
driver_name
);
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
-
ENOMEM
;
}
memset
(
self
->
rx_buff
.
head
,
0
,
self
->
rx_buff
.
truesize
);
memset
(
self
->
tx_buff
.
head
,
0
,
self
->
tx_buff
.
truesize
);
self
->
rx_buff
.
in_frame
=
FALSE
;
self
->
rx_buff
.
state
=
OUTSIDE_FRAME
;
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
return
0
;
}
/*
* Function smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq)
*
* Setup I/O
*
*/
static
int
smsc_ircc_setup_io
(
struct
smsc_ircc_cb
*
self
,
unsigned
int
fir_base
,
unsigned
int
sir_base
,
u8
dma
,
u8
irq
)
{
unsigned
char
config
,
chip_dma
,
chip_irq
;
void
*
ret
;
register_bank
(
fir_base
,
3
);
config
=
inb
(
fir_base
+
IRCC_INTERFACE
);
chip_dma
=
config
&
IRCC_INTERFACE_DMA_MASK
;
chip_irq
=
(
config
&
IRCC_INTERFACE_IRQ_MASK
)
>>
4
;
self
->
io
.
fir_base
=
fir_base
;
self
->
io
.
sir_base
=
sir_base
;
self
->
io
.
fir_ext
=
SMSC_IRCC2_FIR_CHIP_IO_EXTENT
;
self
->
io
.
sir_ext
=
SMSC_IRCC2_SIR_CHIP_IO_EXTENT
;
self
->
io
.
fifo_size
=
SMSC_IRCC2_FIFO_SIZE
;
self
->
io
.
speed
=
SMSC_IRCC2_C_IRDA_FALLBACK_SPEED
;
if
(
irq
<
255
)
{
if
(
irq
!=
chip_irq
)
MESSAGE
(
"%s, Overriding IRQ - chip says %d, using %d
\n
"
,
driver_name
,
chip_irq
,
irq
);
self
->
io
.
irq
=
irq
;
}
else
self
->
io
.
irq
=
chip_irq
;
if
(
dma
<
255
)
{
if
(
dma
!=
chip_dma
)
MESSAGE
(
"%s, Overriding DMA - chip says %d, using %d
\n
"
,
driver_name
,
chip_dma
,
dma
);
self
->
io
.
dma
=
dma
;
}
else
self
->
io
.
dma
=
chip_dma
;
ret
=
request_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
,
driver_name
);
if
(
!
ret
)
{
WARNING
(
"%s(), can't get iobase of 0x%03x
\n
"
,
__FUNCTION__
,
self
->
io
.
fir_base
);
kfree
(
self
->
tx_buff
.
head
);
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
-
ENODEV
;
}
ret
=
request_region
(
self
->
io
.
sir_base
,
self
->
io
.
sir_ext
,
driver_name
);
if
(
!
ret
)
{
WARNING
(
"%s(), can't get iobase of 0x%03x
\n
"
,
__FUNCTION__
,
self
->
io
.
sir_base
);
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
kfree
(
self
->
tx_buff
.
head
);
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
-
ENODEV
;
}
return
0
;
}
/*
* Function smsc_ircc_setup_qos(self)
*
* Setup qos
*
*/
static
void
smsc_ircc_setup_qos
(
struct
smsc_ircc_cb
*
self
)
{
/* Initialize QoS for this device */
irda_init_max_qos_capabilies
(
&
self
->
qos
);
self
->
qos
.
baud_rate
.
bits
=
IR_9600
|
IR_19200
|
IR_38400
|
IR_57600
|
IR_115200
|
IR_576000
|
IR_1152000
|
(
IR_4000000
<<
8
);
self
->
qos
.
min_turn_time
.
bits
=
SMSC_IRCC2_MIN_TURN_TIME
;
self
->
qos
.
window_size
.
bits
=
SMSC_IRCC2_WINDOW_SIZE
;
irda_qos_bits_to_value
(
&
self
->
qos
);
}
/*
* Function smsc_ircc_init_chip(self)
*
* Init chip
*
*/
static
void
smsc_ircc_init_chip
(
struct
smsc_ircc_cb
*
self
)
{
int
iobase
,
ir_mode
,
ctrl
,
fast
;
ASSERT
(
self
!=
NULL
,
return
;
);
iobase
=
self
->
io
.
fir_base
;
ir_mode
=
IRCC_CFGA_IRDA_SIR_A
;
ctrl
=
0
;
fast
=
0
;
register_bank
(
iobase
,
0
);
outb
(
IRCC_MASTER_RESET
,
iobase
+
IRCC_MASTER
);
outb
(
0x00
,
iobase
+
IRCC_MASTER
);
register_bank
(
iobase
,
1
);
outb
(((
inb
(
iobase
+
IRCC_SCE_CFGA
)
&
0x87
)
|
ir_mode
),
iobase
+
IRCC_SCE_CFGA
);
#ifdef smsc_669
/* Uses pin 88/89 for Rx/Tx */
outb
(((
inb
(
iobase
+
IRCC_SCE_CFGB
)
&
0x3f
)
|
IRCC_CFGB_MUX_COM
),
iobase
+
IRCC_SCE_CFGB
);
#else
outb
(((
inb
(
iobase
+
IRCC_SCE_CFGB
)
&
0x3f
)
|
IRCC_CFGB_MUX_IR
),
iobase
+
IRCC_SCE_CFGB
);
#endif
(
void
)
inb
(
iobase
+
IRCC_FIFO_THRESHOLD
);
outb
(
SMSC_IRCC2_FIFO_THRESHOLD
,
iobase
+
IRCC_FIFO_THRESHOLD
);
register_bank
(
iobase
,
4
);
outb
((
inb
(
iobase
+
IRCC_CONTROL
)
&
0x30
)
|
ctrl
,
iobase
+
IRCC_CONTROL
);
register_bank
(
iobase
,
0
);
outb
(
fast
,
iobase
+
IRCC_LCR_A
);
smsc_ircc_set_sir_speed
(
self
,
SMSC_IRCC2_C_IRDA_FALLBACK_SPEED
);
/* Power on device */
outb
(
0x00
,
iobase
+
IRCC_MASTER
);
}
/*
* Function smsc_ircc_setup_netdev(self)
*
* Alloc and setup network device
*
*/
static
int
smsc_ircc_setup_netdev
(
struct
smsc_ircc_cb
*
self
)
{
struct
net_device
*
dev
;
int
err
;
/* Alloc netdev */
if
(
!
(
dev
=
dev_alloc
(
"irda%d"
,
&
err
)))
{
ERROR
(
"%s(), dev_alloc() failed!
\n
"
,
__FUNCTION__
);
kfree
(
self
->
tx_buff
.
head
);
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
-
ENOMEM
;
}
dev
->
priv
=
(
void
*
)
self
;
self
->
netdev
=
dev
;
dev
->
init
=
smsc_ircc_net_init
;
dev
->
hard_start_xmit
=
smsc_ircc_hard_xmit_sir
;
#if SMSC_IRCC2_C_NET_TIMEOUT
dev
->
tx_timeout
=
smsc_ircc_timeout
;
dev
->
watchdog_timeo
=
HZ
*
2
;
/* Allow enough time for speed change */
#endif
dev
->
open
=
smsc_ircc_net_open
;
dev
->
stop
=
smsc_ircc_net_close
;
dev
->
do_ioctl
=
smsc_ircc_net_ioctl
;
dev
->
get_stats
=
smsc_ircc_net_get_stats
;
/* Make ifconfig display some details */
dev
->
base_addr
=
self
->
io
.
fir_base
;
dev
->
irq
=
self
->
io
.
irq
;
rtnl_lock
();
err
=
register_netdevice
(
dev
);
rtnl_unlock
();
if
(
err
)
{
ERROR
(
"%s(), register_netdev() failed!
\n
"
,
__FUNCTION__
);
kfree
(
self
->
tx_buff
.
head
);
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
-
ENODEV
;
}
MESSAGE
(
"IrDA: Registered device %s
\n
"
,
dev
->
name
);
return
0
;
}
/*
* Function smsc_ircc_net_ioctl (dev, rq, cmd)
*
* Process IOCTL commands for this device
*
*/
static
int
smsc_ircc_net_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
struct
if_irda_req
*
irq
=
(
struct
if_irda_req
*
)
rq
;
struct
smsc_ircc_cb
*
self
;
unsigned
long
flags
;
int
ret
=
0
;
ASSERT
(
dev
!=
NULL
,
return
-
1
;);
self
=
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
IRDA_DEBUG
(
2
,
"%s(), %s, (cmd=0x%X)
\n
"
,
__FUNCTION__
,
dev
->
name
,
cmd
);
switch
(
cmd
)
{
case
SIOCSBANDWIDTH
:
/* Set bandwidth */
if
(
!
capable
(
CAP_NET_ADMIN
))
ret
=
-
EPERM
;
else
{
/* Make sure we are the only one touching
* self->io.speed and the hardware - Jean II */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
smsc_ircc_change_speed
(
self
,
irq
->
ifr_baudrate
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
}
break
;
case
SIOCSMEDIABUSY
:
/* Set media busy */
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret
=
-
EPERM
;
break
;
}
irda_device_set_media_busy
(
self
->
netdev
,
TRUE
);
break
;
case
SIOCGRECEIVING
:
/* Check if we are receiving right now */
irq
->
ifr_receiving
=
smsc_ircc_is_receiving
(
self
);
break
;
#if 0
case SIOCSDTRRTS:
if (!capable(CAP_NET_ADMIN)) {
ret = -EPERM;
break;
}
smsc_ircc_sir_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
break;
#endif
default:
ret
=
-
EOPNOTSUPP
;
}
return
ret
;
}
static
struct
net_device_stats
*
smsc_ircc_net_get_stats
(
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
return
&
self
->
stats
;
}
#if SMSC_IRCC2_C_NET_TIMEOUT
/*
* Function smsc_ircc_timeout (struct net_device *dev)
*
* The networking timeout management.
*
*/
static
void
smsc_ircc_timeout
(
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
;
unsigned
long
flags
;
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
WARNING
(
"%s: transmit timed out, changing speed to: %d
\n
"
,
dev
->
name
,
self
->
io
.
speed
);
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
smsc_ircc_sir_start
(
self
);
smsc_ircc_change_speed
(
self
,
self
->
io
.
speed
);
dev
->
trans_start
=
jiffies
;
netif_wake_queue
(
dev
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
}
#endif
/*
* Function smsc_ircc_hard_xmit_sir (struct sk_buff *skb, struct net_device *dev)
*
* Transmits the current frame until FIFO is full, then
* waits until the next transmit interrupt, and continues until the
* frame is transmitted.
*/
int
smsc_ircc_hard_xmit_sir
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
;
unsigned
long
flags
;
int
iobase
;
s32
speed
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
dev
!=
NULL
,
return
0
;);
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
iobase
=
self
->
io
.
sir_base
;
netif_stop_queue
(
dev
);
/* Make sure test of self->io.speed & speed change are atomic */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Check if we need to change the speed */
speed
=
irda_get_next_speed
(
skb
);
if
((
speed
!=
self
->
io
.
speed
)
&&
(
speed
!=
-
1
))
{
/* Check for empty frame */
if
(
!
skb
->
len
)
{
/*
* We send frames one by one in SIR mode (no
* pipelining), so at this point, if we were sending
* a previous frame, we just received the interrupt
* telling us it is finished (UART_IIR_THRI).
* Therefore, waiting for the transmitter to really
* finish draining the fifo won't take too long.
* And the interrupt handler is not expected to run.
* - Jean II */
smsc_ircc_sir_wait_hw_transmitter_finish
(
self
);
smsc_ircc_change_speed
(
self
,
speed
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
}
else
{
self
->
new_speed
=
speed
;
}
}
/* Init tx buffer */
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
self
->
tx_buff
.
len
=
async_wrap_skb
(
skb
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
truesize
);
self
->
stats
.
tx_bytes
+=
self
->
tx_buff
.
len
;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb
(
UART_IER_THRI
,
iobase
+
UART_IER
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
}
/*
* Function smsc_ircc_set_fir_speed (self, baud)
*
* Change the speed of the device
*
*/
static
void
smsc_ircc_set_fir_speed
(
struct
smsc_ircc_cb
*
self
,
u32
speed
)
{
int
fir_base
,
ir_mode
,
ctrl
,
fast
;
ASSERT
(
self
!=
NULL
,
return
;);
fir_base
=
self
->
io
.
fir_base
;
self
->
io
.
speed
=
speed
;
switch
(
speed
)
{
default:
case
576000
:
ir_mode
=
IRCC_CFGA_IRDA_HDLC
;
ctrl
=
IRCC_CRC
;
fast
=
0
;
IRDA_DEBUG
(
0
,
"%s(), handling baud of 576000
\n
"
,
__FUNCTION__
);
break
;
case
1152000
:
ir_mode
=
IRCC_CFGA_IRDA_HDLC
;
ctrl
=
IRCC_1152
|
IRCC_CRC
;
fast
=
IRCC_LCR_A_FAST
|
IRCC_LCR_A_GP_DATA
;
IRDA_DEBUG
(
0
,
"%s(), handling baud of 1152000
\n
"
,
__FUNCTION__
);
break
;
case
4000000
:
ir_mode
=
IRCC_CFGA_IRDA_4PPM
;
ctrl
=
IRCC_CRC
;
fast
=
IRCC_LCR_A_FAST
;
IRDA_DEBUG
(
0
,
"%s(), handling baud of 4000000
\n
"
,
__FUNCTION__
);
break
;
}
#if 0
Now in tranceiver!
/* This causes an interrupt */
register_bank(fir_base, 0);
outb((inb(fir_base+IRCC_LCR_A) & 0xbf) | fast, fir_base+IRCC_LCR_A);
#endif
register_bank
(
fir_base
,
1
);
outb
(((
inb
(
fir_base
+
IRCC_SCE_CFGA
)
&
IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK
)
|
ir_mode
),
fir_base
+
IRCC_SCE_CFGA
);
register_bank
(
fir_base
,
4
);
outb
((
inb
(
fir_base
+
IRCC_CONTROL
)
&
0x30
)
|
ctrl
,
fir_base
+
IRCC_CONTROL
);
}
/*
* Function smsc_ircc_fir_start(self)
*
* Change the speed of the device
*
*/
static
void
smsc_ircc_fir_start
(
struct
smsc_ircc_cb
*
self
)
{
struct
net_device
*
dev
;
int
fir_base
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
self
!=
NULL
,
return
;);
dev
=
self
->
netdev
;
ASSERT
(
dev
!=
NULL
,
return
;);
fir_base
=
self
->
io
.
fir_base
;
/* Reset everything */
/* Install FIR transmit handler */
dev
->
hard_start_xmit
=
smsc_ircc_hard_xmit_fir
;
/* Clear FIFO */
outb
(
inb
(
fir_base
+
IRCC_LCR_A
)
|
IRCC_LCR_A_FIFO_RESET
,
fir_base
+
IRCC_LCR_A
);
/* Enable interrupt */
/*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base+IRCC_IER);*/
register_bank
(
fir_base
,
1
);
/* Select the TX/RX interface */
#ifdef SMSC_669
/* Uses pin 88/89 for Rx/Tx */
outb
(((
inb
(
fir_base
+
IRCC_SCE_CFGB
)
&
0x3f
)
|
IRCC_CFGB_MUX_COM
),
fir_base
+
IRCC_SCE_CFGB
);
#else
outb
(((
inb
(
fir_base
+
IRCC_SCE_CFGB
)
&
0x3f
)
|
IRCC_CFGB_MUX_IR
),
fir_base
+
IRCC_SCE_CFGB
);
#endif
(
void
)
inb
(
fir_base
+
IRCC_FIFO_THRESHOLD
);
/* Enable SCE interrupts */
outb
(
0
,
fir_base
+
IRCC_MASTER
);
register_bank
(
fir_base
,
0
);
outb
(
IRCC_IER_ACTIVE_FRAME
|
IRCC_IER_EOM
,
fir_base
+
IRCC_IER
);
outb
(
IRCC_MASTER_INT_EN
,
fir_base
+
IRCC_MASTER
);
}
/*
* Function smsc_ircc_fir_stop(self, baud)
*
* Change the speed of the device
*
*/
static
void
smsc_ircc_fir_stop
(
struct
smsc_ircc_cb
*
self
)
{
int
fir_base
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
self
!=
NULL
,
return
;);
fir_base
=
self
->
io
.
fir_base
;
register_bank
(
fir_base
,
0
);
/*outb(IRCC_MASTER_RESET, fir_base+IRCC_MASTER);*/
outb
(
inb
(
fir_base
+
IRCC_LCR_B
)
&
IRCC_LCR_B_SIP_ENABLE
,
fir_base
+
IRCC_LCR_B
);
}
/*
* Function smsc_ircc_change_speed(self, baud)
*
* Change the speed of the device
*
* This function *must* be called with spinlock held, because it may
* be called from the irq handler. - Jean II
*/
static
void
smsc_ircc_change_speed
(
void
*
priv
,
u32
speed
)
{
struct
smsc_ircc_cb
*
self
=
(
struct
smsc_ircc_cb
*
)
priv
;
struct
net_device
*
dev
;
int
iobase
;
int
last_speed_was_sir
;
IRDA_DEBUG
(
0
,
"%s() changing speed to: %d
\n
"
,
__FUNCTION__
,
speed
);
ASSERT
(
self
!=
NULL
,
return
;);
dev
=
self
->
netdev
;
iobase
=
self
->
io
.
fir_base
;
last_speed_was_sir
=
self
->
io
.
speed
<=
SMSC_IRCC2_MAX_SIR_SPEED
;
#if 0
/* Temp Hack */
speed= 1152000;
self->io.speed = speed;
last_speed_was_sir = 0;
smsc_ircc_fir_start(self);
#endif
if
(
self
->
io
.
speed
==
0
)
smsc_ircc_sir_start
(
self
);
#if 0
if(!last_speed_was_sir) speed = self->io.speed;
#endif
if
(
self
->
io
.
speed
!=
speed
)
smsc_ircc_set_transceiver_for_speed
(
self
,
speed
);
self
->
io
.
speed
=
speed
;
if
(
speed
<=
SMSC_IRCC2_MAX_SIR_SPEED
)
{
if
(
!
last_speed_was_sir
)
{
smsc_ircc_fir_stop
(
self
);
smsc_ircc_sir_start
(
self
);
}
smsc_ircc_set_sir_speed
(
self
,
speed
);
}
else
{
if
(
last_speed_was_sir
)
{
#if SMSC_IRCC2_C_SIR_STOP
smsc_ircc_sir_stop
(
self
);
#endif
smsc_ircc_fir_start
(
self
);
}
smsc_ircc_set_fir_speed
(
self
,
speed
);
#if 0
self->tx_buff.len = 10;
self->tx_buff.data = self->tx_buff.head;
smsc_ircc_dma_xmit(self, iobase, 4000);
#endif
/* Be ready for incoming frames */
smsc_ircc_dma_receive
(
self
,
iobase
);
}
netif_wake_queue
(
dev
);
}
/*
* Function smsc_ircc_set_sir_speed (self, speed)
*
* Set speed of IrDA port to specified baudrate
*
*/
void
smsc_ircc_set_sir_speed
(
void
*
priv
,
__u32
speed
)
{
struct
smsc_ircc_cb
*
self
=
(
struct
smsc_ircc_cb
*
)
priv
;
int
iobase
;
int
fcr
;
/* FIFO control reg */
int
lcr
;
/* Line control reg */
int
divisor
;
IRDA_DEBUG
(
0
,
"%s(), Setting speed to: %d
\n
"
,
__FUNCTION__
,
speed
);
ASSERT
(
self
!=
NULL
,
return
;);
iobase
=
self
->
io
.
sir_base
;
/* Update accounting for new speed */
self
->
io
.
speed
=
speed
;
/* Turn off interrupts */
outb
(
0
,
iobase
+
UART_IER
);
divisor
=
SMSC_IRCC2_MAX_SIR_SPEED
/
speed
;
fcr
=
UART_FCR_ENABLE_FIFO
;
/*
* Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
* about this timeout since it will always be fast enough.
*/
if
(
self
->
io
.
speed
<
38400
)
fcr
|=
UART_FCR_TRIGGER_1
;
else
fcr
|=
UART_FCR_TRIGGER_14
;
/* IrDA ports use 8N1 */
lcr
=
UART_LCR_WLEN8
;
outb
(
UART_LCR_DLAB
|
lcr
,
iobase
+
UART_LCR
);
/* Set DLAB */
outb
(
divisor
&
0xff
,
iobase
+
UART_DLL
);
/* Set speed */
outb
(
divisor
>>
8
,
iobase
+
UART_DLM
);
outb
(
lcr
,
iobase
+
UART_LCR
);
/* Set 8N1 */
outb
(
fcr
,
iobase
+
UART_FCR
);
/* Enable FIFO's */
/* Turn on interrups */
outb
(
UART_IER_RLSI
|
UART_IER_RDI
|
UART_IER_THRI
,
iobase
+
UART_IER
);
IRDA_DEBUG
(
2
,
"%s() speed changed to: %d
\n
"
,
__FUNCTION__
,
speed
);
}
/*
* Function smsc_ircc_hard_xmit_fir (skb, dev)
*
* Transmit the frame!
*
*/
static
int
smsc_ircc_hard_xmit_fir
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
;
unsigned
long
flags
;
s32
speed
;
int
iobase
;
int
mtt
;
ASSERT
(
dev
!=
NULL
,
return
0
;);
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
iobase
=
self
->
io
.
fir_base
;
netif_stop_queue
(
dev
);
/* Make sure test of self->io.speed & speed change are atomic */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Check if we need to change the speed after this frame */
speed
=
irda_get_next_speed
(
skb
);
if
((
speed
!=
self
->
io
.
speed
)
&&
(
speed
!=
-
1
))
{
/* Check for empty frame */
if
(
!
skb
->
len
)
{
/* Note : you should make sure that speed changes
* are not going to corrupt any outgoing frame.
* Look at nsc-ircc for the gory details - Jean II */
smsc_ircc_change_speed
(
self
,
speed
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
}
else
self
->
new_speed
=
speed
;
}
memcpy
(
self
->
tx_buff
.
head
,
skb
->
data
,
skb
->
len
);
self
->
tx_buff
.
len
=
skb
->
len
;
self
->
tx_buff
.
data
=
self
->
tx_buff
.
head
;
mtt
=
irda_get_mtt
(
skb
);
if
(
mtt
)
{
int
bofs
;
/*
* Compute how many BOFs (STA or PA's) we need to waste the
* min turn time given the speed of the link.
*/
bofs
=
mtt
*
(
self
->
io
.
speed
/
1000
)
/
8000
;
if
(
bofs
>
4095
)
bofs
=
4095
;
smsc_ircc_dma_xmit
(
self
,
iobase
,
bofs
);
}
else
{
/* Transmit frame */
smsc_ircc_dma_xmit
(
self
,
iobase
,
0
);
}
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
dev_kfree_skb
(
skb
);
return
0
;
}
/*
* Function smsc_ircc_dma_xmit (self, iobase)
*
* Transmit data using DMA
*
*/
static
void
smsc_ircc_dma_xmit
(
struct
smsc_ircc_cb
*
self
,
int
iobase
,
int
bofs
)
{
u8
ctrl
;
IRDA_DEBUG
(
3
,
"%s
\n
"
,
__FUNCTION__
);
#if 1
/* Disable Rx */
register_bank
(
iobase
,
0
);
outb
(
0x00
,
iobase
+
IRCC_LCR_B
);
#endif
register_bank
(
iobase
,
1
);
outb
(
inb
(
iobase
+
IRCC_SCE_CFGB
)
&
~
IRCC_CFGB_DMA_ENABLE
,
iobase
+
IRCC_SCE_CFGB
);
self
->
io
.
direction
=
IO_XMIT
;
/* Set BOF additional count for generating the min turn time */
register_bank
(
iobase
,
4
);
outb
(
bofs
&
0xff
,
iobase
+
IRCC_BOF_COUNT_LO
);
ctrl
=
inb
(
iobase
+
IRCC_CONTROL
)
&
0xf0
;
outb
(
ctrl
|
((
bofs
>>
8
)
&
0x0f
),
iobase
+
IRCC_BOF_COUNT_HI
);
/* Set max Tx frame size */
outb
(
self
->
tx_buff
.
len
>>
8
,
iobase
+
IRCC_TX_SIZE_HI
);
outb
(
self
->
tx_buff
.
len
&
0xff
,
iobase
+
IRCC_TX_SIZE_LO
);
/*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/
/* Enable burst mode chip Tx DMA */
register_bank
(
iobase
,
1
);
outb
(
inb
(
iobase
+
IRCC_SCE_CFGB
)
|
IRCC_CFGB_DMA_ENABLE
|
IRCC_CFGB_DMA_BURST
,
iobase
+
IRCC_SCE_CFGB
);
/* Setup DMA controller (must be done after enabling chip DMA) */
setup_dma
(
self
->
io
.
dma
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
,
DMA_TX_MODE
);
/* Enable interrupt */
register_bank
(
iobase
,
0
);
outb
(
IRCC_IER_ACTIVE_FRAME
|
IRCC_IER_EOM
,
iobase
+
IRCC_IER
);
outb
(
IRCC_MASTER_INT_EN
,
iobase
+
IRCC_MASTER
);
/* Enable transmit */
outb
(
IRCC_LCR_B_SCE_TRANSMIT
|
IRCC_LCR_B_SIP_ENABLE
,
iobase
+
IRCC_LCR_B
);
}
/*
* Function smsc_ircc_dma_xmit_complete (self)
*
* The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
static
void
smsc_ircc_dma_xmit_complete
(
struct
smsc_ircc_cb
*
self
,
int
iobase
)
{
IRDA_DEBUG
(
3
,
"%s
\n
"
,
__FUNCTION__
);
#if 0
/* Disable Tx */
register_bank(iobase, 0);
outb(0x00, iobase+IRCC_LCR_B);
#endif
register_bank
(
self
->
io
.
fir_base
,
1
);
outb
(
inb
(
self
->
io
.
fir_base
+
IRCC_SCE_CFGB
)
&
~
IRCC_CFGB_DMA_ENABLE
,
self
->
io
.
fir_base
+
IRCC_SCE_CFGB
);
/* Check for underrun! */
register_bank
(
iobase
,
0
);
if
(
inb
(
iobase
+
IRCC_LSR
)
&
IRCC_LSR_UNDERRUN
)
{
self
->
stats
.
tx_errors
++
;
self
->
stats
.
tx_fifo_errors
++
;
/* Reset error condition */
register_bank
(
iobase
,
0
);
outb
(
IRCC_MASTER_ERROR_RESET
,
iobase
+
IRCC_MASTER
);
outb
(
0x00
,
iobase
+
IRCC_MASTER
);
}
else
{
self
->
stats
.
tx_packets
++
;
self
->
stats
.
tx_bytes
+=
self
->
tx_buff
.
len
;
}
/* Check if it's time to change the speed */
if
(
self
->
new_speed
)
{
smsc_ircc_change_speed
(
self
,
self
->
new_speed
);
self
->
new_speed
=
0
;
}
netif_wake_queue
(
self
->
netdev
);
}
/*
* Function smsc_ircc_dma_receive(self)
*
* Get ready for receiving a frame. The device will initiate a DMA
* if it starts to receive a frame.
*
*/
static
int
smsc_ircc_dma_receive
(
struct
smsc_ircc_cb
*
self
,
int
iobase
)
{
#if 0
/* Turn off chip DMA */
register_bank(iobase, 1);
outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
iobase+IRCC_SCE_CFGB);
#endif
/* Disable Tx */
register_bank
(
iobase
,
0
);
outb
(
0x00
,
iobase
+
IRCC_LCR_B
);
/* Turn off chip DMA */
register_bank
(
iobase
,
1
);
outb
(
inb
(
iobase
+
IRCC_SCE_CFGB
)
&
~
IRCC_CFGB_DMA_ENABLE
,
iobase
+
IRCC_SCE_CFGB
);
self
->
io
.
direction
=
IO_RECV
;
self
->
rx_buff
.
data
=
self
->
rx_buff
.
head
;
/* Set max Rx frame size */
register_bank
(
iobase
,
4
);
outb
((
2050
>>
8
)
&
0x0f
,
iobase
+
IRCC_RX_SIZE_HI
);
outb
(
2050
&
0xff
,
iobase
+
IRCC_RX_SIZE_LO
);
/* Setup DMA controller */
setup_dma
(
self
->
io
.
dma
,
self
->
rx_buff
.
data
,
self
->
rx_buff
.
truesize
,
DMA_RX_MODE
);
/* Enable burst mode chip Rx DMA */
register_bank
(
iobase
,
1
);
outb
(
inb
(
iobase
+
IRCC_SCE_CFGB
)
|
IRCC_CFGB_DMA_ENABLE
|
IRCC_CFGB_DMA_BURST
,
iobase
+
IRCC_SCE_CFGB
);
/* Enable interrupt */
register_bank
(
iobase
,
0
);
outb
(
IRCC_IER_ACTIVE_FRAME
|
IRCC_IER_EOM
,
iobase
+
IRCC_IER
);
outb
(
IRCC_MASTER_INT_EN
,
iobase
+
IRCC_MASTER
);
/* Enable receiver */
register_bank
(
iobase
,
0
);
outb
(
IRCC_LCR_B_SCE_RECEIVE
|
IRCC_LCR_B_SIP_ENABLE
,
iobase
+
IRCC_LCR_B
);
return
0
;
}
/*
* Function smsc_ircc_dma_receive_complete(self, iobase)
*
* Finished with receiving frames
*
*/
static
void
smsc_ircc_dma_receive_complete
(
struct
smsc_ircc_cb
*
self
,
int
iobase
)
{
struct
sk_buff
*
skb
;
int
len
,
msgcnt
,
lsr
;
register_bank
(
iobase
,
0
);
IRDA_DEBUG
(
3
,
"%s
\n
"
,
__FUNCTION__
);
#if 0
/* Disable Rx */
register_bank(iobase, 0);
outb(0x00, iobase+IRCC_LCR_B);
#endif
register_bank
(
iobase
,
0
);
outb
(
inb
(
iobase
+
IRCC_LSAR
)
&
~
IRCC_LSAR_ADDRESS_MASK
,
iobase
+
IRCC_LSAR
);
lsr
=
inb
(
iobase
+
IRCC_LSR
);
msgcnt
=
inb
(
iobase
+
IRCC_LCR_B
)
&
0x08
;
IRDA_DEBUG
(
2
,
"%s: dma count = %d
\n
"
,
__FUNCTION__
,
get_dma_residue
(
self
->
io
.
dma
));
len
=
self
->
rx_buff
.
truesize
-
get_dma_residue
(
self
->
io
.
dma
);
/* Look for errors
*/
if
(
lsr
&
(
IRCC_LSR_FRAME_ERROR
|
IRCC_LSR_CRC_ERROR
|
IRCC_LSR_SIZE_ERROR
))
{
self
->
stats
.
rx_errors
++
;
if
(
lsr
&
IRCC_LSR_FRAME_ERROR
)
self
->
stats
.
rx_frame_errors
++
;
if
(
lsr
&
IRCC_LSR_CRC_ERROR
)
self
->
stats
.
rx_crc_errors
++
;
if
(
lsr
&
IRCC_LSR_SIZE_ERROR
)
self
->
stats
.
rx_length_errors
++
;
if
(
lsr
&
(
IRCC_LSR_UNDERRUN
|
IRCC_LSR_OVERRUN
))
self
->
stats
.
rx_length_errors
++
;
return
;
}
/* Remove CRC */
if
(
self
->
io
.
speed
<
4000000
)
len
-=
2
;
else
len
-=
4
;
if
((
len
<
2
)
||
(
len
>
2050
))
{
WARNING
(
"%s(), bogus len=%d
\n
"
,
__FUNCTION__
,
len
);
return
;
}
IRDA_DEBUG
(
2
,
"%s: msgcnt = %d, len=%d
\n
"
,
__FUNCTION__
,
msgcnt
,
len
);
skb
=
dev_alloc_skb
(
len
+
1
);
if
(
!
skb
)
{
WARNING
(
"%s(), memory squeeze, dropping frame.
\n
"
,
__FUNCTION__
);
return
;
}
/* Make sure IP header gets aligned */
skb_reserve
(
skb
,
1
);
memcpy
(
skb_put
(
skb
,
len
),
self
->
rx_buff
.
data
,
len
);
self
->
stats
.
rx_packets
++
;
self
->
stats
.
rx_bytes
+=
len
;
skb
->
dev
=
self
->
netdev
;
skb
->
mac
.
raw
=
skb
->
data
;
skb
->
protocol
=
htons
(
ETH_P_IRDA
);
netif_rx
(
skb
);
}
/*
* Function smsc_ircc_sir_receive (self)
*
* Receive one frame from the infrared port
*
*/
static
void
smsc_ircc_sir_receive
(
struct
smsc_ircc_cb
*
self
)
{
int
boguscount
=
0
;
int
iobase
;
ASSERT
(
self
!=
NULL
,
return
;);
iobase
=
self
->
io
.
sir_base
;
/*
* Receive all characters in Rx FIFO, unwrap and unstuff them.
* async_unwrap_char will deliver all found frames
*/
do
{
async_unwrap_char
(
self
->
netdev
,
&
self
->
stats
,
&
self
->
rx_buff
,
inb
(
iobase
+
UART_RX
));
/* Make sure we don't stay here to long */
if
(
boguscount
++
>
32
)
{
IRDA_DEBUG
(
2
,
"%s(), breaking!
\n
"
,
__FUNCTION__
);
break
;
}
}
while
(
inb
(
iobase
+
UART_LSR
)
&
UART_LSR_DR
);
}
/*
* Function smsc_ircc_interrupt (irq, dev_id, regs)
*
* An interrupt from the chip has arrived. Time to do some work
*
*/
static
irqreturn_t
smsc_ircc_interrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_id
;
struct
smsc_ircc_cb
*
self
;
int
iobase
,
iir
,
lcra
,
lsr
;
if
(
dev
==
NULL
)
{
printk
(
KERN_WARNING
"%s: irq %d for unknown device.
\n
"
,
driver_name
,
irq
);
return
IRQ_NONE
;
}
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
IRQ_NONE
;);
/* Serialise the interrupt handler in various CPUs, stop Tx path */
spin_lock
(
&
self
->
lock
);
/* Check if we should use the SIR interrupt handler */
if
(
self
->
io
.
speed
<=
SMSC_IRCC2_MAX_SIR_SPEED
)
{
smsc_ircc_interrupt_sir
(
irq
,
dev_id
,
regs
);
spin_unlock
(
&
self
->
lock
);
return
IRQ_HANDLED
;
}
iobase
=
self
->
io
.
fir_base
;
register_bank
(
iobase
,
0
);
iir
=
inb
(
iobase
+
IRCC_IIR
);
/* Disable interrupts */
outb
(
0
,
iobase
+
IRCC_IER
);
lcra
=
inb
(
iobase
+
IRCC_LCR_A
);
lsr
=
inb
(
iobase
+
IRCC_LSR
);
IRDA_DEBUG
(
2
,
"%s(), iir = 0x%02x
\n
"
,
__FUNCTION__
,
iir
);
if
(
iir
&
IRCC_IIR_EOM
)
{
if
(
self
->
io
.
direction
==
IO_RECV
)
smsc_ircc_dma_receive_complete
(
self
,
iobase
);
else
smsc_ircc_dma_xmit_complete
(
self
,
iobase
);
smsc_ircc_dma_receive
(
self
,
iobase
);
}
if
(
iir
&
IRCC_IIR_ACTIVE_FRAME
)
{
/*printk(KERN_WARNING __FUNCTION__ "(): Active Frame\n");*/
}
/* Enable interrupts again */
register_bank
(
iobase
,
0
);
outb
(
IRCC_IER_ACTIVE_FRAME
|
IRCC_IER_EOM
,
iobase
+
IRCC_IER
);
spin_unlock
(
&
self
->
lock
);
return
IRQ_HANDLED
;
}
/*
* Function irport_interrupt_sir (irq, dev_id, regs)
*
* Interrupt handler for SIR modes
*/
void
smsc_ircc_interrupt_sir
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_id
;
struct
smsc_ircc_cb
*
self
;
int
boguscount
=
0
;
int
iobase
;
int
iir
,
lsr
;
if
(
!
dev
)
{
WARNING
(
"%s() irq %d for unknown device.
\n
"
,
__FUNCTION__
,
irq
);
return
;
}
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
/* Already locked comming here in smsc_ircc_interrupt() */
/*spin_lock(&self->lock);*/
iobase
=
self
->
io
.
sir_base
;
iir
=
inb
(
iobase
+
UART_IIR
)
&
UART_IIR_ID
;
while
(
iir
)
{
/* Clear interrupt */
lsr
=
inb
(
iobase
+
UART_LSR
);
IRDA_DEBUG
(
4
,
"%s(), iir=%02x, lsr=%02x, iobase=%#x
\n
"
,
__FUNCTION__
,
iir
,
lsr
,
iobase
);
switch
(
iir
)
{
case
UART_IIR_RLSI
:
IRDA_DEBUG
(
2
,
"%s(), RLSI
\n
"
,
__FUNCTION__
);
break
;
case
UART_IIR_RDI
:
/* Receive interrupt */
smsc_ircc_sir_receive
(
self
);
break
;
case
UART_IIR_THRI
:
if
(
lsr
&
UART_LSR_THRE
)
/* Transmitter ready for data */
smsc_ircc_sir_write_wakeup
(
self
);
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), unhandled IIR=%#x
\n
"
,
__FUNCTION__
,
iir
);
break
;
}
/* Make sure we don't stay here to long */
if
(
boguscount
++
>
100
)
break
;
iir
=
inb
(
iobase
+
UART_IIR
)
&
UART_IIR_ID
;
}
/*spin_unlock(&self->lock);*/
}
#if 0 /* unused */
/*
* Function ircc_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
static int ircc_is_receiving(struct smsc_ircc_cb *self)
{
int status = FALSE;
/* int iobase; */
IRDA_DEBUG(1, "%s\n", __FUNCTION__);
ASSERT(self != NULL, return FALSE;);
IRDA_DEBUG(0, "%s: dma count = %d\n", __FUNCTION__,
get_dma_residue(self->io.dma));
status = (self->rx_buff.state != OUTSIDE_FRAME);
return status;
}
#endif /* unused */
static
int
smsc_ircc_net_init
(
struct
net_device
*
dev
)
{
/* Keep track of module usage */
SET_MODULE_OWNER
(
dev
);
/* Set up to be a normal IrDA network device driver */
irda_device_setup
(
dev
);
/* Insert overrides below this line! */
return
0
;
}
/*
* Function smsc_ircc_net_open (dev)
*
* Start the device
*
*/
static
int
smsc_ircc_net_open
(
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
;
int
iobase
;
char
hwname
[
16
];
unsigned
long
flags
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
dev
!=
NULL
,
return
-
1
;);
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
iobase
=
self
->
io
.
fir_base
;
if
(
request_irq
(
self
->
io
.
irq
,
smsc_ircc_interrupt
,
0
,
dev
->
name
,
(
void
*
)
dev
))
{
IRDA_DEBUG
(
0
,
"%s(), unable to allocate irq=%d
\n
"
,
__FUNCTION__
,
self
->
io
.
irq
);
return
-
EAGAIN
;
}
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/*smsc_ircc_sir_start(self);*/
self
->
io
.
speed
=
0
;
smsc_ircc_change_speed
(
self
,
SMSC_IRCC2_C_IRDA_FALLBACK_SPEED
);
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
/* Give self a hardware name */
/* It would be cool to offer the chip revision here - Jean II */
sprintf
(
hwname
,
"SMSC @ 0x%03x"
,
self
->
io
.
fir_base
);
/*
* Open new IrLAP layer instance, now that everything should be
* initialized properly
*/
self
->
irlap
=
irlap_open
(
dev
,
&
self
->
qos
,
hwname
);
/*
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
*/
if
(
request_dma
(
self
->
io
.
dma
,
dev
->
name
))
{
smsc_ircc_net_close
(
dev
);
WARNING
(
"%s(), unable to allocate DMA=%d
\n
"
,
__FUNCTION__
,
self
->
io
.
dma
);
return
-
EAGAIN
;
}
netif_start_queue
(
dev
);
return
0
;
}
/*
* Function smsc_ircc_net_close (dev)
*
* Stop the device
*
*/
static
int
smsc_ircc_net_close
(
struct
net_device
*
dev
)
{
struct
smsc_ircc_cb
*
self
;
int
iobase
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
dev
!=
NULL
,
return
-
1
;);
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
priv
;
ASSERT
(
self
!=
NULL
,
return
0
;);
iobase
=
self
->
io
.
fir_base
;
/* Stop device */
netif_stop_queue
(
dev
);
/* Stop and remove instance of IrLAP */
if
(
self
->
irlap
)
irlap_close
(
self
->
irlap
);
self
->
irlap
=
NULL
;
free_irq
(
self
->
io
.
irq
,
dev
);
disable_dma
(
self
->
io
.
dma
);
free_dma
(
self
->
io
.
dma
);
return
0
;
}
static
void
smsc_ircc_suspend
(
struct
smsc_ircc_cb
*
self
)
{
MESSAGE
(
"%s, Suspending
\n
"
,
driver_name
);
if
(
self
->
io
.
suspended
)
return
;
smsc_ircc_net_close
(
self
->
netdev
);
self
->
io
.
suspended
=
1
;
}
static
void
smsc_ircc_wakeup
(
struct
smsc_ircc_cb
*
self
)
{
if
(
!
self
->
io
.
suspended
)
return
;
/* The code was doing a "cli()" here, but this can't be right.
* If you need protection, do it in net_open with a spinlock
* or give a good reason. - Jean II */
smsc_ircc_net_open
(
self
->
netdev
);
MESSAGE
(
"%s, Waking up
\n
"
,
driver_name
);
}
static
int
smsc_ircc_pmproc
(
struct
pm_dev
*
dev
,
pm_request_t
rqst
,
void
*
data
)
{
struct
smsc_ircc_cb
*
self
=
(
struct
smsc_ircc_cb
*
)
dev
->
data
;
if
(
self
)
{
switch
(
rqst
)
{
case
PM_SUSPEND
:
smsc_ircc_suspend
(
self
);
break
;
case
PM_RESUME
:
smsc_ircc_wakeup
(
self
);
break
;
}
}
return
0
;
}
/*
* Function smsc_ircc_close (self)
*
* Close driver instance
*
*/
static
int
__exit
smsc_ircc_close
(
struct
smsc_ircc_cb
*
self
)
{
int
iobase
;
unsigned
long
flags
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
self
!=
NULL
,
return
-
1
;);
iobase
=
self
->
io
.
fir_base
;
if
(
self
->
pmdev
)
pm_unregister
(
self
->
pmdev
);
/* Remove netdevice */
if
(
self
->
netdev
)
{
rtnl_lock
();
unregister_netdevice
(
self
->
netdev
);
rtnl_unlock
();
}
/* Make sure the irq handler is not exectuting */
spin_lock_irqsave
(
&
self
->
lock
,
flags
);
/* Stop interrupts */
register_bank
(
iobase
,
0
);
outb
(
0
,
iobase
+
IRCC_IER
);
outb
(
IRCC_MASTER_RESET
,
iobase
+
IRCC_MASTER
);
outb
(
0x00
,
iobase
+
IRCC_MASTER
);
#if 0
/* Reset to SIR mode */
register_bank(iobase, 1);
outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
#endif
spin_unlock_irqrestore
(
&
self
->
lock
,
flags
);
/* Release the PORTS that this driver is using */
IRDA_DEBUG
(
0
,
"%s(), releasing 0x%03x
\n
"
,
__FUNCTION__
,
self
->
io
.
fir_base
);
release_region
(
self
->
io
.
fir_base
,
self
->
io
.
fir_ext
);
IRDA_DEBUG
(
0
,
"%s(), releasing 0x%03x
\n
"
,
__FUNCTION__
,
self
->
io
.
sir_base
);
release_region
(
self
->
io
.
sir_base
,
self
->
io
.
sir_ext
);
if
(
self
->
tx_buff
.
head
)
kfree
(
self
->
tx_buff
.
head
);
if
(
self
->
rx_buff
.
head
)
kfree
(
self
->
rx_buff
.
head
);
kfree
(
self
);
return
0
;
}
void
__exit
smsc_ircc_cleanup
(
void
)
{
int
i
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
dev_self
[
i
])
smsc_ircc_close
(
dev_self
[
i
]);
}
}
/*
* Start SIR operations
*
* This function *must* be called with spinlock held, because it may
* be called from the irq handler (via smsc_ircc_change_speed()). - Jean II
*/
void
smsc_ircc_sir_start
(
struct
smsc_ircc_cb
*
self
)
{
struct
net_device
*
dev
;
int
fir_base
,
sir_base
;
IRDA_DEBUG
(
3
,
"%s
\n
"
,
__FUNCTION__
);
ASSERT
(
self
!=
NULL
,
return
;);
dev
=
self
->
netdev
;
ASSERT
(
dev
!=
NULL
,
return
;);
dev
->
hard_start_xmit
=
&
smsc_ircc_hard_xmit_sir
;
fir_base
=
self
->
io
.
fir_base
;
sir_base
=
self
->
io
.
sir_base
;
/* Reset everything */
outb
(
IRCC_MASTER_RESET
,
fir_base
+
IRCC_MASTER
);
#if SMSC_IRCC2_C_SIR_STOP
/*smsc_ircc_sir_stop(self);*/
#endif
register_bank
(
fir_base
,
1
);
outb
(((
inb
(
fir_base
+
IRCC_SCE_CFGA
)
&
IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK
)
|
IRCC_CFGA_IRDA_SIR_A
),
fir_base
+
IRCC_SCE_CFGA
);
/* Initialize UART */
outb
(
UART_LCR_WLEN8
,
sir_base
+
UART_LCR
);
/* Reset DLAB */
outb
((
UART_MCR_DTR
|
UART_MCR_RTS
|
UART_MCR_OUT2
),
sir_base
+
UART_MCR
);
/* Turn on interrups */
outb
(
UART_IER_RLSI
|
UART_IER_RDI
|
UART_IER_THRI
,
sir_base
+
UART_IER
);
IRDA_DEBUG
(
3
,
"%s() - exit
\n
"
,
__FUNCTION__
);
outb
(
0x00
,
fir_base
+
IRCC_MASTER
);
}
#if SMSC_IRCC2_C_SIR_STOP
void
smsc_ircc_sir_stop
(
struct
smsc_ircc_cb
*
self
)
{
int
iobase
;
IRDA_DEBUG
(
3
,
"%s
\n
"
,
__FUNCTION__
);
iobase
=
self
->
io
.
sir_base
;
/* Reset UART */
outb
(
0
,
iobase
+
UART_MCR
);
/* Turn off interrupts */
outb
(
0
,
iobase
+
UART_IER
);
}
#endif
/*
* Function smsc_sir_write_wakeup (self)
*
* Called by the SIR interrupt handler when there's room for more data.
* If we have more packets to send, we send them here.
*
*/
static
void
smsc_ircc_sir_write_wakeup
(
struct
smsc_ircc_cb
*
self
)
{
int
actual
=
0
;
int
iobase
;
int
fcr
;
ASSERT
(
self
!=
NULL
,
return
;);
IRDA_DEBUG
(
4
,
"%s
\n
"
,
__FUNCTION__
);
iobase
=
self
->
io
.
sir_base
;
/* Finished with frame? */
if
(
self
->
tx_buff
.
len
>
0
)
{
/* Write data left in transmit buffer */
actual
=
smsc_ircc_sir_write
(
iobase
,
self
->
io
.
fifo_size
,
self
->
tx_buff
.
data
,
self
->
tx_buff
.
len
);
self
->
tx_buff
.
data
+=
actual
;
self
->
tx_buff
.
len
-=
actual
;
}
else
{
/*if (self->tx_buff.len ==0) {*/
/*
* Now serial buffer is almost free & we can start
* transmission of another packet. But first we must check
* if we need to change the speed of the hardware
*/
if
(
self
->
new_speed
)
{
IRDA_DEBUG
(
5
,
"%s(), Changing speed to %d.
\n
"
,
__FUNCTION__
,
self
->
new_speed
);
smsc_ircc_sir_wait_hw_transmitter_finish
(
self
);
smsc_ircc_change_speed
(
self
,
self
->
new_speed
);
self
->
new_speed
=
0
;
}
else
{
/* Tell network layer that we want more frames */
netif_wake_queue
(
self
->
netdev
);
}
self
->
stats
.
tx_packets
++
;
if
(
self
->
io
.
speed
<=
115200
)
{
/*
* Reset Rx FIFO to make sure that all reflected transmit data
* is discarded. This is needed for half duplex operation
*/
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_CLEAR_RCVR
;
if
(
self
->
io
.
speed
<
38400
)
fcr
|=
UART_FCR_TRIGGER_1
;
else
fcr
|=
UART_FCR_TRIGGER_14
;
outb
(
fcr
,
iobase
+
UART_FCR
);
/* Turn on receive interrupts */
outb
(
UART_IER_RDI
,
iobase
+
UART_IER
);
}
}
}
/*
* Function smsc_ircc_sir_write (iobase, fifo_size, buf, len)
*
* Fill Tx FIFO with transmit data
*
*/
static
int
smsc_ircc_sir_write
(
int
iobase
,
int
fifo_size
,
__u8
*
buf
,
int
len
)
{
int
actual
=
0
;
/* Tx FIFO should be empty! */
if
(
!
(
inb
(
iobase
+
UART_LSR
)
&
UART_LSR_THRE
))
{
WARNING
(
"%s(), failed, fifo not empty!
\n
"
,
__FUNCTION__
);
return
0
;
}
/* Fill FIFO with current frame */
while
((
fifo_size
--
>
0
)
&&
(
actual
<
len
))
{
/* Transmit next byte */
outb
(
buf
[
actual
],
iobase
+
UART_TX
);
actual
++
;
}
return
actual
;
}
/*
* Function smsc_ircc_is_receiving (self)
*
* Returns true is we are currently receiving data
*
*/
static
int
smsc_ircc_is_receiving
(
struct
smsc_ircc_cb
*
self
)
{
return
(
self
->
rx_buff
.
state
!=
OUTSIDE_FRAME
);
}
/*
* Function smsc_ircc_probe_transceiver(self)
*
* Tries to find the used Transceiver
*
*/
static
void
smsc_ircc_probe_transceiver
(
struct
smsc_ircc_cb
*
self
)
{
unsigned
int
i
;
ASSERT
(
self
!=
NULL
,
return
;);
for
(
i
=
0
;
smsc_transceivers
[
i
].
name
!=
NULL
;
i
++
)
if
((
*
smsc_transceivers
[
i
].
probe
)(
self
->
io
.
fir_base
))
{
MESSAGE
(
" %s transceiver found
\n
"
,
smsc_transceivers
[
i
].
name
);
self
->
transceiver
=
i
+
1
;
return
;
}
MESSAGE
(
"No transceiver found. Defaulting to %s
\n
"
,
smsc_transceivers
[
SMSC_IRCC2_C_DEFAULT_TRANSCEIVER
].
name
);
self
->
transceiver
=
SMSC_IRCC2_C_DEFAULT_TRANSCEIVER
;
}
/*
* Function smsc_ircc_set_transceiver_for_speed(self, speed)
*
* Set the transceiver according to the speed
*
*/
static
void
smsc_ircc_set_transceiver_for_speed
(
struct
smsc_ircc_cb
*
self
,
u32
speed
)
{
unsigned
int
trx
;
trx
=
self
->
transceiver
;
if
(
trx
>
0
)
(
*
smsc_transceivers
[
trx
-
1
].
set_for_speed
)(
self
->
io
.
fir_base
,
speed
);
}
/*
* Function smsc_ircc_wait_hw_transmitter_finish ()
*
* Wait for the real end of HW transmission
*
* The UART is a strict FIFO, and we get called only when we have finished
* pushing data to the FIFO, so the maximum amount of time we must wait
* is only for the FIFO to drain out.
*
* We use a simple calibrated loop. We may need to adjust the loop
* delay (udelay) to balance I/O traffic and latency. And we also need to
* adjust the maximum timeout.
* It would probably be better to wait for the proper interrupt,
* but it doesn't seem to be available.
*
* We can't use jiffies or kernel timers because :
* 1) We are called from the interrupt handler, which disable softirqs,
* so jiffies won't be increased
* 2) Jiffies granularity is usually very coarse (10ms), and we don't
* want to wait that long to detect stuck hardware.
* Jean II
*/
static
void
smsc_ircc_sir_wait_hw_transmitter_finish
(
struct
smsc_ircc_cb
*
self
)
{
int
iobase
;
int
count
=
SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US
;
iobase
=
self
->
io
.
sir_base
;
/* Calibrated busy loop */
while
((
count
--
>
0
)
&&
!
(
inb
(
iobase
+
UART_LSR
)
&
UART_LSR_TEMT
))
udelay
(
1
);
if
(
count
==
0
)
IRDA_DEBUG
(
0
,
"%s(): stuck transmitter
\n
"
,
__FUNCTION__
);
}
/* PROBING
*
*
*/
static
int
__init
smsc_ircc_look_for_chips
(
void
)
{
smsc_chip_address_t
*
address
;
char
*
type
;
unsigned
int
cfg_base
,
found
;
found
=
0
;
address
=
possible_addresses
;
while
(
address
->
cfg_base
){
cfg_base
=
address
->
cfg_base
;
/*printk(KERN_WARNING __FUNCTION__ "(): probing: 0x%02x for: 0x%02x\n", cfg_base, address->type);*/
if
(
address
->
type
&
SMSCSIO_TYPE_FDC
){
type
=
"FDC"
;
if
((
address
->
type
)
&
SMSCSIO_TYPE_FLAT
)
{
if
(
!
smsc_superio_flat
(
fdc_chips_flat
,
cfg_base
,
type
))
found
++
;
}
if
((
address
->
type
)
&
SMSCSIO_TYPE_PAGED
)
{
if
(
!
smsc_superio_paged
(
fdc_chips_paged
,
cfg_base
,
type
))
found
++
;
}
}
if
(
address
->
type
&
SMSCSIO_TYPE_LPC
){
type
=
"LPC"
;
if
((
address
->
type
)
&
SMSCSIO_TYPE_FLAT
)
{
if
(
!
smsc_superio_flat
(
lpc_chips_flat
,
cfg_base
,
type
))
found
++
;
}
if
((
address
->
type
)
&
SMSCSIO_TYPE_PAGED
)
{
if
(
!
smsc_superio_paged
(
lpc_chips_paged
,
cfg_base
,
"LPC"
))
found
++
;
}
}
address
++
;
}
return
found
;
}
/*
* Function smsc_superio_flat (chip, base, type)
*
* Try to get configuration of a smc SuperIO chip with flat register model
*
*/
static
int
__init
smsc_superio_flat
(
const
smsc_chip_t
*
chips
,
unsigned
short
cfgbase
,
char
*
type
)
{
unsigned
short
firbase
,
sirbase
;
u8
mode
,
dma
,
irq
;
int
ret
=
-
ENODEV
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
if
(
smsc_ircc_probe
(
cfgbase
,
SMSCSIOFLAT_DEVICEID_REG
,
chips
,
type
)
==
NULL
)
return
ret
;
outb
(
SMSCSIOFLAT_UARTMODE0C_REG
,
cfgbase
);
mode
=
inb
(
cfgbase
+
1
);
/*printk(KERN_WARNING __FUNCTION__ "(): mode: 0x%02x\n", mode);*/
if
(
!
(
mode
&
SMSCSIOFLAT_UART2MODE_VAL_IRDA
))
WARNING
(
"%s(): IrDA not enabled
\n
"
,
__FUNCTION__
);
outb
(
SMSCSIOFLAT_UART2BASEADDR_REG
,
cfgbase
);
sirbase
=
inb
(
cfgbase
+
1
)
<<
2
;
/* FIR iobase */
outb
(
SMSCSIOFLAT_FIRBASEADDR_REG
,
cfgbase
);
firbase
=
inb
(
cfgbase
+
1
)
<<
3
;
/* DMA */
outb
(
SMSCSIOFLAT_FIRDMASELECT_REG
,
cfgbase
);
dma
=
inb
(
cfgbase
+
1
)
&
SMSCSIOFLAT_FIRDMASELECT_MASK
;
/* IRQ */
outb
(
SMSCSIOFLAT_UARTIRQSELECT_REG
,
cfgbase
);
irq
=
inb
(
cfgbase
+
1
)
&
SMSCSIOFLAT_UART2IRQSELECT_MASK
;
MESSAGE
(
"%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x
\n
"
,
__FUNCTION__
,
firbase
,
sirbase
,
dma
,
irq
,
mode
);
if
(
firbase
)
{
if
(
smsc_ircc_open
(
firbase
,
sirbase
,
dma
,
irq
)
==
0
)
ret
=
0
;
}
/* Exit configuration */
outb
(
SMSCSIO_CFGEXITKEY
,
cfgbase
);
return
ret
;
}
/*
* Function smsc_superio_paged (chip, base, type)
*
* Try to get configuration of a smc SuperIO chip with paged register model
*
*/
static
int
__init
smsc_superio_paged
(
const
smsc_chip_t
*
chips
,
unsigned
short
cfg_base
,
char
*
type
)
{
unsigned
short
fir_io
,
sir_io
;
int
ret
=
-
ENODEV
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
if
(
smsc_ircc_probe
(
cfg_base
,
0x20
,
chips
,
type
)
==
NULL
)
return
ret
;
/* Select logical device (UART2) */
outb
(
0x07
,
cfg_base
);
outb
(
0x05
,
cfg_base
+
1
);
/* SIR iobase */
outb
(
0x60
,
cfg_base
);
sir_io
=
inb
(
cfg_base
+
1
)
<<
8
;
outb
(
0x61
,
cfg_base
);
sir_io
|=
inb
(
cfg_base
+
1
);
/* Read FIR base */
outb
(
0x62
,
cfg_base
);
fir_io
=
inb
(
cfg_base
+
1
)
<<
8
;
outb
(
0x63
,
cfg_base
);
fir_io
|=
inb
(
cfg_base
+
1
);
outb
(
0x2b
,
cfg_base
);
/* ??? */
if
(
fir_io
)
{
if
(
smsc_ircc_open
(
fir_io
,
sir_io
,
ircc_dma
,
ircc_irq
)
==
0
)
ret
=
0
;
}
/* Exit configuration */
outb
(
SMSCSIO_CFGEXITKEY
,
cfg_base
);
return
ret
;
}
static
int
__init
smsc_access
(
unsigned
short
cfg_base
,
unsigned
char
reg
)
{
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
outb
(
reg
,
cfg_base
);
if
(
inb
(
cfg_base
)
!=
reg
)
return
-
1
;
return
0
;
}
static
const
smsc_chip_t
*
__init
smsc_ircc_probe
(
unsigned
short
cfg_base
,
u8
reg
,
const
smsc_chip_t
*
chip
,
char
*
type
)
{
u8
devid
,
xdevid
,
rev
;
IRDA_DEBUG
(
1
,
"%s
\n
"
,
__FUNCTION__
);
/* Leave configuration */
outb
(
SMSCSIO_CFGEXITKEY
,
cfg_base
);
if
(
inb
(
cfg_base
)
==
SMSCSIO_CFGEXITKEY
)
/* not a smc superio chip */
return
NULL
;
outb
(
reg
,
cfg_base
);
xdevid
=
inb
(
cfg_base
+
1
);
/* Enter configuration */
outb
(
SMSCSIO_CFGACCESSKEY
,
cfg_base
);
#if 0
if (smsc_access(cfg_base,0x55)) /* send second key and check */
return NULL;
#endif
/* probe device ID */
if
(
smsc_access
(
cfg_base
,
reg
))
return
NULL
;
devid
=
inb
(
cfg_base
+
1
);
if
(
devid
==
0
)
/* typical value for unused port */
return
NULL
;
if
(
devid
==
0xff
)
/* typical value for unused port */
return
NULL
;
/* probe revision ID */
if
(
smsc_access
(
cfg_base
,
reg
+
1
))
return
NULL
;
rev
=
inb
(
cfg_base
+
1
);
if
(
rev
>=
128
)
/* i think this will make no sense */
return
NULL
;
if
(
devid
==
xdevid
)
/* protection against false positives */
return
NULL
;
/* Check for expected device ID; are there others? */
while
(
chip
->
devid
!=
devid
)
{
chip
++
;
if
(
chip
->
name
==
NULL
)
return
NULL
;
}
MESSAGE
(
"found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s
\n
"
,
devid
,
rev
,
cfg_base
,
type
,
chip
->
name
);
if
(
chip
->
rev
>
rev
){
MESSAGE
(
"Revision higher than expected
\n
"
);
return
NULL
;
}
if
(
chip
->
flags
&
NoIRDA
)
MESSAGE
(
"chipset does not support IRDA
\n
"
);
return
chip
;
}
static
int
__init
smsc_superio_fdc
(
unsigned
short
cfg_base
)
{
if
(
check_region
(
cfg_base
,
2
)
<
0
)
{
WARNING
(
"%s: can't get cfg_base of 0x%03x
\n
"
,
__FUNCTION__
,
cfg_base
);
return
-
1
;
}
if
(
!
smsc_superio_flat
(
fdc_chips_flat
,
cfg_base
,
"FDC"
)
||!
smsc_superio_paged
(
fdc_chips_paged
,
cfg_base
,
"FDC"
))
return
0
;
return
-
1
;
}
static
int
__init
smsc_superio_lpc
(
unsigned
short
cfg_base
)
{
#if 0
if (check_region(cfg_base, 2) < 0) {
IRDA_DEBUG(0, __FUNCTION__ ": can't get cfg_base of 0x%03x\n",
cfg_base);
return -1;
}
#endif
if
(
!
smsc_superio_flat
(
lpc_chips_flat
,
cfg_base
,
"LPC"
)
||!
smsc_superio_paged
(
lpc_chips_paged
,
cfg_base
,
"LPC"
))
return
0
;
return
-
1
;
}
/************************************************
*
* Transceivers specific functions
*
************************************************/
/*
* Function smsc_ircc_set_transceiver_smsc_ircc_atc(fir_base, speed)
*
* Program transceiver through smsc-ircc ATC circuitry
*
*/
static
void
smsc_ircc_set_transceiver_smsc_ircc_atc
(
int
fir_base
,
u32
speed
)
{
unsigned
long
jiffies_now
,
jiffies_timeout
;
u8
val
;
jiffies_now
=
jiffies
;
jiffies_timeout
=
jiffies
+
SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES
;
/* ATC */
register_bank
(
fir_base
,
4
);
outb
((
inb
(
fir_base
+
IRCC_ATC
)
&
IRCC_ATC_MASK
)
|
IRCC_ATC_nPROGREADY
|
IRCC_ATC_ENABLE
,
fir_base
+
IRCC_ATC
);
while
((
val
=
(
inb
(
fir_base
+
IRCC_ATC
)
&
IRCC_ATC_nPROGREADY
))
&&
!
time_after
(
jiffies
,
jiffies_timeout
));
if
(
val
)
WARNING
(
"%s(): ATC: 0x%02x
\n
"
,
__FUNCTION__
,
inb
(
fir_base
+
IRCC_ATC
));
}
/*
* Function smsc_ircc_probe_transceiver_smsc_ircc_atc(fir_base)
*
* Probe transceiver smsc-ircc ATC circuitry
*
*/
static
int
smsc_ircc_probe_transceiver_smsc_ircc_atc
(
int
fir_base
)
{
return
0
;
}
/*
* Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed)
*
* Set transceiver
*
*/
static
void
smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select
(
int
fir_base
,
u32
speed
)
{
u8
fast_mode
;
switch
(
speed
)
{
default:
case
576000
:
fast_mode
=
0
;
break
;
case
1152000
:
case
4000000
:
fast_mode
=
IRCC_LCR_A_FAST
;
break
;
}
register_bank
(
fir_base
,
0
);
outb
((
inb
(
fir_base
+
IRCC_LCR_A
)
&
0xbf
)
|
fast_mode
,
fir_base
+
IRCC_LCR_A
);
}
/*
* Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base)
*
* Probe transceiver
*
*/
static
int
smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select
(
int
fir_base
)
{
return
0
;
}
/*
* Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed)
*
* Set transceiver
*
*/
static
void
smsc_ircc_set_transceiver_toshiba_sat1800
(
int
fir_base
,
u32
speed
)
{
u8
fast_mode
;
switch
(
speed
)
{
default:
case
576000
:
fast_mode
=
0
;
break
;
case
1152000
:
case
4000000
:
fast_mode
=
/*IRCC_LCR_A_FAST |*/
IRCC_LCR_A_GP_DATA
;
break
;
}
/* This causes an interrupt */
register_bank
(
fir_base
,
0
);
outb
((
inb
(
fir_base
+
IRCC_LCR_A
)
&
0xbf
)
|
fast_mode
,
fir_base
+
IRCC_LCR_A
);
}
/*
* Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base)
*
* Probe transceiver
*
*/
static
int
smsc_ircc_probe_transceiver_toshiba_sat1800
(
int
fir_base
)
{
return
0
;
}
module_init
(
smsc_ircc_init
);
module_exit
(
smsc_ircc_cleanup
);
MODULE_AUTHOR
(
"Daniele Peri <peri@csai.unipa.it>"
);
MODULE_DESCRIPTION
(
"SMC IrCC SIR/FIR controller driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
ircc_dma
,
"1i"
);
MODULE_PARM_DESC
(
ircc_dma
,
"DMA channel"
);
MODULE_PARM
(
ircc_irq
,
"1i"
);
MODULE_PARM_DESC
(
ircc_irq
,
"IRQ line"
);
MODULE_PARM
(
ircc_fir
,
"1-4i"
);
MODULE_PARM_DESC
(
ircc_fir
,
"FIR Base Address"
);
MODULE_PARM
(
ircc_sir
,
"1-4i"
);
MODULE_PARM_DESC
(
ircc_sir
,
"SIR Base Address"
);
MODULE_PARM
(
ircc_cfg
,
"1-4i"
);
MODULE_PARM_DESC
(
ircc_cfg
,
"Configuration register base address"
);
MODULE_PARM
(
ircc_transceiver
,
"1i"
);
MODULE_PARM_DESC
(
ircc_transceiver
,
"Transceiver type"
);
drivers/net/irda/smsc-ircc2.h
0 → 100644
View file @
4bcb7d97
/*********************************************************************
* $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
*
* Description: Definitions for the SMC IrCC chipset
* Status: Experimental.
* Author: Daniele Peri (peri@csai.unipa.it)
*
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
*
* Based on smc-ircc.h:
*
* Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
* All Rights Reserved
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#ifndef SMSC_IRCC2_H
#define SMSC_IRCC2_H
/* DMA modes needed */
#define DMA_TX_MODE 0x08
/* Mem to I/O, ++, demand. */
#define DMA_RX_MODE 0x04
/* I/O to mem, ++, demand. */
/* Master Control Register */
#define IRCC_MASTER 0x07
#define IRCC_MASTER_POWERDOWN 0x80
#define IRCC_MASTER_RESET 0x40
#define IRCC_MASTER_INT_EN 0x20
#define IRCC_MASTER_ERROR_RESET 0x10
/* Register block 0 */
/* Interrupt Identification */
#define IRCC_IIR 0x01
#define IRCC_IIR_ACTIVE_FRAME 0x80
#define IRCC_IIR_EOM 0x40
#define IRCC_IIR_RAW_MODE 0x20
#define IRCC_IIR_FIFO 0x10
/* Interrupt Enable */
#define IRCC_IER 0x02
#define IRCC_IER_ACTIVE_FRAME 0x80
#define IRCC_IER_EOM 0x40
#define IRCC_IER_RAW_MODE 0x20
#define IRCC_IER_FIFO 0x10
/* Line Status Register */
#define IRCC_LSR 0x03
#define IRCC_LSR_UNDERRUN 0x80
#define IRCC_LSR_OVERRUN 0x40
#define IRCC_LSR_FRAME_ERROR 0x20
#define IRCC_LSR_SIZE_ERROR 0x10
#define IRCC_LSR_CRC_ERROR 0x80
#define IRCC_LSR_FRAME_ABORT 0x40
/* Line Status Address Register */
#define IRCC_LSAR 0x03
#define IRCC_LSAR_ADDRESS_MASK 0x07
/* Line Control Register A */
#define IRCC_LCR_A 0x04
#define IRCC_LCR_A_FIFO_RESET 0x80
#define IRCC_LCR_A_FAST 0x40
#define IRCC_LCR_A_GP_DATA 0x20
#define IRCC_LCR_A_RAW_TX 0x10
#define IRCC_LCR_A_RAW_RX 0x08
#define IRCC_LCR_A_ABORT 0x04
#define IRCC_LCR_A_DATA_DONE 0x02
/* Line Control Register B */
#define IRCC_LCR_B 0x05
#define IRCC_LCR_B_SCE_DISABLED 0x00
#define IRCC_LCR_B_SCE_TRANSMIT 0x40
#define IRCC_LCR_B_SCE_RECEIVE 0x80
#define IRCC_LCR_B_SCE_UNDEFINED 0xc0
#define IRCC_LCR_B_SIP_ENABLE 0x20
#define IRCC_LCR_B_BRICK_WALL 0x10
/* Bus Status Register */
#define IRCC_BSR 0x06
#define IRCC_BSR_NOT_EMPTY 0x80
#define IRCC_BSR_FIFO_FULL 0x40
#define IRCC_BSR_TIMEOUT 0x20
/* Register block 1 */
#define IRCC_FIFO_THRESHOLD 0x02
#define IRCC_SCE_CFGA 0x00
#define IRCC_CFGA_AUX_IR 0x80
#define IRCC_CFGA_HALF_DUPLEX 0x04
#define IRCC_CFGA_TX_POLARITY 0x02
#define IRCC_CFGA_RX_POLARITY 0x01
#define IRCC_CFGA_COM 0x00
#define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87
#define IRCC_CFGA_IRDA_SIR_A 0x08
#define IRCC_CFGA_ASK_SIR 0x10
#define IRCC_CFGA_IRDA_SIR_B 0x18
#define IRCC_CFGA_IRDA_HDLC 0x20
#define IRCC_CFGA_IRDA_4PPM 0x28
#define IRCC_CFGA_CONSUMER 0x30
#define IRCC_CFGA_RAW_IR 0x38
#define IRCC_CFGA_OTHER 0x40
#define IRCC_IR_HDLC 0x04
#define IRCC_IR_4PPM 0x01
#define IRCC_IR_CONSUMER 0x02
#define IRCC_SCE_CFGB 0x01
#define IRCC_CFGB_LOOPBACK 0x20
#define IRCC_CFGB_LPBCK_TX_CRC 0x10
#define IRCC_CFGB_NOWAIT 0x08
#define IRCC_CFGB_STRING_MOVE 0x04
#define IRCC_CFGB_DMA_BURST 0x02
#define IRCC_CFGB_DMA_ENABLE 0x01
#define IRCC_CFGB_MUX_COM 0x00
#define IRCC_CFGB_MUX_IR 0x40
#define IRCC_CFGB_MUX_AUX 0x80
#define IRCC_CFGB_MUX_INACTIVE 0xc0
/* Register block 3 - Identification Registers! */
#define IRCC_ID_HIGH 0x00
/* 0x10 */
#define IRCC_ID_LOW 0x01
/* 0xB8 */
#define IRCC_CHIP_ID 0x02
/* 0xF1 */
#define IRCC_VERSION 0x03
/* 0x01 */
#define IRCC_INTERFACE 0x04
/* low 4 = DMA, high 4 = IRQ */
#define IRCC_INTERFACE_DMA_MASK 0x0F
/* low 4 = DMA, high 4 = IRQ */
#define IRCC_INTERFACE_IRQ_MASK 0xF0
/* low 4 = DMA, high 4 = IRQ */
/* Register block 4 - IrDA */
#define IRCC_CONTROL 0x00
#define IRCC_BOF_COUNT_LO 0x01
/* Low byte */
#define IRCC_BOF_COUNT_HI 0x00
/* High nibble (bit 0-3) */
#define IRCC_BRICKWALL_CNT_LO 0x02
/* Low byte */
#define IRCC_BRICKWALL_CNT_HI 0x03
/* High nibble (bit 4-7) */
#define IRCC_TX_SIZE_LO 0x04
/* Low byte */
#define IRCC_TX_SIZE_HI 0x03
/* High nibble (bit 0-3) */
#define IRCC_RX_SIZE_HI 0x05
/* High nibble (bit 0-3) */
#define IRCC_RX_SIZE_LO 0x06
/* Low byte */
#define IRCC_1152 0x80
#define IRCC_CRC 0x40
/* Register block 5 - IrDA */
#define IRCC_ATC 0x00
#define IRCC_ATC_nPROGREADY 0x80
#define IRCC_ATC_SPEED 0x40
#define IRCC_ATC_ENABLE 0x20
#define IRCC_ATC_MASK 0xE0
#define IRCC_IRHALFDUPLEX_TIMEOUT 0x01
#define IRCC_SCE_TX_DELAY_TIMER 0x02
/*
* Other definitions
*/
#define SMSC_IRCC2_MAX_SIR_SPEED 115200
#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_FIFO_SIZE 16
#define SMSC_IRCC2_FIFO_THRESHOLD 64
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
#define SMSC_IRCC2_RX_BUFF_TRUESIZE 14384
#define SMSC_IRCC2_TX_BUFF_TRUESIZE 14384
#define SMSC_IRCC2_MIN_TURN_TIME 0x07
#define SMSC_IRCC2_WINDOW_SIZE 0x07
/* Maximum wait for hw transmitter to finish */
#define SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US 1000
/* 1 ms */
/* Maximum wait for ATC transceiver programming to finish */
#define SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES 1
#endif
/* SMSC_IRCC2_H */
drivers/net/irda/smsc-sio.h
0 → 100644
View file @
4bcb7d97
#ifndef SMSC_SIO_H
#define SMSC_SIO_H
/******************************************
Keys. They should work with every SMsC SIO
******************************************/
#define SMSCSIO_CFGACCESSKEY 0x55
#define SMSCSIO_CFGEXITKEY 0xaa
/*****************************
* Generic SIO Flat (!?) *
*****************************/
/* Register 0x0d */
#define SMSCSIOFLAT_DEVICEID_REG 0x0d
/* Register 0x0c */
#define SMSCSIOFLAT_UARTMODE0C_REG 0x0c
#define SMSCSIOFLAT_UART2MODE_MASK 0x38
#define SMSCSIOFLAT_UART2MODE_VAL_COM 0x00
#define SMSCSIOFLAT_UART2MODE_VAL_IRDA 0x08
#define SMSCSIOFLAT_UART2MODE_VAL_ASKIR 0x10
/* Register 0x25 */
#define SMSCSIOFLAT_UART2BASEADDR_REG 0x25
/* Register 0x2b */
#define SMSCSIOFLAT_FIRBASEADDR_REG 0x2b
/* Register 0x2c */
#define SMSCSIOFLAT_FIRDMASELECT_REG 0x2c
#define SMSCSIOFLAT_FIRDMASELECT_MASK 0x0f
/* Register 0x28 */
#define SMSCSIOFLAT_UARTIRQSELECT_REG 0x28
#define SMSCSIOFLAT_UART2IRQSELECT_MASK 0x0f
#define SMSCSIOFLAT_UART1IRQSELECT_MASK 0xf0
#define SMSCSIOFLAT_UARTIRQSELECT_VAL_NONE 0x00
/*********************
* LPC47N227 *
*********************/
#define LPC47N227_CFGACCESSKEY 0x55
#define LPC47N227_CFGEXITKEY 0xaa
/* Register 0x00 */
#define LPC47N227_FDCPOWERVALIDCONF_REG 0x00
#define LPC47N227_FDCPOWER_MASK 0x08
#define LPC47N227_VALID_MASK 0x80
/* Register 0x02 */
#define LPC47N227_UART12POWER_REG 0x02
#define LPC47N227_UART1POWERDOWN_MASK 0x08
#define LPC47N227_UART2POWERDOWN_MASK 0x80
/* Register 0x07 */
#define LPC47N227_APMBOOTDRIVE_REG 0x07
#define LPC47N227_PARPORT2AUTOPWRDOWN_MASK 0x10
/* auto power down on if set */
#define LPC47N227_UART2AUTOPWRDOWN_MASK 0x20
/* auto power down on if set */
#define LPC47N227_UART1AUTOPWRDOWN_MASK 0x40
/* auto power down on if set */
/* Register 0x0c */
#define LPC47N227_UARTMODE0C_REG 0x0c
#define LPC47N227_UART2MODE_MASK 0x38
#define LPC47N227_UART2MODE_VAL_COM 0x00
#define LPC47N227_UART2MODE_VAL_IRDA 0x08
#define LPC47N227_UART2MODE_VAL_ASKIR 0x10
/* Register 0x0d */
#define LPC47N227_DEVICEID_REG 0x0d
#define LPC47N227_DEVICEID_DEFVAL 0x5a
/* Register 0x0e */
#define LPC47N227_REVISIONID_REG 0x0e
/* Register 0x25 */
#define LPC47N227_UART2BASEADDR_REG 0x25
/* Register 0x28 */
#define LPC47N227_UARTIRQSELECT_REG 0x28
#define LPC47N227_UART2IRQSELECT_MASK 0x0f
#define LPC47N227_UART1IRQSELECT_MASK 0xf0
#define LPC47N227_UARTIRQSELECT_VAL_NONE 0x00
/* Register 0x2b */
#define LPC47N227_FIRBASEADDR_REG 0x2b
/* Register 0x2c */
#define LPC47N227_FIRDMASELECT_REG 0x2c
#define LPC47N227_FIRDMASELECT_MASK 0x0f
#define LPC47N227_FIRDMASELECT_VAL_DMA1 0x01
/* 47n227 has three dma channels */
#define LPC47N227_FIRDMASELECT_VAL_DMA2 0x02
#define LPC47N227_FIRDMASELECT_VAL_DMA3 0x03
#define LPC47N227_FIRDMASELECT_VAL_NONE 0x0f
#endif
drivers/net/irda/w83977af_ir.c
View file @
4bcb7d97
...
...
@@ -524,6 +524,7 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Check for empty frame */
if
(
!
skb
->
len
)
{
w83977af_change_speed
(
self
,
speed
);
dev
->
trans_start
=
jiffies
;
dev_kfree_skb
(
skb
);
return
0
;
}
else
...
...
@@ -579,6 +580,7 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
switch_bank
(
iobase
,
SET0
);
outb
(
ICR_ETXTHI
,
iobase
+
ICR
);
}
dev
->
trans_start
=
jiffies
;
dev_kfree_skb
(
skb
);
/* Restore set register */
...
...
include/net/irda/iriap.h
View file @
4bcb7d97
...
...
@@ -66,7 +66,7 @@ struct iriap_cb {
__u32
daddr
;
__u8
operation
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
request_
skb
;
struct
lsap_cb
*
lsap
;
__u8
slsap_sel
;
...
...
include/net/irda/irlmp_event.h
View file @
4bcb7d97
...
...
@@ -79,26 +79,6 @@ typedef enum {
LM_LAP_IDLE_TIMEOUT
,
}
IRLMP_EVENT
;
/*
* Information which is used by the current thread, when executing in the
* state machine.
*/
struct
irlmp_event
{
IRLMP_EVENT
*
event
;
struct
sk_buff
*
skb
;
__u8
hint
;
__u32
daddr
;
__u32
saddr
;
__u8
slsap
;
__u8
dlsap
;
int
reason
;
struct
discovery_t
*
discovery
;
};
extern
const
char
*
irlmp_state
[];
extern
const
char
*
irlsap_state
[];
...
...
include/net/irda/irport.h
View file @
4bcb7d97
...
...
@@ -67,6 +67,7 @@ struct irport_cb {
__u32
new_speed
;
int
mode
;
int
index
;
/* Instance index */
int
transmitting
;
/* Are we transmitting ? */
spinlock_t
lock
;
/* For serializing operations */
...
...
net/irda/af_irda.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
* Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
*
* Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1999-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 1999-200
3
Jean Tourrilhes <jt@hpl.hp.com>
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
...
...
@@ -190,6 +190,9 @@ static void irda_connect_confirm(void *instance, void *sap,
if
(
sk
==
NULL
)
return
;
dev_kfree_skb
(
skb
);
// Should be ??? skb_queue_tail(&sk->receive_queue, skb);
/* How much header space do we need to reserve */
self
->
max_header_size
=
max_header_size
;
...
...
@@ -220,8 +223,6 @@ static void irda_connect_confirm(void *instance, void *sap,
self
->
max_data_size
);
memcpy
(
&
self
->
qos_tx
,
qos
,
sizeof
(
struct
qos_info
));
dev_kfree_skb
(
skb
);
// Should be ??? skb_queue_tail(&sk->receive_queue, skb);
/* We are now connected! */
sk
->
state
=
TCP_ESTABLISHED
;
...
...
@@ -260,6 +261,7 @@ static void irda_connect_indication(void *instance, void *sap,
case
SOCK_STREAM
:
if
(
max_sdu_size
!=
0
)
{
ERROR
(
"%s: max_sdu_size must be 0
\n
"
,
__FUNCTION__
);
kfree_skb
(
skb
);
return
;
}
self
->
max_data_size
=
irttp_get_max_seg_size
(
self
->
tsap
);
...
...
@@ -267,6 +269,7 @@ static void irda_connect_indication(void *instance, void *sap,
case
SOCK_SEQPACKET
:
if
(
max_sdu_size
==
0
)
{
ERROR
(
"%s: max_sdu_size cannot be 0
\n
"
,
__FUNCTION__
);
kfree_skb
(
skb
);
return
;
}
self
->
max_data_size
=
max_sdu_size
;
...
...
@@ -359,7 +362,7 @@ static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
* doesn't touch the dtsap_sel and save the full value structure...
*/
static
void
irda_getvalue_confirm
(
int
result
,
__u16
obj_id
,
struct
ias_value
*
value
,
void
*
priv
)
struct
ias_value
*
value
,
void
*
priv
)
{
struct
irda_sock
*
self
;
...
...
@@ -908,6 +911,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
new
->
tsap
=
irttp_dup
(
self
->
tsap
,
new
);
if
(
!
new
->
tsap
)
{
IRDA_DEBUG
(
0
,
"%s(), dup failed!
\n
"
,
__FUNCTION__
);
kfree_skb
(
skb
);
return
-
1
;
}
...
...
@@ -926,6 +930,7 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
/* Clean up the original one to keep it in listen state */
irttp_listen
(
self
->
tsap
);
/* Wow ! What is that ? Jean II */
skb
->
sk
=
NULL
;
skb
->
destructor
=
NULL
;
kfree_skb
(
skb
);
...
...
net/irda/ircomm/ircomm_core.c
View file @
4bcb7d97
...
...
@@ -10,6 +10,7 @@
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -251,7 +252,6 @@ void ircomm_connect_indication(struct ircomm_cb *self, struct sk_buff *skb,
info
->
max_header_size
,
skb
);
else
{
IRDA_DEBUG
(
0
,
"%s(), missing handler
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
...
...
@@ -295,7 +295,6 @@ void ircomm_connect_confirm(struct ircomm_cb *self, struct sk_buff *skb,
info
->
max_header_size
,
skb
);
else
{
IRDA_DEBUG
(
0
,
"%s(), missing handler
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
...
...
@@ -338,7 +337,6 @@ void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
self
->
notify
.
data_indication
(
self
->
notify
.
instance
,
self
,
skb
);
else
{
IRDA_DEBUG
(
0
,
"%s(), missing handler
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
...
...
@@ -370,9 +368,8 @@ void ircomm_process_data(struct ircomm_cb *self, struct sk_buff *skb)
if
(
skb
->
len
)
ircomm_data_indication
(
self
,
skb
);
else
{
IRDA_DEBUG
(
4
,
"%s(), data was control info only!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
IRDA_DEBUG
(
4
,
"%s(), data was control info only!
\n
"
,
__FUNCTION__
);
}
}
...
...
@@ -408,24 +405,28 @@ EXPORT_SYMBOL(ircomm_control_request);
static
void
ircomm_control_indication
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
skb
,
int
clen
)
{
struct
sk_buff
*
ctrl_skb
;
IRDA_DEBUG
(
2
,
"%s()
\n
"
,
__FUNCTION__
);
ctrl_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
!
ctrl_skb
)
return
;
/* Use udata for delivering data on the control channel */
if
(
self
->
notify
.
udata_indication
)
{
struct
sk_buff
*
ctrl_skb
;
/* We don't own the skb, so clone it */
ctrl_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
!
ctrl_skb
)
return
;
/* Remove data channel from control channel */
skb_trim
(
ctrl_skb
,
clen
+
1
);
/* Remove data channel from control channel */
skb_trim
(
ctrl_skb
,
clen
+
1
);
/* Use udata for delivering data on the control channel */
if
(
self
->
notify
.
udata_indication
)
self
->
notify
.
udata_indication
(
self
->
notify
.
instance
,
self
,
ctrl_skb
);
else
{
/* Drop reference count -
* see ircomm_tty_control_indication(). */
dev_kfree_skb
(
ctrl_skb
);
}
else
{
IRDA_DEBUG
(
0
,
"%s(), missing handler
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
...
...
@@ -470,7 +471,6 @@ void ircomm_disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb,
info
->
reason
,
skb
);
}
else
{
IRDA_DEBUG
(
0
,
"%s(), missing handler
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
...
...
net/irda/ircomm/ircomm_event.c
View file @
4bcb7d97
...
...
@@ -109,9 +109,7 @@ static int ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event,
default:
IRDA_DEBUG
(
4
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
return
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -141,8 +139,6 @@ static int ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
ret
=
-
EINVAL
;
}
return
ret
;
...
...
@@ -176,8 +172,6 @@ static int ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), unknown event = %s
\n
"
,
__FUNCTION__
,
ircomm_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
ret
=
-
EINVAL
;
}
return
ret
;
...
...
@@ -220,8 +214,6 @@ static int ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), unknown event = %s
\n
"
,
__FUNCTION__
,
ircomm_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
ret
=
-
EINVAL
;
}
return
ret
;
...
...
net/irda/ircomm/ircomm_lmp.c
View file @
4bcb7d97
...
...
@@ -11,6 +11,7 @@
* Sources: Previous IrLPT work by Thomas Davis
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -93,6 +94,10 @@ int ircomm_lmp_connect_request(struct ircomm_cb *self,
IRDA_DEBUG
(
0
,
"%s()
\n
"
,
__FUNCTION__
);
/* Don't forget to refcount it - should be NULL anyway */
if
(
userdata
)
skb_get
(
userdata
);
ret
=
irlmp_connect_request
(
self
->
lsap
,
info
->
dlsap_sel
,
info
->
saddr
,
info
->
daddr
,
NULL
,
userdata
);
return
ret
;
...
...
@@ -106,29 +111,32 @@ int ircomm_lmp_connect_request(struct ircomm_cb *self,
*/
int
ircomm_lmp_connect_response
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
userdata
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
int
ret
;
IRDA_DEBUG
(
0
,
"%s()
\n
"
,
__FUNCTION__
);
/* Any userdata supplied? */
if
(
userdata
==
NULL
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
/* Reserve space for MUX and LAP header */
skb_reserve
(
skb
,
LMP_MAX_HEADER
);
skb_reserve
(
tx_
skb
,
LMP_MAX_HEADER
);
}
else
{
skb
=
userdata
;
/*
* Check that the client has reserved enough space for
* headers
*/
ASSERT
(
skb_headroom
(
skb
)
>=
LMP_MAX_HEADER
,
return
-
1
;);
ASSERT
(
skb_headroom
(
userdata
)
>=
LMP_MAX_HEADER
,
return
-
1
;);
/* Don't forget to refcount it - should be NULL anyway */
skb_get
(
userdata
);
tx_skb
=
userdata
;
}
ret
=
irlmp_connect_response
(
self
->
lsap
,
skb
);
ret
=
irlmp_connect_response
(
self
->
lsap
,
tx_
skb
);
return
0
;
}
...
...
@@ -137,20 +145,24 @@ int ircomm_lmp_disconnect_request(struct ircomm_cb *self,
struct
sk_buff
*
userdata
,
struct
ircomm_info
*
info
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
int
ret
;
IRDA_DEBUG
(
0
,
"%s()
\n
"
,
__FUNCTION__
);
if
(
!
userdata
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
/* Reserve space for MUX and LAP header */
skb_reserve
(
skb
,
LMP_MAX_HEADER
);
userdata
=
skb
;
skb_reserve
(
tx_skb
,
LMP_MAX_HEADER
);
userdata
=
tx_skb
;
}
else
{
/* Don't forget to refcount it - should be NULL anyway */
skb_get
(
userdata
);
}
ret
=
irlmp_disconnect_request
(
self
->
lsap
,
userdata
);
return
ret
;
...
...
@@ -217,8 +229,11 @@ int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
IRDA_DEBUG
(
4
,
"%s(), sending frame
\n
"
,
__FUNCTION__
);
/* Don't forget to refcount it - see ircomm_tty_do_softint() */
skb_get
(
skb
);
skb
->
destructor
=
ircomm_lmp_flow_control
;
if
((
self
->
pkt_count
++
>
7
)
&&
(
self
->
flow_status
==
FLOW_START
))
{
IRDA_DEBUG
(
2
,
"%s(), asking TTY to slow down!
\n
"
,
__FUNCTION__
);
self
->
flow_status
=
FLOW_STOP
;
...
...
@@ -229,7 +244,7 @@ int ircomm_lmp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
ret
=
irlmp_data_request
(
self
->
lsap
,
skb
);
if
(
ret
)
{
ERROR
(
"%s(), failed
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
/* irlmp_data_request already free the packet */
}
return
ret
;
...
...
@@ -254,6 +269,9 @@ int ircomm_lmp_data_indication(void *instance, void *sap,
ircomm_do_event
(
self
,
IRCOMM_LMP_DATA_INDICATION
,
skb
,
NULL
);
/* Drop reference count - see ircomm_tty_data_indication(). */
dev_kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -285,6 +303,9 @@ void ircomm_lmp_connect_confirm(void *instance, void *sap,
info
.
qos
=
qos
;
ircomm_do_event
(
self
,
IRCOMM_LMP_CONNECT_CONFIRM
,
skb
,
&
info
);
/* Drop reference count - see ircomm_tty_connect_confirm(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -315,6 +336,9 @@ void ircomm_lmp_connect_indication(void *instance, void *sap,
info
.
qos
=
qos
;
ircomm_do_event
(
self
,
IRCOMM_LMP_CONNECT_INDICATION
,
skb
,
&
info
);
/* Drop reference count - see ircomm_tty_connect_indication(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -338,4 +362,8 @@ void ircomm_lmp_disconnect_indication(void *instance, void *sap,
info
.
reason
=
reason
;
ircomm_do_event
(
self
,
IRCOMM_LMP_DISCONNECT_INDICATION
,
skb
,
&
info
);
/* Drop reference count - see ircomm_tty_disconnect_indication(). */
if
(
skb
)
dev_kfree_skb
(
skb
);
}
net/irda/ircomm/ircomm_ttp.c
View file @
4bcb7d97
...
...
@@ -10,6 +10,7 @@
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -94,9 +95,14 @@ int ircomm_ttp_connect_request(struct ircomm_cb *self,
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
/* Don't forget to refcount it - should be NULL anyway */
if
(
userdata
)
skb_get
(
userdata
);
ret
=
irttp_connect_request
(
self
->
tsap
,
info
->
dlsap_sel
,
info
->
saddr
,
info
->
daddr
,
NULL
,
TTP_SAR_DISABLE
,
userdata
);
return
ret
;
}
...
...
@@ -106,13 +112,18 @@ int ircomm_ttp_connect_request(struct ircomm_cb *self,
*
*
*/
int
ircomm_ttp_connect_response
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
skb
)
int
ircomm_ttp_connect_response
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
userdata
)
{
int
ret
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
ret
=
irttp_connect_response
(
self
->
tsap
,
TTP_SAR_DISABLE
,
skb
);
/* Don't forget to refcount it - should be NULL anyway */
if
(
userdata
)
skb_get
(
userdata
);
ret
=
irttp_connect_response
(
self
->
tsap
,
TTP_SAR_DISABLE
,
userdata
);
return
ret
;
}
...
...
@@ -126,7 +137,8 @@ int ircomm_ttp_connect_response(struct ircomm_cb *self, struct sk_buff *skb)
* some of them are sent after connection establishment, so this can
* increase the latency a bit.
*/
int
ircomm_ttp_data_request
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
skb
,
int
ircomm_ttp_data_request
(
struct
ircomm_cb
*
self
,
struct
sk_buff
*
skb
,
int
clen
)
{
int
ret
;
...
...
@@ -140,6 +152,10 @@ int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
* only frames, to make things easier and avoid queueing
*/
ASSERT
(
skb_headroom
(
skb
)
>=
IRCOMM_HEADER_SIZE
,
return
-
1
;);
/* Don't forget to refcount it - see ircomm_tty_do_softint() */
skb_get
(
skb
);
skb_push
(
skb
,
IRCOMM_HEADER_SIZE
);
skb
->
data
[
0
]
=
clen
;
...
...
@@ -147,7 +163,7 @@ int ircomm_ttp_data_request(struct ircomm_cb *self, struct sk_buff *skb,
ret
=
irttp_data_request
(
self
->
tsap
,
skb
);
if
(
ret
)
{
ERROR
(
"%s(), failed
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
/* irttp_data_request already free the packet */
}
return
ret
;
...
...
@@ -172,6 +188,9 @@ int ircomm_ttp_data_indication(void *instance, void *sap,
ircomm_do_event
(
self
,
IRCOMM_TTP_DATA_INDICATION
,
skb
,
NULL
);
/* Drop reference count - see ircomm_tty_data_indication(). */
dev_kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -189,12 +208,11 @@ void ircomm_ttp_connect_confirm(void *instance, void *sap,
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IRCOMM_MAGIC
,
return
;);
ASSERT
(
skb
!=
NULL
,
return
;);
ASSERT
(
qos
!=
NULL
,
return
;);
ASSERT
(
qos
!=
NULL
,
goto
out
;);
if
(
max_sdu_size
!=
TTP_SAR_DISABLE
)
{
ERROR
(
"%s(), SAR not allowed for IrCOMM!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
;
goto
out
;
}
info
.
max_data_size
=
irttp_get_max_seg_size
(
self
->
tsap
)
...
...
@@ -203,6 +221,10 @@ void ircomm_ttp_connect_confirm(void *instance, void *sap,
info
.
qos
=
qos
;
ircomm_do_event
(
self
,
IRCOMM_TTP_CONNECT_CONFIRM
,
skb
,
&
info
);
out:
/* Drop reference count - see ircomm_tty_connect_confirm(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -226,12 +248,11 @@ void ircomm_ttp_connect_indication(void *instance, void *sap,
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IRCOMM_MAGIC
,
return
;);
ASSERT
(
skb
!=
NULL
,
return
;);
ASSERT
(
qos
!=
NULL
,
return
;);
ASSERT
(
qos
!=
NULL
,
goto
out
;);
if
(
max_sdu_size
!=
TTP_SAR_DISABLE
)
{
ERROR
(
"%s(), SAR not allowed for IrCOMM!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
;
goto
out
;
}
info
.
max_data_size
=
irttp_get_max_seg_size
(
self
->
tsap
)
...
...
@@ -240,6 +261,10 @@ void ircomm_ttp_connect_indication(void *instance, void *sap,
info
.
qos
=
qos
;
ircomm_do_event
(
self
,
IRCOMM_TTP_CONNECT_INDICATION
,
skb
,
&
info
);
out:
/* Drop reference count - see ircomm_tty_connect_indication(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -254,6 +279,10 @@ int ircomm_ttp_disconnect_request(struct ircomm_cb *self,
{
int
ret
;
/* Don't forget to refcount it - should be NULL anyway */
if
(
userdata
)
skb_get
(
userdata
);
ret
=
irttp_disconnect_request
(
self
->
tsap
,
userdata
,
P_NORMAL
);
return
ret
;
...
...
@@ -280,6 +309,10 @@ void ircomm_ttp_disconnect_indication(void *instance, void *sap,
info
.
reason
=
reason
;
ircomm_do_event
(
self
,
IRCOMM_TTP_DISCONNECT_INDICATION
,
skb
,
&
info
);
/* Drop reference count - see ircomm_tty_disconnect_indication(). */
if
(
skb
)
dev_kfree_skb
(
skb
);
}
/*
...
...
net/irda/ircomm/ircomm_tty.c
View file @
4bcb7d97
...
...
@@ -11,6 +11,7 @@
* Sources: serial.c and previous IrCOMM work by Takahide Higuchi
*
* Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -663,8 +664,12 @@ static void ircomm_tty_do_softint(void *private_)
spin_unlock_irqrestore
(
&
self
->
spinlock
,
flags
);
/* Flush control buffer if any */
if
(
ctrl_skb
&&
self
->
flow
==
FLOW_START
)
ircomm_control_request
(
self
->
ircomm
,
ctrl_skb
);
if
(
ctrl_skb
)
{
if
(
self
->
flow
==
FLOW_START
)
ircomm_control_request
(
self
->
ircomm
,
ctrl_skb
);
/* Drop reference count - see ircomm_ttp_data_request(). */
dev_kfree_skb
(
ctrl_skb
);
}
if
(
tty
->
hw_stopped
)
return
;
...
...
@@ -678,8 +683,11 @@ static void ircomm_tty_do_softint(void *private_)
spin_unlock_irqrestore
(
&
self
->
spinlock
,
flags
);
/* Flush transmit buffer if any */
if
(
skb
)
if
(
skb
)
{
ircomm_tty_do_event
(
self
,
IRCOMM_TTY_DATA_REQUEST
,
skb
,
NULL
);
/* Drop reference count - see ircomm_ttp_data_request(). */
dev_kfree_skb
(
skb
);
}
/* Check if user (still) wants to be waken up */
if
((
tty
->
flags
&
(
1
<<
TTY_DO_WRITE_WAKEUP
))
&&
...
...
@@ -1179,7 +1187,6 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
if
(
!
self
->
tty
)
{
IRDA_DEBUG
(
0
,
"%s(), no tty!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -1204,7 +1211,8 @@ static int ircomm_tty_data_indication(void *instance, void *sap,
* handler
*/
self
->
tty
->
ldisc
.
receive_buf
(
self
->
tty
,
skb
->
data
,
NULL
,
skb
->
len
);
dev_kfree_skb
(
skb
);
/* No need to kfree_skb - see ircomm_ttp_data_indication() */
return
0
;
}
...
...
@@ -1231,7 +1239,8 @@ static int ircomm_tty_control_indication(void *instance, void *sap,
irda_param_extract_all
(
self
,
skb
->
data
+
1
,
IRDA_MIN
(
skb
->
len
-
1
,
clen
),
&
ircomm_param_info
);
dev_kfree_skb
(
skb
);
/* No need to kfree_skb - see ircomm_control_indication() */
return
0
;
}
...
...
net/irda/ircomm/ircomm_tty_attach.c
View file @
4bcb7d97
...
...
@@ -10,6 +10,7 @@
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -236,8 +237,9 @@ static void ircomm_tty_ias_register(struct ircomm_tty_cb *self)
irias_insert_object
(
self
->
obj
);
}
self
->
skey
=
irlmp_register_service
(
hints
);
self
->
ckey
=
irlmp_register_client
(
hints
,
ircomm_tty_discovery_indication
,
NULL
,
(
void
*
)
self
);
self
->
ckey
=
irlmp_register_client
(
hints
,
ircomm_tty_discovery_indication
,
NULL
,
(
void
*
)
self
);
}
/*
...
...
@@ -459,7 +461,7 @@ void ircomm_tty_connect_confirm(void *instance, void *sap,
ircomm_tty_do_event
(
self
,
IRCOMM_TTY_CONNECT_CONFIRM
,
NULL
,
NULL
);
dev_kfree_skb
(
skb
);
/* No need to kfree_skb - see ircomm_ttp_connect_confirm() */
}
/*
...
...
@@ -496,7 +498,7 @@ void ircomm_tty_connect_indication(void *instance, void *sap,
ircomm_tty_do_event
(
self
,
IRCOMM_TTY_CONNECT_INDICATION
,
NULL
,
NULL
);
dev_kfree_skb
(
skb
);
/* No need to kfree_skb - see ircomm_ttp_connect_indication() */
}
/*
...
...
@@ -647,7 +649,7 @@ static int ircomm_tty_state_idle(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -718,7 +720,7 @@ static int ircomm_tty_state_search(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -774,7 +776,7 @@ static int ircomm_tty_state_query_parameters(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -822,7 +824,7 @@ static int ircomm_tty_state_query_lsap_sel(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -874,7 +876,7 @@ static int ircomm_tty_state_setup(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
@@ -917,7 +919,7 @@ static int ircomm_tty_state_ready(struct ircomm_tty_cb *self,
default:
IRDA_DEBUG
(
2
,
"%s(), unknown event: %s
\n
"
,
__FUNCTION__
,
ircomm_tty_event
[
event
]);
ret
urn
-
EINVAL
;
ret
=
-
EINVAL
;
}
return
ret
;
}
...
...
net/irda/iriap.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -210,8 +210,8 @@ static void __iriap_close(struct iriap_cb *self)
del_timer
(
&
self
->
watchdog_timer
);
if
(
self
->
skb
)
dev_kfree_skb
(
self
->
skb
);
if
(
self
->
request_
skb
)
dev_kfree_skb
(
self
->
request_
skb
);
self
->
magic
=
0
;
...
...
@@ -278,7 +278,7 @@ static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
*/
static
void
iriap_disconnect_indication
(
void
*
instance
,
void
*
sap
,
LM_REASON
reason
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
struct
iriap_cb
*
self
;
...
...
@@ -293,6 +293,10 @@ static void iriap_disconnect_indication(void *instance, void *sap,
del_timer
(
&
self
->
watchdog_timer
);
/* Not needed */
if
(
skb
)
dev_kfree_skb
(
skb
);
if
(
self
->
mode
==
IAS_CLIENT
)
{
IRDA_DEBUG
(
4
,
"%s(), disconnect as client
\n
"
,
__FUNCTION__
);
...
...
@@ -312,9 +316,6 @@ static void iriap_disconnect_indication(void *instance, void *sap,
NULL
);
iriap_close
(
self
);
}
if
(
userdata
)
dev_kfree_skb
(
userdata
);
}
/*
...
...
@@ -322,15 +323,15 @@ static void iriap_disconnect_indication(void *instance, void *sap,
*/
void
iriap_disconnect_request
(
struct
iriap_cb
*
self
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
;);
skb
=
dev_alloc_skb
(
64
);
if
(
skb
==
NULL
)
{
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
tx_
skb
==
NULL
)
{
IRDA_DEBUG
(
0
,
"%s(), Could not allocate an sk_buff of length %d
\n
"
,
__FUNCTION__
,
64
);
return
;
...
...
@@ -339,9 +340,9 @@ void iriap_disconnect_request(struct iriap_cb *self)
/*
* Reserve space for MUX control and LAP header
*/
skb_reserve
(
skb
,
LMP_MAX_HEADER
);
skb_reserve
(
tx_
skb
,
LMP_MAX_HEADER
);
irlmp_disconnect_request
(
self
->
lsap
,
skb
);
irlmp_disconnect_request
(
self
->
lsap
,
tx_
skb
);
}
void
iriap_getinfobasedetails_request
(
void
)
...
...
@@ -379,7 +380,7 @@ int iriap_getvaluebyclass_request(struct iriap_cb *self,
__u32
saddr
,
__u32
daddr
,
char
*
name
,
char
*
attr
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
int
name_len
,
attr_len
,
skb_len
;
__u8
*
frame
;
...
...
@@ -405,14 +406,14 @@ int iriap_getvaluebyclass_request(struct iriap_cb *self,
attr_len
=
strlen
(
attr
);
/* Up to IAS_MAX_ATTRIBNAME = 60 */
skb_len
=
self
->
max_header_size
+
2
+
name_len
+
1
+
attr_len
+
4
;
skb
=
dev_alloc_skb
(
skb_len
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
skb_len
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
/* Reserve space for MUX and LAP header */
skb_reserve
(
skb
,
self
->
max_header_size
);
skb_put
(
skb
,
3
+
name_len
+
attr_len
);
frame
=
skb
->
data
;
skb_reserve
(
tx_
skb
,
self
->
max_header_size
);
skb_put
(
tx_
skb
,
3
+
name_len
+
attr_len
);
frame
=
tx_
skb
->
data
;
/* Build frame */
frame
[
0
]
=
IAP_LST
|
GET_VALUE_BY_CLASS
;
...
...
@@ -421,7 +422,10 @@ int iriap_getvaluebyclass_request(struct iriap_cb *self,
frame
[
2
+
name_len
]
=
attr_len
;
/* Insert length of attr */
memcpy
(
frame
+
3
+
name_len
,
attr
,
attr_len
);
/* Insert attr */
iriap_do_client_event
(
self
,
IAP_CALL_REQUEST_GVBC
,
skb
);
iriap_do_client_event
(
self
,
IAP_CALL_REQUEST_GVBC
,
tx_skb
);
/* Drop reference count - see state_s_disconnect(). */
dev_kfree_skb
(
tx_skb
);
return
0
;
}
...
...
@@ -495,7 +499,6 @@ void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
/* Aborting, close connection! */
iriap_disconnect_request
(
self
);
dev_kfree_skb
(
skb
);
return
;
/* break; */
}
...
...
@@ -533,7 +536,6 @@ void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
IRDA_DEBUG
(
0
,
"%s(), missing handler!
\n
"
,
__FUNCTION__
);
irias_delete_value
(
value
);
}
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -545,7 +547,7 @@ void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
void
iriap_getvaluebyclass_response
(
struct
iriap_cb
*
self
,
__u16
obj_id
,
__u8
ret_code
,
struct
ias_value
*
value
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
int
n
;
__u32
tmp_be32
,
tmp_be16
;
__u8
*
fp
;
...
...
@@ -565,15 +567,15 @@ void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
* value. We add 32 bytes because of the 6 bytes for the frame and
* max 5 bytes for the value coding.
*/
skb
=
dev_alloc_skb
(
value
->
len
+
self
->
max_header_size
+
32
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
value
->
len
+
self
->
max_header_size
+
32
);
if
(
!
tx_
skb
)
return
;
/* Reserve space for MUX and LAP header */
skb_reserve
(
skb
,
self
->
max_header_size
);
skb_put
(
skb
,
6
);
skb_reserve
(
tx_
skb
,
self
->
max_header_size
);
skb_put
(
tx_
skb
,
6
);
fp
=
skb
->
data
;
fp
=
tx_
skb
->
data
;
/* Build frame */
fp
[
n
++
]
=
GET_VALUE_BY_CLASS
|
IAP_LST
;
...
...
@@ -589,21 +591,21 @@ void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
switch
(
value
->
type
)
{
case
IAS_STRING
:
skb_put
(
skb
,
3
+
value
->
len
);
skb_put
(
tx_
skb
,
3
+
value
->
len
);
fp
[
n
++
]
=
value
->
type
;
fp
[
n
++
]
=
0
;
/* ASCII */
fp
[
n
++
]
=
(
__u8
)
value
->
len
;
memcpy
(
fp
+
n
,
value
->
t
.
string
,
value
->
len
);
n
+=
value
->
len
;
break
;
case
IAS_INTEGER
:
skb_put
(
skb
,
5
);
skb_put
(
tx_
skb
,
5
);
fp
[
n
++
]
=
value
->
type
;
tmp_be32
=
cpu_to_be32
(
value
->
t
.
integer
);
memcpy
(
fp
+
n
,
&
tmp_be32
,
4
);
n
+=
4
;
break
;
case
IAS_OCT_SEQ
:
skb_put
(
skb
,
3
+
value
->
len
);
skb_put
(
tx_
skb
,
3
+
value
->
len
);
fp
[
n
++
]
=
value
->
type
;
tmp_be16
=
cpu_to_be16
(
value
->
len
);
...
...
@@ -612,14 +614,17 @@ void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
break
;
case
IAS_MISSING
:
IRDA_DEBUG
(
3
,
"%s: sending IAS_MISSING
\n
"
,
__FUNCTION__
);
skb_put
(
skb
,
1
);
skb_put
(
tx_
skb
,
1
);
fp
[
n
++
]
=
value
->
type
;
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), type not implemented!
\n
"
,
__FUNCTION__
);
break
;
}
iriap_do_r_connect_event
(
self
,
IAP_CALL_RESPONSE
,
skb
);
iriap_do_r_connect_event
(
self
,
IAP_CALL_RESPONSE
,
tx_skb
);
/* Drop reference count - see state_r_execute(). */
dev_kfree_skb
(
tx_skb
);
}
/*
...
...
@@ -657,9 +662,6 @@ void iriap_getvaluebyclass_indication(struct iriap_cb *self,
memcpy
(
attr
,
fp
+
n
,
attr_len
);
n
+=
attr_len
;
attr
[
attr_len
]
=
'\0'
;
/* We do not need the buffer anymore */
dev_kfree_skb
(
skb
);
IRDA_DEBUG
(
4
,
"LM-IAS: Looking up %s: %s
\n
"
,
name
,
attr
);
obj
=
irias_find_object
(
name
);
...
...
@@ -694,7 +696,7 @@ void iriap_getvaluebyclass_indication(struct iriap_cb *self,
*/
void
iriap_send_ack
(
struct
iriap_cb
*
self
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
__u8
*
frame
;
IRDA_DEBUG
(
2
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -702,19 +704,19 @@ void iriap_send_ack(struct iriap_cb *self)
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
;);
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
;
/* Reserve space for MUX and LAP header */
skb_reserve
(
skb
,
self
->
max_header_size
);
skb_put
(
skb
,
1
);
frame
=
skb
->
data
;
skb_reserve
(
tx_
skb
,
self
->
max_header_size
);
skb_put
(
tx_
skb
,
1
);
frame
=
tx_
skb
->
data
;
/* Build frame */
frame
[
0
]
=
IAP_LST
|
IAP_ACK
|
self
->
operation
;
irlmp_data_request
(
self
->
lsap
,
skb
);
irlmp_data_request
(
self
->
lsap
,
tx_
skb
);
}
void
iriap_connect_request
(
struct
iriap_cb
*
self
)
...
...
@@ -742,7 +744,7 @@ void iriap_connect_request(struct iriap_cb *self)
static
void
iriap_connect_confirm
(
void
*
instance
,
void
*
sap
,
struct
qos_info
*
qos
,
__u32
max_seg_size
,
__u8
max_header_size
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
struct
iriap_cb
*
self
;
...
...
@@ -750,14 +752,17 @@ static void iriap_connect_confirm(void *instance, void *sap,
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
;);
ASSERT
(
userdata
!=
NULL
,
return
;);
ASSERT
(
skb
!=
NULL
,
return
;);
self
->
max_data_size
=
max_seg_size
;
self
->
max_header_size
=
max_header_size
;
del_timer
(
&
self
->
watchdog_timer
);
iriap_do_client_event
(
self
,
IAP_LM_CONNECT_CONFIRM
,
userdata
);
iriap_do_client_event
(
self
,
IAP_LM_CONNECT_CONFIRM
,
skb
);
/* Drop reference count - see state_s_make_call(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -769,7 +774,7 @@ static void iriap_connect_confirm(void *instance, void *sap,
static
void
iriap_connect_indication
(
void
*
instance
,
void
*
sap
,
struct
qos_info
*
qos
,
__u32
max_seg_size
,
__u8
max_header_size
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
struct
iriap_cb
*
self
,
*
new
;
...
...
@@ -777,22 +782,22 @@ static void iriap_connect_indication(void *instance, void *sap,
self
=
(
struct
iriap_cb
*
)
instance
;
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
;);
ASSERT
(
skb
!=
NULL
,
return
;);
ASSERT
(
self
!=
NULL
,
goto
out
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
goto
out
;);
/* Start new server */
new
=
iriap_open
(
LSAP_IAS
,
IAS_SERVER
,
NULL
,
NULL
);
if
(
!
new
)
{
IRDA_DEBUG
(
0
,
"%s(), open failed
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
userdata
);
return
;
goto
out
;
}
/* Now attach up the new "socket" */
new
->
lsap
=
irlmp_dup
(
self
->
lsap
,
new
);
if
(
!
new
->
lsap
)
{
IRDA_DEBUG
(
0
,
"%s(), dup failed!
\n
"
,
__FUNCTION__
);
return
;
goto
out
;
}
new
->
max_data_size
=
max_seg_size
;
...
...
@@ -801,7 +806,11 @@ static void iriap_connect_indication(void *instance, void *sap,
/* Clean up the original one to keep it in listen state */
irlmp_listen
(
self
->
lsap
);
iriap_do_server_event
(
new
,
IAP_LM_CONNECT_INDICATION
,
userdata
);
iriap_do_server_event
(
new
,
IAP_LM_CONNECT_INDICATION
,
skb
);
out:
/* Drop reference count - see state_r_disconnect(). */
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -821,10 +830,9 @@ static int iriap_data_indication(void *instance, void *sap,
self
=
(
struct
iriap_cb
*
)
instance
;
ASSERT
(
self
!=
NULL
,
return
0
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
0
;);
ASSERT
(
skb
!=
NULL
,
return
0
;);
ASSERT
(
self
!=
NULL
,
goto
out
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
goto
out
;);
frame
=
skb
->
data
;
...
...
@@ -832,22 +840,19 @@ static int iriap_data_indication(void *instance, void *sap,
/* Call server */
IRDA_DEBUG
(
4
,
"%s(), Calling server!
\n
"
,
__FUNCTION__
);
iriap_do_r_connect_event
(
self
,
IAP_RECV_F_LST
,
skb
);
return
0
;
goto
out
;
}
opcode
=
frame
[
0
];
if
(
~
opcode
&
IAP_LST
)
{
WARNING
(
"%s:, IrIAS multiframe commands or "
"results is not implemented yet!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
0
;
goto
out
;
}
/* Check for ack frames since they don't contain any data */
if
(
opcode
&
IAP_ACK
)
{
IRDA_DEBUG
(
0
,
"%s() Got ack frame!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
0
;
goto
out
;
}
opcode
&=
~
IAP_LST
;
/* Mask away LST bit */
...
...
@@ -855,7 +860,6 @@ static int iriap_data_indication(void *instance, void *sap,
switch
(
opcode
)
{
case
GET_INFO_BASE
:
IRDA_DEBUG
(
0
,
"IrLMP GetInfoBaseDetails not implemented!
\n
"
);
dev_kfree_skb
(
skb
);
break
;
case
GET_VALUE_BY_CLASS
:
iriap_do_call_event
(
self
,
IAP_RECV_F_LST
,
NULL
);
...
...
@@ -876,7 +880,6 @@ static int iriap_data_indication(void *instance, void *sap,
if
(
self
->
confirm
)
self
->
confirm
(
IAS_CLASS_UNKNOWN
,
0
,
NULL
,
self
->
priv
);
dev_kfree_skb
(
skb
);
break
;
case
IAS_ATTRIB_UNKNOWN
:
IRDA_DEBUG
(
1
,
"%s(), No such attribute!
\n
"
,
__FUNCTION__
);
...
...
@@ -890,16 +893,18 @@ static int iriap_data_indication(void *instance, void *sap,
if
(
self
->
confirm
)
self
->
confirm
(
IAS_ATTRIB_UNKNOWN
,
0
,
NULL
,
self
->
priv
);
dev_kfree_skb
(
skb
);
break
;
}
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown op-code: %02x
\n
"
,
__FUNCTION__
,
opcode
);
dev_kfree_skb
(
skb
);
break
;
}
out:
/* Cleanup - sub-calls will have done skb_get() as needed. */
dev_kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -939,6 +944,7 @@ void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
iriap_getvaluebyclass_indication
(
self
,
skb
);
break
;
}
/* skb will be cleaned up in iriap_data_indication */
}
/*
...
...
net/irda/iriap_event.c
View file @
4bcb7d97
...
...
@@ -11,6 +11,7 @@
*
* Copyright (c) 1997, 1999-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -174,8 +175,11 @@ static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
switch
(
event
)
{
case
IAP_CALL_REQUEST_GVBC
:
iriap_next_client_state
(
self
,
S_CONNECTING
);
ASSERT
(
self
->
skb
==
NULL
,
return
;);
self
->
skb
=
skb
;
ASSERT
(
self
->
request_skb
==
NULL
,
return
;);
/* Don't forget to refcount it -
* see iriap_getvaluebyclass_request(). */
skb_get
(
skb
);
self
->
request_skb
=
skb
;
iriap_connect_request
(
self
);
break
;
case
IAP_LM_DISCONNECT_INDICATION
:
...
...
@@ -251,20 +255,21 @@ static void state_s_call(struct iriap_cb *self, IRIAP_EVENT event,
static
void
state_s_make_call
(
struct
iriap_cb
*
self
,
IRIAP_EVENT
event
,
struct
sk_buff
*
skb
)
{
struct
sk_buff
*
tx_skb
;
ASSERT
(
self
!=
NULL
,
return
;);
switch
(
event
)
{
case
IAP_CALL_REQUEST
:
skb
=
self
->
skb
;
self
->
skb
=
NULL
;
/* Already refcounted - see state_s_disconnect() */
tx_skb
=
self
->
request_skb
;
self
->
request_skb
=
NULL
;
irlmp_data_request
(
self
->
lsap
,
skb
);
irlmp_data_request
(
self
->
lsap
,
tx_
skb
);
iriap_next_call_state
(
self
,
S_OUTSTANDING
);
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %d
\n
"
,
__FUNCTION__
,
event
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
}
...
...
@@ -379,10 +384,6 @@ static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
* care about LM_Idle_request()!
*/
iriap_next_r_connect_state
(
self
,
R_RECEIVING
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), unknown event %d
\n
"
,
__FUNCTION__
,
event
);
...
...
@@ -450,7 +451,6 @@ static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
IRDA_DEBUG
(
0
,
"%s(), unknown event!
\n
"
,
__FUNCTION__
);
break
;
}
}
/*
...
...
@@ -465,11 +465,8 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
ASSERT
(
skb
!=
NULL
,
return
;);
if
(
!
self
||
self
->
magic
!=
IAS_MAGIC
)
{
IRDA_DEBUG
(
0
,
"%s(), bad pointer self
\n
"
,
__FUNCTION__
);
return
;
}
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
IAS_MAGIC
,
return
;);
switch
(
event
)
{
case
IAP_CALL_RESPONSE
:
...
...
@@ -479,6 +476,10 @@ static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
*/
iriap_next_r_connect_state
(
self
,
R_RECEIVING
);
/* Don't forget to refcount it - see
* iriap_getvaluebyclass_response(). */
skb_get
(
skb
);
irlmp_data_request
(
self
->
lsap
,
skb
);
break
;
default:
...
...
net/irda/irlan/irlan_eth.c
View file @
4bcb7d97
...
...
@@ -206,7 +206,7 @@ int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
* confuse do_dev_queue_xmit() in dev.c! I have
* tried :-) DB
*/
dev_kfree_skb
(
skb
);
/* irttp_data_request already free the packet */
self
->
stats
.
tx_dropped
++
;
}
else
{
self
->
stats
.
tx_packets
++
;
...
...
net/irda/irlap.c
View file @
4bcb7d97
...
...
@@ -10,7 +10,7 @@
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -244,7 +244,6 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
irlap_init_qos_capabilities
(
self
,
NULL
);
/* No user QoS! */
skb_get
(
skb
);
/*LEVEL4*/
irlmp_link_connect_indication
(
self
->
notify
.
instance
,
self
->
saddr
,
self
->
daddr
,
&
self
->
qos_tx
,
skb
);
}
...
...
@@ -255,12 +254,11 @@ void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb)
* Service user has accepted incoming connection
*
*/
void
irlap_connect_response
(
struct
irlap_cb
*
self
,
struct
sk_buff
*
skb
)
void
irlap_connect_response
(
struct
irlap_cb
*
self
,
struct
sk_buff
*
userdata
)
{
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
irlap_do_event
(
self
,
CONNECT_RESPONSE
,
skb
,
NULL
);
kfree_skb
(
skb
);
irlap_do_event
(
self
,
CONNECT_RESPONSE
,
userdata
,
NULL
);
}
/*
...
...
@@ -305,7 +303,6 @@ void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb)
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
skb_get
(
skb
);
/*LEVEL4*/
irlmp_link_connect_confirm
(
self
->
notify
.
instance
,
&
self
->
qos_tx
,
skb
);
}
...
...
@@ -322,7 +319,6 @@ void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,
/* Hide LAP header from IrLMP layer */
skb_pull
(
skb
,
LAP_ADDR_HEADER
+
LAP_CTRL_HEADER
);
skb_get
(
skb
);
/*LEVEL4*/
irlmp_link_data_indication
(
self
->
notify
.
instance
,
skb
,
unreliable
);
}
...
...
@@ -354,6 +350,9 @@ void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb,
else
skb
->
data
[
1
]
=
I_FRAME
;
/* Don't forget to refcount it - see irlmp_connect_request(). */
skb_get
(
skb
);
/* Add at the end of the queue (keep ordering) - Jean II */
skb_queue_tail
(
&
self
->
txq
,
skb
);
...
...
@@ -392,6 +391,8 @@ void irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb)
skb
->
data
[
0
]
=
CBROADCAST
;
skb
->
data
[
1
]
=
UI_FRAME
;
/* Don't need to refcount, see irlmp_connless_data_request() */
skb_queue_tail
(
&
self
->
txq_ultra
,
skb
);
irlap_do_event
(
self
,
SEND_UI_FRAME
,
NULL
,
NULL
);
...
...
@@ -416,7 +417,6 @@ void irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb)
/* Hide LAP header from IrLMP layer */
skb_pull
(
skb
,
LAP_ADDR_HEADER
+
LAP_CTRL_HEADER
);
skb_get
(
skb
);
/*LEVEL4*/
irlmp_link_unitdata_indication
(
self
->
notify
.
instance
,
skb
);
}
#endif
/* CONFIG_IRDA_ULTRA */
...
...
net/irda/irlap_event.c
View file @
4bcb7d97
...
...
@@ -12,7 +12,7 @@
* Copyright (c) 1998-2000 Dag Brattli <dag@brattli.net>,
* Copyright (c) 1998 Thomas Davis <ratbert@radiks.net>
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -287,6 +287,9 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event,
/* Send one frame */
ret
=
(
*
state
[
self
->
state
])(
self
,
SEND_I_CMD
,
skb
,
NULL
);
/* Drop reference count.
* It will be increase as needed in
* irlap_send_data_xxx() */
kfree_skb
(
skb
);
/* Poll the higher layers for one more frame */
...
...
@@ -517,6 +520,8 @@ static int irlap_state_ndm(struct irlap_cb *self, IRLAP_EVENT event,
CMD_FRAME
);
else
break
;
/* irlap_send_ui_frame() won't increase skb reference
* count, so no dev_kfree_skb() - Jean II */
}
if
(
i
==
2
)
{
/* Force us to listen 500 ms again */
...
...
net/irda/irlap_frame.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -106,7 +106,7 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
*/
void
irlap_send_snrm_frame
(
struct
irlap_cb
*
self
,
struct
qos_info
*
qos
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
struct
snrm_frame
*
frame
;
int
ret
;
...
...
@@ -114,11 +114,11 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
/* Allocate frame */
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
;
frame
=
(
struct
snrm_frame
*
)
skb_put
(
skb
,
2
);
frame
=
(
struct
snrm_frame
*
)
skb_put
(
tx_
skb
,
2
);
/* Insert connection address field */
if
(
qos
)
...
...
@@ -133,19 +133,19 @@ void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos)
* If we are establishing a connection then insert QoS paramerters
*/
if
(
qos
)
{
skb_put
(
skb
,
9
);
/* 21 left */
skb_put
(
tx_
skb
,
9
);
/* 21 left */
frame
->
saddr
=
cpu_to_le32
(
self
->
saddr
);
frame
->
daddr
=
cpu_to_le32
(
self
->
daddr
);
frame
->
ncaddr
=
self
->
caddr
;
ret
=
irlap_insert_qos_negotiation_params
(
self
,
skb
);
ret
=
irlap_insert_qos_negotiation_params
(
self
,
tx_
skb
);
if
(
ret
<
0
)
{
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
tx_
skb
);
return
;
}
}
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -162,8 +162,8 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
frame
=
(
struct
snrm_frame
*
)
skb
->
data
;
if
(
skb
->
len
>=
sizeof
(
struct
snrm_frame
))
{
/* Copy the new connection address */
info
->
caddr
=
frame
->
ncaddr
;
/* Copy the new connection address
ignoring the C/R bit
*/
info
->
caddr
=
frame
->
ncaddr
&
0xFE
;
/* Check if the new connection address is valid */
if
((
info
->
caddr
==
0x00
)
||
(
info
->
caddr
==
0xfe
))
{
...
...
@@ -197,7 +197,7 @@ static void irlap_recv_snrm_cmd(struct irlap_cb *self, struct sk_buff *skb,
*/
void
irlap_send_ua_response_frame
(
struct
irlap_cb
*
self
,
struct
qos_info
*
qos
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
struct
ua_frame
*
frame
;
int
ret
;
...
...
@@ -206,14 +206,12 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
skb
=
NULL
;
/* Allocate frame */
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
;
frame
=
(
struct
ua_frame
*
)
skb_put
(
skb
,
10
);
frame
=
(
struct
ua_frame
*
)
skb_put
(
tx_
skb
,
10
);
/* Build UA response */
frame
->
caddr
=
self
->
caddr
;
...
...
@@ -224,14 +222,14 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
/* Should we send QoS negotiation parameters? */
if
(
qos
)
{
ret
=
irlap_insert_qos_negotiation_params
(
self
,
skb
);
ret
=
irlap_insert_qos_negotiation_params
(
self
,
tx_
skb
);
if
(
ret
<
0
)
{
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
tx_
skb
);
return
;
}
}
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
...
...
@@ -243,17 +241,17 @@ void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
*/
void
irlap_send_dm_frame
(
struct
irlap_cb
*
self
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
tx_
skb
=
NULL
;
__u8
*
frame
;
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
skb
=
dev_alloc_skb
(
32
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
32
);
if
(
!
tx_
skb
)
return
;
frame
=
skb_put
(
skb
,
2
);
frame
=
skb_put
(
tx_
skb
,
2
);
if
(
self
->
state
==
LAP_NDM
)
frame
[
0
]
=
CBROADCAST
;
...
...
@@ -262,7 +260,7 @@ void irlap_send_dm_frame( struct irlap_cb *self)
frame
[
1
]
=
DM_RSP
|
PF_BIT
;
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -273,7 +271,7 @@ void irlap_send_dm_frame( struct irlap_cb *self)
*/
void
irlap_send_disc_frame
(
struct
irlap_cb
*
self
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
tx_
skb
=
NULL
;
__u8
*
frame
;
IRDA_DEBUG
(
3
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -281,16 +279,16 @@ void irlap_send_disc_frame(struct irlap_cb *self)
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
skb
=
dev_alloc_skb
(
16
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
16
);
if
(
!
tx_
skb
)
return
;
frame
=
skb_put
(
skb
,
2
);
frame
=
skb_put
(
tx_
skb
,
2
);
frame
[
0
]
=
self
->
caddr
|
CMD_FRAME
;
frame
[
1
]
=
DISC_CMD
|
PF_BIT
;
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -302,7 +300,7 @@ void irlap_send_disc_frame(struct irlap_cb *self)
void
irlap_send_discovery_xid_frame
(
struct
irlap_cb
*
self
,
int
S
,
__u8
s
,
__u8
command
,
discovery_t
*
discovery
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
tx_
skb
=
NULL
;
struct
xid_frame
*
frame
;
__u32
bcast
=
BROADCAST
;
__u8
*
info
;
...
...
@@ -314,12 +312,12 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
ASSERT
(
discovery
!=
NULL
,
return
;);
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
;
skb_put
(
skb
,
14
);
frame
=
(
struct
xid_frame
*
)
skb
->
data
;
skb_put
(
tx_
skb
,
14
);
frame
=
(
struct
xid_frame
*
)
tx_
skb
->
data
;
if
(
command
)
{
frame
->
caddr
=
CBROADCAST
|
CMD_FRAME
;
...
...
@@ -367,21 +365,21 @@ void irlap_send_discovery_xid_frame(struct irlap_cb *self, int S, __u8 s,
int
len
;
if
(
discovery
->
data
.
hints
[
0
]
&
HINT_EXTENSION
)
{
info
=
skb_put
(
skb
,
2
);
info
=
skb_put
(
tx_
skb
,
2
);
info
[
0
]
=
discovery
->
data
.
hints
[
0
];
info
[
1
]
=
discovery
->
data
.
hints
[
1
];
}
else
{
info
=
skb_put
(
skb
,
1
);
info
=
skb_put
(
tx_
skb
,
1
);
info
[
0
]
=
discovery
->
data
.
hints
[
0
];
}
info
=
skb_put
(
skb
,
1
);
info
=
skb_put
(
tx_
skb
,
1
);
info
[
0
]
=
discovery
->
data
.
charset
;
len
=
IRDA_MIN
(
discovery
->
name_len
,
skb_tailroom
(
skb
));
info
=
skb_put
(
skb
,
len
);
len
=
IRDA_MIN
(
discovery
->
name_len
,
skb_tailroom
(
tx_
skb
));
info
=
skb_put
(
tx_
skb
,
len
);
memcpy
(
info
,
discovery
->
data
.
info
,
len
);
}
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -498,7 +496,6 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
break
;
default:
/* Error!! */
dev_kfree_skb
(
skb
);
return
;
}
info
->
s
=
xid
->
slotnr
;
...
...
@@ -561,21 +558,21 @@ static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,
*/
void
irlap_send_rr_frame
(
struct
irlap_cb
*
self
,
int
command
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
__u8
*
frame
;
skb
=
dev_alloc_skb
(
16
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
16
);
if
(
!
tx_
skb
)
return
;
frame
=
skb_put
(
skb
,
2
);
frame
=
skb_put
(
tx_
skb
,
2
);
frame
[
0
]
=
self
->
caddr
;
frame
[
0
]
|=
(
command
)
?
CMD_FRAME
:
0
;
frame
[
1
]
=
RR
|
PF_BIT
|
(
self
->
vr
<<
5
);
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -586,19 +583,19 @@ void irlap_send_rr_frame(struct irlap_cb *self, int command)
*/
void
irlap_send_rd_frame
(
struct
irlap_cb
*
self
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
__u8
*
frame
;
skb
=
dev_alloc_skb
(
16
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
16
);
if
(
!
tx_
skb
)
return
;
frame
=
skb_put
(
skb
,
2
);
frame
=
skb_put
(
tx_
skb
,
2
);
frame
[
0
]
=
self
->
caddr
;
frame
[
1
]
=
RD_RSP
|
PF_BIT
;
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -623,17 +620,17 @@ static inline void irlap_recv_rr_frame(struct irlap_cb *self,
void
irlap_send_frmr_frame
(
struct
irlap_cb
*
self
,
int
command
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
tx_
skb
=
NULL
;
__u8
*
frame
;
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
skb
=
dev_alloc_skb
(
32
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
32
);
if
(
!
tx_
skb
)
return
;
frame
=
skb_put
(
skb
,
2
);
frame
=
skb_put
(
tx_
skb
,
2
);
frame
[
0
]
=
self
->
caddr
;
frame
[
0
]
|=
(
command
)
?
CMD_FRAME
:
0
;
...
...
@@ -646,7 +643,7 @@ void irlap_send_frmr_frame( struct irlap_cb *self, int command)
IRDA_DEBUG
(
4
,
"%s(), vr=%d, %ld
\n
"
,
__FUNCTION__
,
self
->
vr
,
jiffies
);
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -739,17 +736,19 @@ void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb)
*/
skb
->
data
[
1
]
=
I_FRAME
|
(
self
->
vs
<<
1
);
/*
* Insert frame in store, in case of retransmissions
* Increase skb reference count, see irlap_do_event()
*/
skb_get
(
skb
);
skb_queue_tail
(
&
self
->
wx_list
,
skb
);
/* Copy buffer */
tx_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
tx_skb
==
NULL
)
{
return
;
}
/*
* Insert frame in store, in case of retransmissions
*/
skb_queue_tail
(
&
self
->
wx_list
,
skb_get
(
skb
));
self
->
vs
=
(
self
->
vs
+
1
)
%
8
;
self
->
ack_required
=
FALSE
;
self
->
window
-=
1
;
...
...
@@ -782,17 +781,19 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb)
*/
skb
->
data
[
1
]
=
I_FRAME
|
(
self
->
vs
<<
1
);
/*
* Insert frame in store, in case of retransmissions
* Increase skb reference count, see irlap_do_event()
*/
skb_get
(
skb
);
skb_queue_tail
(
&
self
->
wx_list
,
skb
);
/* Copy buffer */
tx_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
tx_skb
==
NULL
)
{
return
;
}
/*
* Insert frame in store, in case of retransmissions
*/
skb_queue_tail
(
&
self
->
wx_list
,
skb_get
(
skb
));
/*
* Set poll bit if necessary. We do this to the copied
* skb, since retransmitted need to set or clear the poll
...
...
@@ -850,14 +851,18 @@ void irlap_send_data_secondary_final(struct irlap_cb *self,
*/
skb
->
data
[
1
]
=
I_FRAME
|
(
self
->
vs
<<
1
);
/*
* Insert frame in store, in case of retransmissions
* Increase skb reference count, see irlap_do_event()
*/
skb_get
(
skb
);
skb_queue_tail
(
&
self
->
wx_list
,
skb
);
tx_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
tx_skb
==
NULL
)
{
return
;
}
/* Insert frame in store */
skb_queue_tail
(
&
self
->
wx_list
,
skb_get
(
skb
));
tx_skb
->
data
[
1
]
|=
PF_BIT
;
self
->
vs
=
(
self
->
vs
+
1
)
%
8
;
...
...
@@ -903,14 +908,18 @@ void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb)
*/
skb
->
data
[
1
]
=
I_FRAME
|
(
self
->
vs
<<
1
);
/*
* Insert frame in store, in case of retransmissions
* Increase skb reference count, see irlap_do_event()
*/
skb_get
(
skb
);
skb_queue_tail
(
&
self
->
wx_list
,
skb
);
tx_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
tx_skb
==
NULL
)
{
return
;
}
/* Insert frame in store */
skb_queue_tail
(
&
self
->
wx_list
,
skb_get
(
skb
));
self
->
vs
=
(
self
->
vs
+
1
)
%
8
;
self
->
ack_required
=
FALSE
;
self
->
window
-=
1
;
...
...
@@ -939,8 +948,6 @@ void irlap_resend_rejected_frames(struct irlap_cb *self, int command)
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
/* Initialize variables */
skb
=
tx_skb
=
NULL
;
count
=
skb_queue_len
(
&
self
->
wx_list
);
/* Resend unacknowledged frame(s) */
...
...
@@ -1020,9 +1027,6 @@ void irlap_resend_rejected_frame(struct irlap_cb *self, int command)
ASSERT
(
self
!=
NULL
,
return
;);
ASSERT
(
self
->
magic
==
LAP_MAGIC
,
return
;);
/* Initialize variables */
skb
=
tx_skb
=
NULL
;
/* Resend unacknowledged frame(s) */
skb
=
skb_peek
(
&
self
->
wx_list
);
if
(
skb
!=
NULL
)
{
...
...
@@ -1186,35 +1190,35 @@ static void irlap_recv_frmr_frame(struct irlap_cb *self, struct sk_buff *skb,
void
irlap_send_test_frame
(
struct
irlap_cb
*
self
,
__u8
caddr
,
__u32
daddr
,
struct
sk_buff
*
cmd
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
struct
test_frame
*
frame
;
__u8
*
info
;
skb
=
dev_alloc_skb
(
cmd
->
len
+
sizeof
(
struct
test_frame
));
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
cmd
->
len
+
sizeof
(
struct
test_frame
));
if
(
!
tx_
skb
)
return
;
/* Broadcast frames must include saddr and daddr fields */
if
(
caddr
==
CBROADCAST
)
{
frame
=
(
struct
test_frame
*
)
skb_put
(
skb
,
sizeof
(
struct
test_frame
));
skb_put
(
tx_
skb
,
sizeof
(
struct
test_frame
));
/* Insert the swapped addresses */
frame
->
saddr
=
cpu_to_le32
(
self
->
saddr
);
frame
->
daddr
=
cpu_to_le32
(
daddr
);
}
else
frame
=
(
struct
test_frame
*
)
skb_put
(
skb
,
LAP_ADDR_HEADER
+
LAP_CTRL_HEADER
);
frame
=
(
struct
test_frame
*
)
skb_put
(
tx_
skb
,
LAP_ADDR_HEADER
+
LAP_CTRL_HEADER
);
frame
->
caddr
=
caddr
;
frame
->
control
=
TEST_RSP
|
PF_BIT
;
/* Copy info */
info
=
skb_put
(
skb
,
cmd
->
len
);
info
=
skb_put
(
tx_
skb
,
cmd
->
len
);
memcpy
(
info
,
cmd
->
data
,
cmd
->
len
);
/* Return to sender */
irlap_wait_min_turn_around
(
self
,
&
self
->
qos_tx
);
irlap_queue_xmit
(
self
,
skb
);
irlap_queue_xmit
(
self
,
tx_
skb
);
}
/*
...
...
@@ -1263,6 +1267,15 @@ static void irlap_recv_test_frame(struct irlap_cb *self, struct sk_buff *skb,
* Called when a frame is received. Dispatches the right receive function
* for processing of the frame.
*
* Note on skb management :
* After calling the higher layers of the IrDA stack, we always
* kfree() the skb, which drop the reference count (and potentially
* destroy it).
* If a higher layer of the stack want to keep the skb around (to put
* in a queue or pass it to the higher layer), it will need to use
* skb_get() to keep a reference on it. This is usually done at the
* LMP level in irlmp.c.
* Jean II
*/
int
irlap_driver_rcv
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
ptype
)
...
...
@@ -1286,6 +1299,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
* we don't need to be clever about it. Jean II */
if
((
skb
=
skb_share_check
(
skb
,
GFP_ATOMIC
))
==
NULL
)
{
ERROR
(
"%s: can't clone shared skb!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
-
1
;
}
if
(
skb_is_nonlinear
(
skb
))
...
...
@@ -1390,6 +1404,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct net_device *dev,
break
;
}
out:
/* Always drop our reference on the skb */
dev_kfree_skb
(
skb
);
return
0
;
}
net/irda/irlmp.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -345,9 +345,10 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
__u32
saddr
,
__u32
daddr
,
struct
qos_info
*
qos
,
struct
sk_buff
*
userdata
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
sk_buff
*
tx_skb
=
userdata
;
struct
lap_cb
*
lap
;
struct
lsap_cb
*
lsap
;
int
ret
;
ASSERT
(
self
!=
NULL
,
return
-
EBADR
;);
ASSERT
(
self
->
magic
==
LMP_LSAP_MAGIC
,
return
-
EBADR
;);
...
...
@@ -356,26 +357,29 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
"%s(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x
\n
"
,
__FUNCTION__
,
self
->
slsap_sel
,
dlsap_sel
,
saddr
,
daddr
);
if
(
test_bit
(
0
,
&
self
->
connected
))
return
-
EISCONN
;
if
(
test_bit
(
0
,
&
self
->
connected
))
{
ret
=
-
EISCONN
;
goto
err
;
}
/* Client must supply destination device address */
if
(
!
daddr
)
return
-
EINVAL
;
if
(
!
daddr
)
{
ret
=
-
EINVAL
;
goto
err
;
}
/* Any userdata? */
if
(
userdata
==
NULL
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
if
(
tx_skb
==
NULL
)
{
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
skb_reserve
(
skb
,
LMP_MAX_HEADER
);
}
else
skb
=
userdata
;
skb_reserve
(
tx_skb
,
LMP_MAX_HEADER
);
}
/* Make room for MUX control header (3 bytes) */
ASSERT
(
skb_headroom
(
skb
)
>=
LMP_CONTROL_HEADER
,
return
-
1
;);
skb_push
(
skb
,
LMP_CONTROL_HEADER
);
ASSERT
(
skb_headroom
(
tx_
skb
)
>=
LMP_CONTROL_HEADER
,
return
-
1
;);
skb_push
(
tx_
skb
,
LMP_CONTROL_HEADER
);
self
->
dlsap_sel
=
dlsap_sel
;
...
...
@@ -409,7 +413,8 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
lap
=
hashbin_lock_find
(
irlmp
->
links
,
saddr
,
NULL
);
if
(
lap
==
NULL
)
{
IRDA_DEBUG
(
1
,
"%s(), Unable to find a usable link!
\n
"
,
__FUNCTION__
);
return
-
EHOSTUNREACH
;
ret
=
-
EHOSTUNREACH
;
goto
err
;
}
/* Check if LAP is disconnected or already connected */
...
...
@@ -423,13 +428,15 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
* Maybe we could give LAP a bit of help in this case.
*/
IRDA_DEBUG
(
0
,
"%s(), sorry, but I'm waiting for LAP to timeout!
\n
"
,
__FUNCTION__
);
return
-
EAGAIN
;
ret
=
-
EAGAIN
;
goto
err
;
}
/* LAP is already connected to a different node, and LAP
* can only talk to one node at a time */
IRDA_DEBUG
(
0
,
"%s(), sorry, but link is busy!
\n
"
,
__FUNCTION__
);
return
-
EBUSY
;
ret
=
-
EBUSY
;
goto
err
;
}
self
->
lap
=
lap
;
...
...
@@ -456,9 +463,18 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel,
if
(
qos
)
self
->
qos
=
*
qos
;
irlmp_do_lsap_event
(
self
,
LM_CONNECT_REQUEST
,
skb
);
irlmp_do_lsap_event
(
self
,
LM_CONNECT_REQUEST
,
tx_skb
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
tx_skb
);
return
0
;
err:
/* Cleanup */
if
(
tx_skb
)
dev_kfree_skb
(
tx_skb
);
return
ret
;
}
/*
...
...
@@ -495,12 +511,13 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb)
/* Hide LMP_CONTROL_HEADER header from layer above */
skb_pull
(
skb
,
LMP_CONTROL_HEADER
);
if
(
self
->
notify
.
connect_indication
)
if
(
self
->
notify
.
connect_indication
)
{
/* Don't forget to refcount it - see irlap_driver_rcv(). */
skb_get
(
skb
);
self
->
notify
.
connect_indication
(
self
->
notify
.
instance
,
self
,
&
self
->
qos
,
max_seg_size
,
max_header_size
,
skb
);
else
dev_kfree_skb
(
skb
);
}
}
/*
...
...
@@ -526,6 +543,9 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
irlmp_do_lsap_event
(
self
,
LM_CONNECT_RESPONSE
,
userdata
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
userdata
);
return
0
;
}
...
...
@@ -560,11 +580,12 @@ void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb)
skb_pull
(
skb
,
LMP_CONTROL_HEADER
);
if
(
self
->
notify
.
connect_confirm
)
{
/* Don't forget to refcount it - see irlap_driver_rcv() */
skb_get
(
skb
);
self
->
notify
.
connect_confirm
(
self
->
notify
.
instance
,
self
,
&
self
->
qos
,
max_seg_size
,
max_header_size
,
skb
);
}
else
dev_kfree_skb
(
skb
);
}
}
/*
...
...
@@ -602,6 +623,7 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
memcpy
(
new
,
orig
,
sizeof
(
struct
lsap_cb
));
/* new->lap = orig->lap; => done in the memcpy() */
/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
new
->
conn_skb
=
NULL
;
spin_unlock_irqrestore
(
&
irlmp
->
unconnected_lsaps
->
hb_spinlock
,
flags
);
...
...
@@ -653,6 +675,9 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
*/
irlmp_do_lsap_event
(
self
,
LM_DISCONNECT_REQUEST
,
userdata
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
userdata
);
/*
* Remove LSAP from list of connected LSAPs for the particular link
* and insert it into the list of unconnected LSAPs
...
...
@@ -686,7 +711,7 @@ int irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata)
* LSAP is being closed!
*/
void
irlmp_disconnect_indication
(
struct
lsap_cb
*
self
,
LM_REASON
reason
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
struct
lsap_cb
*
lsap
;
...
...
@@ -703,8 +728,6 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
* Jean II */
if
(
!
test_and_clear_bit
(
0
,
&
self
->
connected
))
{
IRDA_DEBUG
(
0
,
"%s(), already disconnected!
\n
"
,
__FUNCTION__
);
if
(
userdata
)
dev_kfree_skb
(
userdata
);
return
;
}
...
...
@@ -730,13 +753,14 @@ void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason,
/*
* Inform service user
*/
if
(
self
->
notify
.
disconnect_indication
)
if
(
self
->
notify
.
disconnect_indication
)
{
/* Don't forget to refcount it - see irlap_driver_rcv(). */
if
(
skb
)
skb_get
(
skb
);
self
->
notify
.
disconnect_indication
(
self
->
notify
.
instance
,
self
,
reason
,
userdata
);
else
{
self
,
reason
,
skb
);
}
else
{
IRDA_DEBUG
(
0
,
"%s(), no handler
\n
"
,
__FUNCTION__
);
if
(
userdata
)
dev_kfree_skb
(
userdata
);
}
}
...
...
@@ -1047,17 +1071,31 @@ discovery_t *irlmp_get_discovery_response()
*
* Send some data to peer device
*
* Note on skb management :
* After calling the lower layers of the IrDA stack, we always
* kfree() the skb, which drop the reference count (and potentially
* destroy it).
* IrLMP and IrLAP may queue the packet, and in those cases will need
* to use skb_get() to keep it around.
* Jean II
*/
int
irlmp_data_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
skb
)
int
irlmp_data_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
userdata
)
{
int
ret
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
magic
==
LMP_LSAP_MAGIC
,
return
-
1
;);
/* Make room for MUX header */
ASSERT
(
skb_headroom
(
skb
)
>=
LMP_HEADER
,
return
-
1
;);
skb_push
(
skb
,
LMP_HEADER
);
ASSERT
(
skb_headroom
(
userdata
)
>=
LMP_HEADER
,
return
-
1
;);
skb_push
(
userdata
,
LMP_HEADER
);
ret
=
irlmp_do_lsap_event
(
self
,
LM_DATA_REQUEST
,
userdata
);
return
irlmp_do_lsap_event
(
self
,
LM_DATA_REQUEST
,
skb
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
userdata
);
return
ret
;
}
/*
...
...
@@ -1071,26 +1109,34 @@ void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb)
/* Hide LMP header from layer above */
skb_pull
(
skb
,
LMP_HEADER
);
if
(
self
->
notify
.
data_indication
)
if
(
self
->
notify
.
data_indication
)
{
/* Don't forget to refcount it - see irlap_driver_rcv(). */
skb_get
(
skb
);
self
->
notify
.
data_indication
(
self
->
notify
.
instance
,
self
,
skb
);
else
dev_kfree_skb
(
skb
);
}
}
/*
* Function irlmp_udata_request (self, skb)
*/
int
irlmp_udata_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
skb
)
int
irlmp_udata_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
userdata
)
{
int
ret
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
ASSERT
(
skb
!=
NULL
,
return
-
1
;);
ASSERT
(
userdata
!=
NULL
,
return
-
1
;);
/* Make room for MUX header */
ASSERT
(
skb_headroom
(
skb
)
>=
LMP_HEADER
,
return
-
1
;);
skb_push
(
skb
,
LMP_HEADER
);
ASSERT
(
skb_headroom
(
userdata
)
>=
LMP_HEADER
,
return
-
1
;);
skb_push
(
userdata
,
LMP_HEADER
);
ret
=
irlmp_do_lsap_event
(
self
,
LM_UDATA_REQUEST
,
userdata
);
return
irlmp_do_lsap_event
(
self
,
LM_UDATA_REQUEST
,
skb
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
userdata
);
return
ret
;
}
/*
...
...
@@ -1110,51 +1156,57 @@ void irlmp_udata_indication(struct lsap_cb *self, struct sk_buff *skb)
/* Hide LMP header from layer above */
skb_pull
(
skb
,
LMP_HEADER
);
if
(
self
->
notify
.
udata_indication
)
if
(
self
->
notify
.
udata_indication
)
{
/* Don't forget to refcount it - see irlap_driver_rcv(). */
skb_get
(
skb
);
self
->
notify
.
udata_indication
(
self
->
notify
.
instance
,
self
,
skb
);
else
dev_kfree_skb
(
skb
);
}
}
/*
* Function irlmp_connless_data_request (self, skb)
*/
#ifdef CONFIG_IRDA_ULTRA
int
irlmp_connless_data_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
skb
)
int
irlmp_connless_data_request
(
struct
lsap_cb
*
self
,
struct
sk_buff
*
userdata
)
{
struct
sk_buff
*
clone_skb
;
struct
lap_cb
*
lap
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
ASSERT
(
skb
!=
NULL
,
return
-
1
;);
ASSERT
(
userdata
!=
NULL
,
return
-
1
;);
/* Make room for MUX and PID header */
ASSERT
(
skb_headroom
(
skb
)
>=
LMP_HEADER
+
LMP_PID_HEADER
,
return
-
1
;);
ASSERT
(
skb_headroom
(
userdata
)
>=
LMP_HEADER
+
LMP_PID_HEADER
,
return
-
1
;);
/* Insert protocol identifier */
skb_push
(
skb
,
LMP_PID_HEADER
);
skb
->
data
[
0
]
=
self
->
pid
;
skb_push
(
userdata
,
LMP_PID_HEADER
);
userdata
->
data
[
0
]
=
self
->
pid
;
/* Connectionless sockets must use 0x70 */
skb_push
(
skb
,
LMP_HEADER
);
skb
->
data
[
0
]
=
skb
->
data
[
1
]
=
LSAP_CONNLESS
;
skb_push
(
userdata
,
LMP_HEADER
);
userdata
->
data
[
0
]
=
userdata
->
data
[
1
]
=
LSAP_CONNLESS
;
/* Try to send Connectionless packets out on all links */
lap
=
(
struct
lap_cb
*
)
hashbin_get_first
(
irlmp
->
links
);
while
(
lap
!=
NULL
)
{
ASSERT
(
lap
->
magic
==
LMP_LAP_MAGIC
,
return
-
1
;);
clone_skb
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
!
clone_skb
)
clone_skb
=
skb_clone
(
userdata
,
GFP_ATOMIC
);
if
(
!
clone_skb
)
{
dev_kfree_skb
(
userdata
);
return
-
ENOMEM
;
}
irlap_unitdata_request
(
lap
->
irlap
,
clone_skb
);
/* irlap_unitdata_request() don't increase refcount,
* so no dev_kfree_skb() - Jean II */
lap
=
(
struct
lap_cb
*
)
hashbin_get_next
(
irlmp
->
links
);
}
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
userdata
);
return
0
;
}
...
...
@@ -1178,11 +1230,12 @@ void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb)
/* Hide LMP and PID header from layer above */
skb_pull
(
skb
,
LMP_HEADER
+
LMP_PID_HEADER
);
if
(
self
->
notify
.
udata_indication
)
if
(
self
->
notify
.
udata_indication
)
{
/* Don't forget to refcount it - see irlap_driver_rcv(). */
skb_get
(
skb
);
self
->
notify
.
udata_indication
(
self
->
notify
.
instance
,
self
,
skb
);
else
dev_kfree_skb
(
skb
);
}
}
#endif
/* CONFIG_IRDA_ULTRA */
...
...
net/irda/irlmp_event.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -295,8 +295,6 @@ static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
}
...
...
@@ -373,8 +371,6 @@ static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
}
...
...
@@ -468,8 +464,6 @@ static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
]);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
}
...
...
@@ -499,6 +493,9 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
switch
(
event
)
{
#ifdef CONFIG_IRDA_ULTRA
case
LM_UDATA_INDICATION
:
/* This is most bizzare. Those packets are aka unreliable
* connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
* Why do we pass them as Ultra ??? Jean II */
irlmp_connless_data_indication
(
self
,
skb
);
break
;
#endif
/* CONFIG_IRDA_ULTRA */
...
...
@@ -510,6 +507,8 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
__FUNCTION__
);
return
-
EBUSY
;
}
/* Don't forget to refcount it (see irlmp_connect_request()) */
skb_get
(
skb
);
self
->
conn_skb
=
skb
;
irlmp_next_lsap_state
(
self
,
LSAP_SETUP_PEND
);
...
...
@@ -525,6 +524,8 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
__FUNCTION__
);
return
-
EBUSY
;
}
/* Don't forget to refcount it (see irlap_driver_rcv()) */
skb_get
(
skb
);
self
->
conn_skb
=
skb
;
irlmp_next_lsap_state
(
self
,
LSAP_CONNECT_PEND
);
...
...
@@ -547,8 +548,6 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
1
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
@@ -606,8 +605,6 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
@@ -622,6 +619,7 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
static
int
irlmp_state_connect_pend
(
struct
lsap_cb
*
self
,
IRLMP_EVENT
event
,
struct
sk_buff
*
skb
)
{
struct
sk_buff
*
tx_skb
;
int
ret
=
0
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -647,10 +645,12 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG
(
4
,
"%s(), LS_CONNECT_CONFIRM
\n
"
,
__FUNCTION__
);
irlmp_next_lsap_state
(
self
,
LSAP_CONNECT
);
skb
=
self
->
conn_skb
;
tx_
skb
=
self
->
conn_skb
;
self
->
conn_skb
=
NULL
;
irlmp_connect_indication
(
self
,
skb
);
irlmp_connect_indication
(
self
,
tx_skb
);
/* Drop reference count - see irlmp_connect_indication(). */
dev_kfree_skb
(
tx_skb
);
break
;
case
LM_WATCHDOG_TIMEOUT
:
/* Will happen in some rare cases because of a race condition.
...
...
@@ -668,8 +668,6 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
@@ -759,8 +757,6 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
@@ -832,8 +828,6 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
@@ -850,6 +844,7 @@ static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
static
int
irlmp_state_setup_pend
(
struct
lsap_cb
*
self
,
IRLMP_EVENT
event
,
struct
sk_buff
*
skb
)
{
struct
sk_buff
*
tx_skb
;
LM_REASON
reason
;
int
ret
=
0
;
...
...
@@ -862,11 +857,13 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
case
LM_LAP_CONNECT_CONFIRM
:
ASSERT
(
self
->
conn_skb
!=
NULL
,
return
-
1
;);
skb
=
self
->
conn_skb
;
tx_
skb
=
self
->
conn_skb
;
self
->
conn_skb
=
NULL
;
irlmp_send_lcf_pdu
(
self
->
lap
,
self
->
dlsap_sel
,
self
->
slsap_sel
,
CONNECT_CMD
,
skb
);
self
->
slsap_sel
,
CONNECT_CMD
,
tx_skb
);
/* Drop reference count - see irlap_data_request(). */
dev_kfree_skb
(
tx_skb
);
irlmp_next_lsap_state
(
self
,
LSAP_SETUP
);
break
;
...
...
@@ -891,8 +888,6 @@ static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown event %s on LSAP %#02x
\n
"
,
__FUNCTION__
,
irlmp_event
[
event
],
self
->
slsap_sel
);
if
(
skb
)
dev_kfree_skb
(
skb
);
break
;
}
return
ret
;
...
...
net/irda/irlmp_frame.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -144,7 +144,6 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
}
else
{
IRDA_DEBUG
(
2
,
"%s(), received data frame
\n
"
,
__FUNCTION__
);
}
dev_kfree_skb
(
skb
);
return
;
}
...
...
@@ -168,16 +167,13 @@ void irlmp_link_data_indication(struct lap_cb *self, struct sk_buff *skb,
break
;
case
ACCESSMODE_CMD
:
IRDA_DEBUG
(
0
,
"Access mode cmd not implemented!
\n
"
);
dev_kfree_skb
(
skb
);
break
;
case
ACCESSMODE_CNF
:
IRDA_DEBUG
(
0
,
"Access mode cnf not implemented!
\n
"
);
dev_kfree_skb
(
skb
);
break
;
default:
IRDA_DEBUG
(
0
,
"%s(), Unknown control frame %02x
\n
"
,
__FUNCTION__
,
fp
[
2
]);
dev_kfree_skb
(
skb
);
break
;
}
}
else
if
(
unreliable
)
{
...
...
@@ -230,16 +226,12 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
if
(
pid
&
0x80
)
{
IRDA_DEBUG
(
0
,
"%s(), extension in PID not supp!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
;
}
/* Check if frame is addressed to the connectionless LSAP */
if
((
slsap_sel
!=
LSAP_CONNLESS
)
||
(
dlsap_sel
!=
LSAP_CONNLESS
))
{
IRDA_DEBUG
(
0
,
"%s(), dropping frame!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
return
;
}
...
...
@@ -264,7 +256,6 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
irlmp_connless_data_indication
(
lsap
,
skb
);
else
{
IRDA_DEBUG
(
0
,
"%s(), found no matching LSAP!
\n
"
,
__FUNCTION__
);
dev_kfree_skb
(
skb
);
}
}
#endif
/* CONFIG_IRDA_ULTRA */
...
...
@@ -278,7 +269,7 @@ void irlmp_link_unitdata_indication(struct lap_cb *self, struct sk_buff *skb)
void
irlmp_link_disconnect_indication
(
struct
lap_cb
*
lap
,
struct
irlap_cb
*
irlap
,
LAP_REASON
reason
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
IRDA_DEBUG
(
2
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -288,9 +279,7 @@ void irlmp_link_disconnect_indication(struct lap_cb *lap,
lap
->
reason
=
reason
;
lap
->
daddr
=
DEV_ADDR_ANY
;
/* FIXME: must do something with the userdata if any */
if
(
userdata
)
dev_kfree_skb
(
userdata
);
/* FIXME: must do something with the skb if any */
/*
* Inform station state machine
...
...
@@ -327,7 +316,7 @@ void irlmp_link_connect_indication(struct lap_cb *self, __u32 saddr,
*
*/
void
irlmp_link_connect_confirm
(
struct
lap_cb
*
self
,
struct
qos_info
*
qos
,
struct
sk_buff
*
userdata
)
struct
sk_buff
*
skb
)
{
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -335,9 +324,7 @@ void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos,
ASSERT
(
self
->
magic
==
LMP_LAP_MAGIC
,
return
;);
ASSERT
(
qos
!=
NULL
,
return
;);
/* Don't need use the userdata for now */
if
(
userdata
)
dev_kfree_skb
(
userdata
);
/* Don't need use the skb for now */
/* Copy QoS settings for this session */
self
->
qos
=
qos
;
...
...
net/irda/irnet/irnet.h
View file @
4bcb7d97
...
...
@@ -229,6 +229,11 @@
* v14 - 20.2.03 - Jean II
* o Add discovery hint bits in the control channel.
* o Remove obsolete MOD_INC/DEC_USE_COUNT in favor of .owner
*
* v15 - 7.4.03 - Jean II
* o Replace spin_lock_irqsave() with spin_lock_bh() so that we can
* use ppp_unit_number(). It's probably also better overall...
* o Disable call to ppp_unregister_channel(), because we can't do it.
*/
/***************************** INCLUDES *****************************/
...
...
@@ -276,6 +281,7 @@
#undef CONNECT_INDIC_KICK
/* Might mess IrDA, not needed */
#undef FAIL_SEND_DISCONNECT
/* Might mess IrDA, not needed */
#undef PASS_CONNECT_PACKETS
/* Not needed ? Safe */
#undef MISSING_PPP_API
/* Stuff I wish I could do */
/* PPP side of the business */
#define BLOCK_WHEN_CONNECT
/* Block packets when connecting */
...
...
net/irda/irnet/irnet_irda.c
View file @
4bcb7d97
...
...
@@ -31,7 +31,6 @@ irnet_post_event(irnet_socket * ap,
char
*
name
,
__u16
hints
)
{
unsigned
long
flags
;
/* For spinlock */
int
index
;
/* In the log */
DENTER
(
CTRL_TRACE
,
"(ap=0x%X, event=%d, daddr=%08x, name=``%s'')
\n
"
,
...
...
@@ -41,7 +40,7 @@ irnet_post_event(irnet_socket * ap,
* Note : as we are the only event producer, we only need to exclude
* ourself when touching the log, which is nice and easy.
*/
spin_lock_
irqsave
(
&
irnet_events
.
spinlock
,
flags
);
spin_lock_
bh
(
&
irnet_events
.
spinlock
);
/* Copy the event in the log */
index
=
irnet_events
.
index
;
...
...
@@ -69,7 +68,7 @@ irnet_post_event(irnet_socket * ap,
DEBUG
(
CTRL_INFO
,
"New event index is %d
\n
"
,
irnet_events
.
index
);
/* Spin lock end */
spin_unlock_
irqrestore
(
&
irnet_events
.
spinlock
,
flags
);
spin_unlock_
bh
(
&
irnet_events
.
spinlock
);
/* Now : wake up everybody waiting for events... */
wake_up_interruptible_all
(
&
irnet_events
.
rwait
);
...
...
@@ -536,10 +535,9 @@ irda_irnet_connect(irnet_socket * self)
* Can't re-insert (MUST remove first) so check for that... */
if
((
irnet_server
.
running
)
&&
(
self
->
q
.
q_next
==
NULL
))
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
irnet_server
.
spinlock
,
flags
);
spin_lock_bh
(
&
irnet_server
.
spinlock
);
hashbin_insert
(
irnet_server
.
list
,
(
irda_queue_t
*
)
self
,
0
,
self
->
rname
);
spin_unlock_
irqrestore
(
&
irnet_server
.
spinlock
,
flags
);
spin_unlock_
bh
(
&
irnet_server
.
spinlock
);
DEBUG
(
IRDA_SOCK_INFO
,
"Inserted ``%s'' in hashbin...
\n
"
,
self
->
rname
);
}
...
...
@@ -596,12 +594,11 @@ irda_irnet_destroy(irnet_socket * self)
if
((
irnet_server
.
running
)
&&
(
self
->
q
.
q_next
!=
NULL
))
{
struct
irnet_socket
*
entry
;
unsigned
long
flags
;
DEBUG
(
IRDA_SOCK_INFO
,
"Removing from hash..
\n
"
);
spin_lock_
irqsave
(
&
irnet_server
.
spinlock
,
flags
);
spin_lock_
bh
(
&
irnet_server
.
spinlock
);
entry
=
hashbin_remove_this
(
irnet_server
.
list
,
(
irda_queue_t
*
)
self
);
self
->
q
.
q_next
=
NULL
;
spin_unlock_
irqrestore
(
&
irnet_server
.
spinlock
,
flags
);
spin_unlock_
bh
(
&
irnet_server
.
spinlock
);
DASSERT
(
entry
==
self
,
,
IRDA_SOCK_ERROR
,
"Can't remove from hash.
\n
"
);
}
...
...
@@ -723,7 +720,6 @@ static inline irnet_socket *
irnet_find_socket
(
irnet_socket
*
self
)
{
irnet_socket
*
new
=
(
irnet_socket
*
)
NULL
;
unsigned
long
flags
;
int
err
;
DENTER
(
IRDA_SERV_TRACE
,
"(self=0x%X)
\n
"
,
(
unsigned
int
)
self
);
...
...
@@ -736,7 +732,7 @@ irnet_find_socket(irnet_socket * self)
err
=
irnet_daddr_to_dname
(
self
);
/* Protect access to the instance list */
spin_lock_
irqsave
(
&
irnet_server
.
spinlock
,
flags
);
spin_lock_
bh
(
&
irnet_server
.
spinlock
);
/* So now, try to get an socket having specifically
* requested that nickname */
...
...
@@ -790,7 +786,7 @@ irnet_find_socket(irnet_socket * self)
}
/* Spin lock end */
spin_unlock_
irqrestore
(
&
irnet_server
.
spinlock
,
flags
);
spin_unlock_
bh
(
&
irnet_server
.
spinlock
);
DEXIT
(
IRDA_SERV_TRACE
,
" - new = 0x%X
\n
"
,
(
unsigned
int
)
new
);
return
new
;
...
...
@@ -1135,10 +1131,15 @@ irnet_disconnect_indication(void * instance,
{
if
(
test_open
)
{
#ifdef MISSING_PPP_API
/* ppp_unregister_channel() wants a user context, which we
* are guaranteed to NOT have here. What are we supposed
* to do here ? Jean II */
/* If we were connected, cleanup & close the PPP channel,
* which will kill pppd (hangup) and the rest */
ppp_unregister_channel
(
&
self
->
chan
);
self
->
ppp_open
=
0
;
#endif
}
else
{
...
...
@@ -1711,7 +1712,6 @@ irnet_proc_read(char * buf,
{
irnet_socket
*
self
;
char
*
state
;
unsigned
long
flags
;
int
i
=
0
;
len
=
0
;
...
...
@@ -1728,7 +1728,7 @@ irnet_proc_read(char * buf,
return
len
;
/* Protect access to the instance list */
spin_lock_
irqsave
(
&
irnet_server
.
spinlock
,
flags
);
spin_lock_
bh
(
&
irnet_server
.
spinlock
);
/* Get the sockets one by one... */
self
=
(
irnet_socket
*
)
hashbin_get_first
(
irnet_server
.
list
);
...
...
@@ -1780,7 +1780,7 @@ irnet_proc_read(char * buf,
}
/* Spin lock end */
spin_unlock_
irqrestore
(
&
irnet_server
.
spinlock
,
flags
);
spin_unlock_
bh
(
&
irnet_server
.
spinlock
);
return
len
;
}
...
...
net/irda/irnet/irnet_ppp.c
View file @
4bcb7d97
...
...
@@ -927,7 +927,7 @@ ppp_irnet_send(struct ppp_channel * chan,
* Jean II
*/
DERROR
(
PPP_ERROR
,
"IrTTP doesn't like this packet !!! (0x%X)
\n
"
,
ret
);
dev_kfree_skb
(
skb
);
/* irttp_data_request already free the packet */
}
DEXIT
(
PPP_TRACE
,
"
\n
"
);
...
...
net/irda/irttp.c
View file @
4bcb7d97
...
...
@@ -11,7 +11,7 @@
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
* Copyright (c) 2000-200
1
Jean Tourrilhes <jt@hpl.hp.com>
* Copyright (c) 2000-200
3
Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
...
...
@@ -259,11 +259,17 @@ static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
dev_kfree_skb
(
frag
);
}
IRDA_DEBUG
(
2
,
"%s(), frame len=%d
\n
"
,
__FUNCTION__
,
n
);
IRDA_DEBUG
(
2
,
"%s(), rx_sdu_size=%d
\n
"
,
__FUNCTION__
,
self
->
rx_sdu_size
);
ASSERT
(
n
<=
self
->
rx_sdu_size
,
return
NULL
;);
IRDA_DEBUG
(
2
,
"%s(), frame len=%d, rx_sdu_size=%d, rx_max_sdu_size=%d
\n
"
,
__FUNCTION__
,
n
,
self
->
rx_sdu_size
,
self
->
rx_max_sdu_size
);
/* Note : irttp_run_rx_queue() calculate self->rx_sdu_size
* by summing the size of all fragments, so we should always
* have n == self->rx_sdu_size, except in cases where we
* droped the last fragment (when self->rx_sdu_size exceed
* self->rx_max_sdu_size), where n < self->rx_sdu_size.
* Jean II */
ASSERT
(
n
<=
self
->
rx_sdu_size
,
n
=
self
->
rx_sdu_size
;);
/* Set the new length */
skb_trim
(
skb
,
n
);
...
...
@@ -537,19 +543,23 @@ int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
if
((
skb
->
len
==
0
)
||
(
!
self
->
connected
))
{
IRDA_DEBUG
(
1
,
"%s(), No data, or not connected
\n
"
,
__FUNCTION__
);
return
-
1
;
goto
err
;
}
if
(
skb
->
len
>
self
->
max_seg_size
)
{
IRDA_DEBUG
(
1
,
"%s(), UData is to large for IrLAP!
\n
"
,
__FUNCTION__
);
return
-
1
;
goto
err
;
}
irlmp_udata_request
(
self
->
lsap
,
skb
);
self
->
stats
.
tx_packets
++
;
return
0
;
err:
dev_kfree_skb
(
skb
);
return
-
1
;
}
/*
...
...
@@ -561,6 +571,7 @@ int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb)
int
irttp_data_request
(
struct
tsap_cb
*
self
,
struct
sk_buff
*
skb
)
{
__u8
*
frame
;
int
ret
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
ASSERT
(
self
->
magic
==
TTP_TSAP_MAGIC
,
return
-
1
;);
...
...
@@ -572,7 +583,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
/* Check that nothing bad happens */
if
((
skb
->
len
==
0
)
||
(
!
self
->
connected
))
{
WARNING
(
"%s: No data, or not connected
\n
"
,
__FUNCTION__
);
return
-
ENOTCONN
;
ret
=
-
ENOTCONN
;
goto
err
;
}
/*
...
...
@@ -582,7 +594,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
if
((
self
->
tx_max_sdu_size
==
0
)
&&
(
skb
->
len
>
self
->
max_seg_size
))
{
ERROR
(
"%s: SAR disabled, and data is to large for IrLAP!
\n
"
,
__FUNCTION__
);
return
-
EMSGSIZE
;
ret
=
-
EMSGSIZE
;
goto
err
;
}
/*
...
...
@@ -595,7 +608,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
{
ERROR
(
"%s: SAR enabled, but data is larger than TxMaxSduSize!
\n
"
,
__FUNCTION__
);
return
-
EMSGSIZE
;
ret
=
-
EMSGSIZE
;
goto
err
;
}
/*
* Check if transmit queue is full
...
...
@@ -607,8 +621,9 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
irttp_run_tx_queue
(
self
);
/* Drop packet. This error code should trigger the caller
* to requeue the packet in the client code - Jean II */
return
-
ENOBUFS
;
* to resend the data in the client code - Jean II */
ret
=
-
ENOBUFS
;
goto
err
;
}
/* Queue frame, or queue frame segments */
...
...
@@ -651,6 +666,10 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb)
irttp_run_tx_queue
(
self
);
return
0
;
err:
dev_kfree_skb
(
skb
);
return
ret
;
}
/*
...
...
@@ -822,6 +841,7 @@ static int irttp_udata_indication(void *instance, void *sap,
struct
sk_buff
*
skb
)
{
struct
tsap_cb
*
self
;
int
err
;
IRDA_DEBUG
(
4
,
"%s()
\n
"
,
__FUNCTION__
);
...
...
@@ -831,14 +851,19 @@ static int irttp_udata_indication(void *instance, void *sap,
ASSERT
(
self
->
magic
==
TTP_TSAP_MAGIC
,
return
-
1
;);
ASSERT
(
skb
!=
NULL
,
return
-
1
;);
/* Just pass data to layer above */
if
(
self
->
notify
.
udata_indication
)
self
->
notify
.
udata_indication
(
self
->
notify
.
instance
,
self
,
skb
);
else
dev_kfree_skb
(
skb
);
self
->
stats
.
rx_packets
++
;
/* Just pass data to layer above */
if
(
self
->
notify
.
udata_indication
)
{
err
=
self
->
notify
.
udata_indication
(
self
->
notify
.
instance
,
self
,
skb
);
/* Same comment as in irttp_do_data_indication() */
if
(
err
!=
-
ENOMEM
)
return
0
;
}
/* Either no handler, or -ENOMEM */
dev_kfree_skb
(
skb
);
return
0
;
}
...
...
@@ -1040,7 +1065,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
struct
qos_info
*
qos
,
__u32
max_sdu_size
,
struct
sk_buff
*
userdata
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
__u8
*
frame
;
__u8
n
;
...
...
@@ -1049,19 +1074,22 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
ASSERT
(
self
!=
NULL
,
return
-
EBADR
;);
ASSERT
(
self
->
magic
==
TTP_TSAP_MAGIC
,
return
-
EBADR
;);
if
(
self
->
connected
)
if
(
self
->
connected
)
{
if
(
userdata
)
dev_kfree_skb
(
userdata
);
return
-
EISCONN
;
}
/* Any userdata supplied? */
if
(
userdata
==
NULL
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
/* Reserve space for MUX_CONTROL and LAP header */
skb_reserve
(
skb
,
TTP_MAX_HEADER
);
skb_reserve
(
tx_
skb
,
TTP_MAX_HEADER
);
}
else
{
skb
=
userdata
;
tx_
skb
=
userdata
;
/*
* Check that the client has reserved enough space for
* headers
...
...
@@ -1094,11 +1122,11 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
/* SAR enabled? */
if
(
max_sdu_size
>
0
)
{
ASSERT
(
skb_headroom
(
skb
)
>=
(
TTP_MAX_HEADER
+
TTP_SAR_HEADER
),
ASSERT
(
skb_headroom
(
tx_
skb
)
>=
(
TTP_MAX_HEADER
+
TTP_SAR_HEADER
),
return
-
1
;);
/* Insert SAR parameters */
frame
=
skb_push
(
skb
,
TTP_HEADER
+
TTP_SAR_HEADER
);
frame
=
skb_push
(
tx_
skb
,
TTP_HEADER
+
TTP_SAR_HEADER
);
frame
[
0
]
=
TTP_PARAMETERS
|
n
;
frame
[
1
]
=
0x04
;
/* Length */
...
...
@@ -1109,7 +1137,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
(
__u16
*
)(
frame
+
4
));
}
else
{
/* Insert plain TTP header */
frame
=
skb_push
(
skb
,
TTP_HEADER
);
frame
=
skb_push
(
tx_
skb
,
TTP_HEADER
);
/* Insert initial credit in frame */
frame
[
0
]
=
n
&
0x7f
;
...
...
@@ -1117,7 +1145,7 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,
/* Connect with IrLMP. No QoS parameters for now */
return
irlmp_connect_request
(
self
->
lsap
,
dtsap_sel
,
saddr
,
daddr
,
qos
,
skb
);
tx_
skb
);
}
/*
...
...
@@ -1201,7 +1229,8 @@ static void irttp_connect_confirm(void *instance, void *sap,
self
->
notify
.
connect_confirm
(
self
->
notify
.
instance
,
self
,
qos
,
self
->
tx_max_sdu_size
,
self
->
max_header_size
,
skb
);
}
}
else
dev_kfree_skb
(
skb
);
}
/*
...
...
@@ -1286,7 +1315,7 @@ void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,
int
irttp_connect_response
(
struct
tsap_cb
*
self
,
__u32
max_sdu_size
,
struct
sk_buff
*
userdata
)
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
tx_
skb
;
__u8
*
frame
;
int
ret
;
__u8
n
;
...
...
@@ -1299,19 +1328,19 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
/* Any userdata supplied? */
if
(
userdata
==
NULL
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
tx_
skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_
skb
)
return
-
ENOMEM
;
/* Reserve space for MUX_CONTROL and LAP header */
skb_reserve
(
skb
,
TTP_MAX_HEADER
);
skb_reserve
(
tx_
skb
,
TTP_MAX_HEADER
);
}
else
{
skb
=
userdata
;
tx_
skb
=
userdata
;
/*
* Check that the client has reserved enough space for
* headers
*/
ASSERT
(
skb_headroom
(
skb
)
>=
TTP_MAX_HEADER
,
return
-
1
;);
ASSERT
(
skb_headroom
(
tx_
skb
)
>=
TTP_MAX_HEADER
,
return
-
1
;);
}
self
->
avail_credit
=
0
;
...
...
@@ -1333,11 +1362,11 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
/* SAR enabled? */
if
(
max_sdu_size
>
0
)
{
ASSERT
(
skb_headroom
(
skb
)
>=
(
TTP_MAX_HEADER
+
TTP_SAR_HEADER
),
ASSERT
(
skb_headroom
(
tx_
skb
)
>=
(
TTP_MAX_HEADER
+
TTP_SAR_HEADER
),
return
-
1
;);
/* Insert TTP header with SAR parameters */
frame
=
skb_push
(
skb
,
TTP_HEADER
+
TTP_SAR_HEADER
);
frame
=
skb_push
(
tx_
skb
,
TTP_HEADER
+
TTP_SAR_HEADER
);
frame
[
0
]
=
TTP_PARAMETERS
|
n
;
frame
[
1
]
=
0x04
;
/* Length */
...
...
@@ -1352,12 +1381,12 @@ int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,
(
__u16
*
)(
frame
+
4
));
}
else
{
/* Insert TTP header */
frame
=
skb_push
(
skb
,
TTP_HEADER
);
frame
=
skb_push
(
tx_
skb
,
TTP_HEADER
);
frame
[
0
]
=
n
&
0x7f
;
}
ret
=
irlmp_connect_response
(
self
->
lsap
,
skb
);
ret
=
irlmp_connect_response
(
self
->
lsap
,
tx_
skb
);
return
ret
;
}
...
...
@@ -1423,7 +1452,6 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
int
irttp_disconnect_request
(
struct
tsap_cb
*
self
,
struct
sk_buff
*
userdata
,
int
priority
)
{
struct
sk_buff
*
skb
;
int
ret
;
ASSERT
(
self
!=
NULL
,
return
-
1
;);
...
...
@@ -1488,16 +1516,17 @@ int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata,
self
->
connected
=
FALSE
;
if
(
!
userdata
)
{
skb
=
dev_alloc_skb
(
64
);
if
(
!
skb
)
struct
sk_buff
*
tx_skb
;
tx_skb
=
dev_alloc_skb
(
64
);
if
(
!
tx_skb
)
return
-
ENOMEM
;
/*
* Reserve space for MUX and LAP header
*/
skb_reserve
(
skb
,
TTP_MAX_HEADER
);
skb_reserve
(
tx_
skb
,
TTP_MAX_HEADER
);
userdata
=
skb
;
userdata
=
tx_
skb
;
}
ret
=
irlmp_disconnect_request
(
self
->
lsap
,
userdata
);
...
...
@@ -1556,7 +1585,7 @@ void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason,
/*
* Function irttp_do_data_indication (self, skb)
*
* Try to deliver reassebled skb to layer above, and requeue it if that
* Try to deliver reasse
m
bled skb to layer above, and requeue it if that
* for some reason should fail. We mark rx sdu as busy to apply back
* pressure is necessary.
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment