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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [alpha/] [kernel/] [srmcons.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      linux/arch/alpha/kernel/srmcons.c
3
 *
4
 * Callback based driver for SRM Console console device.
5
 * (TTY driver and console driver)
6
 */
7
 
8
#include <linux/config.h>
9
#include <linux/kernel.h>
10
#include <linux/init.h>
11
#include <linux/console.h>
12
#include <linux/delay.h>
13
#include <linux/mm.h>
14
#include <linux/slab.h>
15
#include <linux/spinlock.h>
16
#include <linux/timer.h>
17
#include <linux/tty.h>
18
#include <linux/tty_driver.h>
19
#include <linux/tty_flip.h>
20
 
21
#include <asm/console.h>
22
#include <asm/uaccess.h>
23
 
24
 
25
static spinlock_t srmcons_callback_lock = SPIN_LOCK_UNLOCKED;
26
static int srm_is_registered_console = 0;
27
 
28
/*
29
 * The TTY driver
30
 */
31
#define MAX_SRM_CONSOLE_DEVICES 1       /* only support 1 console device */
32
 
33
static int srmcons_refcount;
34
static struct tty_struct *srmcons_table[MAX_SRM_CONSOLE_DEVICES];
35
static struct termios *srmcons_termios[MAX_SRM_CONSOLE_DEVICES];
36
static struct termios *srmcons_termios_locked[MAX_SRM_CONSOLE_DEVICES];
37
 
38
struct srmcons_private {
39
        struct tty_struct *tty;
40
        struct timer_list timer;
41
        spinlock_t lock;
42
};
43
 
44
typedef union _srmcons_result {
45
        struct {
46
                unsigned long c :61;
47
                unsigned long status :3;
48
        } bits;
49
        long as_long;
50
} srmcons_result;
51
 
52
/* called with callback_lock held */
53
static int
54
srmcons_do_receive_chars(struct tty_struct *tty)
55
{
56
        srmcons_result result;
57
        int count = 0, loops = 0;
58
 
59
        do {
60
                result.as_long = callback_getc(0);
61
                if (result.bits.status < 2) {
62
                        tty_insert_flip_char(tty, (char)result.bits.c, 0);
63
                        count++;
64
                }
65
        } while((result.bits.status & 1) && (++loops < 10));
66
 
67
        if (count)
68
                tty_schedule_flip(tty);
69
 
70
        return count;
71
}
72
 
73
static void
74
srmcons_receive_chars(unsigned long data)
75
{
76
        struct srmcons_private *srmconsp = (struct srmcons_private *)data;
77
        unsigned long flags;
78
        int incr = 10;
79
 
80
        local_irq_save(flags);
81
        if (spin_trylock(&srmcons_callback_lock)) {
82
                if (!srmcons_do_receive_chars(srmconsp->tty))
83
                        incr = 100;
84
                spin_unlock(&srmcons_callback_lock);
85
        }
86
 
87
        spin_lock(&srmconsp->lock);
88
        if (srmconsp->tty) {
89
                srmconsp->timer.expires = jiffies + incr;
90
                add_timer(&srmconsp->timer);
91
        }
92
        spin_unlock(&srmconsp->lock);
93
 
94
        local_irq_restore(flags);
95
}
96
 
97
/* called with callback_lock held */
98
static int
99
srmcons_do_write(struct tty_struct *tty, const unsigned char *buf, int count)
100
{
101
        unsigned char *str_cr = "\r";
102
        long c, remaining = count;
103
        srmcons_result result;
104
        unsigned char *cur;
105
        int need_cr;
106
 
107
        for (cur = (unsigned char *)buf; remaining > 0; ) {
108
                need_cr = 0;
109
                /*
110
                 * Break it up into reasonable size chunks to allow a chance
111
                 * for input to get in
112
                 */
113
                for (c = 0; c < min_t(long, 128L, remaining) && !need_cr; c++)
114
                        if (cur[c] == '\n')
115
                                need_cr = 1;
116
 
117
                while (c > 0) {
118
                        result.as_long = callback_puts(0, cur, c);
119
                        c -= result.bits.c;
120
                        remaining -= result.bits.c;
121
                        cur += result.bits.c;
122
 
123
                        /*
124
                         * Check for pending input iff a tty was provided
125
                         */
126
                        if (tty)
127
                                srmcons_do_receive_chars(tty);
128
                }
129
 
130
                while (need_cr) {
131
                        result.as_long = callback_puts(0, str_cr, 1);
132
                        if (result.bits.c > 0)
133
                                need_cr = 0;
134
                }
135
        }
136
        return count;
137
}
138
 
139
static int
140
srmcons_write(struct tty_struct *tty, int from_user,
141
              const unsigned char *buf, int count)
142
{
143
        unsigned long flags;
144
 
145
        if (from_user) {
146
                unsigned char tmp[512];
147
                int ret = 0;
148
                size_t c;
149
 
150
                while ((c = count) > 0) {
151
                        if (c > sizeof(tmp))
152
                                c = sizeof(tmp);
153
 
154
                        c -= copy_from_user(tmp, buf, c);
155
 
156
                        if (!c) {
157
                                printk("%s: EFAULT (count %d)\n",
158
                                       __FUNCTION__, count);
159
                                return -EFAULT;
160
                        }
161
 
162
                        spin_lock_irqsave(&srmcons_callback_lock, flags);
163
                        srmcons_do_write(tty, tmp, c);
164
                        spin_unlock_irqrestore(&srmcons_callback_lock, flags);
165
 
166
                        buf += c;
167
                        count -= c;
168
                        ret += c;
169
                }
170
 
171
                return ret;
172
        }
173
 
174
        spin_lock_irqsave(&srmcons_callback_lock, flags);
175
        srmcons_do_write(tty, buf, count);
176
        spin_unlock_irqrestore(&srmcons_callback_lock, flags);
177
 
178
        return count;
179
}
180
 
181
static int
182
srmcons_write_room(struct tty_struct *tty)
183
{
184
        return 512;
185
}
186
 
187
static int
188
srmcons_chars_in_buffer(struct tty_struct *tty)
189
{
190
        return 0;
191
}
192
 
193
static int
194
srmcons_get_private_struct(struct srmcons_private **ps)
195
{
196
        static struct srmcons_private *srmconsp = NULL;
197
        static spinlock_t srmconsp_lock = SPIN_LOCK_UNLOCKED;
198
        unsigned long flags;
199
        int retval = 0;
200
 
201
        spin_lock_irqsave(&srmconsp_lock, flags);
202
 
203
        do {
204
                if (srmconsp != NULL) {
205
                        *ps = srmconsp;
206
                        break;
207
                }
208
 
209
                srmconsp = kmalloc(sizeof(*srmconsp), GFP_KERNEL);
210
                if (srmconsp == NULL) {
211
                        retval = -ENOMEM;
212
                        break;
213
                }
214
 
215
                srmconsp->tty = NULL;
216
                srmconsp->lock = SPIN_LOCK_UNLOCKED;
217
                init_timer(&srmconsp->timer);
218
 
219
                *ps = srmconsp;
220
        } while(0);
221
 
222
        spin_unlock_irqrestore(&srmconsp_lock, flags);
223
 
224
        return retval;
225
}
226
 
227
static int
228
srmcons_open(struct tty_struct *tty, struct file *filp)
229
{
230
        struct srmcons_private *srmconsp;
231
        unsigned long flags;
232
        int retval;
233
 
234
        retval = srmcons_get_private_struct(&srmconsp);
235
        if (retval)
236
                return retval;
237
 
238
        spin_lock_irqsave(&srmconsp->lock, flags);
239
 
240
        if (!srmconsp->tty) {
241
                tty->driver_data = srmconsp;
242
 
243
                srmconsp->tty = tty;
244
                srmconsp->timer.function = srmcons_receive_chars;
245
                srmconsp->timer.data = (unsigned long)srmconsp;
246
                srmconsp->timer.expires = jiffies + 10;
247
                add_timer(&srmconsp->timer);
248
        }
249
 
250
        spin_unlock_irqrestore(&srmconsp->lock, flags);
251
 
252
        return 0;
253
}
254
 
255
static void
256
srmcons_close(struct tty_struct *tty, struct file *filp)
257
{
258
        struct srmcons_private *srmconsp = tty->driver_data;
259
        unsigned long flags;
260
 
261
        spin_lock_irqsave(&srmconsp->lock, flags);
262
 
263
        if (tty->count == 1) {
264
                srmconsp->tty = NULL;
265
                del_timer(&srmconsp->timer);
266
        }
267
 
268
        spin_unlock_irqrestore(&srmconsp->lock, flags);
269
}
270
 
271
 
272
static struct tty_driver srmcons_driver = {
273
        .driver_name    = "srm",
274
        .name           = "srm",
275
        .magic          = TTY_DRIVER_MAGIC,
276
        .major          = 0,     /* dynamic */
277
        .minor_start    = 0,
278
        .num            = MAX_SRM_CONSOLE_DEVICES,
279
        .type           = TTY_DRIVER_TYPE_SYSTEM,
280
        .subtype        = SYSTEM_TYPE_SYSCONS,
281
 
282
        .table          = srmcons_table,
283
        .termios        = srmcons_termios,
284
        .termios_locked = srmcons_termios_locked,
285
        .refcount       = &srmcons_refcount,
286
 
287
        .open           = srmcons_open,
288
        .close          = srmcons_close,
289
        .write          = srmcons_write,
290
        .write_room     = srmcons_write_room,
291
        .chars_in_buffer= srmcons_chars_in_buffer,
292
};
293
 
294
static int __init
295
srmcons_init(void)
296
{
297
        if (srm_is_registered_console) {
298
                srmcons_driver.init_termios = tty_std_termios;
299
                return tty_register_driver(&srmcons_driver);
300
        }
301
 
302
        return -ENODEV;
303
}
304
 
305
module_init(srmcons_init);
306
 
307
 
308
/*
309
 * The console driver
310
 */
311
static void
312
srm_console_write(struct console *co, const char *s, unsigned count)
313
{
314
        unsigned long flags;
315
 
316
        spin_lock_irqsave(&srmcons_callback_lock, flags);
317
        srmcons_do_write(NULL, s, count);
318
        spin_unlock_irqrestore(&srmcons_callback_lock, flags);
319
}
320
 
321
static kdev_t
322
srm_console_device(struct console *co)
323
{
324
        return mk_kdev(srmcons_driver.major,
325
                       srmcons_driver.minor_start + co->index);
326
}
327
 
328
static int __init
329
srm_console_setup(struct console *co, char *options)
330
{
331
        return 0;
332
}
333
 
334
static struct console srmcons = {
335
        .name           = "srm",
336
        .write          = srm_console_write,
337
        .device         = srm_console_device,
338
        .setup          = srm_console_setup,
339
        .flags          = CON_PRINTBUFFER,
340
        .index          = -1,
341
};
342
 
343
void __init
344
register_srm_console(void)
345
{
346
        if (!srm_is_registered_console) {
347
                callback_open_console();
348
                register_console(&srmcons);
349
                srm_is_registered_console = 1;
350
        }
351
}
352
 
353
void __init
354
unregister_srm_console(void)
355
{
356
        if (srm_is_registered_console) {
357
                callback_close_console();
358
                unregister_console(&srmcons);
359
                srm_is_registered_console = 0;
360
        }
361
}

powered by: WebSVN 2.1.0

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