Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
isdn
hysdn
hysdn_sched.c
Go to the documentation of this file.
1
/* $Id: hysdn_sched.c,v 1.5.6.4 2001/11/06 21:58:19 kai Exp $
2
*
3
* Linux driver for HYSDN cards
4
* scheduler routines for handling exchange card <-> pc.
5
*
6
* Author Werner Cornelius (
[email protected]
) for Hypercope GmbH
7
* Copyright 1999 by Werner Cornelius (
[email protected]
)
8
*
9
* This software may be used and distributed according to the terms
10
* of the GNU General Public License, incorporated herein by reference.
11
*
12
*/
13
14
#include <linux/signal.h>
15
#include <linux/kernel.h>
16
#include <
linux/ioport.h
>
17
#include <
linux/interrupt.h
>
18
#include <
linux/delay.h
>
19
#include <asm/io.h>
20
21
#include "
hysdn_defs.h
"
22
23
/*****************************************************************************/
24
/* hysdn_sched_rx is called from the cards handler to announce new data is */
25
/* available from the card. The routine has to handle the data and return */
26
/* with a nonzero code if the data could be worked (or even thrown away), if */
27
/* no room to buffer the data is available a zero return tells the card */
28
/* to keep the data until later. */
29
/*****************************************************************************/
30
int
31
hysdn_sched_rx
(
hysdn_card
*
card
,
unsigned
char
*
buf
,
unsigned
short
len,
32
unsigned
short
chan
)
33
{
34
35
switch
(chan) {
36
case
CHAN_NDIS_DATA
:
37
if
(
hynet_enable
& (1 << card->
myid
)) {
38
/* give packet to network handler */
39
hysdn_rx_netpkt
(card, buf, len);
40
}
41
break
;
42
43
case
CHAN_ERRLOG
:
44
hysdn_card_errlog
(card, (
tErrLogEntry
*) buf, len);
45
if
(card->
err_log_state
==
ERRLOG_STATE_ON
)
46
card->
err_log_state
=
ERRLOG_STATE_START
;
/* start new fetch */
47
break
;
48
#ifdef CONFIG_HYSDN_CAPI
49
case
CHAN_CAPI
:
50
/* give packet to CAPI handler */
51
if
(
hycapi_enable
& (1 << card->
myid
)) {
52
hycapi_rx_capipkt
(card, buf, len);
53
}
54
break
;
55
#endif
/* CONFIG_HYSDN_CAPI */
56
default
:
57
printk
(
KERN_INFO
"irq message channel %d len %d unhandled \n"
, chan, len);
58
break
;
59
60
}
/* switch rx channel */
61
62
return
(1);
/* always handled */
63
}
/* hysdn_sched_rx */
64
65
/*****************************************************************************/
66
/* hysdn_sched_tx is called from the cards handler to announce that there is */
67
/* room in the tx-buffer to the card and data may be sent if needed. */
68
/* If the routine wants to send data it must fill buf, len and chan with the */
69
/* appropriate data and return a nonzero value. With a zero return no new */
70
/* data to send is assumed. maxlen specifies the buffer size available for */
71
/* sending. */
72
/*****************************************************************************/
73
int
74
hysdn_sched_tx
(
hysdn_card
*
card
,
unsigned
char
*
buf
,
75
unsigned
short
volatile
*len,
unsigned
short
volatile
*
chan
,
76
unsigned
short
maxlen)
77
{
78
struct
sk_buff
*
skb
;
79
80
if
(card->
net_tx_busy
) {
81
card->
net_tx_busy
= 0;
/* reset flag */
82
hysdn_tx_netack
(card);
/* acknowledge packet send */
83
}
/* a network packet has completely been transferred */
84
/* first of all async requests are handled */
85
if
(card->
async_busy
) {
86
if
(card->
async_len
<= maxlen) {
87
memcpy
(buf, card->
async_data
, card->
async_len
);
88
*len = card->
async_len
;
89
*chan = card->
async_channel
;
90
card->
async_busy
= 0;
/* reset request */
91
return
(1);
92
}
93
card->
async_busy
= 0;
/* in case of length error */
94
}
/* async request */
95
if
((card->
err_log_state
==
ERRLOG_STATE_START
) &&
96
(maxlen >=
ERRLOG_CMD_REQ_SIZE
)) {
97
strcpy
(buf,
ERRLOG_CMD_REQ
);
/* copy the command */
98
*len =
ERRLOG_CMD_REQ_SIZE
;
/* buffer length */
99
*chan =
CHAN_ERRLOG
;
/* and channel */
100
card->
err_log_state
=
ERRLOG_STATE_ON
;
/* new state is on */
101
return
(1);
/* tell that data should be send */
102
}
/* error log start and able to send */
103
if
((card->
err_log_state
==
ERRLOG_STATE_STOP
) &&
104
(maxlen >=
ERRLOG_CMD_STOP_SIZE
)) {
105
strcpy
(buf,
ERRLOG_CMD_STOP
);
/* copy the command */
106
*len =
ERRLOG_CMD_STOP_SIZE
;
/* buffer length */
107
*chan =
CHAN_ERRLOG
;
/* and channel */
108
card->
err_log_state
=
ERRLOG_STATE_OFF
;
/* new state is off */
109
return
(1);
/* tell that data should be send */
110
}
/* error log start and able to send */
111
/* now handle network interface packets */
112
if
((
hynet_enable
& (1 << card->
myid
)) &&
113
(skb =
hysdn_tx_netget
(card)) !=
NULL
)
114
{
115
if
(skb->
len
<= maxlen) {
116
/* copy the packet to the buffer */
117
skb_copy_from_linear_data(skb, buf, skb->
len
);
118
*len = skb->
len
;
119
*chan =
CHAN_NDIS_DATA
;
120
card->
net_tx_busy
= 1;
/* we are busy sending network data */
121
return
(1);
/* go and send the data */
122
}
else
123
hysdn_tx_netack
(card);
/* aknowledge packet -> throw away */
124
}
/* send a network packet if available */
125
#ifdef CONFIG_HYSDN_CAPI
126
if
(((
hycapi_enable
& (1 << card->
myid
))) &&
127
((skb =
hycapi_tx_capiget
(card)) !=
NULL
))
128
{
129
if
(skb->
len
<= maxlen) {
130
skb_copy_from_linear_data(skb, buf, skb->
len
);
131
*len = skb->
len
;
132
*chan =
CHAN_CAPI
;
133
hycapi_tx_capiack
(card);
134
return
(1);
/* go and send the data */
135
}
136
}
137
#endif
/* CONFIG_HYSDN_CAPI */
138
return
(0);
/* nothing to send */
139
}
/* hysdn_sched_tx */
140
141
142
/*****************************************************************************/
143
/* send one config line to the card and return 0 if successful, otherwise a */
144
/* negative error code. */
145
/* The function works with timeouts perhaps not giving the greatest speed */
146
/* sending the line, but this should be meaningless because only some lines */
147
/* are to be sent and this happens very seldom. */
148
/*****************************************************************************/
149
int
150
hysdn_tx_cfgline
(
hysdn_card
*
card
,
unsigned
char
*
line
,
unsigned
short
chan
)
151
{
152
int
cnt
= 50;
/* timeout intervalls */
153
unsigned
long
flags
;
154
155
if
(card->
debug_flags
&
LOG_SCHED_ASYN
)
156
hysdn_addlog
(card,
"async tx-cfg chan=%d len=%d"
, chan,
strlen
(line) + 1);
157
158
while
(card->
async_busy
) {
159
160
if
(card->
debug_flags
&
LOG_SCHED_ASYN
)
161
hysdn_addlog
(card,
"async tx-cfg delayed"
);
162
163
msleep_interruptible
(20);
/* Timeout 20ms */
164
if
(!--cnt)
165
return
(-
ERR_ASYNC_TIME
);
/* timed out */
166
}
/* wait for buffer to become free */
167
168
spin_lock_irqsave
(&card->
hysdn_lock
, flags);
169
strcpy
(card->
async_data
, line);
170
card->
async_len
=
strlen
(line) + 1;
171
card->
async_channel
= chan;
172
card->
async_busy
= 1;
/* request transfer */
173
174
/* now queue the task */
175
schedule_work
(&card->
irq_queue
);
176
spin_unlock_irqrestore(&card->
hysdn_lock
, flags);
177
178
if
(card->
debug_flags
&
LOG_SCHED_ASYN
)
179
hysdn_addlog
(card,
"async tx-cfg data queued"
);
180
181
cnt++;
/* short delay */
182
183
while
(card->
async_busy
) {
184
185
if
(card->
debug_flags
&
LOG_SCHED_ASYN
)
186
hysdn_addlog
(card,
"async tx-cfg waiting for tx-ready"
);
187
188
msleep_interruptible
(20);
/* Timeout 20ms */
189
if
(!--cnt)
190
return
(-
ERR_ASYNC_TIME
);
/* timed out */
191
}
/* wait for buffer to become free again */
192
193
if
(card->
debug_flags
&
LOG_SCHED_ASYN
)
194
hysdn_addlog
(card,
"async tx-cfg data send"
);
195
196
return
(0);
/* line send correctly */
197
}
/* hysdn_tx_cfgline */
Generated on Thu Jan 10 2013 13:42:17 for Linux Kernel by
1.8.2