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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [serial/] [dz.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * dz.c: Serial port driver for DECstations equipped
3
 *       with the DZ chipset.
4
 *
5
 * Copyright (C) 1998 Olivier A. D. Lebaillif
6
 *
7
 * Email: olivier.lebaillif@ifrsys.com
8
 *
9
 * Copyright (C) 2004, 2006  Maciej W. Rozycki
10
 *
11
 * [31-AUG-98] triemer
12
 * Changed IRQ to use Harald's dec internals interrupts.h
13
 * removed base_addr code - moving address assignment to setup.c
14
 * Changed name of dz_init to rs_init to be consistent with tc code
15
 * [13-NOV-98] triemer fixed code to receive characters
16
 *    after patches by harald to irq code.
17
 * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
18
 *            field from "current" - somewhere between 2.1.121 and 2.1.131
19
 Qua Jun 27 15:02:26 BRT 2001
20
 * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
21
 *
22
 * Parts (C) 1999 David Airlie, airlied@linux.ie
23
 * [07-SEP-99] Bugfixes
24
 *
25
 * [06-Jan-2002] Russell King <rmk@arm.linux.org.uk>
26
 * Converted to new serial core
27
 */
28
 
29
#undef DEBUG_DZ
30
 
31
#if defined(CONFIG_SERIAL_DZ_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
32
#define SUPPORT_SYSRQ
33
#endif
34
 
35
#include <linux/delay.h>
36
#include <linux/module.h>
37
#include <linux/interrupt.h>
38
#include <linux/init.h>
39
#include <linux/console.h>
40
#include <linux/sysrq.h>
41
#include <linux/tty.h>
42
#include <linux/tty_flip.h>
43
#include <linux/serial_core.h>
44
#include <linux/serial.h>
45
 
46
#include <asm/bootinfo.h>
47
#include <asm/dec/interrupts.h>
48
#include <asm/dec/kn01.h>
49
#include <asm/dec/kn02.h>
50
#include <asm/dec/machtype.h>
51
#include <asm/dec/prom.h>
52
#include <asm/irq.h>
53
#include <asm/system.h>
54
#include <asm/uaccess.h>
55
 
56
#include "dz.h"
57
 
58
static char *dz_name = "DECstation DZ serial driver version ";
59
static char *dz_version = "1.03";
60
 
61
struct dz_port {
62
        struct uart_port        port;
63
        unsigned int            cflag;
64
};
65
 
66
static struct dz_port dz_ports[DZ_NB_PORT];
67
 
68
/*
69
 * ------------------------------------------------------------
70
 * dz_in () and dz_out ()
71
 *
72
 * These routines are used to access the registers of the DZ
73
 * chip, hiding relocation differences between implementation.
74
 * ------------------------------------------------------------
75
 */
76
 
77
static inline unsigned short dz_in(struct dz_port *dport, unsigned offset)
78
{
79
        volatile unsigned short *addr =
80
                (volatile unsigned short *) (dport->port.membase + offset);
81
 
82
        return *addr;
83
}
84
 
85
static inline void dz_out(struct dz_port *dport, unsigned offset,
86
                          unsigned short value)
87
{
88
        volatile unsigned short *addr =
89
                (volatile unsigned short *) (dport->port.membase + offset);
90
 
91
        *addr = value;
92
}
93
 
94
/*
95
 * ------------------------------------------------------------
96
 * rs_stop () and rs_start ()
97
 *
98
 * These routines are called before setting or resetting
99
 * tty->stopped. They enable or disable transmitter interrupts,
100
 * as necessary.
101
 * ------------------------------------------------------------
102
 */
103
 
104
static void dz_stop_tx(struct uart_port *uport)
105
{
106
        struct dz_port *dport = (struct dz_port *)uport;
107
        unsigned short tmp, mask = 1 << dport->port.line;
108
        unsigned long flags;
109
 
110
        spin_lock_irqsave(&dport->port.lock, flags);
111
        tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
112
        tmp &= ~mask;                   /* clear the TX flag */
113
        dz_out(dport, DZ_TCR, tmp);
114
        spin_unlock_irqrestore(&dport->port.lock, flags);
115
}
116
 
117
static void dz_start_tx(struct uart_port *uport)
118
{
119
        struct dz_port *dport = (struct dz_port *)uport;
120
        unsigned short tmp, mask = 1 << dport->port.line;
121
        unsigned long flags;
122
 
123
        spin_lock_irqsave(&dport->port.lock, flags);
124
        tmp = dz_in(dport, DZ_TCR);     /* read the TX flag */
125
        tmp |= mask;                    /* set the TX flag */
126
        dz_out(dport, DZ_TCR, tmp);
127
        spin_unlock_irqrestore(&dport->port.lock, flags);
128
}
129
 
130
static void dz_stop_rx(struct uart_port *uport)
131
{
132
        struct dz_port *dport = (struct dz_port *)uport;
133
        unsigned long flags;
134
 
135
        spin_lock_irqsave(&dport->port.lock, flags);
136
        dport->cflag &= ~DZ_CREAD;
137
        dz_out(dport, DZ_LPR, dport->cflag | dport->port.line);
138
        spin_unlock_irqrestore(&dport->port.lock, flags);
139
}
140
 
141
static void dz_enable_ms(struct uart_port *port)
142
{
143
        /* nothing to do */
144
}
145
 
146
/*
147
 * ------------------------------------------------------------
148
 *
149
 * Here start the interrupt handling routines.  All of the following
150
 * subroutines are declared as inline and are folded into
151
 * dz_interrupt.  They were separated out for readability's sake.
152
 *
153
 * Note: dz_interrupt() is a "fast" interrupt, which means that it
154
 * runs with interrupts turned off.  People who may want to modify
155
 * dz_interrupt() should try to keep the interrupt handler as fast as
156
 * possible.  After you are done making modifications, it is not a bad
157
 * idea to do:
158
 *
159
 *      make drivers/serial/dz.s
160
 *
161
 * and look at the resulting assemble code in dz.s.
162
 *
163
 * ------------------------------------------------------------
164
 */
165
 
166
/*
167
 * ------------------------------------------------------------
168
 * receive_char ()
169
 *
170
 * This routine deals with inputs from any lines.
171
 * ------------------------------------------------------------
172
 */
173
static inline void dz_receive_chars(struct dz_port *dport_in)
174
{
175
        struct dz_port *dport;
176
        struct tty_struct *tty = NULL;
177
        struct uart_icount *icount;
178
        int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 };
179
        unsigned short status;
180
        unsigned char ch, flag;
181
        int i;
182
 
183
        while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) {
184
                dport = &dz_ports[LINE(status)];
185
                tty = dport->port.info->tty;    /* point to the proper dev */
186
 
187
                ch = UCHAR(status);             /* grab the char */
188
 
189
                icount = &dport->port.icount;
190
                icount->rx++;
191
 
192
                flag = TTY_NORMAL;
193
                if (status & DZ_FERR) {         /* frame error */
194
                        /*
195
                         * There is no separate BREAK status bit, so
196
                         * treat framing errors as BREAKs for Magic SysRq
197
                         * and SAK; normally, otherwise.
198
                         */
199
                        if (uart_handle_break(&dport->port))
200
                                continue;
201
                        if (dport->port.flags & UPF_SAK)
202
                                flag = TTY_BREAK;
203
                        else
204
                                flag = TTY_FRAME;
205
                } else if (status & DZ_OERR)    /* overrun error */
206
                        flag = TTY_OVERRUN;
207
                else if (status & DZ_PERR)      /* parity error */
208
                        flag = TTY_PARITY;
209
 
210
                /* keep track of the statistics */
211
                switch (flag) {
212
                case TTY_FRAME:
213
                        icount->frame++;
214
                        break;
215
                case TTY_PARITY:
216
                        icount->parity++;
217
                        break;
218
                case TTY_OVERRUN:
219
                        icount->overrun++;
220
                        break;
221
                case TTY_BREAK:
222
                        icount->brk++;
223
                        break;
224
                default:
225
                        break;
226
                }
227
 
228
                if (uart_handle_sysrq_char(&dport->port, ch))
229
                        continue;
230
 
231
                if ((status & dport->port.ignore_status_mask) == 0) {
232
                        uart_insert_char(&dport->port,
233
                                         status, DZ_OERR, ch, flag);
234
                        lines_rx[LINE(status)] = 1;
235
                }
236
        }
