OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [isdn/] [hysdn/] [hysdn_sched.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* $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 (werner@titro.de) for Hypercope GmbH
7
 * Copyright 1999 by Werner Cornelius (werner@titro.de)
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 beacuse 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 */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.