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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [mcfserial.c] - Blame information for rev 199

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

Line No. Rev Author Line
1 199 simons
/*
2
 * mcfserial.c -- serial driver for ColdFire internal UARTS.
3
 *
4
 * Copyright (C) 1999 Greg Ungerer (gerg@moreton.com.au)
5
 *
6
 * Based on code from 68332serial.c which was:
7
 *
8
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
9
 * Copyright (C) 1998 TSHG
10
 */
11
 
12
#include <linux/errno.h>
13
#include <linux/signal.h>
14
#include <linux/sched.h>
15
#include <linux/timer.h>
16
#include <linux/interrupt.h>
17
#include <linux/tty.h>
18
#include <linux/tty_flip.h>
19
#include <linux/config.h>
20
#include <linux/major.h>
21
#include <linux/string.h>
22
#include <linux/fcntl.h>
23
#include <linux/mm.h>
24
#include <linux/kernel.h>
25
 
26
#include <asm/io.h>
27
#include <asm/irq.h>
28
#include <asm/system.h>
29
#include <asm/segment.h>
30
#include <asm/bitops.h>
31
#include <asm/delay.h>
32
#include <asm/coldfire.h>
33
#include <asm/mcfsim.h>
34
#include <asm/mcfuart.h>
35
#include <asm/nettel.h>
36
#include "mcfserial.h"
37
 
38
 
39
/*
40
 *      Default console port and baud rate...
41
 */
42
#ifndef CONSOLE_PORT
43
#define CONSOLE_PORT            0
44
#endif
45
#ifndef CONSOLE_BAUD_RATE
46
#define CONSOLE_BAUD_RATE       9600
47
#endif
48
 
49
int mcfrs_console_inited = 0;
50
int mcfrs_console_port = CONSOLE_PORT;
51
int mcfrs_console_baud = CONSOLE_BAUD_RATE;
52
 
53
 
54
DECLARE_TASK_QUEUE(mcf_tq_serial);
55
 
56
/*
57
 *      Driver data structures.
58
 */
59
struct tty_driver       mcfrs_serial_driver, mcfrs_callout_driver;
60
static int              mcfrs_serial_refcount;
61
 
62
/* serial subtype definitions */
63
#define SERIAL_TYPE_NORMAL      1
64
#define SERIAL_TYPE_CALLOUT     2
65
 
66
/* number of characters left in xmit buffer before we ask for more */
67
#define WAKEUP_CHARS 256
68
 
69
/* Debugging...
70
 */
71
#undef SERIAL_DEBUG_OPEN
72
#undef SERIAL_DEBUG_FLOW
73
 
74
#define _INLINE_ inline
75
 
76
#define IRQBASE 224
77
 
78
/*
79
 *      Configuration table, UARTs to look for at startup.
80
 */
81
static struct mcf_serial mcfrs_table[] = {
82
  { 0, (MCF_MBAR+MCFUART_BASE1), IRQBASE,   ASYNC_BOOT_AUTOCONF },  /* ttyS0 */
83
  { 0, (MCF_MBAR+MCFUART_BASE2), IRQBASE+1, ASYNC_BOOT_AUTOCONF },  /* ttyS1 */
84
};
85
 
86
 
87
#define NR_PORTS        (sizeof(mcfrs_table) / sizeof(struct mcf_serial))
88
 
89
static struct tty_struct        *mcfrs_serial_table[NR_PORTS];
90
static struct termios           *mcfrs_serial_termios[NR_PORTS];
91
static struct termios           *mcfrs_serial_termios_locked[NR_PORTS];
92
 
93
/*
94
 * This is used to figure out the divisor speeds and the timeouts.
95
 */
96
static int mcfrs_baud_table[] = {
97
        0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
98
        9600, 19200, 38400, 57600, 115200, 230400, 460800, 0
99
};
100
 
101
 
102
#ifndef MIN
103
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
104
#endif
105
 
106
#ifdef CONFIG_MAGIC_SYSRQ
107
/*
108
 *      Magic system request keys. Used for debugging...
109
 */
110
extern int      magic_sysrq_key(int ch);
111
#endif
112
 
113
 
114
/*
115
 * tmp_buf is used as a temporary buffer by serial_write.  We need to
116
 * lock it in case the memcpy_fromfs blocks while swapping in a page,
117
 * and some other program tries to do a serial write at the same time.
118
 * Since the lock will only come under contention when the system is
119
 * swapping and available memory is low, it makes sense to share one
120
 * buffer across all the serial ports, since it significantly saves
121
 * memory if large numbers of serial ports are open.
122
 */
123
static unsigned char mcfrs_tmp_buf[4096]; /* This is cheating */
124
static struct semaphore mcfrs_tmp_buf_sem = MUTEX;
125
 
126
/*
127
 *      Forware declarations...
128
 */
129
static void     mcfrs_change_speed(struct mcf_serial *info);
130
 
131
 
132
static inline int serial_paranoia_check(struct mcf_serial *info,
133
                                        dev_t device, const char *routine)
134
{
135
#ifdef SERIAL_PARANOIA_CHECK
136
        static const char *badmagic =
137
                "Warning: bad magic number for serial struct (%d, %d) in %s\n";
138
        static const char *badinfo =
139
                "Warning: null mcf_serial for (%d, %d) in %s\n";
140
 
141
        if (!info) {
142
                printk(badinfo, MAJOR(device), MINOR(device), routine);
143
                return 1;
144
        }
145
        if (info->magic != SERIAL_MAGIC) {
146
                printk(badmagic, MAJOR(device), MINOR(device), routine);
147
                return 1;
148
        }
149
#endif
150
        return 0;
151
}
152
 
153
/*
154
 *      Sets or clears DTR and RTS on the requested line.
155
 */
156
static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts)
157
{
158
        volatile unsigned char  *uartp;
159
        unsigned long           flags;
160
 
161
#if 0
162
        printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n",
163
                __FILE__, __LINE__, info, dtr, rts);
164
#endif
165
 
166
        save_flags(flags); cli();
167
        if (dtr >= 0) {
168
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
169
                if (dtr) {
170
                        info->sigs |= TIOCM_DTR;
171
                        ppdata &= ~(info->line ? NETtel_DTR1 : NETtel_DTR0);
172
                } else {
173
                        info->sigs &= ~TIOCM_DTR;
174
                        ppdata |= (info->line ? NETtel_DTR1 : NETtel_DTR0);
175
                }
176
                *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADAT)) = ppdata;
177
#endif
178
        }
179
        if (rts >= 0) {
180
                uartp = (volatile unsigned char *) info->addr;
181
                if (rts) {
182
                        info->sigs |= TIOCM_RTS;
183
                        uartp[MCFUART_UOP1] = MCFUART_UOP_RTS;
184
                } else {
185
                        info->sigs &= ~TIOCM_RTS;
186
                        uartp[MCFUART_UOP0] = MCFUART_UOP_RTS;
187
                }
188
        }
189
        restore_flags(flags);
190
        return;
191
}
192
 
193
/*
194
 *      Gets values of serial signals.
195
 */
196
static int mcfrs_getsignals(struct mcf_serial *info)
197
{
198
        volatile unsigned char  *uartp;
199
        unsigned long           flags;
200
        int                     sigs;
201
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
202
        unsigned short          ppdata;
203
#endif
204
 
205
#if 0
206
        printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__);
207
#endif
208
 
209
        save_flags(flags); cli();
210
        uartp = (volatile unsigned char *) info->addr;
211
        sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS;
212
        sigs |= (info->sigs & TIOCM_RTS);
213
 
214
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
215
        ppdata = *((volatile unsigned short *) (MCF_MBAR+MCFSIM_PADAT));