237
        for (i = 0; i < DZ_NB_PORT; i++)
238
                if (lines_rx[i])
239
                        tty_flip_buffer_push(dz_ports[i].port.info->tty);
240
}
241
 
242
/*
243
 * ------------------------------------------------------------
244
 * transmit_char ()
245
 *
246
 * This routine deals with outputs to any lines.
247
 * ------------------------------------------------------------
248
 */
249
static inline void dz_transmit_chars(struct dz_port *dport_in)
250
{
251
        struct dz_port *dport;
252
        struct circ_buf *xmit;
253
        unsigned short status;
254
        unsigned char tmp;
255
 
256
        status = dz_in(dport_in, DZ_CSR);
257
        dport = &dz_ports[LINE(status)];
258
        xmit = &dport->port.info->xmit;
259
 
260
        if (dport->port.x_char) {               /* XON/XOFF chars */
261
                dz_out(dport, DZ_TDR, dport->port.x_char);
262
                dport->port.icount.tx++;
263
                dport->port.x_char = 0;
264
                return;
265
        }
266
        /* If nothing to do or stopped or hardware stopped. */
267
        if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) {
268
                dz_stop_tx(&dport->port);
269
                return;
270
        }
271
 
272
        /*
273
         * If something to do... (remember the dz has no output fifo,
274
         * so we go one char at a time) :-<
275
         */
