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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [vme_scc.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
3
 * implementation.
4
 * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
5
 *
6
 * Based on atari_SCC.c which was
7
 *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
8
 *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
9
 *
10
 * This file is subject to the terms and conditions of the GNU General Public
11
 * License.  See the file COPYING in the main directory of this archive
12
 * for more details.
13
 *
14
 */
15
 
16
#include <linux/module.h>
17
#include <linux/config.h>
18
#include <linux/kdev_t.h>
19
#include <asm/io.h>
20
#include <linux/kernel.h>
21
#include <linux/sched.h>
22
#include <linux/ioport.h>
23
#include <linux/interrupt.h>
24
#include <linux/errno.h>
25
#include <linux/tty.h>
26
#include <linux/tty_flip.h>
27
#include <linux/mm.h>
28
#include <linux/serial.h>
29
#include <linux/fcntl.h>
30
#include <linux/major.h>
31
#include <linux/delay.h>
32
#include <linux/tqueue.h>
33
#include <linux/version.h>
34
#include <linux/slab.h>
35
#include <linux/miscdevice.h>
36
#include <linux/console.h>
37
#include <linux/init.h>
38
#include <asm/setup.h>
39
#include <asm/bootinfo.h>
40
 
41
#ifdef CONFIG_MVME147_SCC
42
#include <asm/mvme147hw.h>
43
#endif
44
#ifdef CONFIG_MVME162_SCC
45
#include <asm/mvme16xhw.h>
46
#endif
47
#ifdef CONFIG_BVME6000_SCC
48
#include <asm/bvme6000hw.h>
49
#endif
50
 
51
#include <linux/generic_serial.h>
52
#include "scc.h"
53
 
54
 
55
#define CHANNEL_A       0
56
#define CHANNEL_B       1
57
 
58
#define SCC_MINOR_BASE  64
59
 
60
/* Shadows for all SCC write registers */
61
static unsigned char scc_shadow[2][16];
62
 
63
/* Location to access for SCC register access delay */
64
static volatile unsigned char *scc_del = NULL;
65
 
66
/* To keep track of STATUS_REG state for detection of Ext/Status int source */
67
static unsigned char scc_last_status_reg[2];
68
 
69
/***************************** Prototypes *****************************/
70
 
71
/* Function prototypes */
72
static void scc_disable_tx_interrupts(void * ptr);
73
static void scc_enable_tx_interrupts(void * ptr);
74
static void scc_disable_rx_interrupts(void * ptr);
75
static void scc_enable_rx_interrupts(void * ptr);
76
static int  scc_get_CD(void * ptr);
77
static void scc_shutdown_port(void * ptr);
78
static int scc_set_real_termios(void  *ptr);
79
static void scc_hungup(void  *ptr);
80
static void scc_close(void  *ptr);
81
static int scc_chars_in_buffer(void * ptr);
82
static int scc_open(struct tty_struct * tty, struct file * filp);
83
static int scc_ioctl(struct tty_struct * tty, struct file * filp,
84
                     unsigned int cmd, unsigned long arg);
85
static void scc_throttle(struct tty_struct *tty);
86
static void scc_unthrottle(struct tty_struct *tty);
87
static void scc_tx_int(int irq, void *data, struct pt_regs *fp);
88
static void scc_rx_int(int irq, void *data, struct pt_regs *fp);
89
static void scc_stat_int(int irq, void *data, struct pt_regs *fp);
90
static void scc_spcond_int(int irq, void *data, struct pt_regs *fp);
91
static void scc_setsignals(struct scc_port *port, int dtr, int rts);
92
static void scc_break_ctl(struct tty_struct *tty, int break_state);
93
 
94
static struct tty_driver scc_driver, scc_callout_driver;
95
 
96
static struct tty_struct *scc_table[2] = { NULL, };
97
static struct termios * scc_termios[2];
98
static struct termios * scc_termios_locked[2];
99
struct scc_port scc_ports[2];
100
 
101
int scc_refcount;
102
int scc_initialized = 0;
103
 
104
/*---------------------------------------------------------------------------
105
 * Interface from generic_serial.c back here
106
 *--------------------------------------------------------------------------*/
107
 
108
static struct real_driver scc_real_driver = {
109
        scc_disable_tx_interrupts,
110
        scc_enable_tx_interrupts,
111
        scc_disable_rx_interrupts,
112
        scc_enable_rx_interrupts,
113
        scc_get_CD,
114
        scc_shutdown_port,
115
        scc_set_real_termios,
116
        scc_chars_in_buffer,
117
        scc_close,
118
        scc_hungup,
119
        NULL
120
};
121
 
122
 
123
/*----------------------------------------------------------------------------
124
 * vme_scc_init() and support functions
125
 *---------------------------------------------------------------------------*/
126
 
127
static int scc_init_drivers(void)
128
{
129
        int error;
130
 
131
        memset(&scc_driver, 0, sizeof(scc_driver));
132
        scc_driver.magic = TTY_DRIVER_MAGIC;
133
        scc_driver.driver_name = "scc";
134
#ifdef CONFIG_DEVFS_FS
135
        scc_driver.name = "tts/%d";
136
#else
137
        scc_driver.name = "ttyS";
138
#endif
139
        scc_driver.major = TTY_MAJOR;
140
        scc_driver.minor_start = SCC_MINOR_BASE;
141
        scc_driver.num = 2;
142
        scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
143
        scc_driver.subtype = SERIAL_TYPE_NORMAL;
144
        scc_driver.init_termios = tty_std_termios;
145
        scc_driver.init_termios.c_cflag =
146
          B9600 | CS8 | CREAD | HUPCL | CLOCAL;
147
        scc_driver.flags = TTY_DRIVER_REAL_RAW;
148
        scc_driver.refcount = &scc_refcount;
149
        scc_driver.table = scc_table;
150
        scc_driver.termios = scc_termios;
151
        scc_driver.termios_locked = scc_termios_locked;
152
 
153
        scc_driver.open = scc_open;
154
        scc_driver.close = gs_close;
155
        scc_driver.write = gs_write;
156
        scc_driver.put_char = gs_put_char;
157
        scc_driver.flush_chars = gs_flush_chars;
158
        scc_driver.write_room = gs_write_room;
159
        scc_driver.chars_in_buffer = gs_chars_in_buffer;
160
        scc_driver.flush_buffer = gs_flush_buffer;
161
        scc_driver.ioctl = scc_ioctl;
162
        scc_driver.throttle = scc_throttle;
163
        scc_driver.unthrottle = scc_unthrottle;
164
        scc_driver.set_termios = gs_set_termios;
165
        scc_driver.stop = gs_stop;
166
        scc_driver.start = gs_start;
167
        scc_driver.hangup = gs_hangup;
168
        scc_driver.break_ctl = scc_break_ctl;
169
 
170
        scc_callout_driver = scc_driver;
171
#ifdef CONFIG_DEVFS_FS
172
        scc_callout_driver.name = "cua/%d";
173
#else
174
        scc_callout_driver.name = "cua";
175
#endif
176
        scc_callout_driver.major = TTYAUX_MAJOR;
177
        scc_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
178
 
179
        if ((error = tty_register_driver(&scc_driver))) {
180
                printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
181
                       error);
182
                return 1;
183
        }
184
        if ((error = tty_register_driver(&scc_callout_driver))) {
185
                tty_unregister_driver(&scc_driver);
186
                printk(KERN_ERR "scc: Couldn't register scc callout driver, error = %d\n",
187
                       error);
188
                return 1;
189
        }
190
 
191
        return 0;
192
}
193
 