216
        if (info->line == 0) {
217
                sigs |= (ppdata & NETtel_DCD0) ? 0 : TIOCM_CD;
218
                sigs |= (ppdata & NETtel_DTR0) ? 0 : TIOCM_DTR;
219
        } else if (info->line == 1) {
220
                sigs |= (ppdata & NETtel_DCD1) ? 0 : TIOCM_CD;
221
                sigs |= (ppdata & NETtel_DTR1) ? 0 : TIOCM_DTR;
222
        }
223
#endif
224
 
225
        restore_flags(flags);
226
        return(sigs);
227
}
228
 
229
/*
230
 * ------------------------------------------------------------
231
 * mcfrs_stop() and mcfrs_start()
232
 *
233
 * This routines are called before setting or resetting tty->stopped.
234
 * They enable or disable transmitter interrupts, as necessary.
235
 * ------------------------------------------------------------
236
 */
237
static void mcfrs_stop(struct tty_struct *tty)
238
{
239
        volatile unsigned char  *uartp;
240
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
241
        unsigned long           flags;
242
 
243
        if (serial_paranoia_check(info, tty->device, "mcfrs_stop"))
244
                return;
245
 
246
        save_flags(flags); cli();
247
        uartp = (volatile unsigned char *) info->addr;
248
        info->imr &= ~MCFUART_UIR_TXREADY;
249
        uartp[MCFUART_UIMR] = info->imr;
250
        restore_flags(flags);
251
}
252
 
253
static void mcfrs_start(struct tty_struct *tty)
254
{
255
        volatile unsigned char  *uartp;
256
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
257
        unsigned long           flags;
258
 
259
        if (serial_paranoia_check(info, tty->device, "mcfrs_start"))
260
                return;
261
 
262
        save_flags(flags); cli();
263
        if (info->xmit_cnt && info->xmit_buf) {
264
                uartp = (volatile unsigned char *) info->addr;
265
                info->imr |= MCFUART_UIR_TXREADY;
266
                uartp[MCFUART_UIMR] = info->imr;
267
        }
268
        restore_flags(flags);
269
}
270
 
271
/*
272
 * ----------------------------------------------------------------------
273
 *
274
 * Here starts the interrupt handling routines.  All of the following
275
 * subroutines are declared as inline and are folded into
276
 * mcfrs_interrupt().  They were separated out for readability's sake.
277
 *
278
 * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it
279
 * runs with interrupts turned off.  People who may want to modify
280
 * mcfrs_interrupt() should try to keep the interrupt handler as fast as
281
 * possible.  After you are done making modifications, it is not a bad
282
 * idea to do:
283
 *
284
 * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
285
 *
286
 * and look at the resulting assemble code in serial.s.
287
 *
288
 *                              - Ted Ts'o (tytso@mit.edu), 7-Mar-93
289
 * -----------------------------------------------------------------------
290
 */
291
 
292
/*
293
 * This routine is used by the interrupt handler to schedule
294
 * processing in the software interrupt portion of the driver.
295
 */
296
static _INLINE_ void mcfrs_sched_event(struct mcf_serial *info, int event)
297
{
298
        info->event |= 1 << event;
299
        queue_task_irq_off(&info->tqueue, &mcf_tq_serial);
300
        mark_bh(SERIAL_BH);
301
}
302
 
303
static _INLINE_ void receive_chars(struct mcf_serial *info, struct pt_regs *regs, unsigned short rx)
304
{
305
        volatile unsigned char  *uartp;
306
        struct tty_struct       *tty = info->tty;
307
        unsigned char           status, ch;
308
 
309
        if (!tty)
310
                return;
311
 
312
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
313
        setled(info->line ? NETtel_LEDRX2 : NETtel_LEDRX1);
314
#endif
315
 
316
        uartp = (volatile unsigned char *) info->addr;
317
 
318
        while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) {
319
 
320
                if (tty->flip.count >= TTY_FLIPBUF_SIZE)
321
                        break;
322
 
323
                ch = uartp[MCFUART_URB];
324
                info->stats.rx++;
325
 
326
#ifdef CONFIG_MAGIC_SYSRQ
327
                if (mcfrs_console_inited && (info->line == mcfrs_console_port)) {
328
                        if (magic_sysrq_key(ch))
329
                                continue;
330
                }
331
#endif
332
 
333
                tty->flip.count++;
334
                if (status & MCFUART_USR_RXERR)
335
                        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
336
                if (status & MCFUART_USR_RXBREAK) {
337
                        info->stats.rxbreak++;
338
                        *tty->flip.flag_buf_ptr++ = TTY_BREAK;
339
                } else if (status & MCFUART_USR_RXPARITY) {
340
                        info->stats.rxparity++;
341
                        *tty->flip.flag_buf_ptr++ = TTY_PARITY;
342
                } else if (status & MCFUART_USR_RXOVERRUN) {
343
                        info->stats.rxoverrun++;
344
                        *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
345
                } else if (status & MCFUART_USR_RXFRAMING) {
346
                        info->stats.rxframing++;
347
                        *tty->flip.flag_buf_ptr++ = TTY_FRAME;
348
                } else {
349
                        *tty->flip.flag_buf_ptr++ = 0;
350
                }
351
                *tty->flip.char_buf_ptr++ = ch;
352
        }
353
 
354
        queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
355
        return;
356
}
357
 
358
static _INLINE_ void transmit_chars(struct mcf_serial *info)
359
{
360
        volatile unsigned char  *uartp;
361
 
362
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
363
        setled(info->line ? NETtel_LEDTX2 : NETtel_LEDTX1);
364
#endif
365
        uartp = (volatile unsigned char *) info->addr;
366
 
367
        if (info->x_char) {
368
                /* Send special char - probably flow control */
369
                uartp[MCFUART_UTB] = info->x_char;
370
#if 0
371
                printk("%s(%d): sending flow=%x\n", __FILE__, __LINE__, info->x_char);
372
#endif
373
                info->x_char = 0;
374
                info->stats.tx++;
375
        }
376
 
377
        if ((info->xmit_cnt <= 0) || info->tty->stopped) {
378
                info->imr &= ~MCFUART_UIR_TXREADY;
379
                uartp[MCFUART_UIMR] = info->imr;
380
                return;
381
        }
382
 
383
        while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) {
384
                uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++];
385
                info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
386
                info->stats.tx++;
387
                if (--info->xmit_cnt <= 0)
388
                        break;
389
        }
390
 
391
        if (info->xmit_cnt < WAKEUP_CHARS)
392
                mcfrs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
393
        return;
394
}
395
 
396
/*
397
 * This is the serial driver's generic interrupt routine
398
 */
399
void mcfrs_interrupt(int irq, void *dev_id, struct pt_regs *regs)
400
{
401
        struct mcf_serial       *info;
402
        unsigned char           isr;
403
 
404
        info = &mcfrs_table[(irq - IRQBASE)];
405
        isr = (((volatile unsigned char *)info->addr)[MCFUART_UISR]) & info->imr;
406
 
407
        if (isr & MCFUART_UIR_RXREADY)
408
                receive_chars(info, regs, isr);
409
        if (isr & MCFUART_UIR_TXREADY)
410
                transmit_chars(info);
411
#if 0
412
        if (isr & MCFUART_UIR_DELTABREAK) {
413
                printk("%s(%d): delta break!\n", __FILE__, __LINE__);
414
                receive_chars(info, regs, isr);
415
        }
416
#endif
417
 
418
        return;
419
}
420
 
421
/*
422
 * -------------------------------------------------------------------
423
 * Here ends the serial interrupt routines.
424
 * -------------------------------------------------------------------
425
 */
426
 
427
/*
428
 * This routine is used to handle the "bottom half" processing for the
429
 * serial driver, known also the "software interrupt" processing.
430
 * This processing is done at the kernel interrupt level, after the
431
 * mcfrs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
432
 * is where time-consuming activities which can not be done in the
433
 * interrupt driver proper are done; the interrupt driver schedules
434
 * them using mcfrs_sched_event(), and they get done here.
435
 */
