00001 #include <minix/config.h>
00002
00003
00004
00005
00006
00007 #include "../drivers.h"
00008 #include <termios.h>
00009 #include <signal.h>
00010 #include "tty.h"
00011
00012 #if NR_RS_LINES > 0
00013
00014 #if (MACHINE != IBM_PC) && (MACHINE != ATARI)
00015 #error
00016 #endif
00017
00018 #if (MACHINE == ATARI)
00019 #include "staddr.h"
00020 #include "stsound.h"
00021 #include "stmfp.h"
00022 #if (NR_RS_LINES > 1)
00023 #error
00024 #endif
00025 #endif
00026
00027 #if (MACHINE == IBM_PC)
00028
00029
00030 #define UART_FREQ 115200L
00031
00032
00033 #define IE_RECEIVER_READY 1
00034 #define IE_TRANSMITTER_READY 2
00035 #define IE_LINE_STATUS_CHANGE 4
00036 #define IE_MODEM_STATUS_CHANGE 8
00037
00038
00039 #define IS_MODEM_STATUS_CHANGE 0
00040 #define IS_TRANSMITTER_READY 2
00041 #define IS_RECEIVER_READY 4
00042 #define IS_LINE_STATUS_CHANGE 6
00043
00044
00045 #define LC_2STOP_BITS 0x04
00046 #define LC_PARITY 0x08
00047 #define LC_PAREVEN 0x10
00048 #define LC_BREAK 0x40
00049 #define LC_ADDRESS_DIVISOR 0x80
00050
00051
00052 #define LS_OVERRUN_ERR 2
00053 #define LS_PARITY_ERR 4
00054 #define LS_FRAMING_ERR 8
00055 #define LS_BREAK_INTERRUPT 0x10
00056 #define LS_TRANSMITTER_READY 0x20
00057
00058
00059 #define MC_DTR 1
00060 #define MC_RTS 2
00061 #define MC_OUT2 8
00062
00063
00064 #define MS_CTS 0x10
00065 #define MS_RLSD 0x80
00066 #define MS_DRLSD 0x08
00067
00068 #else
00069
00070
00071
00072
00073
00074 #define UART_FREQ 19200L
00075
00076
00077 #define LS_OVERRUN_ERR R_OE
00078 #define LS_PARITY_ERR R_PE
00079 #define LS_FRAMING_ERR R_FE
00080 #define LS_BREAK_INTERRUPT R_BREAK
00081
00082
00083 #define MS_CTS IO_SCTS
00084
00085 #endif
00086
00087 #define DATA_BITS_SHIFT 8
00088 #define DEF_BAUD 1200
00089
00090 #define RS_IBUFSIZE 1024
00091 #define RS_OBUFSIZE 1024
00092
00093
00094
00095
00096
00097
00098 #define RS_ILOWWATER (1 * RS_IBUFSIZE / 4)
00099 #define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4)
00100
00101
00102
00103
00104
00105 #define RS_OLOWWATER (1 * RS_OBUFSIZE / 4)
00106
00107 #if (MACHINE == IBM_PC)
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #define istart(rs) \
00120 (sys_outb((rs)->modem_ctl_port, MC_OUT2 | MC_RTS | MC_DTR), \
00121 (rs)->idevready = TRUE)
00122 #define istop(rs) \
00123 (sys_outb((rs)->modem_ctl_port, MC_OUT2 | MC_DTR), \
00124 (rs)->idevready = FALSE)
00125
00126
00127
00128
00129 #define devready(rs) ((my_inb(rs->modem_status_port) | rs->cts) & MS_CTS)
00130
00131
00132 #define txready(rs) (my_inb(rs->line_status_port) & LS_TRANSMITTER_READY)
00133
00134
00135
00136
00137
00138
00139
00140
00141 #define devhup(rs) \
00142 ((my_inb(rs->modem_status_port) & (MS_RLSD|MS_DRLSD)) == MS_DRLSD)
00143
00144 #else
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 #define set_porta(msk,val) { register int s = lock(); \
00155 SOUND->sd_selr = YM_IOA; \
00156 SOUND->sd_wdat = \
00157 SOUND->sd_rdat & (msk) | (val); \
00158 restore(s); }
00159 #define istart(rs) { set_porta( ~(PA_SRTS|PA_SDTR),0 ); \
00160 (rs)->idevready = TRUE; }
00161 #define istop(rs) { set_porta( ~PA_SDTR, PA_SRTS ); \
00162 (rs)->idevready = FALSE; }
00163
00164
00165
00166
00167 #define devready(rs) ((~MFP->mf_gpip | rs->cts) & MS_CTS)
00168
00169
00170 #define txready(rs) (MFP->mf_tsr & (T_EMPTY | T_UE))
00171
00172 #endif
00173
00174
00175 typedef unsigned char bool_t;
00176
00177
00178 typedef struct rs232 {
00179 tty_t *tty;
00180
00181 int icount;
00182 char *ihead;
00183 char *itail;
00184 bool_t idevready;
00185 char cts;
00186
00187 unsigned char ostate;
00188 #define ODONE 1
00189 #define ORAW 2
00190 #define OWAKEUP 4
00191 #define ODEVREADY MS_CTS
00192 #define OQUEUED 0x20
00193 #define OSWREADY 0x40
00194 #define ODEVHUP MS_RLSD
00195 #define OSOFTBITS (ODONE | ORAW | OWAKEUP | OQUEUED | OSWREADY)
00196
00197 #if (OSOFTBITS | ODEVREADY | ODEVHUP) == OSOFTBITS
00198
00199 #error
00200 #endif
00201 unsigned char oxoff;
00202 bool_t inhibited;
00203 bool_t drain;
00204 int ocount;
00205 char *ohead;
00206 char *otail;
00207
00208 #if (MACHINE == IBM_PC)
00209 port_t xmit_port;
00210 port_t recv_port;
00211 port_t div_low_port;
00212 port_t div_hi_port;
00213 port_t int_enab_port;
00214 port_t int_id_port;
00215 port_t line_ctl_port;
00216 port_t modem_ctl_port;
00217 port_t line_status_port;
00218 port_t modem_status_port;
00219 #endif
00220
00221 unsigned char lstatus;
00222 unsigned char pad;
00223 unsigned framing_errors;
00224 unsigned overrun_errors;
00225 unsigned parity_errors;
00226 unsigned break_interrupts;
00227
00228 int irq;
00229 int irq_hook_id;
00230
00231 char ibuf[RS_IBUFSIZE];
00232 char obuf[RS_OBUFSIZE];
00233 } rs232_t;
00234
00235 PUBLIC rs232_t rs_lines[NR_RS_LINES];
00236
00237
00238 PRIVATE rs232_t *p_rs_addr[NR_RS_LINES];
00239
00240 #define rs_addr(line) (p_rs_addr[line])
00241
00242 #if (MACHINE == IBM_PC)
00243
00244 PRIVATE port_t addr_8250[] = {
00245 0x3F8,
00246 0x2F8,
00247 0x3E8,
00248 0x2E8,
00249 };
00250 #endif
00251
00252 FORWARD _PROTOTYPE( void in_int, (rs232_t *rs) );
00253 FORWARD _PROTOTYPE( void line_int, (rs232_t *rs) );
00254 FORWARD _PROTOTYPE( void modem_int, (rs232_t *rs) );
00255 FORWARD _PROTOTYPE( int rs_write, (tty_t *tp, int try) );
00256 FORWARD _PROTOTYPE( void rs_echo, (tty_t *tp, int c) );
00257 FORWARD _PROTOTYPE( int rs_ioctl, (tty_t *tp, int try) );
00258 FORWARD _PROTOTYPE( void rs_config, (rs232_t *rs) );
00259 FORWARD _PROTOTYPE( int rs_read, (tty_t *tp, int try) );
00260 FORWARD _PROTOTYPE( int rs_icancel, (tty_t *tp, int try) );
00261 FORWARD _PROTOTYPE( int rs_ocancel, (tty_t *tp, int try) );
00262 FORWARD _PROTOTYPE( void rs_ostart, (rs232_t *rs) );
00263 FORWARD _PROTOTYPE( int rs_break, (tty_t *tp, int try) );
00264 FORWARD _PROTOTYPE( int rs_close, (tty_t *tp, int try) );
00265 FORWARD _PROTOTYPE( void out_int, (rs232_t *rs) );
00266 FORWARD _PROTOTYPE( void rs232_handler, (rs232_t *rs) );
00267
00268
00269 PRIVATE void lock(void) {}
00270 PRIVATE void unlock(void) {}
00271
00272 PRIVATE int my_inb(port_t port)
00273 {
00274 int r;
00275 unsigned long v = 0;
00276 r = sys_inb(port, &v);
00277 if (r != OK)
00278 printf("RS232 warning: failed inb 0x%x\n", port);
00279
00280 return (int) v;
00281 }
00282
00283
00284
00285
00286 PRIVATE int rs_write(tp, try)
00287 register tty_t *tp;
00288 int try;
00289 {
00290
00291
00292 rs232_t *rs = tp->tty_priv;
00293 int count, ocount;
00294
00295 if (rs->inhibited != tp->tty_inhibited) {
00296
00297 lock();
00298 rs->ostate |= OSWREADY;
00299 if (tp->tty_inhibited) rs->ostate &= ~OSWREADY;
00300 unlock();
00301 rs->inhibited = tp->tty_inhibited;
00302 }
00303
00304 if (rs->drain) {
00305
00306 if (rs->ocount > 0) return 0;
00307 rs->drain = FALSE;
00308 rs_config(rs);
00309 }
00310
00311
00312 for (;;) {
00313 ocount = buflen(rs->obuf) - rs->ocount;
00314 count = bufend(rs->obuf) - rs->ohead;
00315 if (count > ocount) count = ocount;
00316 if (count > tp->tty_outleft) count = tp->tty_outleft;
00317 if (count == 0 || tp->tty_inhibited) {
00318 if (try) return 0;
00319 break;
00320 }
00321 if (try) return 1;
00322
00323
00324 sys_vircopy(tp->tty_outproc, D, (vir_bytes) tp->tty_out_vir,
00325 SELF, D, (vir_bytes) rs->ohead, (phys_bytes) count);
00326
00327
00328 out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
00329 if (count == 0) break;
00330
00331
00332 tp->tty_reprint = TRUE;
00333
00334
00335 lock();
00336 rs->ocount += ocount;
00337 rs_ostart(rs);
00338 unlock();
00339 if ((rs->ohead += ocount) >= bufend(rs->obuf))
00340 rs->ohead -= buflen(rs->obuf);
00341 tp->tty_out_vir += count;
00342 tp->tty_outcum += count;
00343 if ((tp->tty_outleft -= count) == 0) {
00344
00345 tty_reply(tp->tty_outrepcode, tp->tty_outcaller,
00346 tp->tty_outproc, tp->tty_outcum);
00347 tp->tty_outcum = 0;
00348 }
00349 }
00350 if (tp->tty_outleft > 0 && tp->tty_termios.c_ospeed == B0) {
00351
00352 tty_reply(tp->tty_outrepcode, tp->tty_outcaller, tp->tty_outproc, EIO);
00353 tp->tty_outleft = tp->tty_outcum = 0;
00354 }
00355
00356 return 1;
00357 }
00358
00359
00360
00361
00362 PRIVATE void rs_echo(tp, c)
00363 tty_t *tp;
00364 int c;
00365 {
00366
00367
00368 rs232_t *rs = tp->tty_priv;
00369 int count, ocount;
00370
00371 ocount = buflen(rs->obuf) - rs->ocount;
00372 if (ocount == 0) return;
00373 count = 1;
00374 *rs->ohead = c;
00375
00376 out_process(tp, rs->obuf, rs->ohead, bufend(rs->obuf), &count, &ocount);
00377 if (count == 0) return;
00378
00379 lock();
00380 rs->ocount += ocount;
00381 rs_ostart(rs);
00382 unlock();
00383 if ((rs->ohead += ocount) >= bufend(rs->obuf)) rs->ohead -= buflen(rs->obuf);
00384 }
00385
00386
00387
00388
00389 PRIVATE int rs_ioctl(tp, dummy)
00390 tty_t *tp;
00391 int dummy;
00392 {
00393
00394 rs232_t *rs = tp->tty_priv;
00395
00396 rs->drain = TRUE;
00397 return 0;
00398 }
00399
00400
00401
00402
00403 PRIVATE void rs_config(rs)
00404 rs232_t *rs;
00405 {
00406
00407
00408
00409
00410
00411 tty_t *tp = rs->tty;
00412 int divisor;
00413 int line_controls;
00414 static struct speed2divisor {
00415 speed_t speed;
00416 int divisor;
00417 } s2d[] = {
00418 #if (MACHINE == IBM_PC)
00419 { B50, UART_FREQ / 50 },
00420 #endif
00421 { B75, UART_FREQ / 75 },
00422 { B110, UART_FREQ / 110 },
00423 { B134, UART_FREQ * 10 / 1345 },
00424 { B150, UART_FREQ / 150 },
00425 { B200, UART_FREQ / 200 },
00426 { B300, UART_FREQ / 300 },
00427 { B600, UART_FREQ / 600 },
00428 { B1200, UART_FREQ / 1200 },
00429 #if (MACHINE == IBM_PC)
00430 { B1800, UART_FREQ / 1800 },
00431 #endif
00432 { B2400, UART_FREQ / 2400 },
00433 { B4800, UART_FREQ / 4800 },
00434 { B9600, UART_FREQ / 9600 },
00435 { B19200, UART_FREQ / 19200 },
00436 #if (MACHINE == IBM_PC)
00437 { B38400, UART_FREQ / 38400 },
00438 { B57600, UART_FREQ / 57600 },
00439 { B115200, UART_FREQ / 115200L },
00440 #endif
00441 };
00442 struct speed2divisor *s2dp;
00443
00444
00445 rs->oxoff = tp->tty_termios.c_cc[VSTOP];
00446 rs->cts = (tp->tty_termios.c_cflag & CLOCAL) ? MS_CTS : 0;
00447
00448
00449 divisor = 0;
00450 for (s2dp = s2d; s2dp < s2d + sizeof(s2d)/sizeof(s2d[0]); s2dp++) {
00451 if (s2dp->speed == tp->tty_termios.c_ospeed) divisor = s2dp->divisor;
00452 }
00453 if (divisor == 0) return;
00454
00455 #if (MACHINE == IBM_PC)
00456
00457 line_controls = 0;
00458 if (tp->tty_termios.c_cflag & PARENB) {
00459 line_controls |= LC_PARITY;
00460 if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= LC_PAREVEN;
00461 }
00462 if (divisor >= (UART_FREQ / 110)) line_controls |= LC_2STOP_BITS;
00463 line_controls |= (tp->tty_termios.c_cflag & CSIZE) >> 2;
00464
00465
00466
00467
00468
00469
00470 lock();
00471
00472
00473 sys_outb(rs->line_ctl_port, LC_ADDRESS_DIVISOR);
00474 sys_outb(rs->div_low_port, divisor);
00475 sys_outb(rs->div_hi_port, divisor >> 8);
00476
00477
00478 sys_outb(rs->line_ctl_port, line_controls);
00479
00480 rs->ostate = devready(rs) | ORAW | OSWREADY;
00481 if ((tp->tty_termios.c_lflag & IXON) && rs->oxoff != _POSIX_VDISABLE)
00482 rs->ostate &= ~ORAW;
00483
00484 unlock();
00485
00486 #else
00487
00488 line_controls = U_Q16;
00489 if (tp->tty_termios.c_cflag & PARENB) {
00490 line_controls |= U_PAR;
00491 if (!(tp->tty_termios.c_cflag & PARODD)) line_controls |= U_EVEN;
00492 }
00493 line_controls |= (divisor >= (UART_FREQ / 110)) ? U_ST2 : U_ST1;
00494
00495 switch (tp->tty_termios.c_cflag & CSIZE) {
00496 case CS5: line_controls |= U_D5; break;
00497 case CS5: line_controls |= U_D6; break;
00498 case CS5: line_controls |= U_D7; break;
00499 case CS5: line_controls |= U_D8; break;
00500 }
00501 lock();
00502 MFP->mf_ucr = line_controls;
00503 MFP->mf_tddr = divisor;
00504 unlock();
00505 #endif
00506 }
00507
00508
00509
00510
00511 PUBLIC void rs_init(tp)
00512 tty_t *tp;
00513 {
00514 unsigned long dummy;
00515
00516
00517 register rs232_t *rs;
00518 int line;
00519 #if (MACHINE == IBM_PC)
00520 port_t this_8250;
00521 int irq;
00522 long v;
00523 #endif
00524
00525
00526 line = tp - &tty_table[NR_CONS];
00527 rs = tp->tty_priv = &rs_lines[line];
00528 rs->tty = tp;
00529
00530
00531 rs->ihead = rs->itail = rs->ibuf;
00532
00533 #if (MACHINE == IBM_PC)
00534
00535 this_8250 = addr_8250[line];
00536 rs->xmit_port = this_8250 + 0;
00537 rs->recv_port = this_8250 + 0;
00538 rs->div_low_port = this_8250 + 0;
00539 rs->div_hi_port = this_8250 + 1;
00540 rs->int_enab_port = this_8250 + 1;
00541 rs->int_id_port = this_8250 + 2;
00542 rs->line_ctl_port = this_8250 + 3;
00543 rs->modem_ctl_port = this_8250 + 4;
00544 rs->line_status_port = this_8250 + 5;
00545 rs->modem_status_port = this_8250 + 6;
00546 #endif
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 istop(rs);
00562 rs_config(rs);
00563 #if (MACHINE == IBM_PC)
00564 sys_outb(rs->int_enab_port, 0);
00565 #endif
00566
00567
00568
00569
00570
00571 #if (MACHINE == IBM_PC)
00572 sys_inb(rs->line_status_port, &dummy);
00573 sys_inb(rs->recv_port, &dummy);
00574 #endif
00575 rs->ostate = devready(rs) | ORAW | OSWREADY;
00576 rs->ohead = rs->otail = rs->obuf;
00577
00578 #if (MACHINE == IBM_PC)
00579
00580 irq = (line & 1) == 0 ? RS232_IRQ : SECONDARY_IRQ;
00581
00582 rs->irq = irq;
00583 rs->irq_hook_id = rs->irq;
00584 if (sys_irqsetpolicy(irq, IRQ_REENABLE, &rs->irq_hook_id) != OK) {
00585 printf("RS232: Couldn't obtain hook for irq %d\n", irq);
00586 } else {
00587 if (sys_irqenable(&rs->irq_hook_id) != OK) {
00588 printf("RS232: Couldn't enable irq %d (hooked)\n", irq);
00589 }
00590 }
00591
00592 rs_irq_set |= (1 << irq);
00593
00594 sys_outb(rs->int_enab_port, IE_LINE_STATUS_CHANGE | IE_MODEM_STATUS_CHANGE
00595 | IE_RECEIVER_READY | IE_TRANSMITTER_READY);
00596 #else
00597
00598 MFP->mf_scr = 0x00;
00599 MFP->mf_tcdcr |= T_Q004;
00600 MFP->mf_rsr = R_ENA;
00601 MFP->mf_tsr = T_ENA;
00602 MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
00603 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
00604 MFP->mf_ddr = (MFP->mf_ddr & ~ (IO_SCTS|IO_SDCD));
00605 MFP->mf_iera |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
00606 MFP->mf_imra |= (IA_RRDY|IA_RERR|IA_TRDY|IA_TERR);
00607 MFP->mf_ierb |= (IB_SCTS|IB_SDCD);
00608 MFP->mf_imrb |= (IB_SCTS|IB_SDCD);
00609 #endif
00610
00611
00612 tp->tty_devread = rs_read;
00613 tp->tty_devwrite = rs_write;
00614 tp->tty_echo = rs_echo;
00615 tp->tty_icancel = rs_icancel;
00616 tp->tty_ocancel = rs_ocancel;
00617 tp->tty_ioctl = rs_ioctl;
00618 tp->tty_break = rs_break;
00619 tp->tty_close = rs_close;
00620
00621
00622 istart(rs);
00623
00624 }
00625
00626
00627
00628
00629 PUBLIC void rs_interrupt(m)
00630 message *m;
00631 {
00632 unsigned long irq_set;
00633 int i;
00634 rs232_t *rs;
00635
00636 irq_set= m->NOTIFY_ARG;
00637 for (i= 0, rs = rs_lines; i<NR_RS_LINES; i++, rs++)
00638 {
00639 if (irq_set & (1 << rs->irq))
00640 rs232_handler(rs);
00641 }
00642 }
00643
00644
00645
00646
00647 PRIVATE int rs_icancel(tp, dummy)
00648 tty_t *tp;
00649 int dummy;
00650 {
00651
00652 rs232_t *rs = tp->tty_priv;
00653
00654 lock();
00655 rs->icount = 0;
00656 rs->itail = rs->ihead;
00657 istart(rs);
00658 unlock();
00659
00660 return 0;
00661 }
00662
00663
00664
00665
00666 PRIVATE int rs_ocancel(tp, dummy)
00667 tty_t *tp;
00668 int dummy;
00669 {
00670
00671 rs232_t *rs = tp->tty_priv;
00672
00673 lock();
00674 rs->ostate &= ~(ODONE | OQUEUED);
00675 rs->ocount = 0;
00676 rs->otail = rs->ohead;
00677 unlock();
00678
00679 return 0;
00680 }
00681
00682
00683
00684
00685 PRIVATE int rs_read(tp, try)
00686 tty_t *tp;
00687 int try;
00688 {
00689
00690
00691 rs232_t *rs = tp->tty_priv;
00692 int icount, count, ostate;
00693
00694 if (!(tp->tty_termios.c_cflag & CLOCAL)) {
00695 if (try) return 1;
00696
00697 lock();
00698 ostate = rs->ostate;
00699 rs->ostate &= ~ODEVHUP;
00700 unlock();
00701 if (ostate & ODEVHUP) {
00702 sigchar(tp, SIGHUP);
00703 tp->tty_termios.c_ospeed = B0;
00704 return;
00705 }
00706 }
00707
00708 if (try) {
00709 if (rs->icount > 0)
00710 return 1;
00711 return 0;
00712 }
00713
00714 while ((count = rs->icount) > 0) {
00715 icount = bufend(rs->ibuf) - rs->itail;
00716 if (count > icount) count = icount;
00717
00718
00719 if ((count = in_process(tp, rs->itail, count)) == 0) break;
00720
00721 lock();
00722 rs->icount -= count;
00723 if (!rs->idevready && rs->icount < RS_ILOWWATER) istart(rs);
00724 unlock();
00725 if ((rs->itail += count) == bufend(rs->ibuf)) rs->itail = rs->ibuf;
00726 }
00727 }
00728
00729
00730
00731
00732 PRIVATE void rs_ostart(rs)
00733 rs232_t *rs;
00734 {
00735
00736
00737 rs->ostate |= OQUEUED;
00738 if (txready(rs)) out_int(rs);
00739 }
00740
00741
00742
00743
00744 PRIVATE int rs_break(tp, dummy)
00745 tty_t *tp;
00746 int dummy;
00747 {
00748
00749 rs232_t *rs = tp->tty_priv;
00750 unsigned long line_controls;
00751
00752 sys_inb(rs->line_ctl_port, &line_controls);
00753 sys_outb(rs->line_ctl_port, line_controls | LC_BREAK);
00754
00755
00756 printf("RS232 break\n");
00757 sys_outb(rs->line_ctl_port, line_controls);
00758 return 0;
00759 }
00760
00761
00762
00763
00764 PRIVATE int rs_close(tp, dummy)
00765 tty_t *tp;
00766 int dummy;
00767 {
00768
00769 rs232_t *rs = tp->tty_priv;
00770 int r;
00771
00772 if (tp->tty_termios.c_cflag & HUPCL) {
00773 sys_outb(rs->modem_ctl_port, MC_OUT2 | MC_RTS);
00774 }
00775 return 0;
00776 }
00777
00778
00779
00780 #if (MACHINE == IBM_PC)
00781
00782
00783
00784 PRIVATE void rs232_handler(rs)
00785 struct rs232 *rs;
00786 {
00787
00788
00789 while (TRUE) {
00790 unsigned long v;
00791
00792
00793
00794
00795
00796 sys_inb(rs->int_id_port, &v);
00797 switch (v) {
00798 case IS_RECEIVER_READY:
00799 in_int(rs);
00800 continue;
00801 case IS_TRANSMITTER_READY:
00802 out_int(rs);
00803 continue;
00804 case IS_MODEM_STATUS_CHANGE:
00805 modem_int(rs);
00806 continue;
00807 case IS_LINE_STATUS_CHANGE:
00808 line_int(rs);
00809 continue;
00810 }
00811 return;
00812 }
00813 }
00814 #endif
00815
00816 #if (MACHINE == ATARI)
00817
00818
00819
00820 PRIVATE void siaint(type)
00821 int type;
00822 {
00823
00824
00825
00826
00827
00828 register unsigned char code;
00829 register rs232_t *rs = &rs_lines[0];
00830 int s = lock();
00831
00832 switch (type & 0x00FF)
00833 {
00834 case 0x00:
00835 in_int(rs);
00836 break;
00837 case 0x01:
00838 line_int(rs);
00839 break;
00840 case 0x02:
00841 out_int(rs);
00842 break;
00843 case 0x03:
00844 code = MFP->mf_tsr;
00845 if (code & ~(T_ENA | T_UE | T_EMPTY))
00846 {
00847 printf("sia: transmit error: status=%x\r\n", code);
00848
00849 }
00850 break;
00851 case 0x04:
00852 modem_int(rs);
00853 break;
00854 }
00855 restore(s);
00856 }
00857 #endif
00858
00859
00860
00861
00862 PRIVATE void in_int(rs)
00863 register rs232_t *rs;
00864 {
00865
00866
00867
00868
00869
00870
00871
00872 unsigned long c;
00873
00874 #if (MACHINE == IBM_PC)
00875 sys_inb(rs->recv_port, &c);
00876 #else
00877 c = MFP->mf_udr;
00878 #endif
00879
00880 if (!(rs->ostate & ORAW)) {
00881 if (c == rs->oxoff) {
00882 rs->ostate &= ~OSWREADY;
00883 } else
00884 if (!(rs->ostate & OSWREADY)) {
00885 rs->ostate |= OSWREADY;
00886 if (txready(rs)) out_int(rs);
00887 }
00888 }
00889
00890 if (rs->icount == buflen(rs->ibuf))
00891 {
00892 printf("in_int: discarding byte\n");
00893 return;
00894 }
00895
00896 if (++rs->icount == RS_IHIGHWATER && rs->idevready) istop(rs);
00897 *rs->ihead = c;
00898 if (++rs->ihead == bufend(rs->ibuf)) rs->ihead = rs->ibuf;
00899 if (rs->icount == 1) {
00900 rs->tty->tty_events = 1;
00901 force_timeout();
00902 }
00903 else
00904 printf("in_int: icount = %d\n", rs->icount);
00905 }
00906
00907
00908
00909
00910 PRIVATE void line_int(rs)
00911 register rs232_t *rs;
00912 {
00913
00914
00915 unsigned long s;
00916 #if (MACHINE == IBM_PC)
00917 sys_inb(rs->line_status_port, &s);
00918 rs->lstatus = s;
00919 #else
00920 rs->lstatus = MFP->mf_rsr;
00921 MFP->mf_rsr &= R_ENA;
00922 rs->pad = MFP->mf_udr;
00923 #endif
00924 if (rs->lstatus & LS_FRAMING_ERR) ++rs->framing_errors;
00925 if (rs->lstatus & LS_OVERRUN_ERR) ++rs->overrun_errors;
00926 if (rs->lstatus & LS_PARITY_ERR) ++rs->parity_errors;
00927 if (rs->lstatus & LS_BREAK_INTERRUPT) ++rs->break_interrupts;
00928 }
00929
00930
00931
00932
00933 PRIVATE void modem_int(rs)
00934 register rs232_t *rs;
00935 {
00936
00937
00938
00939
00940 #if (MACHINE == ATARI)
00941
00942 MFP->mf_aer = (MFP->mf_aer | (IO_SCTS|IO_SDCD)) ^
00943 (MFP->mf_gpip & (IO_SCTS|IO_SDCD));
00944 #endif
00945
00946 if (devhup(rs)) {
00947 rs->ostate |= ODEVHUP;
00948 rs->tty->tty_events = 1;
00949 force_timeout();
00950 }
00951
00952 if (!devready(rs))
00953 rs->ostate &= ~ODEVREADY;
00954 else if (!(rs->ostate & ODEVREADY)) {
00955 rs->ostate |= ODEVREADY;
00956 if (txready(rs)) out_int(rs);
00957 }
00958 }
00959
00960
00961
00962
00963 PRIVATE void out_int(rs)
00964 register rs232_t *rs;
00965 {
00966
00967
00968
00969
00970
00971 if (rs->ostate >= (ODEVREADY | OQUEUED | OSWREADY)) {
00972
00973 #if (MACHINE == IBM_PC)
00974 sys_outb(rs->xmit_port, *rs->otail);
00975 #else
00976 MFP->mf_udr = *rs->otail;
00977 #endif
00978 if (++rs->otail == bufend(rs->obuf)) rs->otail = rs->obuf;
00979 if (--rs->ocount == 0) {
00980 rs->ostate ^= (ODONE | OQUEUED);
00981 rs->tty->tty_events = 1;
00982 force_timeout();
00983 } else
00984 if (rs->ocount == RS_OLOWWATER) {
00985 rs->tty->tty_events = 1;
00986 force_timeout();
00987 }
00988 }
00989 }
00990 #endif
00991