194
 
195
/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
196
 */
197
 
198
static void scc_init_portstructs(void)
199
{
200
        struct scc_port *port;
201
        int i;
202
 
203
        for (i = 0; i < 2; i++) {
204
                port = scc_ports + i;
205
                port->gs.callout_termios = tty_std_termios;
206
                port->gs.normal_termios = tty_std_termios;
207
                port->gs.magic = SCC_MAGIC;
208
                port->gs.close_delay = HZ/2;
209
                port->gs.closing_wait = 30 * HZ;
210
                port->gs.rd = &scc_real_driver;
211
#ifdef NEW_WRITE_LOCKING
212
                port->gs.port_write_sem = MUTEX;
213
#endif
214
                init_waitqueue_head(&port->gs.open_wait);
215
                init_waitqueue_head(&port->gs.close_wait);
216
        }
217
}
218
 
219
 
220
#ifdef CONFIG_MVME147_SCC
221
static int mvme147_scc_init(void)
222
{
223
        struct scc_port *port;
224
 
225
        printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
226
        /* Init channel A */
227
        port = &scc_ports[0];
228
        port->channel = CHANNEL_A;
229
        port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
230
        port->datap = port->ctrlp + 1;
231
        port->port_a = &scc_ports[0];
232
        port->port_b = &scc_ports[1];
233
        request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
234
                            "SCC-A TX", port);
235
        request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
236
                            "SCC-A status", port);
237
        request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
238
                            "SCC-A RX", port);
239
        request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
240
                            "SCC-A special cond", port);
241
        {
242
                SCC_ACCESS_INIT(port);
243
 
244
                /* disable interrupts for this channel */
245
                SCCwrite(INT_AND_DMA_REG, 0);
246
                /* Set the interrupt vector */
247
                SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
248
                /* Interrupt parameters: vector includes status, status low */
249
                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
250
                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
251
        }