436
static void do_serial_bh(void)
437
{
438
        run_task_queue(&mcf_tq_serial);
439
}
440
 
441
static void do_softint(void *private_)
442
{
443
        struct mcf_serial       *info = (struct mcf_serial *) private_;
444
        struct tty_struct       *tty;
445
 
446
        tty = info->tty;
447
        if (!tty)
448
                return;
449
 
450
        if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
451
                if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
452
                    tty->ldisc.write_wakeup)
453
                        (tty->ldisc.write_wakeup)(tty);
454
                wake_up_interruptible(&tty->write_wait);
455
        }
456
}
457
 
458
 
459
/*
460
 *      Change of state on a DCD line.
461
 */
462
void mcfrs_modem_change(struct mcf_serial *info, int dcd)
463
{
464
        if (info->count == 0)
465
                return;
466
 
467
        if (info->flags & ASYNC_CHECK_CD) {
468
                if (dcd) {
469
                        wake_up_interruptible(&info->open_wait);
470
                } else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
471
                    (info->flags & ASYNC_CALLOUT_NOHUP))) {
472
                        queue_task_irq_off(&info->tqueue_hangup, &tq_scheduler);
473
                }
474
        }
475
}
476
 
477
 
478
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
479
 
480
unsigned short  mcfrs_ppstatus;
481
 
482
/*
483
 * This subroutine is called when the RS_TIMER goes off. It is used
484
 * to monitor the state of the DCD lines - since they have no edge
485
 * sensors and interrupt generators.
486
 */
487
static void mcfrs_timer(void)
488
{
489
        unsigned short  ppstatus, dcdval;
490
        int             i;
491
 
492
        ppstatus = *((volatile unsigned short *) (MCF_MBAR + MCFSIM_PADAT)) &
493
                (NETtel_DCD0 | NETtel_DCD1);
494
 
495
        if (ppstatus != mcfrs_ppstatus) {
496
                for (i = 0; (i < 2); i++) {
497
                        dcdval = (i ? NETtel_DCD1 : NETtel_DCD0);
498
                        if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) {
499
                                mcfrs_modem_change(&mcfrs_table[i],
500
                                        ((ppstatus & dcdval) ? 0 : 1));
501
                        }
502
                }
503
        }
504
        mcfrs_ppstatus = ppstatus;
505
 
506
        /* Re-arm timer */
507
        timer_table[RS_TIMER].expires = jiffies + HZ/25;
508
        timer_active |= 1 << RS_TIMER;
509
 
510
        /* Re-set the serial activity LEDs */
511
        unsetled((NETtel_LEDRX1|NETtel_LEDRX2|NETtel_LEDTX1|NETtel_LEDTX2));
512
}
513
 
514
#endif  /* CONFIG_NETtel */
515
 
516
 
517
/*
518
 * This routine is called from the scheduler tqueue when the interrupt
519
 * routine has signalled that a hangup has occurred.  The path of
520
 * hangup processing is:
521
 *
522
 *      serial interrupt routine -> (scheduler tqueue) ->
523
 *      do_serial_hangup() -> tty->hangup() -> mcfrs_hangup()
524
 *
525
 */
526
static void do_serial_hangup(void *private_)
527
{
528
        struct mcf_serial       *info = (struct mcf_serial *) private_;
529
        struct tty_struct       *tty;
530
 
531
        tty = info->tty;
532
        if (!tty)
533
                return;
534
 
535
        tty_hangup(tty);
536
}
537
 
538
static int startup(struct mcf_serial * info)
539
{
540
        volatile unsigned char  *uartp;
541
        unsigned long           flags;
542
 
543
        if (info->flags & ASYNC_INITIALIZED)
544
                return 0;
545
 
546
        if (!info->xmit_buf) {
547
                info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
548
                if (!info->xmit_buf)
549
                        return -ENOMEM;
550
        }
551
 
552
        save_flags(flags); cli();
553
 
554
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
555
        /*
556
         * Set up poll timer. It is used to check DCD status.
557
         */
558
        if ((timer_active & (1 << RS_TIMER)) == 0) {
559
                timer_table[RS_TIMER].expires = jiffies + HZ/25;
560
                timer_active |= 1 << RS_TIMER;
561
        }
562
#endif
563
 
564
#ifdef SERIAL_DEBUG_OPEN
565
        printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
566
#endif
567
 
568
        /*
569
         *      Reset UART, get it into known state...
570
         */
571
        uartp = (volatile unsigned char *) info->addr;
572
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
573
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
574
        mcfrs_setsignals(info, 1, 1);
575
 
576
        if (info->tty)
577
                clear_bit(TTY_IO_ERROR, &info->tty->flags);
578
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
579
 
580
        /*
581
         * and set the speed of the serial port
582
         */
583
        mcfrs_change_speed(info);
584
 
585
        /*
586
         * Lastly enable the UART transmitter and receiver, and
587
         * interrupt enables.
588
         */
589
        info->imr = MCFUART_UIR_RXREADY;
590
        uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
591
        uartp[MCFUART_UIMR] = info->imr;
592
 
593
        info->flags |= ASYNC_INITIALIZED;
594
        restore_flags(flags);
595
        return 0;
596
}
597
 
598
/*
599
 * This routine will shutdown a serial port; interrupts are disabled, and
600
 * DTR is dropped if the hangup on close termio flag is on.
601
 */
602
static void shutdown(struct mcf_serial * info)
603
{
604
        volatile unsigned char  *uartp;
605
        unsigned long           flags;
606
 
607
        if (!(info->flags & ASYNC_INITIALIZED))
608
                return;
609
 
610
#ifdef SERIAL_DEBUG_OPEN
611
        printk("Shutting down serial port %d (irq %d)....\n", info->line,
612
               info->irq);
613
#endif
614
 
615
        save_flags(flags); cli(); /* Disable interrupts */
616
 
617
        uartp = (volatile unsigned char *) info->addr;
618
        uartp[MCFUART_UIMR] = 0;  /* mask all interrupts */
619
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
620
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
621
 
622
        if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
623
                mcfrs_setsignals(info, 0, 0);
624
 
625
        if (info->xmit_buf) {
626
                free_page((unsigned long) info->xmit_buf);
627
                info->xmit_buf = 0;
628
        }
629
 
630
        if (info->tty)
631
                set_bit(TTY_IO_ERROR, &info->tty->flags);
632
 
633
        info->flags &= ~ASYNC_INITIALIZED;
634
        restore_flags(flags);
635
}
636
 
637
 
638
/*
639
 * This routine is called to set the UART divisor registers to match
640
 * the specified baud rate for a serial port.
641
 */
642
static void mcfrs_change_speed(struct mcf_serial *info)
643
{
644
        volatile unsigned char  *uartp;
645
        unsigned int            baudclk, cflag;
646
        unsigned long           flags;
647
        unsigned char           mr1, mr2;
648
        int                     i;
649
 
650
        if (!info->tty || !info->tty->termios)
651
                return;
652
        cflag = info->tty->termios->c_cflag;
653
        if (info->addr == 0)
654
                return;
655
 
656
#if 0
657
        printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__);
658
#endif
659
 
660
        i = cflag & CBAUD;
661
        if (i & CBAUDEX) {
662
                i &= ~CBAUDEX;
663
                if (i < 1 || i > 4)
664
                        info->tty->termios->c_cflag &= ~CBAUDEX;
665
                else
666
                        i += 15;
667
        }
668
        if (i == 0) {
669
                mcfrs_setsignals(info, 0, -1);
670
                return;
671
        }
672
        baudclk = ((MCF_CLK / 32) / mcfrs_baud_table[i]);
673
        info->baud = mcfrs_baud_table[i];
674
 
675
        mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR;
676
        mr2 = 0;
677
 
