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
nexedi
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