252
 
253
        /* Init channel B */
254
        port = &scc_ports[1];
255
        port->channel = CHANNEL_B;
256
        port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
257
        port->datap = port->ctrlp + 1;
258
        port->port_a = &scc_ports[0];
259
        port->port_b = &scc_ports[1];
260
        request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
261
                            "SCC-B TX", port);
262
        request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
263
                            "SCC-B status", port);
264
        request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
265
                            "SCC-B RX", port);
266
        request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
267
                            "SCC-B special cond", port);
268
        {
269
                SCC_ACCESS_INIT(port);
270
 
271
                /* disable interrupts for this channel */
272
                SCCwrite(INT_AND_DMA_REG, 0);
273
        }
274
 
275
        /* Ensure interrupts are enabled in the PCC chip */
276
        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
277
 
278
        /* Initialise the tty driver structures and register */
279
        scc_init_portstructs();
280
        scc_init_drivers();
281
 
282
        return 0;
283
}
284
#endif
285
 
286
 
287
#ifdef CONFIG_MVME162_SCC
288
static int mvme162_scc_init(void)
289
{
290
        struct scc_port *port;
291
 
292
        if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
293
                return (-ENODEV);
294
 
295
        printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
296
        /* Init channel A */
297
        port = &scc_ports[0];
298
        port->channel = CHANNEL_A;
299
        port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
300
        port->datap = port->ctrlp + 2;
301
        port->port_a = &scc_ports[0];
302
        port->port_b = &scc_ports[1];
303
        request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
304
                            "SCC-A TX", port);
305
        request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
306
                            "SCC-A status", port);
307
        request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
308
                            "SCC-A RX", port);
309
        request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
310
                            "SCC-A special cond", port);
311
        {
312
                SCC_ACCESS_INIT(port);
313
 
314
                /* disable interrupts for this channel */
315
                SCCwrite(INT_AND_DMA_REG, 0);
316
                /* Set the interrupt vector */
317
                SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
318
                /* Interrupt parameters: vector includes status, status low */
319
                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
320
                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
321
        }
322
 
323
        /* Init channel B */
324
        port = &scc_ports[1];
325
        port->channel = CHANNEL_B;
326
        port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
327
        port->datap = port->ctrlp + 2;
328
        port->port_a = &scc_ports[0];
329
        port->port_b = &scc_ports[1];
330
        request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
331
                            "SCC-B TX", port);
332
        request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
333
                            "SCC-B status", port);
334
        request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
335
                            "SCC-B RX", port);
336
        request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
337
                            "SCC-B special cond", port);
338
 
339
        {
340
                SCC_ACCESS_INIT(port);  /* Either channel will do */
341
 
342
                /* disable interrupts for this channel */
343
                SCCwrite(INT_AND_DMA_REG, 0);
344
        }
345
 
346
        /* Ensure interrupts are enabled in the MC2 chip */
347
        *(volatile char *)0xfff4201d = 0x14;
348
 
349
        /* Initialise the tty driver structures and register */
350
        scc_init_portstructs();
351
        scc_init_drivers();
352
 
353
        return 0;
354
}
355
#endif
356
 
357
 
358
#ifdef CONFIG_BVME6000_SCC
359
static int bvme6000_scc_init(void)
360
{
361
        struct scc_port *port;
362
 
363
        printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
364
        /* Init channel A */
365
        port = &scc_ports[0];
366
        port->channel = CHANNEL_A;
367
        port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
368
        port->datap = port->ctrlp + 4;
369
        port->port_a = &scc_ports[0];
370
        port->port_b = &scc_ports[1];
371
        request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
372
                            "SCC-A TX", port);
373
        request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
374
                            "SCC-A status", port);
375
        request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
376
                            "SCC-A RX", port);
377
        request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
378
                            "SCC-A special cond", port);
379
        {
380
                SCC_ACCESS_INIT(port);
381
 
382
                /* disable interrupts for this channel */
383
                SCCwrite(INT_AND_DMA_REG, 0);
384
                /* Set the interrupt vector */
385
                SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
386
                /* Interrupt parameters: vector includes status, status low */
387
                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
388
                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
389
        }
390
 
391
        /* Init channel B */
392
        port = &scc_ports[1];
393
        port->channel = CHANNEL_B;
394
        port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
395
        port->datap = port->ctrlp + 4;
396
        port->port_a = &scc_ports[0];
397
        port->port_b = &scc_ports[1];
398
        request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
399
                            "SCC-B TX", port);
400
        request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
401
                            "SCC-B status", port);