678
        switch (cflag & CSIZE) {
679
        case CS5:       mr1 |= MCFUART_MR1_CS5; break;
680
        case CS6:       mr1 |= MCFUART_MR1_CS6; break;
681
        case CS7:       mr1 |= MCFUART_MR1_CS7; break;
682
        case CS8:
683
        default:        mr1 |= MCFUART_MR1_CS8; break;
684
        }
685
 
686
        if (cflag & PARENB) {
687
                if (cflag & PARODD)
688
                        mr1 |= MCFUART_MR1_PARITYODD;
689
                else
690
                        mr1 |= MCFUART_MR1_PARITYEVEN;
691
        } else {
692
                mr1 |= MCFUART_MR1_PARITYNONE;
693
        }
694
 
695
        if (cflag & CSTOPB)
696
                mr2 |= MCFUART_MR2_STOP2;
697
        else
698
                mr2 |= MCFUART_MR2_STOP1;
699
 
700
        if (cflag & CRTSCTS) {
701
                mr1 |= MCFUART_MR1_RXRTS;
702
                mr2 |= MCFUART_MR2_TXCTS;
703
        }
704
 
705
        if (cflag & CLOCAL)
706
                info->flags &= ~ASYNC_CHECK_CD;
707
        else
708
                info->flags |= ASYNC_CHECK_CD;
709
 
710
        uartp = (volatile unsigned char *) info->addr;
711
 
712
        save_flags(flags); cli();
713
#if 0
714
        printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__,
715
                mr1, mr2, baudclk);
716
#endif
717
        /*
718
          Note: pg 12-16 of MCF5206e User's Manual states that a
719
          software reset should be performed prior to changing
720
          UMR1,2, UCSR, UACR, bit 7
721
        */
722
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;    /* reset RX */
723
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;    /* reset TX */
724
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
725
        uartp[MCFUART_UMR] = mr1;
726
        uartp[MCFUART_UMR] = mr2;
727
        uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8;  /* set msb byte */
728
        uartp[MCFUART_UBG2] = (baudclk & 0xff);         /* set lsb byte */
729
        uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
730
        uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
731
        mcfrs_setsignals(info, 1, -1);
732
        restore_flags(flags);
733
        return;
734
}
735
 
736
static void mcfrs_flush_chars(struct tty_struct *tty)
737
{
738
        volatile unsigned char  *uartp;
739
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
740
        unsigned long           flags;
741
 
742
        if (serial_paranoia_check(info, tty->device, "mcfrs_flush_chars"))
743
                return;
744
 
745
        if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
746
            !info->xmit_buf)
747
                return;
748
 
749
        /* Enable transmitter */
750
        save_flags(flags); cli();
751
        uartp = (volatile unsigned char *) info->addr;
752
        info->imr |= MCFUART_UIR_TXREADY;
753
        uartp[MCFUART_UIMR] = info->imr;
754
        restore_flags(flags);
755
}
756
 
757
static int mcfrs_write(struct tty_struct * tty, int from_user,
758
                    const unsigned char *buf, int count)
759
{
760
        volatile unsigned char  *uartp;
761
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
762
        unsigned long           flags;
763
        int                     c, total = 0;
764
 
765
#if 0
766
        printk("%s(%d): mcfrs_write(tty=%x,from_user=%d,buf=%x,count=%d)\n",
767
                __FILE__, __LINE__, tty, from_user, buf, count);
768
#endif
769
 
770
        if (serial_paranoia_check(info, tty->device, "mcfrs_write"))
771
                return 0;
772
 
773
        if (!tty || !info->xmit_buf)
774
                return 0;
775
 
776
        save_flags(flags);
777
        while (1) {
778
                cli();
779
                c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
780
                                   SERIAL_XMIT_SIZE - info->xmit_head));
781
 
782
                if (c <= 0) {
783
                        restore_flags(flags);
784
                        break;
785
                }
786
 
787
                if (from_user) {
788
                        down(&mcfrs_tmp_buf_sem);
789
                        memcpy_fromfs(mcfrs_tmp_buf, buf, c);
790
                        restore_flags(flags);
791
                        cli();
792
                        c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
793
                                       SERIAL_XMIT_SIZE - info->xmit_head));
794
                        memcpy(info->xmit_buf + info->xmit_head, mcfrs_tmp_buf, c);
795
                        up(&mcfrs_tmp_buf_sem);
796
                } else
797
                        memcpy(info->xmit_buf + info->xmit_head, buf, c);
798
 
799
                info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
800
                info->xmit_cnt += c;
801
                restore_flags(flags);
802
 
803
                buf += c;
804
                count -= c;
805
                total += c;
806
        }
807
 
808
        cli();
809
        uartp = (volatile unsigned char *) info->addr;
810
        info->imr |= MCFUART_UIR_TXREADY;
811
        uartp[MCFUART_UIMR] = info->imr;
812
        restore_flags(flags);
813
 
814
        return total;
815
}
816
 
817
static int mcfrs_write_room(struct tty_struct *tty)
818
{
819
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
820
        int     ret;
821
 
822
        if (serial_paranoia_check(info, tty->device, "mcfrs_write_room"))
823
                return 0;
824
        ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
825
        if (ret < 0)
826
                ret = 0;
827
        return ret;
828
}
829
 
830
static int mcfrs_chars_in_buffer(struct tty_struct *tty)
831
{
832
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
833
 
834
        if (serial_paranoia_check(info, tty->device, "mcfrs_chars_in_buffer"))
835
                return 0;
836
        return info->xmit_cnt;
837
}
838
 
839
static void mcfrs_flush_buffer(struct tty_struct *tty)
840
{
841
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
842
        unsigned long           flags;
843
 
844
        if (serial_paranoia_check(info, tty->device, "mcfrs_flush_buffer"))
845
                return;
846
 
847
        save_flags(flags); cli();
848
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
849
        restore_flags(flags);
850
 
851
        wake_up_interruptible(&tty->write_wait);
852
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
853
            tty->ldisc.write_wakeup)
854
                (tty->ldisc.write_wakeup)(tty);
855
}
856
 
857
/*
858
 * ------------------------------------------------------------
859
 * mcfrs_throttle()
860
 *
861
 * This routine is called by the upper-layer tty layer to signal that
862
 * incoming characters should be throttled.
863
 * ------------------------------------------------------------
864
 */
865
static void mcfrs_throttle(struct tty_struct * tty)
866
{
867
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
868
#ifdef SERIAL_DEBUG_THROTTLE
869
        char    buf[64];
870
 
871
        printk("throttle %s: %d....\n", _tty_name(tty, buf),
872
               tty->ldisc.chars_in_buffer(tty));
873
#endif
874
 
875
        if (serial_paranoia_check(info, tty->device, "mcfrs_throttle"))
876
                return;
877
 
878
        if (I_IXOFF(tty))
879
                info->x_char = STOP_CHAR(tty);
880
 
881
        /* Turn off RTS line (do this atomic) */
882
}
883
 
884
static void mcfrs_unthrottle(struct tty_struct * tty)
885
{
886
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
887
#ifdef SERIAL_DEBUG_THROTTLE
888
        char    buf[64];
889
 
890
        printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
891
               tty->ldisc.chars_in_buffer(tty));
892
#endif
893
 
894
        if (serial_paranoia_check(info, tty->device, "mcfrs_unthrottle"))
895
                return;
896
 
897
        if (I_IXOFF(tty)) {
898
                if (info->x_char)
899
                        info->x_char = 0;
900
                else
901
                        info->x_char = START_CHAR(tty);
902
        }
903
 
904
        /* Assert RTS line (do this atomic) */
905
}
906
 
907
/*
908
 * ------------------------------------------------------------
909
 * mcfrs_ioctl() and friends
910
 * ------------------------------------------------------------
911
 */
912
 
913
static int get_serial_info(struct mcf_serial * info,
914
                           struct serial_struct * retinfo)