276
        tmp = xmit->buf[xmit->tail];
277
        xmit->tail = (xmit->tail + 1) & (DZ_XMIT_SIZE - 1);
278
        dz_out(dport, DZ_TDR, tmp);
279
        dport->port.icount.tx++;
280
 
281
        if (uart_circ_chars_pending(xmit) < DZ_WAKEUP_CHARS)
282
                uart_write_wakeup(&dport->port);
283
 
284
        /* Are we are done. */
285
        if (uart_circ_empty(xmit))
286
                dz_stop_tx(&dport->port);
287
}
288
 
289
/*
290
 * ------------------------------------------------------------
291
 * check_modem_status()
292
 *
293
 * DS 3100 & 5100: Only valid for the MODEM line, duh!
294
 * DS 5000/200: Valid for the MODEM and PRINTER line.
295
 * ------------------------------------------------------------
296
 */
297
static inline void check_modem_status(struct dz_port *dport)
298
{
299
        /*
300
         * FIXME:
301
         * 1. No status change interrupt; use a timer.
302
         * 2. Handle the 3100/5000 as appropriate. --macro
303
         */
304
        unsigned short status;
305
 
306
        /* If not the modem line just return.  */
307
        if (dport->port.line != DZ_MODEM)
308
                return;
309
 
310
        status = dz_in(dport, DZ_MSR);
311
 
312
        /* it's easy, since DSR2 is the only bit in the register */
313
        if (status)
314
                dport->port.icount.dsr++;
315
}
316
 
317
/*
318
 * ------------------------------------------------------------
319
 * dz_interrupt ()
320
 *
321
 * this is the main interrupt routine for the DZ chip.
322
 * It deals with the multiple ports.
323
 * ------------------------------------------------------------
324
 */
325
static irqreturn_t dz_interrupt(int irq, void *dev)
326
{
327
        struct dz_port *dport = (struct dz_port *)dev;
328
        unsigned short status;
329
 
330
        /* get the reason why we just got an irq */
331
        status = dz_in(dport, DZ_CSR);
332
 
333
        if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE))
334
                dz_receive_chars(dport);
335
 
336
        if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE))
337
                dz_transmit_chars(dport);
338
 
339
        return IRQ_HANDLED;
340
}
341
 