402
        request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
403
                            "SCC-B RX", port);
404
        request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
405
                            "SCC-B special cond", port);
406
 
407
        {
408
                SCC_ACCESS_INIT(port);  /* Either channel will do */
409
 
410
                /* disable interrupts for this channel */
411
                SCCwrite(INT_AND_DMA_REG, 0);
412
        }
413
 
414
        /* Initialise the tty driver structures and register */
415
        scc_init_portstructs();
416
        scc_init_drivers();
417
 
418
        return 0;
419
}
420
#endif
421
 
422
 
423
int vme_scc_init(void)
424
{
425
        int res = -ENODEV;
426
        static int called = 0;
427
 
428
        if (called)
429
                return res;
430
        called = 1;
431
#ifdef CONFIG_MVME147_SCC
432
        if (MACH_IS_MVME147)
433
                res = mvme147_scc_init();
434
#endif
435
#ifdef CONFIG_MVME162_SCC
436
        if (MACH_IS_MVME16x)
437
                res = mvme162_scc_init();
438
#endif
439
#ifdef CONFIG_BVME6000_SCC
440
        if (MACH_IS_BVME6000)
441
                res = bvme6000_scc_init();
442
#endif
443
        return res;
444
}
445
 
446
 
447
/*---------------------------------------------------------------------------
448
 * Interrupt handlers
449
 *--------------------------------------------------------------------------*/
450
 
451
static void scc_rx_int(int irq, void *data, struct pt_regs *fp)
452
{
453
        unsigned char   ch;
454
        struct scc_port *port = data;
455
        struct tty_struct *tty = port->gs.tty;
456
        SCC_ACCESS_INIT(port);
457
 
458
        ch = SCCread_NB(RX_DATA_REG);
459
        if (!tty) {
460
                printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
461
                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
462
                return;
463
        }
464
        if (tty->flip.count < TTY_FLIPBUF_SIZE) {
465
                *tty->flip.char_buf_ptr = ch;
466
                *tty->flip.flag_buf_ptr = 0;
467
                tty->flip.flag_buf_ptr++;
468
                tty->flip.char_buf_ptr++;
469
                tty->flip.count++;
470
        }
471
 
472
        /* Check if another character is already ready; in that case, the
473
         * spcond_int() function must be used, because this character may have an
474
         * error condition that isn't signalled by the interrupt vector used!
475
         */
476
        if (SCCread(INT_PENDING_REG) &
477
            (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
478
                scc_spcond_int (irq, data, fp);
479
                return;
480
        }
481
 
482
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
483
 
484
        tty_flip_buffer_push(tty);
485
}
486
 
487
 
488
static void scc_spcond_int(int irq, void *data, struct pt_regs *fp)
489
{
490
        struct scc_port *port = data;
491
        struct tty_struct *tty = port->gs.tty;
492
        unsigned char   stat, ch, err;
493
        int             int_pending_mask = port->channel == CHANNEL_A ?
494
                                           IPR_A_RX : IPR_B_RX;
495
        SCC_ACCESS_INIT(port);
496
 
497
        if (!tty) {
498
                printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
499
                SCCwrite(COMMAND_REG, CR_ERROR_RESET);
500
                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
501
                return;
502
        }
503
        do {
504
                stat = SCCread(SPCOND_STATUS_REG);
505
                ch = SCCread_NB(RX_DATA_REG);
506
 
507
                if (stat & SCSR_RX_OVERRUN)
508
                        err = TTY_OVERRUN;
509
                else if (stat & SCSR_PARITY_ERR)
510
                        err = TTY_PARITY;
511
                else if (stat & SCSR_CRC_FRAME_ERR)
512
                        err = TTY_FRAME;
513
                else
514
                        err = 0;
515
 
516
                if (tty->flip.count < TTY_FLIPBUF_SIZE) {
517
                        *tty->flip.char_buf_ptr = ch;
518
                        *tty->flip.flag_buf_ptr = err;
519
                        tty->flip.flag_buf_ptr++;
520
                        tty->flip.char_buf_ptr++;
521
                        tty->flip.count++;
522
                }
523
 
524
                /* ++TeSche: *All* errors have to be cleared manually,
525
                 * else the condition persists for the next chars
526
                 */
527
                if (err)
528
                  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
529
 
530
        } while(SCCread(INT_PENDING_REG) & int_pending_mask);
531
 
532
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
533
 
534
        tty_flip_buffer_push(tty);
535
}
536
 
537
 
538
static void scc_tx_int(int irq, void *data, struct pt_regs *fp)
539
{
540
        struct scc_port *port = data;
541
        SCC_ACCESS_INIT(port);
542
 
543
        if (!port->gs.tty) {
544
                printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
545
                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
546
                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
547
                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
548
                return;
549
        }
550
        while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
551
                if (port->x_char) {
552
                        SCCwrite(TX_DATA_REG, port->x_char);
553
                        port->x_char = 0;
554
                }
555
                else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
556
                                port->gs.tty->hw_stopped)
557
                        break;
558
                else {
559
                        SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
560
                        port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
561
                        if (--port->gs.xmit_cnt <= 0)
562
                                break;
563
                }
564
        }