915
{
916
        struct serial_struct tmp;
917
 
918
        if (!retinfo)
919
                return -EFAULT;
920
        memset(&tmp, 0, sizeof(tmp));
921
        tmp.type = info->type;
922
        tmp.line = info->line;
923
        tmp.port = info->addr;
924
        tmp.irq = info->irq;
925
        tmp.flags = info->flags;
926
        tmp.baud_base = info->baud_base;
927
        tmp.close_delay = info->close_delay;
928
        tmp.closing_wait = info->closing_wait;
929
        tmp.custom_divisor = info->custom_divisor;
930
        memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
931
        return 0;
932
}
933
 
934
static int set_serial_info(struct mcf_serial * info,
935
                           struct serial_struct * new_info)
936
{
937
        struct serial_struct new_serial;
938
        struct mcf_serial old_info;
939
        int                     retval = 0;
940
 
941
        if (!new_info)
942
                return -EFAULT;
943
        memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
944
        old_info = *info;
945
 
946
        if (!suser()) {
947
                if ((new_serial.baud_base != info->baud_base) ||
948
                    (new_serial.type != info->type) ||
949
                    (new_serial.close_delay != info->close_delay) ||
950
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
951
                     (info->flags & ~ASYNC_USR_MASK)))
952
                        return -EPERM;
953
                info->flags = ((info->flags & ~ASYNC_USR_MASK) |
954
                               (new_serial.flags & ASYNC_USR_MASK));
955
                info->custom_divisor = new_serial.custom_divisor;
956
                goto check_and_exit;
957
        }
958
 
959
        if (info->count > 1)
960
                return -EBUSY;
961
 
962
        /*
963
         * OK, past this point, all the error checking has been done.
964
         * At this point, we start making changes.....
965
         */
966
 
967
        info->baud_base = new_serial.baud_base;
968
        info->flags = ((info->flags & ~ASYNC_FLAGS) |
969
                        (new_serial.flags & ASYNC_FLAGS));
970
        info->type = new_serial.type;
971
        info->close_delay = new_serial.close_delay;
972
        info->closing_wait = new_serial.closing_wait;
973
 
974
check_and_exit:
975
        retval = startup(info);
976
        return retval;
977
}
978
 
979
/*
980
 * get_lsr_info - get line status register info
981
 *
982
 * Purpose: Let user call ioctl() to get info when the UART physically
983
 *          is emptied.  On bus types like RS485, the transmitter must
984
 *          release the bus after transmitting. This must be done when
985
 *          the transmit shift register is empty, not be done when the
986
 *          transmit holding register is empty.  This functionality
987
 *          allows an RS485 driver to be written in user space.
988
 */
989
static int get_lsr_info(struct mcf_serial * info, unsigned int *value)
990
{
991
        volatile unsigned char  *uartp;
992
        unsigned long           flags;
993
        unsigned char           status;
994
 
995
        save_flags(flags); cli();
996
        uartp = (volatile unsigned char *) info->addr;
997
        status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0;
998
        restore_flags(flags);
999
 
1000
        put_user(status,value);
1001
        return 0;
1002
}
1003
 
1004
/*
1005
 * This routine sends a break character out the serial port.
1006
 */
1007
static void send_break( struct mcf_serial * info, int duration)
1008
{
1009
        volatile unsigned char  *uartp;
1010
        unsigned long           flags;
1011
 
1012
        if (!info->addr)
1013
                return;
1014
        current->state = TASK_INTERRUPTIBLE;
1015
        current->timeout = jiffies + duration;
1016
        uartp = (volatile unsigned char *) info->addr;
1017
 
1018
        save_flags(flags); cli();
1019
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART;
1020
        schedule();
1021
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP;
1022
        restore_flags(flags);
1023
}
1024
 
1025
static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
1026
                    unsigned int cmd, unsigned long arg)
1027
{
1028
        int error;
1029
        struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
1030
        int retval;
1031
 
1032
        if (serial_paranoia_check(info, tty->device, "mcfrs_ioctl"))
1033
                return -ENODEV;
1034
 
1035
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1036
            (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
1037
            (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
1038
                if (tty->flags & (1 << TTY_IO_ERROR))
1039
                    return -EIO;
1040
        }
1041
 
1042
        switch (cmd) {
1043
                case TCSBRK:    /* SVID version: non-zero arg --> no break */
1044
                        retval = tty_check_change(tty);
1045
                        if (retval)
1046
                                return retval;
1047
                        tty_wait_until_sent(tty, 0);
1048
                        if (!arg)
1049
                                send_break(info, HZ/4); /* 1/4 second */
1050
                        return 0;
1051
                case TCSBRKP:   /* support for POSIX tcsendbreak() */
1052
                        retval = tty_check_change(tty);
1053
                        if (retval)
1054
                                return retval;
1055
                        tty_wait_until_sent(tty, 0);
1056
                        send_break(info, arg ? arg*(HZ/10) : HZ/4);
1057
                        return 0;
1058
                case TIOCGSOFTCAR:
1059
                        error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
1060
                        if (error)
1061
                                return error;
1062
                        put_fs_long(C_CLOCAL(tty) ? 1 : 0,
1063
                                    (unsigned long *) arg);
1064
                        return 0;
1065
                case TIOCSSOFTCAR:
1066
                        arg = get_fs_long((unsigned long *) arg);
1067
                        tty->termios->c_cflag =
1068
                                ((tty->termios->c_cflag & ~CLOCAL) |
1069
                                 (arg ? CLOCAL : 0));
1070
                        return 0;
1071
                case TIOCGSERIAL:
1072
                        error = verify_area(VERIFY_WRITE, (void *) arg,
1073
                                                sizeof(struct serial_struct));
1074
                        if (error)
1075
                                return error;
1076
                        return get_serial_info(info,
1077
                                               (struct serial_struct *) arg);
1078
                case TIOCSSERIAL:
1079
                        return set_serial_info(info,
1080
                                               (struct serial_struct *) arg);
1081
                case TIOCSERGETLSR: /* Get line status register */
1082
                        error = verify_area(VERIFY_WRITE, (void *) arg,
1083
                                sizeof(unsigned int));
1084
                        if (error)
1085
                                return error;
1086
                        else
1087
                            return get_lsr_info(info, (unsigned int *) arg);
1088
 
1089
                case TIOCSERGSTRUCT:
1090
                        error = verify_area(VERIFY_WRITE, (void *) arg,
1091
                                                sizeof(struct mcf_serial));
1092
                        if (error)
1093
                                return error;
1094
                        memcpy_tofs((struct mcf_serial *) arg,
1095
                                    info, sizeof(struct mcf_serial));
1096
                        return 0;
1097
 
1098
                default:
1099
                        return -ENOIOCTLCMD;
1100
                }
1101
        return 0;
1102
}
1103
 
1104
static void mcfrs_set_termios(struct tty_struct *tty, struct termios *old_termios)
1105
{
1106
        struct mcf_serial *info = (struct mcf_serial *)tty->driver_data;
1107
 
1108
        if (tty->termios->c_cflag == old_termios->c_cflag)
1109
                return;
1110
 
1111
        mcfrs_change_speed(info);
1112
 
1113
        if ((old_termios->c_cflag & CRTSCTS) &&
1114
            !(tty->termios->c_cflag & CRTSCTS)) {
1115
                tty->hw_stopped = 0;
1116
                mcfrs_setsignals(info, -1, 1);
1117
                mcfrs_start(tty);
1118
        }
1119
}
1120
 
1121
/*
1122
 * ------------------------------------------------------------
1123
 * mcfrs_close()
1124
 *
1125
 * This routine is called when the serial port gets closed.  First, we
1126
 * wait for the last remaining data to be sent.  Then, we unlink its
1127
 * S structure from the interrupt chain if necessary, and we free
1128
 * that IRQ if nothing is left in the chain.
1129
 * ------------------------------------------------------------
1130
 */
1131
static void mcfrs_close(struct tty_struct *tty, struct file * filp)
1132
{
1133
        volatile unsigned char  *uartp;
1134
        struct mcf_serial       *info = (struct mcf_serial *)tty->driver_data;
1135
        unsigned long           flags;
1136
 
1137
        if (!info || serial_paranoia_check(info, tty->device, "mcfrs_close"))
1138
                return;
1139
 
1140
        save_flags(flags); cli();
1141
 
1142
        if (tty_hung_up_p(filp)) {
1143
                restore_flags(flags);
1144
                return;
1145
        }
1146
 
1147
#ifdef SERIAL_DEBUG_OPEN
1148
        printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count);
1149
#endif
1150
        if ((tty->count == 1) && (info->count != 1)) {
1151
                /*
1152
                 * Uh, oh.  tty->count is 1, which means that the tty
1153
                 * structure will be freed.  Info->count should always
1154
                 * be one in these conditions.  If it's greater than
1155
                 * one, we've got real problems, since it means the
1156
                 * serial port won't be shutdown.
1157
                 */
1158
                printk("mcfrs_close: bad serial port count; tty->count is 1, "
1159
                       "info->count is %d\n", info->count);
1160
                info->count = 1;
1161
        }
1162
        if (--info->count < 0) {
1163
                printk("mcfrs_close: bad serial port count for ttyS%d: %d\n",
1164
                       info->line, info->count);
1165
                info->count = 0;
1166
        }
1167
        if (info->count) {
1168
                restore_flags(flags);
1169
                return;
1170
        }
1171
        info->flags |= ASYNC_CLOSING;
1172
 
1173
        /*
1174
         * Save the termios structure, since this port may have
1175
         * separate termios for callout and dialin.
1176
         */
1177
        if (info->flags & ASYNC_NORMAL_ACTIVE)
1178
                info->normal_termios = *tty->termios;
1179
        if (info->flags & ASYNC_CALLOUT_ACTIVE)
1180
                info->callout_termios = *tty->termios;
1181
 
1182
        /*
1183
         * Now we wait for the transmit buffer to clear; and we notify
1184
         * the line discipline to only process XON/XOFF characters.
1185
         */
1186
        tty->closing = 1;
1187
        if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
1188
                tty_wait_until_sent(tty, info->closing_wait);
1189
 
1190
        /*
1191
         * At this point we stop accepting input.  To do this, we
1192
         * disable the receive line status interrupts, and tell the
1193
         * interrupt driver to stop checking the data ready bit in the
1194
         * line status register.
1195
         */
1196
        info->imr &= ~MCFUART_UIR_RXREADY;
1197
        uartp = (volatile unsigned char *) info->addr;
1198
        uartp[MCFUART_UIMR] = info->imr;
1199
 
1200
        shutdown(info);
1201
        if (tty->driver.flush_buffer)
1202
                tty->driver.flush_buffer(tty);
1203
        if (tty->ldisc.flush_buffer)
1204
                tty->ldisc.flush_buffer(tty);
1205
        tty->closing = 0;
1206
        info->event = 0;
1207
        info->tty = 0;
1208
        if (tty->ldisc.num != ldiscs[N_TTY].num) {
1209
                if (tty->ldisc.close)
1210
                        (tty->ldisc.close)(tty);
1211
                tty->ldisc = ldiscs[N_TTY];
1212
                tty->termios->c_line = N_TTY;
1213
                if (tty->ldisc.open)
1214
                        (tty->ldisc.open)(tty);
1215
        }
1216
        if (info->blocked_open) {
1217
                if (info->close_delay) {
1218
                        current->state = TASK_INTERRUPTIBLE;
1219
                        current->timeout = jiffies + info->close_delay;
1220
                        schedule();
1221
                }
1222
                wake_up_interruptible(&info->open_wait);
1223
        }
1224
        info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
1225
                         ASYNC_CLOSING);