342
/*
343
 * -------------------------------------------------------------------
344
 * Here ends the DZ interrupt routines.
345
 * -------------------------------------------------------------------
346
 */
347
 
348
static unsigned int dz_get_mctrl(struct uart_port *uport)
349
{
350
        /*
351
         * FIXME: Handle the 3100/5000 as appropriate. --macro
352
         */
353
        struct dz_port *dport = (struct dz_port *)uport;
354
        unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
355
 
356
        if (dport->port.line == DZ_MODEM) {
357
                if (dz_in(dport, DZ_MSR) & DZ_MODEM_DSR)
358
                        mctrl &= ~TIOCM_DSR;
359
        }
360
 
361
        return mctrl;
362
}
363
 
364
static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl)
365
{
366
        /*
367
         * FIXME: Handle the 3100/5000 as appropriate. --macro
368
         */
369
        struct dz_port *dport = (struct dz_port *)uport;
370
        unsigned short tmp;
371
 
372
        if (dport->port.line == DZ_MODEM) {
373
                tmp = dz_in(dport, DZ_TCR);
374
                if (mctrl & TIOCM_DTR)
375
                        tmp &= ~DZ_MODEM_DTR;
376
                else
377
                        tmp |= DZ_MODEM_DTR;
378
                dz_out(dport, DZ_TCR, tmp);
379
        }
380
}
381
 
382
/*
383
 * -------------------------------------------------------------------
384
 * startup ()
385
 *
386
 * various initialization tasks
387
 * -------------------------------------------------------------------
388
 */
389
static int dz_startup(struct uart_port *uport)
390
{
391
        struct dz_port *dport = (struct dz_port *)uport;
392
        unsigned long flags;
393
        unsigned short tmp;
394
 
395
        spin_lock_irqsave(&dport->port.lock, flags);
396
 
397
        /* enable the interrupt and the scanning */
398
        tmp = dz_in(dport, DZ_CSR);
399
        tmp |= DZ_RIE | DZ_TIE | DZ_MSE;
400
        dz_out(dport, DZ_CSR, tmp);
401
 
402
        spin_unlock_irqrestore(&dport->port.lock, flags);
403
 
404
        return 0;
405
}
406
 
407
/*
408
 * -------------------------------------------------------------------
409
 * shutdown ()
410
 *
411
 * This routine will shutdown a serial port; interrupts are disabled, and
412
 * DTR is dropped if the hangup on close termio flag is on.
413
 * -------------------------------------------------------------------
414
 */
415
static void dz_shutdown(struct uart_port *uport)
416
{
417
        dz_stop_tx(uport);
418
}
419
 
420
/*
421
 * -------------------------------------------------------------------
422
 * dz_tx_empty() -- get the transmitter empty status
423
 *
424
 * Purpose: Let user call ioctl() to get info when the UART physically
425
 *          is emptied.  On bus types like RS485, the transmitter must
426
 *          release the bus after transmitting. This must be done when
427
 *          the transmit shift register is empty, not be done when the
428
 *          transmit holding register is empty.  This functionality
429
 *          allows an RS485 driver to be written in user space.
430
 * -------------------------------------------------------------------
431
 */
432
static unsigned int dz_tx_empty(struct uart_port *uport)
433
{
434
        struct dz_port *dport = (struct dz_port *)uport;
435
        unsigned short tmp, mask = 1 << dport->port.line;
436
 
437
        tmp = dz_in(dport, DZ_TCR);
438
        tmp &= mask;
439
 
440
        return tmp ? 0 : TIOCSER_TEMT;
441
}
442
 
443
static void dz_break_ctl(struct uart_port *uport, int break_state)
444
{
445
        /*
446
         * FIXME: Can't access BREAK bits in TDR easily;
447
         * reuse the code for polled TX. --macro
448
         */
449
        struct dz_port *dport = (struct dz_port *)uport;
450
        unsigned long flags;
451
        unsigned short tmp, mask = 1 << dport->port.line;
452
 
453
        spin_lock_irqsave(&uport->lock, flags);
454
        tmp = dz_in(dport, DZ_TCR);
455
        if (break_state)
456
                tmp |= mask;
457
        else
458
                tmp &= ~mask;
459
        dz_out(dport, DZ_TCR, tmp);
460
        spin_unlock_irqrestore(&uport->lock, flags);
461
}
462
 