565
        if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
566
                        port->gs.tty->hw_stopped) {
567
                /* disable tx interrupts */
568
                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
569
                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
570
                port->gs.flags &= ~GS_TX_INTEN;
571
        }
572
        if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
573
                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
574
                                port->gs.tty->ldisc.write_wakeup)
575
                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
576
                wake_up_interruptible(&port->gs.tty->write_wait);
577
        }
578
 
579
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
580
}
581
 
582
 
583
static void scc_stat_int(int irq, void *data, struct pt_regs *fp)
584
{
585
        struct scc_port *port = data;
586
        unsigned channel = port->channel;
587
        unsigned char   last_sr, sr, changed;
588
        SCC_ACCESS_INIT(port);
589
 
590
        last_sr = scc_last_status_reg[channel];
591
        sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
592
        changed = last_sr ^ sr;
593
 
594
        if (changed & SR_DCD) {
595
                port->c_dcd = !!(sr & SR_DCD);
596
                if (!(port->gs.flags & ASYNC_CHECK_CD))
597
                        ;       /* Don't report DCD changes */
598
                else if (port->c_dcd) {
599
                        if (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) ||
600
                                ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) {
601
                                /* Are we blocking in open?*/
602
                                wake_up_interruptible(&port->gs.open_wait);
603
                        }
604
                }
605
                else {
606
                        if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&
607
                                        (port->gs.flags & ASYNC_CALLOUT_NOHUP))) {
608
                                if (port->gs.tty)
609
                                        tty_hangup (port->gs.tty);
610
                        }
611
                }
612
        }
613
        SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
614
        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
615
}
616
 
617
 
618
/*---------------------------------------------------------------------------
619
 * generic_serial.c callback funtions
620
 *--------------------------------------------------------------------------*/
621
 
622
static void scc_disable_tx_interrupts(void *ptr)
623
{
624
        struct scc_port *port = ptr;
625
        unsigned long   flags;
626
        SCC_ACCESS_INIT(port);
627
 
628
        save_flags(flags);
629
        cli();
630
        SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
631
        port->gs.flags &= ~GS_TX_INTEN;
632
        restore_flags(flags);
633
}
634
 
635
 
636
static void scc_enable_tx_interrupts(void *ptr)
637
{
638
        struct scc_port *port = ptr;
639
        unsigned long   flags;
640
        SCC_ACCESS_INIT(port);
641
 
642
        save_flags(flags);
643
        cli();
644
        SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
645
        /* restart the transmitter */
646
        scc_tx_int (0, port, 0);
647
        restore_flags(flags);
648
}
649
 
650
 