1226
        wake_up_interruptible(&info->close_wait);
1227
        restore_flags(flags);
1228
}
1229
 
1230
/*
1231
 * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled.
1232
 */
1233
void mcfrs_hangup(struct tty_struct *tty)
1234
{
1235
        struct mcf_serial * info = (struct mcf_serial *)tty->driver_data;
1236
 
1237
        if (serial_paranoia_check(info, tty->device, "mcfrs_hangup"))
1238
                return;
1239
 
1240
        mcfrs_flush_buffer(tty);
1241
        shutdown(info);
1242
        info->event = 0;
1243
        info->count = 0;
1244
        info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1245
        info->tty = 0;
1246
        wake_up_interruptible(&info->open_wait);
1247
}
1248
 
1249
/*
1250
 * ------------------------------------------------------------
1251
 * mcfrs_open() and friends
1252
 * ------------------------------------------------------------
1253
 */
1254
static int block_til_ready(struct tty_struct *tty, struct file * filp,
1255
                           struct mcf_serial *info)
1256
{
1257
        struct wait_queue wait = { current, NULL };
1258
        int             retval;
1259
        int             do_clocal = 0;
1260
 
1261
        /*
1262
         * If the device is in the middle of being closed, then block
1263
         * until it's done, and then try again.
1264
         */
1265
        if (info->flags & ASYNC_CLOSING) {
1266
                interruptible_sleep_on(&info->close_wait);
1267
#ifdef SERIAL_DO_RESTART
1268
                if (info->flags & ASYNC_HUP_NOTIFY)
1269
                        return -EAGAIN;
1270
                else
1271
                        return -ERESTARTSYS;
1272
#else
1273
                return -EAGAIN;
1274
#endif
1275
        }
1276
 
1277
        /*
1278
         * If this is a callout device, then just make sure the normal
1279
         * device isn't being used.
1280
         */
1281
        if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
1282
                if (info->flags & ASYNC_NORMAL_ACTIVE)
1283
                        return -EBUSY;
1284
                if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1285
                    (info->flags & ASYNC_SESSION_LOCKOUT) &&
1286
                    (info->session != current->session))
1287
                    return -EBUSY;
1288
                if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
1289
                    (info->flags & ASYNC_PGRP_LOCKOUT) &&
1290
                    (info->pgrp != current->pgrp))
1291
                    return -EBUSY;
1292
                info->flags |= ASYNC_CALLOUT_ACTIVE;
1293
                return 0;
1294
        }
1295
 
1296
        /*
1297
         * If non-blocking mode is set, or the port is not enabled,
1298
         * then make the check up front and then exit.
1299
         */
1300
        if ((filp->f_flags & O_NONBLOCK) ||
1301
            (tty->flags & (1 << TTY_IO_ERROR))) {
1302
                if (info->flags & ASYNC_CALLOUT_ACTIVE)
1303
                        return -EBUSY;
1304
                info->flags |= ASYNC_NORMAL_ACTIVE;
1305
                return 0;
1306
        }
1307
 
1308
        if (info->flags & ASYNC_CALLOUT_ACTIVE) {
1309
                if (info->normal_termios.c_cflag & CLOCAL)
1310
                        do_clocal = 1;
1311
        } else {
1312
                if (tty->termios->c_cflag & CLOCAL)
1313
                        do_clocal = 1;
1314
        }
1315
 
1316
        /*
1317
         * Block waiting for the carrier detect and the line to become
1318
         * free (i.e., not in use by the callout).  While we are in
1319
         * this loop, info->count is dropped by one, so that
1320
         * mcfrs_close() knows when to free things.  We restore it upon
1321
         * exit, either normal or abnormal.
1322
         */
1323
        retval = 0;
1324
        add_wait_queue(&info->open_wait, &wait);
1325
#ifdef SERIAL_DEBUG_OPEN
1326
        printk("block_til_ready before block: ttyS%d, count = %d\n",
1327
               info->line, info->count);
1328
#endif
1329
        info->count--;
1330
        info->blocked_open++;
1331
        while (1) {
1332
                cli();
1333
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE))
1334
                        mcfrs_setsignals(info, 1, 1);
1335
                sti();
