00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef MODULE
00020 #include <linux/module.h>
00021 #include <linux/version.h>
00022 #else
00023 #define MOD_INC_USE_COUNT
00024 #define MOD_DEC_USE_COUNT
00025 #endif
00026
00027 #include <linux/kernel.h>
00028 #include <linux/sched.h>
00029 #include <linux/init.h>
00030 #include <linux/malloc.h>
00031 #include <linux/mm.h>
00032 #include <linux/major.h>
00033 #include <linux/param.h>
00034 #include <linux/tqueue.h>
00035 #include <linux/interrupt.h>
00036 #include <asm-mips/wbflush.h>
00037
00038 #include <asm/dec/interrupts.h>
00039
00040
00041 #ifdef CONFIG_SERIAL_CONSOLE
00042 #define CONSOLE_LINE (3)
00043 #include <linux/console.h>
00044 #endif
00045
00046 #include <linux/tty.h>
00047 #include <linux/tty_flip.h>
00048 #include <linux/serial.h>
00049
00050 #include <asm/uaccess.h>
00051 #include <asm/irq.h>
00052 #include <asm/dec/machtype.h>
00053 #include <asm/dec/kn01.h>
00054 #include <asm/dec/kn02.h>
00055
00056 #define DEBUG_DZ 1
00057 #ifdef DEBUG_DZ
00058 #include <linux/tty.h>
00059 #include <linux/major.h>
00060 #include <linux/ptrace.h>
00061 #include <linux/init.h>
00062 #include <linux/console.h>
00063 #include <linux/fs.h>
00064 #include <asm/bootinfo.h>
00065
00066 extern int (*prom_printf) (char *,...);
00067 #endif
00068
00069
00070
00071 #include "dz.h"
00072
00073 #define DZ_INTR_DEBUG 1
00074
00075 DECLARE_TASK_QUEUE(tq_serial);
00076
00077 extern struct wait_queue *keypress_wait;
00078 static struct dz_serial *lines[4];
00079 static unsigned char tmp_buffer[256];
00080
00081
00082
00083 #ifdef DEBUG_DZ
00084
00085
00086
00087 static void debug_console( const char *s,int count)
00088 {
00089 unsigned i;
00090
00091 for (i = 0; i < count; i++) {
00092 if (*s == 10)
00093 prom_printf("%c", 13);
00094 prom_printf("%c", *s++);
00095 }
00096 }
00097 #endif
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 static inline unsigned short dz_in (struct dz_serial *info, unsigned offset)
00109 {
00110 volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
00111 return *addr;
00112 }
00113
00114 static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value)
00115 {
00116
00117 volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
00118 *addr = value;
00119
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 static void dz_stop (struct tty_struct *tty)
00133 {
00134 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00135 unsigned short mask, tmp;
00136
00137
00138 mask = 1 << info->line;
00139 tmp = dz_in (info, DZ_TCR);
00140
00141 tmp &= ~mask;
00142 dz_out (info, DZ_TCR, tmp);
00143 }
00144
00145 static void dz_start (struct tty_struct *tty)
00146 {
00147 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00148 unsigned short mask, tmp;
00149
00150 mask = 1 << info->line;
00151 tmp = dz_in (info, DZ_TCR);
00152
00153 tmp |= mask;
00154 dz_out (info, DZ_TCR, tmp);
00155
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186 static inline void dz_sched_event (struct dz_serial *info, int event)
00187 {
00188 info->event |= 1 << event;
00189 queue_task (&info->tqueue, &tq_serial);
00190 mark_bh (SERIAL_BH);
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200 static inline void receive_chars (struct dz_serial *info_in)
00201 {
00202
00203 struct dz_serial *info;
00204 struct tty_struct *tty = 0;
00205 struct async_icount *icount;
00206 int ignore = 0;
00207 unsigned short status, tmp;
00208 unsigned char ch;
00209
00210
00211
00212
00213
00214 do
00215 {
00216 status = dz_in (info_in, DZ_RBUF);
00217 info = lines[LINE(status)];
00218
00219
00220 if (!(status & DZ_DVAL))
00221 goto ignore_char;
00222
00223
00224 ch = UCHAR(status);
00225
00226 #ifdef 0
00227 if (info->is_console) {
00228 if (ch == 0) return;
00229
00230 wake_up (&keypress_wait);
00231 }
00232 #endif
00233
00234 tty = info->tty;
00235 icount = &info->icount;
00236
00237 if (!tty) break;
00238 if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
00239
00240 *tty->flip.char_buf_ptr = ch;
00241 *tty->flip.flag_buf_ptr = 0;
00242 icount->rx++;
00243
00244
00245 if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
00246 if (status & DZ_PERR)
00247 icount->parity++;
00248 else if (status & DZ_FERR)
00249 icount->frame++;
00250 if (status & DZ_OERR)
00251 icount->overrun++;
00252
00253
00254
00255
00256
00257 if (status & info->ignore_status_mask) {
00258 if (++ignore > 100 ) break;
00259 goto ignore_char;
00260 }
00261
00262
00263 tmp = status & info->read_status_mask;
00264
00265 if (tmp & DZ_PERR)
00266 {
00267 *tty->flip.flag_buf_ptr = TTY_PARITY;
00268 debug_console("PERR\n",5);
00269 }
00270 else if (tmp & DZ_FERR)
00271 {
00272 *tty->flip.flag_buf_ptr = TTY_FRAME;
00273 debug_console("FERR\n",5);
00274 }
00275 if (tmp & DZ_OERR)
00276 {
00277 debug_console("OERR\n",5);
00278 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
00279 tty->flip.count++;
00280 tty->flip.flag_buf_ptr++;
00281 tty->flip.char_buf_ptr++;
00282 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
00283 }
00284 }
00285 }
00286 tty->flip.flag_buf_ptr++;
00287 tty->flip.char_buf_ptr++;
00288 tty->flip.count++;
00289 ignore_char:
00290 } while (status & DZ_DVAL);
00291
00292 if (tty)
00293 tty_flip_buffer_push(tty);
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303 static inline void transmit_chars (struct dz_serial *info)
00304 {
00305 unsigned char tmp;
00306
00307
00308
00309 if (info->x_char) {
00310 dz_out (info, DZ_TDR, info->x_char);
00311 info->icount.tx++;
00312 info->x_char = 0;
00313 return;
00314 }
00315
00316
00317 if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
00318 dz_stop (info->tty);
00319 return;
00320 }
00321
00322
00323 tmp = (unsigned short)info->xmit_buf[info->xmit_tail++];
00324 dz_out (info, DZ_TDR, tmp);
00325 info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1);
00326 info->icount.tx++;
00327
00328 if (--info->xmit_cnt < WAKEUP_CHARS)
00329 dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP);
00330
00331
00332
00333 if (info->xmit_cnt <= 0) dz_stop (info->tty);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343 static inline void check_modem_status (struct dz_serial *info)
00344 {
00345 unsigned short status;
00346
00347
00348 if (info->line != DZ_MODEM) return;
00349
00350 status = dz_in (info, DZ_MSR);
00351
00352
00353 if (status) info->icount.dsr++;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 static void dz_interrupt (int irq, void *dev, struct pt_regs *regs)
00365 {
00366 struct dz_serial *info;
00367 unsigned short status;
00368
00369 status = dz_in ((struct dz_serial *)dev, DZ_CSR);
00370 info = lines[LINE(status)];
00371
00372 if (status & DZ_RDONE)
00373 receive_chars (info);
00374
00375 if (status & DZ_TRDY)
00376 transmit_chars (info);
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 static void do_serial_bh (void)
00395 {
00396 run_task_queue (&tq_serial);
00397 }
00398
00399 static void do_softint (void *private_data)
00400 {
00401 struct dz_serial *info = (struct dz_serial *)private_data;
00402 struct tty_struct *tty = info->tty;
00403
00404 if (!tty) return;
00405
00406 if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) {
00407 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
00408 (tty->ldisc.write_wakeup) (tty);
00409 wake_up_interruptible (&tty->write_wait);
00410 wake_up_interruptible (&tty->poll_wait);
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 static void do_serial_hangup (void *private_data)
00425 {
00426 struct dz_serial *info = (struct dz_serial *)private_data;
00427 struct tty_struct *tty = info->tty;;
00428
00429 if (!tty) return;
00430
00431 tty_hangup (tty);
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441 static int startup (struct dz_serial *info)
00442 {
00443 unsigned long page, flags;
00444 unsigned short tmp;
00445
00446 if (info->is_initialized) return 0;
00447
00448 save_flags (flags);
00449 cli ();
00450
00451 if (!info->port) {
00452 if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
00453 restore_flags (flags);
00454 return -ENODEV;
00455 }
00456
00457 if (!info->xmit_buf) {
00458 page = get_free_page (GFP_KERNEL);
00459 if (!page) {
00460 restore_flags (flags);
00461 return -ENOMEM;
00462 }
00463 info->xmit_buf = (unsigned char *)page;
00464 }
00465
00466 if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags);
00467
00468
00469 tmp = dz_in (info, DZ_CSR);
00470 tmp |= (DZ_RIE | DZ_TIE | DZ_MSE);
00471 dz_out (info, DZ_CSR, tmp);
00472
00473 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
00474
00475
00476 change_speed (info);
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 info->is_initialized = 1;
00491
00492 restore_flags (flags);
00493 return 0;
00494 }
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 static void shutdown (struct dz_serial *info)
00505 {
00506 unsigned long flags;
00507 unsigned short tmp;
00508
00509 if (!info->is_initialized) return;
00510
00511 save_flags (flags);
00512 cli ();
00513
00514 dz_stop (info->tty);
00515
00516
00517
00518 info->cflags &= ~DZ_CREAD;
00519 dz_out (info, DZ_LPR, info->cflags);
00520
00521 if (info->xmit_buf) {
00522 free_page ((unsigned long)info->xmit_buf);
00523 info->xmit_buf = 0;
00524 }
00525
00526 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
00527 tmp = dz_in (info, DZ_TCR);
00528 if (tmp & DZ_MODEM_DTR) {
00529 tmp &= ~DZ_MODEM_DTR;
00530 dz_out (info, DZ_TCR, tmp);
00531 }
00532 }
00533
00534 if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
00535
00536 info->is_initialized = 0;
00537 restore_flags (flags);
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547 static void change_speed (struct dz_serial *info)
00548 {
00549 unsigned long flags;
00550 unsigned cflag;
00551 int baud;
00552
00553 if (!info->tty || !info->tty->termios) return;
00554
00555 save_flags (flags);
00556 cli ();
00557
00558 info->cflags = info->line;
00559
00560 cflag = info->tty->termios->c_cflag;
00561
00562 switch (cflag & CSIZE) {
00563 case CS5: info->cflags |= DZ_CS5; break;
00564 case CS6: info->cflags |= DZ_CS6; break;
00565 case CS7: info->cflags |= DZ_CS7; break;
00566 case CS8:
00567 default: info->cflags |= DZ_CS8;
00568 }
00569
00570 if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB;
00571 if (cflag & PARENB) info->cflags |= DZ_PARENB;
00572 if (cflag & PARODD) info->cflags |= DZ_PARODD;
00573
00574 baud = tty_get_baud_rate (info->tty);
00575 switch (baud) {
00576 case 50 : info->cflags |= DZ_B50; break;
00577 case 75 : info->cflags |= DZ_B75; break;
00578 case 110 : info->cflags |= DZ_B110; break;
00579 case 134 : info->cflags |= DZ_B134; break;
00580 case 150 : info->cflags |= DZ_B150; break;
00581 case 300 : info->cflags |= DZ_B300; break;
00582 case 600 : info->cflags |= DZ_B600; break;
00583 case 1200: info->cflags |= DZ_B1200; break;
00584 case 1800: info->cflags |= DZ_B1800; break;
00585 case 2000: info->cflags |= DZ_B2000; break;
00586 case 2400: info->cflags |= DZ_B2400; break;
00587 case 3600: info->cflags |= DZ_B3600; break;
00588 case 4800: info->cflags |= DZ_B4800; break;
00589 case 7200: info->cflags |= DZ_B7200; break;
00590 case 9600:
00591 default : info->cflags |= DZ_B9600;
00592 }
00593
00594 info->cflags |= DZ_RXENAB;
00595 dz_out (info, DZ_LPR, info->cflags);
00596
00597
00598 info->read_status_mask = DZ_OERR;
00599 if (I_INPCK(info->tty))
00600 info->read_status_mask |= (DZ_FERR | DZ_PERR);
00601
00602
00603 info->ignore_status_mask = 0;
00604 if (I_IGNPAR(info->tty))
00605 info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
00606
00607 restore_flags (flags);
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617 static void dz_flush_chars (struct tty_struct *tty)
00618 {
00619 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00620 unsigned long flags;
00621
00622 if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
00623 return;
00624
00625 save_flags (flags);
00626 cli ();
00627
00628 dz_start (info->tty);
00629
00630 restore_flags (flags);
00631 }
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641 static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
00642 {
00643 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00644 unsigned long flags;
00645 int c, ret = 0;
00646
00647 if (!tty ) return ret;
00648 if (!info->xmit_buf) return ret;
00649 if (!tmp_buf) tmp_buf = tmp_buffer;
00650
00651
00652
00653 if (from_user) {
00654
00655 down (&tmp_buf_sem);
00656 while (1) {
00657 c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00658 if (c <= 0) break;
00659
00660 c -= copy_from_user (tmp_buf, buf, c);
00661 if (!c) {
00662 if (!ret) ret = -EFAULT;
00663 break;
00664 }
00665
00666 save_flags (flags);
00667 cli ();
00668
00669 c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00670 memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
00671 info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
00672 info->xmit_cnt += c;
00673
00674 restore_flags(flags);
00675
00676 buf += c;
00677 count -= c;
00678 ret += c;
00679 }
00680
00681 up (&tmp_buf_sem);
00682 } else {
00683
00684
00685 while (1) {
00686 save_flags (flags);
00687 cli ();
00688
00689 c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00690 if (c <= 0) {
00691 restore_flags (flags);
00692 break;
00693 }
00694 memcpy (info->xmit_buf + info->xmit_head, buf, c);
00695 info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
00696 info->xmit_cnt += c;
00697
00698 restore_flags (flags);
00699
00700 buf += c;
00701 count -= c;
00702 ret += c;
00703 }
00704 }
00705
00706
00707 if (info->xmit_cnt)
00708 {
00709 if (!tty->stopped)
00710 {
00711 if (!tty->hw_stopped)
00712 {
00713 dz_start (info->tty);
00714 }
00715 }
00716 }
00717 return ret;
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727 static int dz_write_room (struct tty_struct *tty)
00728 {
00729 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00730 int ret;
00731
00732 ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
00733 if (ret < 0) ret = 0;
00734 return ret;
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744 static int dz_chars_in_buffer (struct tty_struct *tty)
00745 {
00746 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00747
00748 return info->xmit_cnt;
00749 }
00750
00751
00752
00753
00754
00755
00756
00757
00758 static void dz_flush_buffer (struct tty_struct *tty)
00759 {
00760 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00761
00762 cli ();
00763 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
00764 sti ();
00765
00766 wake_up_interruptible (&tty->write_wait);
00767 wake_up_interruptible (&tty->poll_wait);
00768
00769 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
00770 (tty->ldisc.write_wakeup)(tty);
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 static void dz_throttle (struct tty_struct *tty)
00782 {
00783 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00784
00785 if (I_IXOFF(tty))
00786 info->x_char = STOP_CHAR(tty);
00787 }
00788
00789 static void dz_unthrottle (struct tty_struct *tty)
00790 {
00791 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00792
00793 if (I_IXOFF(tty)) {
00794 if (info->x_char)
00795 info->x_char = 0;
00796 else
00797 info->x_char = START_CHAR(tty);
00798 }
00799 }
00800
00801 static void dz_send_xchar (struct tty_struct *tty, char ch)
00802 {
00803 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00804
00805 info->x_char = ch;
00806
00807 if (ch) dz_start (info->tty);
00808 }
00809
00810
00811
00812
00813
00814
00815 static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo)
00816 {
00817 struct serial_struct tmp;
00818
00819 if (!retinfo)
00820 return -EFAULT;
00821
00822 memset (&tmp, 0, sizeof(tmp));
00823
00824 tmp.type = info->type;
00825 tmp.line = info->line;
00826 tmp.port = info->port;
00827 tmp.irq = SERIAL;
00828 tmp.flags = info->flags;
00829 tmp.baud_base = info->baud_base;
00830 tmp.close_delay = info->close_delay;
00831 tmp.closing_wait = info->closing_wait;
00832
00833 return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
00834 }
00835
00836 static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info)
00837 {
00838 struct serial_struct new_serial;
00839 struct dz_serial old_info;
00840 int retval = 0;
00841
00842 if (!new_info)
00843 return -EFAULT;
00844
00845 copy_from_user (&new_serial, new_info, sizeof(new_serial));
00846 old_info = *info;
00847
00848 if (!suser())
00849 return -EPERM;
00850
00851 if (info->count > 1)
00852 return -EBUSY;
00853
00854
00855
00856
00857
00858
00859 info->baud_base = new_serial.baud_base;
00860 info->type = new_serial.type;
00861 info->close_delay = new_serial.close_delay;
00862 info->closing_wait = new_serial.closing_wait;
00863
00864 retval = startup (info);
00865 return retval;
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 static int get_lsr_info (struct dz_serial *info, unsigned int *value)
00879 {
00880 unsigned short status = dz_in (info, DZ_LPR);
00881
00882 return put_user (status, value);
00883 }
00884
00885
00886
00887
00888 static void send_break (struct dz_serial *info, int duration)
00889 {
00890 unsigned long flags;
00891 unsigned short tmp, mask;
00892
00893 if (!info->port)
00894 return;
00895
00896 mask = 1 << info->line;
00897 tmp = dz_in (info, DZ_TCR);
00898 tmp |= mask;
00899
00900 current->state = TASK_INTERRUPTIBLE;
00901
00902 save_flags (flags);
00903 cli();
00904
00905 dz_out (info, DZ_TCR, tmp);
00906
00907 schedule_timeout(duration);
00908
00909 tmp &= ~mask;
00910 dz_out (info, DZ_TCR, tmp);
00911
00912 restore_flags (flags);
00913 }
00914
00915 static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
00916 {
00917 int error;
00918 struct dz_serial * info = (struct dz_serial *)tty->driver_data;
00919 int retval;
00920
00921 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
00922 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
00923 (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
00924 if (tty->flags & (1 << TTY_IO_ERROR))
00925 return -EIO;
00926 }
00927
00928 switch (cmd) {
00929 case TCSBRK:
00930 retval = tty_check_change (tty);
00931 if (retval)
00932 return retval;
00933 tty_wait_until_sent (tty, 0);
00934 if (!arg)
00935 send_break (info, HZ/4);
00936 return 0;
00937
00938 case TCSBRKP:
00939 retval = tty_check_change (tty);
00940 if (retval)
00941 return retval;
00942 tty_wait_until_sent (tty, 0);
00943 send_break (info, arg ? arg*(HZ/10) : HZ/4);
00944 return 0;
00945
00946 case TIOCGSOFTCAR:
00947 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));
00948 if (error)
00949 return error;
00950 put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
00951 return 0;
00952
00953 case TIOCSSOFTCAR:
00954 error = get_user (arg, (unsigned long *)arg);
00955 if (error)
00956 return error;
00957 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
00958 return 0;
00959
00960 case TIOCGSERIAL:
00961 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
00962 if (error)
00963 return error;
00964 return get_serial_info (info, (struct serial_struct *)arg);
00965
00966 case TIOCSSERIAL:
00967 return set_serial_info (info, (struct serial_struct *) arg);
00968
00969 case TIOCSERGETLSR:
00970 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
00971 if (error)
00972 return error;
00973 else
00974 return get_lsr_info (info, (unsigned int *)arg);
00975
00976 case TIOCSERGSTRUCT:
00977 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial));
00978 if (error)
00979 return error;
00980 copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial));
00981 return 0;
00982
00983 default:
00984 return -ENOIOCTLCMD;
00985 }
00986
00987 return 0;
00988 }
00989
00990 static void dz_set_termios (struct tty_struct *tty,
00991 struct termios *old_termios)
00992 {
00993 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00994
00995 if (tty->termios->c_cflag == old_termios->c_cflag)
00996 return;
00997
00998 change_speed (info);
00999
01000 if ((old_termios->c_cflag & CRTSCTS) &&
01001 !(tty->termios->c_cflag & CRTSCTS)) {
01002 tty->hw_stopped = 0;
01003 dz_start (tty);
01004 }
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 static void dz_close (struct tty_struct *tty, struct file *filp)
01017 {
01018 struct dz_serial * info = (struct dz_serial *)tty->driver_data;
01019 unsigned long flags;
01020
01021 if (!info) return;
01022
01023 save_flags (flags);
01024 cli();
01025
01026 if (tty_hung_up_p (filp)) {
01027 restore_flags (flags);
01028 return;
01029 }
01030
01031 if ((tty->count == 1) && (info->count != 1)) {
01032
01033
01034
01035
01036
01037
01038
01039 printk("dz_close: bad serial port count; tty->count is 1, "
01040 "info->count is %d\n", info->count);
01041 info->count = 1;
01042 }
01043
01044 if (--info->count < 0) {
01045 printk("rs_close: bad serial port count for ttys%d: %d\n",
01046 info->line, info->count);
01047 info->count = 0;
01048 }
01049
01050 if (info->count) {
01051 restore_flags (flags);
01052 return;
01053 }
01054 info->flags |= DZ_CLOSING;
01055
01056
01057
01058
01059 if (info->flags & DZ_NORMAL_ACTIVE)
01060 info->normal_termios = *tty->termios;
01061 if (info->flags & DZ_CALLOUT_ACTIVE)
01062 info->callout_termios = *tty->termios;
01063
01064
01065
01066
01067 tty->closing = 1;
01068
01069 if (info->closing_wait != DZ_CLOSING_WAIT_NONE)
01070 tty_wait_until_sent (tty, info->closing_wait);
01071
01072
01073
01074
01075
01076
01077 shutdown (info);
01078
01079 if (tty->driver.flush_buffer)
01080 tty->driver.flush_buffer (tty);
01081 if (tty->ldisc.flush_buffer)
01082 tty->ldisc.flush_buffer (tty);
01083 tty->closing = 0;
01084 info->event = 0;
01085 info->tty = 0;
01086
01087 if (tty->ldisc.num != ldiscs[N_TTY].num) {
01088 if (tty->ldisc.close)
01089 (tty->ldisc.close)(tty);
01090 tty->ldisc = ldiscs[N_TTY];
01091 tty->termios->c_line = N_TTY;
01092 if (tty->ldisc.open)
01093 (tty->ldisc.open)(tty);
01094 }
01095 if (info->blocked_open) {
01096 if (info->close_delay) {
01097 current->state = TASK_INTERRUPTIBLE;
01098 schedule_timeout(info->close_delay);
01099 }
01100 wake_up_interruptible (&info->open_wait);
01101 }
01102
01103 info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
01104 wake_up_interruptible (&info->close_wait);
01105
01106 restore_flags (flags);
01107 }
01108
01109
01110
01111
01112 static void dz_hangup (struct tty_struct *tty)
01113 {
01114 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
01115
01116 dz_flush_buffer (tty);
01117 shutdown (info);
01118 info->event = 0;
01119 info->count = 0;
01120 info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);
01121 info->tty = 0;
01122 wake_up_interruptible (&info->open_wait);
01123 }
01124
01125
01126
01127
01128
01129
01130 static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info)
01131 {
01132 struct wait_queue wait = { current, NULL };
01133 int retval;
01134 int do_clocal = 0;
01135
01136
01137
01138
01139
01140 if (info->flags & DZ_CLOSING) {
01141 interruptible_sleep_on (&info->close_wait);
01142 return -EAGAIN;
01143 }
01144
01145
01146
01147
01148
01149 if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
01150 if (info->flags & DZ_NORMAL_ACTIVE)
01151 return -EBUSY;
01152
01153 if ((info->flags & DZ_CALLOUT_ACTIVE) &&
01154 (info->flags & DZ_SESSION_LOCKOUT) &&
01155 (info->session != current->session))
01156 return -EBUSY;
01157
01158 if ((info->flags & DZ_CALLOUT_ACTIVE) &&
01159 (info->flags & DZ_PGRP_LOCKOUT) &&
01160 (info->pgrp != current->pgrp))
01161 return -EBUSY;
01162 info->flags |= DZ_CALLOUT_ACTIVE;
01163 return 0;
01164 }
01165
01166
01167
01168
01169
01170 if ((filp->f_flags & O_NONBLOCK) ||
01171 (tty->flags & (1 << TTY_IO_ERROR))) {
01172 if (info->flags & DZ_CALLOUT_ACTIVE)
01173 return -EBUSY;
01174 info->flags |= DZ_NORMAL_ACTIVE;
01175 return 0;
01176 }
01177
01178 if (info->flags & DZ_CALLOUT_ACTIVE) {
01179 if (info->normal_termios.c_cflag & CLOCAL)
01180 do_clocal = 1;
01181 } else {
01182 if (tty->termios->c_cflag & CLOCAL)
01183 do_clocal = 1;
01184 }
01185
01186
01187
01188
01189
01190
01191
01192
01193 retval = 0;
01194 add_wait_queue (&info->open_wait, &wait);
01195
01196 info->count--;
01197 info->blocked_open++;
01198 while (1) {
01199 current->state = TASK_INTERRUPTIBLE;
01200 if (tty_hung_up_p (filp) || !(info->is_initialized)) {
01201 retval = -EAGAIN;
01202 break;
01203 }
01204 if (!(info->flags & DZ_CALLOUT_ACTIVE) &&
01205 !(info->flags & DZ_CLOSING) && do_clocal)
01206 break;
01207 if (signal_pending (current)) {
01208 retval = -ERESTARTSYS;
01209 break;
01210 }
01211 schedule();
01212 }
01213
01214 current->state = TASK_RUNNING;
01215 remove_wait_queue (&info->open_wait, &wait);
01216 if (!tty_hung_up_p(filp))
01217 info->count++;
01218 info->blocked_open--;
01219
01220 if (retval)
01221 return retval;
01222 info->flags |= DZ_NORMAL_ACTIVE;
01223 return 0;
01224 }
01225
01226
01227
01228
01229
01230
01231 static int dz_open (struct tty_struct *tty, struct file *filp)
01232 {
01233 struct dz_serial *info;
01234 int retval, line;
01235
01236 line = MINOR(tty->device) - tty->driver.minor_start;
01237
01238
01239
01240
01241 if ((line < 0) || (line >= DZ_NB_PORT))
01242 return -ENODEV;
01243
01244 if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
01245 return -ENODEV;
01246
01247 info = lines[line];
01248 info->count++;
01249
01250 tty->driver_data = info;
01251 info->tty = tty;
01252
01253
01254
01255
01256 retval = startup (info);
01257 if (retval)
01258 return retval;
01259
01260
01261
01262 retval = block_til_ready (tty, filp, info);
01263 if (retval)
01264 return retval;
01265
01266 if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
01267 if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
01268 *tty->termios = info->normal_termios;
01269 else
01270 *tty->termios = info->callout_termios;
01271 change_speed (info);
01272
01273 }
01274
01275 info->session = current->session;
01276 info->pgrp = current->pgrp;
01277 return 0;
01278 }
01279
01280 static void show_serial_version (void)
01281 {
01282 printk("%s%s\n", dz_name, dz_version);
01283 }
01284
01285
01286 __initfunc(int dz_init(void))
01287 {
01288 int i, flags;
01289 struct dz_serial *info;
01290
01291
01292 init_bh (SERIAL_BH, do_serial_bh);
01293
01294 show_serial_version ();
01295
01296 memset(&serial_driver, 0, sizeof(struct tty_driver));
01297 serial_driver.magic = TTY_DRIVER_MAGIC;
01298 serial_driver.name = "ttyS";
01299 serial_driver.major = TTY_MAJOR;
01300 serial_driver.minor_start = 64;
01301 serial_driver.num = DZ_NB_PORT;
01302 serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
01303 serial_driver.subtype = SERIAL_TYPE_NORMAL;
01304 serial_driver.init_termios = tty_std_termios;
01305
01306 serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
01307 serial_driver.flags = TTY_DRIVER_REAL_RAW;
01308 serial_driver.refcount = &serial_refcount;
01309 serial_driver.table = serial_table;
01310 serial_driver.termios = serial_termios;
01311 serial_driver.termios_locked = serial_termios_locked;
01312
01313 serial_driver.open = dz_open;
01314 serial_driver.close = dz_close;
01315 serial_driver.write = dz_write;
01316 serial_driver.flush_chars = dz_flush_chars;
01317 serial_driver.write_room = dz_write_room;
01318 serial_driver.chars_in_buffer = dz_chars_in_buffer;
01319 serial_driver.flush_buffer = dz_flush_buffer;
01320 serial_driver.ioctl = dz_ioctl;
01321 serial_driver.throttle = dz_throttle;
01322 serial_driver.unthrottle = dz_unthrottle;
01323 serial_driver.send_xchar = dz_send_xchar;
01324 serial_driver.set_termios = dz_set_termios;
01325 serial_driver.stop = dz_stop;
01326 serial_driver.start = dz_start;
01327 serial_driver.hangup = dz_hangup;
01328
01329
01330
01331
01332
01333 callout_driver = serial_driver;
01334 callout_driver.name = "cua";
01335 callout_driver.major = TTYAUX_MAJOR;
01336 callout_driver.subtype = SERIAL_TYPE_CALLOUT;
01337
01338 if (tty_register_driver (&serial_driver))
01339 panic("Couldn't register serial driver\n");
01340 if (tty_register_driver (&callout_driver))
01341 panic("Couldn't register callout driver\n");
01342 save_flags(flags); cli();
01343
01344 i = 0;
01345 for (info = &multi[i]; i < DZ_NB_PORT; i++)
01346 {
01347 lines[i] = info;
01348 info->magic = SERIAL_MAGIC;
01349
01350 if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
01351 info->port = (unsigned long) KN01_DZ11_BASE;
01352 else
01353 info->port = (unsigned long) KN02_DZ11_BASE;
01354
01355 info->line = i;
01356 info->tty = 0;
01357 info->close_delay = 50;
01358 info->closing_wait = 3000;
01359 info->x_char = 0;
01360 info->event = 0;
01361 info->count = 0;
01362 info->blocked_open = 0;
01363 info->tqueue.routine = do_softint;
01364 info->tqueue.data = info;
01365 info->tqueue_hangup.routine = do_serial_hangup;
01366 info->tqueue_hangup.data = info;
01367 info->callout_termios = callout_driver.init_termios;
01368 info->normal_termios = serial_driver.init_termios;
01369 info->open_wait = 0;
01370 info->close_wait = 0;
01371
01372
01373
01374 if (! info->port)
01375 return 0;
01376
01377 printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL);
01378 }
01379
01380
01381 #ifndef CONFIG_SERIAL_CONSOLE
01382 dz_out(info, DZ_CSR, DZ_CLR);
01383 while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ;
01384 wbflush();
01385
01386
01387 dz_out(info, DZ_CSR, DZ_MSE);
01388 #endif
01389
01390
01391
01392
01393 restore_flags(flags);
01394
01395
01396 if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
01397 panic ("Unable to register DZ interrupt\n");
01398
01399 return 0;
01400 }
01401
01402 #ifdef CONFIG_SERIAL_CONSOLE
01403 static void dz_console_put_char (unsigned char ch)
01404 {
01405 long flags;
01406 int loops = 2500;
01407 unsigned short tmp = ch;
01408
01409
01410
01411
01412 dz_console=&multi[CONSOLE_LINE];
01413
01414 save_flags(flags);
01415 cli();
01416
01417
01418
01419 while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) && loops--)
01420 ;
01421
01422
01423 dz_out (dz_console, DZ_TDR, tmp);
01424
01425 restore_flags(flags);
01426 }
01427
01428
01429
01430
01431
01432
01433
01434 static void dz_console_print (struct console *cons,
01435 const char *str,
01436 unsigned int count)
01437 {
01438 #ifdef DEBUG_DZ
01439 prom_printf((char *)str);
01440 #endif
01441 while (count--)
01442 {
01443 if (*str == '\n')
01444 dz_console_put_char ('\r');
01445 dz_console_put_char (*str++);
01446 }
01447 }
01448
01449 static int dz_console_wait_key(struct console *co)
01450 {
01451 return 0;
01452 }
01453
01454 static kdev_t dz_console_device(struct console *c)
01455 {
01456 return MKDEV(TTY_MAJOR, 64 + c->index);
01457 }
01458
01459 __initfunc(static int dz_console_setup(struct console *co, char *options))
01460 {
01461 int baud = 9600;
01462 int bits = 8;
01463 int parity = 'n';
01464 int cflag = CREAD | HUPCL | CLOCAL;
01465 char *s;
01466 unsigned short mask,tmp;
01467
01468