463
static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,
464
                           struct ktermios *old_termios)
465
{
466
        struct dz_port *dport = (struct dz_port *)uport;
467
        unsigned long flags;
468
        unsigned int cflag, baud;
469
 
470
        cflag = dport->port.line;
471
 
472
        switch (termios->c_cflag & CSIZE) {
473
        case CS5:
474
                cflag |= DZ_CS5;
475
                break;
476
        case CS6:
477
                cflag |= DZ_CS6;
478
                break;
479
        case CS7:
480
                cflag |= DZ_CS7;
481
                break;
482
        case CS8:
483
        default:
484
                cflag |= DZ_CS8;
485
        }
486
 
487
        if (termios->c_cflag & CSTOPB)
488
                cflag |= DZ_CSTOPB;
489
        if (termios->c_cflag & PARENB)
490
                cflag |= DZ_PARENB;
491
        if (termios->c_cflag & PARODD)
492
                cflag |= DZ_PARODD;
493
 
494
        baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600);
495
        switch (baud) {
496
        case 50:
497
                cflag |= DZ_B50;
498
                break;
499
        case 75:
500
                cflag |= DZ_B75;
501
                break;
502
        case 110:
503
                cflag |= DZ_B110;
504
                break;
505
        case 134:
506
                cflag |= DZ_B134;
507
                break;
508
        case 150:
509
                cflag |= DZ_B150;
510
                break;
511
        case 300:
512
                cflag |= DZ_B300;
513
                break;
514
        case 600:
515
                cflag |= DZ_B600;
516
                break;
517
        case 1200:
518
                cflag |= DZ_B1200;
519
                break;
520
        case 1800:
521
                cflag |= DZ_B1800;
522
                break;
523
        case 2000:
524
                cflag |= DZ_B2000;
525
                break;
526
        case 2400:
527
                cflag |= DZ_B2400;
528
                break;
529
        case 3600:
530
                cflag |= DZ_B3600;
531
                break;
532
        case 4800:
533
                cflag |= DZ_B4800;
534
                break;
535
        case 7200:
536
                cflag |= DZ_B7200;
537
                break;
538
        case 9600:
539
        default:
540
                cflag |= DZ_B9600;
541
        }
542
 
543
        if (termios->c_cflag & CREAD)
544
                cflag |= DZ_RXENAB;
545
 
546
        spin_lock_irqsave(&dport->port.lock, flags);
547
 
548
        dz_out(dport, DZ_LPR, cflag | dport->port.line);
549
        dport->cflag = cflag;
550
 
551
        /* setup accept flag */
552
        dport->port.read_status_mask = DZ_OERR;
553
        if (termios->c_iflag & INPCK)
554
                dport->port.read_status_mask |= DZ_FERR | DZ_PERR;
555
 
556
        /* characters to ignore */
557
        uport->ignore_status_mask = 0;
558
        if (termios->c_iflag & IGNPAR)
559
                dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR;
560
 
561
        spin_unlock_irqrestore(&dport->port.lock, flags);
562
}
563
 
564
static const char *dz_type(struct uart_port *port)
565
{
566
        return "DZ";
567
}
568
 
569
static void dz_release_port(struct uart_port *port)
570
{
571
        /* nothing to do */
572
}
573
 
574
static int dz_request_port(struct uart_port *port)
575
{
576
        return 0;
577
}
578
 
579
static void dz_config_port(struct uart_port *port, int flags)
580
{
581
        if (flags & UART_CONFIG_TYPE)
582
                port->type = PORT_DZ;
583
}
584
 
585
/*
586
 * verify the new serial_struct (for TIOCSSERIAL).
587
 */
588
static int dz_verify_port(struct uart_port *port, struct serial_struct *ser)
589
{
590
        int ret = 0;
591
        if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ)