1336
                current->state = TASK_INTERRUPTIBLE;
1337
                if (tty_hung_up_p(filp) ||
1338
                    !(info->flags & ASYNC_INITIALIZED)) {
1339
#ifdef SERIAL_DO_RESTART
1340
                        if (info->flags & ASYNC_HUP_NOTIFY)
1341
                                retval = -EAGAIN;
1342
                        else
1343
                                retval = -ERESTARTSYS;
1344
#else
1345
                        retval = -EAGAIN;
1346
#endif
1347
                        break;
1348
                }
1349
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
1350
                    !(info->flags & ASYNC_CLOSING) && do_clocal)
1351
                        break;
1352
                if (current->signal & ~current->blocked) {
1353
                        retval = -ERESTARTSYS;
1354
                        break;
1355
                }
1356
#ifdef SERIAL_DEBUG_OPEN
1357
                printk("block_til_ready blocking: ttyS%d, count = %d\n",
1358
                       info->line, info->count);
1359
#endif
1360
                schedule();
1361
        }
1362
        current->state = TASK_RUNNING;
1363
        remove_wait_queue(&info->open_wait, &wait);
1364
        if (!tty_hung_up_p(filp))
1365
                info->count++;
1366
        info->blocked_open--;
1367
#ifdef SERIAL_DEBUG_OPEN
1368
        printk("block_til_ready after blocking: ttyS%d, count = %d\n",
1369
               info->line, info->count);
1370
#endif
1371
        if (retval)
1372
                return retval;
1373
        info->flags |= ASYNC_NORMAL_ACTIVE;
1374
        return 0;
1375
}
1376
 
1377
/*
1378
 * This routine is called whenever a serial port is opened. It
1379
 * enables interrupts for a serial port, linking in its structure into
1380
 * the IRQ chain.   It also performs the serial-specific
1381
 * initialization for the tty structure.
1382
 */
1383
int mcfrs_open(struct tty_struct *tty, struct file * filp)
1384
{
1385
        struct mcf_serial       *info;
1386
        int                     retval, line;
1387
 
1388
        line = MINOR(tty->device) - tty->driver.minor_start;
1389
        if ((line < 0) || (line >= NR_PORTS))
1390
                return -ENODEV;
1391
        info = mcfrs_table + line;
1392
        if (serial_paranoia_check(info, tty->device, "mcfrs_open"))
1393
                return -ENODEV;
1394
#ifdef SERIAL_DEBUG_OPEN
1395
        printk("mcfrs_open %s%d, count = %d\n", tty->driver.name, info->line,
1396
               info->count);
1397
#endif
1398
        info->count++;
1399
        tty->driver_data = info;
1400
        info->tty = tty;
1401
 
1402
        /*
1403
         * Start up serial port
1404
         */
1405
        retval = startup(info);
1406
        if (retval)
1407
                return retval;
1408
 
1409
        retval = block_til_ready(tty, filp, info);
1410
        if (retval) {
1411
#ifdef SERIAL_DEBUG_OPEN
1412
                printk("mcfrs_open returning after block_til_ready with %d\n",
1413
                       retval);
1414
#endif
1415
                return retval;
1416
        }
1417
 
1418
        if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
1419
                if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
1420
                        *tty->termios = info->normal_termios;
1421
                else
1422
                        *tty->termios = info->callout_termios;
1423
                mcfrs_change_speed(info);
1424
        }
1425
 
1426
        info->session = current->session;
1427
        info->pgrp = current->pgrp;
1428
 
1429
#ifdef SERIAL_DEBUG_OPEN
1430
        printk("mcfrs_open ttyS%d successful...\n", info->line);
1431
#endif
1432
        return 0;
1433
}
1434
 
1435
/*
1436
 *      Based on the line number set up the internal interrupt stuff.
1437
 */
1438
static void mcfrs_irqinit(struct mcf_serial *info)
1439
{
1440
        volatile unsigned char  *icrp, *uartp;
1441
 
1442
#if 0
1443
        printk("%s(%d): setting interrupt for line=%d\n", __FILE__, __LINE__,
1444
                info->line);
1445
#endif
1446
 
1447
        switch (info->line) {
1448
 
1449
        case 0:
1450
                icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR);
1451
                *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
1452
                        MCFSIM_ICR_PRI1;
1453
                mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1);
1454
                break;
1455
 
1456
        case 1:
1457
                icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR);
1458
                *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 |
1459
                        MCFSIM_ICR_PRI2;
1460
                mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2);
1461
                break;
1462
 
1463
        default:
1464
                printk("SERIAL: don't know how to handle UART %d interrupt?\n",
1465
                        info->line);
1466
                return;
1467
        }
1468
 
1469
        uartp = (volatile unsigned char *) info->addr;
1470
        uartp[MCFUART_UIVR] = info->irq;
1471
 
1472
        if (request_irq(info->irq, mcfrs_interrupt, SA_INTERRUPT,
1473
            "ColdFire UART", NULL)) {
1474
                printk("SERIAL: Unable to attach ColdFire UART %d interrupt "
1475
                        "vector=%d\n", info->line, info->irq);
1476
        }
1477
 
1478
        return;
1479
}
1480
 
1481
 
1482
char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n";
1483
 
1484
 
1485
/*
1486
 * Serial stats reporting...
1487
 */
1488
int mcfrs_readproc(char *buffer)
1489
{
1490
        struct mcf_serial       *info;
1491
        char                    str[20];
1492
        int                     len, sigs, i;
1493
 
1494
        len = sprintf(buffer, mcfrs_drivername);
1495
        for (i = 0; (i < NR_PORTS); i++) {
1496
                info = &mcfrs_table[i];
1497
                len += sprintf((buffer + len), "%d: port:%x irq=%d baud:%d ",
1498
                        i, info->addr, info->irq, info->baud);
1499
                if (info->stats.rx || info->stats.tx)
1500
                        len += sprintf((buffer + len), "tx:%d rx:%d ",
1501
                        info->stats.tx, info->stats.rx);
1502
                if (info->stats.rxframing)
1503
                        len += sprintf((buffer + len), "fe:%d ",
1504
                        info->stats.rxframing);
1505
                if (info->stats.rxparity)
1506
                        len += sprintf((buffer + len), "pe:%d ",
1507
                        info->stats.rxparity);
1508
                if (info->stats.rxbreak)
1509
                        len += sprintf((buffer + len), "brk:%d ",
1510
                        info->stats.rxbreak);
1511
                if (info->stats.rxoverrun)
1512
                        len += sprintf((buffer + len), "oe:%d ",
1513
                        info->stats.rxoverrun);
1514
 
1515
                str[0] = str[1] = 0;
1516
                if ((sigs = mcfrs_getsignals(info))) {
1517
                        if (sigs & TIOCM_RTS)
1518
                                strcat(str, "|RTS");
1519
                        if (sigs & TIOCM_CTS)
1520
                                strcat(str, "|CTS");
1521
                        if (sigs & TIOCM_DTR)
1522
                                strcat(str, "|DTR");
1523
                        if (sigs & TIOCM_CD)
1524
                                strcat(str, "|CD");
1525
                }
1526
 
1527
                len += sprintf((buffer + len), "%s\n", &str[1]);
1528
        }
1529
 
1530
        return(len);
1531
}
1532
 
1533
 
1534
/* Finally, routines used to initialize the serial driver. */
1535
 
1536
static void show_serial_version(void)
1537
{
1538
        printk(mcfrs_drivername);
1539
}
1540
 