651
static void scc_disable_rx_interrupts(void *ptr)
652
{
653
        struct scc_port *port = ptr;
654
        unsigned long   flags;
655
        SCC_ACCESS_INIT(port);
656
 
657
        save_flags(flags);
658
        cli();
659
        SCCmod(INT_AND_DMA_REG,
660
            ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
661
        restore_flags(flags);
662
}
663
 
664
 
665
static void scc_enable_rx_interrupts(void *ptr)
666
{
667
        struct scc_port *port = ptr;
668
        unsigned long   flags;
669
        SCC_ACCESS_INIT(port);
670
 
671
        save_flags(flags);
672
        cli();
673
        SCCmod(INT_AND_DMA_REG, 0xff,
674
                IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
675
        restore_flags(flags);
676
}
677
 
678
 
679
static int scc_get_CD(void *ptr)
680
{
681
        struct scc_port *port = ptr;
682
        unsigned channel = port->channel;
683
 
684
        return !!(scc_last_status_reg[channel] & SR_DCD);
685
}
686
 
687
 
688
static void scc_shutdown_port(void *ptr)
689
{
690
        struct scc_port *port = ptr;
691
 
692
        port->gs.flags &= ~ GS_ACTIVE;
693
        if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
694
                scc_setsignals (port, 0, 0);
695
        }
696
}
697
 
698
 
699
static int scc_set_real_termios (void *ptr)
700
{
701
        /* the SCC has char sizes 5,7,6,8 in that order! */
702
        static int chsize_map[4] = { 0, 2, 1, 3 };
703
        unsigned cflag, baud, chsize, channel, brgval = 0;
704
        unsigned long flags;
705
        struct scc_port *port = ptr;
706
        SCC_ACCESS_INIT(port);
707
 
708
        if (!port->gs.tty || !port->gs.tty->termios) return 0;
709
 
710
        channel = port->channel;
711
 
712
        if (channel == CHANNEL_A)
713
                return 0;                /* Settings controlled by boot PROM */
714
 
715
        cflag  = port->gs.tty->termios->c_cflag;
716
        baud = port->gs.baud;
717
        chsize = (cflag & CSIZE) >> 4;
718
 
719
        if (baud == 0) {
720
                /* speed == 0 -> drop DTR */
721
                save_flags(flags);
722
                cli();
723
                SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
724
                restore_flags(flags);
725
                return 0;
726
        }
727
        else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
728
                 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
729
                 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
730
                printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
731
                return 0;
732
        }
733
 
734
        if (cflag & CLOCAL)
735
                port->gs.flags &= ~ASYNC_CHECK_CD;
736
        else
737
                port->gs.flags |= ASYNC_CHECK_CD;
738
 
739
#ifdef CONFIG_MVME147_SCC
740
        if (MACH_IS_MVME147)
741
                brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
742
#endif
743
#ifdef CONFIG_MVME162_SCC
744
        if (MACH_IS_MVME16x)
745
                brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
746
#endif
747
#ifdef CONFIG_BVME6000_SCC
748
        if (MACH_IS_BVME6000)
749
                brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
750
#endif
751
        /* Now we have all parameters and can go to set them: */
752
        save_flags(flags);
753
        cli();
754
 
755
        /* receiver's character size and auto-enables */
756
        SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
757
                        (chsize_map[chsize] << 6) |
758
                        ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
759
        /* parity and stop bits (both, Tx and Rx), clock mode never changes */
760
        SCCmod (AUX1_CTRL_REG,
761
                ~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
762
                ((cflag & PARENB
763
                  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
764
                  : A1CR_PARITY_NONE)
765
                 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
766
        /* sender's character size, set DTR for valid baud rate */
767
        SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
768
        /* clock sources never change */
769
        /* disable BRG before changing the value */
770
        SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
771
        /* BRG value */
772
        SCCwrite(TIMER_LOW_REG, brgval & 0xff);
773
        SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
774
        /* BRG enable, and clock source never changes */
775
        SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
776
 
777
        restore_flags(flags);
778
 
779
        return 0;
780
}
781
 
782
 
783
static int scc_chars_in_buffer (void *ptr)
784
{
785
        struct scc_port *port = ptr;
786
        SCC_ACCESS_INIT(port);
787
 
788
        return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
789
}
790
 
791
 
792
/* Comment taken from sx.c (2.4.0):
793
   I haven't the foggiest why the decrement use count has to happen
794
   here. The whole linux serial drivers stuff needs to be redesigned.
795
   My guess is that this is a hack to minimize the impact of a bug
796
   elsewhere. Thinking about it some more. (try it sometime) Try
797
   running minicom on a serial port that is driven by a modularized
798
   driver. Have the modem hangup. Then remove the driver module. Then
799
   exit minicom.  I expect an "oops".  -- REW */
800
 
801
static void scc_hungup(void *ptr)
802
{
803
        scc_disable_tx_interrupts(ptr);
804
        scc_disable_rx_interrupts(ptr);
805
        MOD_DEC_USE_COUNT;
806
}
807
 
808
 
809
static void scc_close(void *ptr)
810
{
811
        scc_disable_tx_interrupts(ptr);
812
        scc_disable_rx_interrupts(ptr);
813
        MOD_DEC_USE_COUNT;
814
}
815
 
816
 
817
/*---------------------------------------------------------------------------
818
 * Internal support functions
819
 *--------------------------------------------------------------------------*/
820
 
821
static void scc_setsignals(struct scc_port *port, int dtr, int rts)
822
{
823
        unsigned long flags;
824
        unsigned char t;
825
        SCC_ACCESS_INIT(port);
826
 
827
        save_flags(flags);
828
        cli();
829
        t = SCCread(TX_CTRL_REG);
830
        if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
831
        if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
832
        SCCwrite(TX_CTRL_REG, t);
833
        restore_flags(flags);
834
}
835
 
836
 
837
static void scc_send_xchar(struct tty_struct *tty, char ch)
838
{
839
        struct scc_port *port = (struct scc_port *)tty->driver_data;
840
 
841
        port->x_char = ch;
842
        if (ch)
843
                scc_enable_tx_interrupts(port);
844
}
845
 
846
 
847
/*---------------------------------------------------------------------------
848
 * Driver entrypoints referenced from above
849
 *--------------------------------------------------------------------------*/
850
 
851
static int scc_open (struct tty_struct * tty, struct file * filp)
852
{
853
        int line = MINOR(tty->device) - SCC_MINOR_BASE;
854
        int retval;
855
        struct scc_port *port = &scc_ports[line];
856
        int i, channel = port->channel;
857
        unsigned long   flags;
858
        SCC_ACCESS_INIT(port);
859
#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
860
        static const struct {
861
                unsigned reg, val;
862
        } mvme_init_tab[] = {
863
                /* Values for MVME162 and MVME147 */
864
                /* no parity, 1 stop bit, async, 1:16 */
865
                { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
866
                /* parity error is special cond, ints disabled, no DMA */
867
                { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
868
                /* Rx 8 bits/char, no auto enable, Rx off */
869
                { RX_CTRL_REG, RCR_CHSIZE_8 },
870
                /* DTR off, Tx 8 bits/char, RTS off, Tx off */
871
                { TX_CTRL_REG, TCR_CHSIZE_8 },
872
                /* special features off */
873
                { AUX2_CTRL_REG, 0 },
874
                { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
875
                { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
876
                /* Start Rx */
877
                { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
878
                /* Start Tx */
879
                { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
880
                /* Ext/Stat ints: DCD only */
881
                { INT_CTRL_REG, ICR_ENAB_DCD_INT },
882
                /* Reset Ext/Stat ints */
883
                { COMMAND_REG, CR_EXTSTAT_RESET },
884
                /* ...again */
885
                { COMMAND_REG, CR_EXTSTAT_RESET },
886
        };
887
#endif
888
#if defined(CONFIG_BVME6000_SCC)
889
        static const struct {
890
                unsigned reg, val;
891
        } bvme_init_tab[] = {
892
                /* Values for BVME6000 */
893
                /* no parity, 1 stop bit, async, 1:16 */
894
                { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
895
                /* parity error is special cond, ints disabled, no DMA */
896
                { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
897
                /* Rx 8 bits/char, no auto enable, Rx off */
898
                { RX_CTRL_REG, RCR_CHSIZE_8 },
899
                /* DTR off, Tx 8 bits/char, RTS off, Tx off */
900
                { TX_CTRL_REG, TCR_CHSIZE_8 },
901
                /* special features off */
902
                { AUX2_CTRL_REG, 0 },
903
                { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
904
                { DPLL_CTRL_REG, DCR_BRG_ENAB },
905
                /* Start Rx */
906
                { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
907
                /* Start Tx */
908
                { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
909
                /* Ext/Stat ints: DCD only */
910
                { INT_CTRL_REG, ICR_ENAB_DCD_INT },
911
                /* Reset Ext/Stat ints */
912
                { COMMAND_REG, CR_EXTSTAT_RESET },
913
                /* ...again */
914
                { COMMAND_REG, CR_EXTSTAT_RESET },
915
        };
916
#endif
917
        if (!(port->gs.flags & ASYNC_INITIALIZED)) {
918
                save_flags(flags);
919
                cli();
920
#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
921
                if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
922
                        for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
923
                                SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
924
                }
925
#endif
926
#if defined(CONFIG_BVME6000_SCC)
927
                if (MACH_IS_BVME6000) {
928
                        for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)
929
                                SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
930
                }
931
#endif
932
 
933
                /* remember status register for detection of DCD and CTS changes */
934
                scc_last_status_reg[channel] = SCCread(STATUS_REG);
935
 
936
                port->c_dcd = 0; /* Prevent initial 1->0 interrupt */
937
                scc_setsignals (port, 1,1);
938
                restore_flags(flags);
939
        }
940
 
941
        tty->driver_data = port;
942
        port->gs.tty = tty;
943
        port->gs.count++;
944
        retval = gs_init_port(&port->gs);
945
        if (retval) {
946
                port->gs.count--;
947
                return retval;
948
        }
949
        port->gs.flags |= GS_ACTIVE;
950
        if (port->gs.count == 1) {
951
                MOD_INC_USE_COUNT;
952
        }
953
        retval = gs_block_til_ready(port, filp);
954
 
955
        if (retval) {
956
                MOD_DEC_USE_COUNT;
957
                port->gs.count--;
958
                return retval;
959
        }
960
 
961
        if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
962
                if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
963
                        *tty->termios = port->gs.normal_termios;
964
                else
965
                        *tty->termios = port->gs.callout_termios;
966
                scc_set_real_termios (port);
967
        }
968
 
969
        port->gs.session = current->session;
970
        port->gs.pgrp = current->pgrp;
971
        port->c_dcd = scc_get_CD (port);
972
 
973
        scc_enable_rx_interrupts(port);
974
 
975
        return 0;
976
}
977
 
978
 
979
static void scc_throttle (struct tty_struct * tty)
980
{
981
        struct scc_port *port = (struct scc_port *)tty->driver_data;
982
        unsigned long   flags;
983
        SCC_ACCESS_INIT(port);
984
 
985
        if (tty->termios->c_cflag & CRTSCTS) {
986
                save_flags(flags);
987
                cli();
988
                SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
989
                restore_flags(flags);
990
        }
991
        if (I_IXOFF(tty))
992
                scc_send_xchar(tty, STOP_CHAR(tty));
993
}
994
 
995
 
996
static void scc_unthrottle (struct tty_struct * tty)
997
{
998
        struct scc_port *port = (struct scc_port *)tty->driver_data;
999
        unsigned long   flags;
1000
        SCC_ACCESS_INIT(port);
1001
 
1002
        if (tty->termios->c_cflag & CRTSCTS) {
1003
                save_flags(flags);
1004
                cli();
1005
                SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
1006
                restore_flags(flags);
1007
        }
1008
        if (I_IXOFF(tty))
1009
                scc_send_xchar(tty, START_CHAR(tty));
1010
}
1011
 
1012
 
1013
static int scc_ioctl(struct tty_struct *tty, struct file *file,
1014
                     unsigned int cmd, unsigned long arg)
1015
{
1016
        return -ENOIOCTLCMD;
1017
}
1018
 
1019
 
1020
static void scc_break_ctl(struct tty_struct *tty, int break_state)
1021
{
1022
        struct scc_port *port = (struct scc_port *)tty->driver_data;
1023
        unsigned long   flags;
1024
        SCC_ACCESS_INIT(port);
1025
 
1026
        save_flags(flags);
1027
        cli();
1028
        SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
1029
                        break_state ? TCR_SEND_BREAK : 0);
1030
        restore_flags(flags);
1031
}
1032
 
1033
 
1034
/*---------------------------------------------------------------------------
1035
 * Serial console stuff...
1036
 *--------------------------------------------------------------------------*/
1037
 
1038
#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
1039
 
1040
static void scc_ch_write (char ch)
1041
{
1042
        volatile char *p = NULL;
1043
 
1044
#ifdef CONFIG_MVME147_SCC
1045
        if (MACH_IS_MVME147)
1046
                p = (volatile char *)M147_SCC_A_ADDR;
1047
#endif
1048
#ifdef CONFIG_MVME162_SCC
1049
        if (MACH_IS_MVME16x)
1050
                p = (volatile char *)MVME_SCC_A_ADDR;
1051
#endif
1052
#ifdef CONFIG_BVME6000_SCC
1053
        if (MACH_IS_BVME6000)
1054
                p = (volatile char *)BVME_SCC_A_ADDR;
1055
#endif
1056
 
1057
        do {
1058
                scc_delay();
1059
        }
1060
        while (!(*p & 4));
1061
        scc_delay();
1062
        *p = 8;
1063
        scc_delay();
1064
        *p = ch;
1065
}
1066
 
1067
/* The console must be locked when we get here. */
1068
 
1069
static void scc_console_write (struct console *co, const char *str, unsigned count)
1070
{
1071
        unsigned long   flags;
1072
 
1073
        save_flags(flags);
1074
        cli();
1075
 
1076
        while (count--)
1077
        {
1078
                if (*str == '\n')
1079
                        scc_ch_write ('\r');
1080
                scc_ch_write (*str++);
1081
        }
1082
        restore_flags(flags);
1083
}
1084
 
1085
static kdev_t scc_console_device(struct console *c)
1086
{
1087
        return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index);
1088
}
1089
 
1090
 
1091
static int __init scc_console_setup(struct console *co, char *options)
1092
{
1093
        return 0;
1094
}
1095
 
1096
 
1097
static struct console sercons = {
1098
        name:           "ttyS",
1099
        write:          scc_console_write,
1100
        device:         scc_console_device,
1101
        setup:          scc_console_setup,
1102
        flags:          CON_PRINTBUFFER,
1103
        index:          -1,
1104
};
1105
 
1106
 
1107
void __init vme_scc_console_init(void)
1108
{
1109
        if (vme_brdtype == VME_TYPE_MVME147 ||
1110
                        vme_brdtype == VME_TYPE_MVME162 ||
1111
                        vme_brdtype == VME_TYPE_MVME172 ||
1112
                        vme_brdtype == VME_TYPE_BVME4000 ||
1113
                        vme_brdtype == VME_TYPE_BVME6000)
1114
                register_console(&sercons);
1115
}
1116
 

powered by: WebSVN 2.1.0

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