592
                ret = -EINVAL;
593
        if (ser->irq != port->irq)
594
                ret = -EINVAL;
595
        return ret;
596
}
597
 
598
static struct uart_ops dz_ops = {
599
        .tx_empty       = dz_tx_empty,
600
        .get_mctrl      = dz_get_mctrl,
601
        .set_mctrl      = dz_set_mctrl,
602
        .stop_tx        = dz_stop_tx,
603
        .start_tx       = dz_start_tx,
604
        .stop_rx        = dz_stop_rx,
605
        .enable_ms      = dz_enable_ms,
606
        .break_ctl      = dz_break_ctl,
607
        .startup        = dz_startup,
608
        .shutdown       = dz_shutdown,
609
        .set_termios    = dz_set_termios,
610
        .type           = dz_type,
611
        .release_port   = dz_release_port,
612
        .request_port   = dz_request_port,
613
        .config_port    = dz_config_port,
614
        .verify_port    = dz_verify_port,
615
};
616
 
617
static void __init dz_init_ports(void)
618
{
619
        static int first = 1;
620
        struct dz_port *dport;
621
        unsigned long base;
622
        int i;
623
 
624
        if (!first)
625
                return;
626
        first = 0;
627
 
628
        if (mips_machtype == MACH_DS23100 ||
629
            mips_machtype == MACH_DS5100)
630
                base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11);
631
        else
632
                base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11);
633
 
634
        for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) {
635
                spin_lock_init(&dport->port.lock);
636
                dport->port.membase     = (char *) base;
637
                dport->port.iotype      = UPIO_MEM;
638
                dport->port.irq         = dec_interrupt[DEC_IRQ_DZ11];
639
                dport->port.line        = i;
640
                dport->port.fifosize    = 1;
641
                dport->port.ops         = &dz_ops;
642
                dport->port.flags       = UPF_BOOT_AUTOCONF;
643
        }
644
}
645
 
646
static void dz_reset(struct dz_port *dport)
647
{
648
        dz_out(dport, DZ_CSR, DZ_CLR);
649
        while (dz_in(dport, DZ_CSR) & DZ_CLR);
650
        iob();
651
 
652
        /* enable scanning */
653
        dz_out(dport, DZ_CSR, DZ_MSE);
654
}
655
 
656
#ifdef CONFIG_SERIAL_DZ_CONSOLE
657
/*
658
 * -------------------------------------------------------------------
659
 * dz_console_putchar() -- transmit a character
660
 *
661
 * Polled transmission.  This is tricky.  We need to mask transmit
662
 * interrupts so that they do not interfere, enable the transmitter
663
 * for the line requested and then wait till the transmit scanner
664
 * requests data for this line.  But it may request data for another
665
 * line first, in which case we have to disable its transmitter and
666
 * repeat waiting till our line pops up.  Only then the character may
667
 * be transmitted.  Finally, the state of the transmitter mask is
668
 * restored.  Welcome to the world of PDP-11!
669
 * -------------------------------------------------------------------
670
 */
671
static void dz_console_putchar(struct uart_port *uport, int ch)
672
{
673
        struct dz_port *dport = (struct dz_port *)uport;
674
        unsigned long flags;
675
        unsigned short csr, tcr, trdy, mask;
676
        int loops = 10000;
677
 
678
        spin_lock_irqsave(&dport->port.lock, flags);
679
        csr = dz_in(dport, DZ_CSR);
680
        dz_out(dport, DZ_CSR, csr & ~DZ_TIE);
681
        tcr = dz_in(dport, DZ_TCR);
682
        tcr |= 1 << dport->port.line;
683
        mask = tcr;
684
        dz_out(dport, DZ_TCR, mask);
685
        iob();
686
        spin_unlock_irqrestore(&dport->port.lock, flags);
687
 
688
        while (loops--) {
689
                trdy = dz_in(dport, DZ_CSR);
690
                if (!(trdy & DZ_TRDY))
691
                        continue;
692
                trdy = (trdy & DZ_TLINE) >> 8;
693
                if (trdy == dport->port.line)
694
                        break;
695
                mask &= ~(1 << trdy);
696
                dz_out(dport, DZ_TCR, mask);
697
                iob();
698
                udelay(2);
699
        }
700
 
701
        if (loops)                              /* Cannot send otherwise. */
702
                dz_out(dport, DZ_TDR, ch);
703
 
704
        dz_out(dport, DZ_TCR, tcr);
705
        dz_out(dport, DZ_CSR, csr);
706
}
707
 