1541
/* mcfrs_init inits the driver */
1542
int mcfrs_init(void)
1543
{
1544
        struct mcf_serial       *info;
1545
        unsigned long           flags;
1546
        int                     i;
1547
 
1548
        /* Setup base handler, and timer table. */
1549
        init_bh(SERIAL_BH, do_serial_bh);
1550
#if defined(CONFIG_NETtel) && defined(CONFIG_M5307)
1551
        timer_table[RS_TIMER].fn = mcfrs_timer;
1552
        timer_table[RS_TIMER].expires = 0;
1553
#endif
1554
 
1555
        show_serial_version();
1556
 
1557
        /* Initialize the tty_driver structure */
1558
        memset(&mcfrs_serial_driver, 0, sizeof(struct tty_driver));
1559
        mcfrs_serial_driver.magic = TTY_DRIVER_MAGIC;
1560
        mcfrs_serial_driver.name = "ttyS";
1561
        mcfrs_serial_driver.major = TTY_MAJOR;
1562
        mcfrs_serial_driver.minor_start = 64;
1563
        mcfrs_serial_driver.num = NR_PORTS;
1564
        mcfrs_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
1565
        mcfrs_serial_driver.subtype = SERIAL_TYPE_NORMAL;
1566
        mcfrs_serial_driver.init_termios = tty_std_termios;
1567
 
1568
        mcfrs_serial_driver.init_termios.c_cflag =
1569
                B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1570
        mcfrs_serial_driver.flags = TTY_DRIVER_REAL_RAW;
1571
        mcfrs_serial_driver.refcount = &mcfrs_serial_refcount;
1572
        mcfrs_serial_driver.table = mcfrs_serial_table;
1573
        mcfrs_serial_driver.termios = mcfrs_serial_termios;
1574
        mcfrs_serial_driver.termios_locked = mcfrs_serial_termios_locked;
1575
 
1576
        mcfrs_serial_driver.open = mcfrs_open;
1577
        mcfrs_serial_driver.close = mcfrs_close;
1578
        mcfrs_serial_driver.write = mcfrs_write;
1579
        mcfrs_serial_driver.flush_chars = mcfrs_flush_chars;
1580
        mcfrs_serial_driver.write_room = mcfrs_write_room;
1581
        mcfrs_serial_driver.chars_in_buffer = mcfrs_chars_in_buffer;
1582
        mcfrs_serial_driver.flush_buffer = mcfrs_flush_buffer;
1583
        mcfrs_serial_driver.ioctl = mcfrs_ioctl;
1584
        mcfrs_serial_driver.throttle = mcfrs_throttle;
1585
        mcfrs_serial_driver.unthrottle = mcfrs_unthrottle;
1586
        mcfrs_serial_driver.set_termios = mcfrs_set_termios;
1587
        mcfrs_serial_driver.stop = mcfrs_stop;
1588
        mcfrs_serial_driver.start = mcfrs_start;
1589
        mcfrs_serial_driver.hangup = mcfrs_hangup;
1590
 
1591
        /*
1592
         * The callout device is just like normal device except for
1593
         * major number and the subtype code.
1594
         */
1595
        mcfrs_callout_driver = mcfrs_serial_driver;
1596
        mcfrs_callout_driver.name = "cua";
1597
        mcfrs_callout_driver.major = TTYAUX_MAJOR;
1598
        mcfrs_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
1599
 
1600
        if (tty_register_driver(&mcfrs_serial_driver))
1601
                panic("Couldn't register serial driver\n");
1602
        if (tty_register_driver(&mcfrs_callout_driver))
1603
                panic("Couldn't register callout driver\n");
1604
 
1605
        save_flags(flags); cli();
1606
 
1607
        /*
1608
         *      Configure all the attached serial ports.
1609
         */
1610
        for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) {
1611
                info->magic = SERIAL_MAGIC;
1612
                info->line = i;
1613
                info->tty = 0;
1614
                info->custom_divisor = 16;
1615
                info->close_delay = 50;
1616
                info->closing_wait = 3000;
1617
                info->x_char = 0;
1618
                info->event = 0;
1619
                info->count = 0;
1620
                info->blocked_open = 0;
1621
                info->tqueue.routine = do_softint;
1622
                info->tqueue.data = info;
1623
                info->tqueue_hangup.routine = do_serial_hangup;
1624
                info->tqueue_hangup.data = info;
1625
                info->callout_termios = mcfrs_callout_driver.init_termios;
1626
                info->normal_termios = mcfrs_serial_driver.init_termios;
1627
                info->open_wait = 0;
1628
                info->close_wait = 0;
1629
 
1630
                mcfrs_setsignals(info, 0, 0);
1631
                mcfrs_irqinit(info);
1632
 
1633
                printk("%s%d at 0x%04x (irq = %d)", mcfrs_serial_driver.name,
1634
                        info->line, info->addr, info->irq);
1635
                printk(" is a builtin ColdFire UART\n");
1636
        }
1637
 
1638
        restore_flags(flags);
1639
        return 0;
1640
}
1641
 
1642
/****************************************************************************/
1643
/*                          Serial Console                                  */
1644
/****************************************************************************/
1645
 
1646
/*
1647
 *      Quick and dirty UART initialization, for console output.
1648
 */
1649
 
1650
void rs_console_init(void)
1651
{
1652
        volatile unsigned char  *uartp;
1653
        unsigned int            clk;
1654
 
1655
        /*
1656
         *      Reset UART, get it into known state...
1657
         */
1658
        uartp = (volatile unsigned char *) (MCF_MBAR +
1659
                (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
1660
 
1661
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX;  /* reset RX */
1662
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX;  /* reset TX */
1663
        uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR;  /* reset MR pointer */
1664
 
1665
        /*
1666
         * Set port for defined baud , 8 data bits, 1 stop bit, no parity.
1667
         */
1668
        uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
1669
        uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
1670
 
1671
        clk = ((MCF_CLK / 32) / mcfrs_console_baud);  /* Set baud above */
1672
        uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8;  /* set msb baud */
1673
        uartp[MCFUART_UBG2] = (clk & 0xff);  /* set lsb baud */
1674
 
1675
        uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
1676
        uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
1677
 
1678
        mcfrs_console_inited++;
1679
        return;
1680
}
1681
 
1682
 
1683
/*
1684
 *      Setup for console. Argument comes from the boot command line.
1685
 */
1686
 
1687
int rs_console_setup(char *arg)
1688
{
1689
        int     rc = 0;
1690
 
1691
        if (!strncmp(arg, "/dev/ttyS", 9)) {
1692
                mcfrs_console_port = arg[9] - '0';
1693
                arg += 10;
1694
                rc = 1;
1695
        } else if (!strncmp(arg, "/dev/cua", 8)) {
1696
                mcfrs_console_port = arg[8] - '0';
1697
                arg += 9;
1698
                rc = 1;
1699
        }
1700
        if (*arg == ',')
1701
                mcfrs_console_baud = simple_strtoul(arg+1,NULL,0);
1702
        return(rc);
1703
}
1704
 
1705
 
1706
/*
1707
 *      Output a single character, using UART polled mode.
1708
 *      This is ised for console output.
1709
 */
1710
 
1711
void rs_put_char(char ch)
1712
{
1713
        volatile unsigned char  *uartp;
1714
        unsigned long           flags;
1715
        int                     i;
1716
 
1717
        uartp = (volatile unsigned char *) (MCF_MBAR +
1718
                (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1));
1719
 
1720
        save_flags(flags); cli();
1721
        for (i = 0; (i < 0x10000); i++) {
1722
                if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY)
1723
                        break;
1724
        }
1725
        uartp[MCFUART_UTB] = ch;
1726
        restore_flags(flags);
1727
 
1728
        return;
1729
}
1730
 
1731
 
1732
/*
1733
 * rs_console_print is registered for printk output.
1734
 */
1735
 
1736
void rs_console_print(const char *p)
1737
{
1738
        char c;
1739
 
1740
        while ((c = *(p++)) != 0) {
1741
                if(c == '\n')
1742
                        rs_put_char('\r');
1743
                rs_put_char(c);
1744
        }
1745
        return;
1746
}
1747
 
1748
/****************************************************************************/

powered by: WebSVN 2.1.0

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