708
/*
709
 * -------------------------------------------------------------------
710
 * dz_console_print ()
711
 *
712
 * dz_console_print is registered for printk.
713
 * The console must be locked when we get here.
714
 * -------------------------------------------------------------------
715
 */
716
static void dz_console_print(struct console *co,
717
                             const char *str,
718
                             unsigned int count)
719
{
720
        struct dz_port *dport = &dz_ports[co->index];
721
#ifdef DEBUG_DZ
722
        prom_printf((char *) str);
723
#endif
724
        uart_console_write(&dport->port, str, count, dz_console_putchar);
725
}
726
 
727
static int __init dz_console_setup(struct console *co, char *options)
728
{
729
        struct dz_port *dport = &dz_ports[co->index];
730
        int baud = 9600;
731
        int bits = 8;
732
        int parity = 'n';
733
        int flow = 'n';
734
 
735
        if (options)
736
                uart_parse_options(options, &baud, &parity, &bits, &flow);
737
 
738
        dz_reset(dport);
739
 
740
        return uart_set_options(&dport->port, co, baud, parity, bits, flow);
741
}
742
 
743
static struct uart_driver dz_reg;
744
static struct console dz_sercons = {
745
        .name   = "ttyS",
746
        .write  = dz_console_print,
747
        .device = uart_console_device,
748
        .setup  = dz_console_setup,
749
        .flags  = CON_PRINTBUFFER,
750
        .index  = -1,
751
        .data   = &dz_reg,
752
};
753
 
754
static int __init dz_serial_console_init(void)
755
{
756
        if (!IOASIC) {
757
                dz_init_ports();
758
                register_console(&dz_sercons);
759
                return 0;
760
        } else
761
                return -ENXIO;
762
}
763
 
764
console_initcall(dz_serial_console_init);
765
 
766
#define SERIAL_DZ_CONSOLE       &dz_sercons
767
#else
768
#define SERIAL_DZ_CONSOLE       NULL
769
#endif /* CONFIG_SERIAL_DZ_CONSOLE */
770
 
771
static struct uart_driver dz_reg = {
772
        .owner                  = THIS_MODULE,
773
        .driver_name            = "serial",
774
        .dev_name               = "ttyS",
775
        .major                  = TTY_MAJOR,
776
        .minor                  = 64,
777
        .nr                     = DZ_NB_PORT,
778
        .cons                   = SERIAL_DZ_CONSOLE,
779
};
780
 
781
static int __init dz_init(void)
782
{
783
        int ret, i;
784
 
785
        if (IOASIC)
786
                return -ENXIO;
787
 
788
        printk("%s%s\n", dz_name, dz_version);
789
 
790
        dz_init_ports();
791
 
792
#ifndef CONFIG_SERIAL_DZ_CONSOLE
793
        /* reset the chip */
794
        dz_reset(&dz_ports[0]);
795
#endif
796
 
797
        if (request_irq(dz_ports[0].port.irq, dz_interrupt,
798
                        IRQF_DISABLED, "DZ", &dz_ports[0]))
799
                panic("Unable to register DZ interrupt");
800
 
801
        ret = uart_register_driver(&dz_reg);
802
        if (ret != 0)
803
                return ret;
804
 
805
        for (i = 0; i < DZ_NB_PORT; i++)
806
                uart_add_one_port(&dz_reg, &dz_ports[i].port);
807
 
808
        return ret;
809
}
810
 
811
module_init(dz_init);
812
 
813
MODULE_DESCRIPTION("DECstation DZ serial driver");
814
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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