home *** CD-ROM | disk | FTP | other *** search
/ ftp.whtech.com / ftp.whtech.com.7z / ftp.whtech.com / emulators / v9t9 / linux / sources / V9t9 / source / Modules / dsr_rs232.c < prev    next >
Encoding:
C/C++ Source or Header  |  2006-10-19  |  18.3 KB  |  816 lines

  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <errno.h>
  4. #include <stddef.h>
  5.  
  6. #include "v9t9_common.h"
  7. #include "v9t9.h"
  8. #include "roms.h"
  9. #include "cru.h"
  10. #include "command.h"
  11. #include "9900.h"
  12. #include "memory.h"
  13. #include "dsr.h"
  14. #include "timer.h"
  15.  
  16. #include "dsr_rs232.h"
  17.  
  18. extern vmModule realRS232DSR;
  19.  
  20. char        realrs232filename[OS_NAMESIZE] = "rs232.bin";
  21. u8          realrs232dsr[8192];
  22. char        rs232name[MAX_RS232_DEVS][OS_PATHSIZE] = { "", "" };
  23.  
  24. rs232regs   rsregs[MAX_RS232_DEVS];
  25.  
  26. #define _L     LOG_RS232 | LOG_INFO
  27. #if BUFFERED_RS232
  28. static int  rs232_interrupt_tag;
  29. #endif
  30.  
  31. /********************************************************************/
  32.  
  33.  
  34. static void 
  35. dumprs232(rs232regs * rs)
  36. {
  37.     logger(_L | L_3, "RS232:    loadctrl=%1X\t\n", rs->loadctrl);
  38.     if (rs->loadctrl >= 8) {
  39.         logger(_L | L_3, "* ");
  40.         logger(_L | L_3,
  41.              "ctrl=%02X\nrcl0=%d,rcl1=%d, clk4m=%d, Podd=%d,Penb=%d, SBS2=%d,SBS1=%d\t",
  42.              rs->ctrl, !!(rs->ctrl & CTRL_RCL0), !!(rs->ctrl & CTRL_RCL1),
  43.              !!(rs->ctrl & CTRL_CLK4M), !!(rs->ctrl & CTRL_Podd),
  44.              !!(rs->ctrl & CTRL_Penb), !!(rs->ctrl & CTRL_SBS2),
  45.              !!(rs->ctrl & CTRL_SBS1));
  46.     }
  47.     if (rs->loadctrl < 8 && rs->loadctrl >= 4) {
  48.         logger(_L | L_3 |  0, "* ");
  49.         logger(_L | L_3 |  0, "invl=%03X\t", rs->invl);
  50.     }
  51.     if (rs->loadctrl < 4 && rs->loadctrl >= 2) {
  52.         logger(_L | L_3, "* ");
  53.         logger(_L | L_3 |  0, "rcvrate=%03X\t", rs->rcvrate);
  54.     }
  55.     if (rs->loadctrl < 2 && rs->loadctrl >= 1) {
  56.         logger(_L | L_3, "* ");
  57.         logger(_L | L_3 |  0, "xmitrate=%03X\t", rs->xmitrate);
  58.     }
  59.     if (rs->loadctrl < 1) {
  60.         logger(_L | L_3, "* ");
  61.         logger(_L | L_3 |  0, "txchar=%02X (%c)\t", rs->txchar, rs->txchar);
  62.     }
  63.     logger(_L | L_3, "recvbps=%d, xmitbps=%d\n", rs->recvbps, rs->xmitbps);
  64.  
  65. #if BUFFERED_RS232
  66.     logger(_L | L_3, "Write buffer: %d/%d  Read buffer: %d/%d\n",
  67.          rs->t_st, rs->t_en, rs->r_st, rs->r_en);
  68. #endif
  69.  
  70. /*    logger(_L | L_3,"rtson=%d, brkon=%d, rienb=%d, xbienb=%d, timenb=%d, dscenb=%d\n",
  71.         !!(rs->wrport&RS_RTSON), !!(rs->wrport&RS_BRKON), !!(rs->wrport&RS_RIENB),
  72.         !!(rs->wrport&RS_XBIENB), !!(rs->wrport&RS_TIMEMB), !!(rs->wrport&RS_DSCENB));
  73.  
  74.     logger(_L | L_3,"rcverr=%d,rper=%d,rover=%d,rfer=%d,rfbd=%d,rsbd=%d,rin=%d\n",
  75.         !!(rs->rdport&RS_RCVERR), !!(rs->rdport&RS_RPER), !!(rs->rdport&RS_ROVER),
  76.         !!(rs->rdport&RS_RFER), !!(rs->rdport&RS_RFBD), !!(rs->rdport&RS_RSBD),
  77.         !!(rs->rdport&RS_RIN));
  78.     logger(_L | L_3,"rbint=%d,xbint=%d,timint=%d,dscint=%d,rbrl=%d,xbre=%d,xsre=%d\n",
  79.         !!(rs->rdport&RS_RBINT), !!(rs->rdport&RS_XBINT), !!(rs->rdport&RS_TIMINT), !!(rs->rdport&RS_DSCINT),
  80.         !!(rs->rdport&RS_RBRL), !!(rs->rdport&RS_XBRE), !!(rs->rdport&RS_XSRE));
  81.     logger(_L | L_3,"timerr=%d,timelp=%d,rts=%d,dsr=%d,cts=%d,dsch=%d,flag=%d,int=%d\n",
  82.         !!(rs->rdport&RS_TIMERR), !!(rs->rdport&RS_TIMELP), !!(rs->rdport&RS_RTS),
  83.         !!(rs->rdport&RS_DSR), !!(rs->rdport&RS_CTS), !!(rs->rdport&RS_DSCH),
  84.         !!(rs->rdport&RS_FLAG), !!(rs->rdport&RS_INT));
  85. */
  86. }
  87.  
  88. #define SETUP_RS232REGS(rs,addr)    rs232regs *rs = &rsregs[(addr - RS232_CRU_BASE) / 0x40 - 1]
  89.  
  90. /********************************************************************/
  91.  
  92. #if BUFFERED_RS232
  93.  
  94. /*    BUFFER STUFFERS    */
  95.  
  96. //  Update status bits when buffer state changes,
  97. //  possibly triggering an interrupt.
  98. static void
  99. Update_Flags_And_Ints(rs232regs * rs)
  100. {
  101.     bool        interruptible = false;
  102.  
  103.     // all buffered chars are immediately
  104.     // available to be read.
  105.     //
  106.     if (!BUFFER_EMPTY(rs, r)) {
  107.         rs->rdport |= RS_RBRL;
  108.  
  109.         // trigger interrupt?
  110.         if (rs->wrport & RS_RIENB) {
  111.             rs->rdport |= RS_RBINT;
  112.             interruptible = true;
  113.         }
  114.     } else {
  115.         rs->rdport &= ~(RS_RBRL | RS_RBINT);
  116.     }
  117.  
  118.     // contrary to popular opinion, we will set RS_XBRE
  119.     // here if the buffer is NOT FULL, so the 99/4A
  120.     // can continue to stuff the buffer.
  121.     //
  122.     if (!BUFFER_FULL(rs, t)) {
  123.         rs->rdport |= RS_XBRE;
  124.  
  125.         // trigger interrupt?
  126.         if (rs->wrport & RS_XBIENB) {
  127.             rs->rdport |= RS_XBINT;
  128.             interruptible = true;
  129.         }
  130.     } else {
  131.         rs->rdport &= ~(RS_XBRE | RS_XBINT);
  132.     }
  133.  
  134. #warning data lines
  135.  
  136.     //  NOTE:  when buffering, the DSR state can change physically
  137.     //  while interrupts should still be generated logically.
  138.     //  Be sure to bias the DSR state by the buffer state.
  139.     //
  140.     //  The typical routine for RS_RIENB goes like this:
  141.     //  
  142.     //  <interrupt>
  143.     //  test bit 31     -- must be 1 else RESET
  144.     //  test bit RBINT  -- must be 1 else RESET
  145.     //  test bit DSR    -- must be 1 else RESET
  146.     //  test bit RBRL   -- must be 1 else RESET
  147.     //  read char
  148.     //  set bit RIENB   -- ACK; this resets RBRL
  149.     // 
  150.     //  We will immediately set RBRL and RBINT again if needed.
  151.     //  We won't reset the interrupt state until all the bits
  152.     //  are off.
  153.  
  154.     if (interruptible) {
  155.         logger(_L | L_2, "*** Interrupt ***");
  156.         rs->rdport |= RS_INT;
  157.         trigger9901int(M_INT_EXT);
  158.     } else {
  159.         rs->rdport &= ~RS_INT;
  160.         reset9901int(M_INT_EXT);
  161.     }
  162. }
  163.  
  164.  
  165. static void
  166. Transmit_Char(rs232regs * rs)
  167. {
  168.     logger(_L | L_1, "Buffering char %02X (%c)\n\n", rs->txchar, rs->txchar);
  169.  
  170.     // Put char in buffer.  Kill most recent char if full.
  171.     if (!BUFFER_FULL(rs, t)) {
  172.         rs->xmit[rs->t_en] = rs->txchar;
  173.         rs->t_en = (rs->t_en + 1) & BUF_MASK;
  174.     } else {
  175.         rs->xmit[(rs->t_en - 1 + BUF_SIZ) & BUF_MASK] = rs->txchar;
  176.     }
  177.     Update_Flags_And_Ints(rs);
  178. }
  179.  
  180. static void
  181. Receive_Data(rs232regs * rs)
  182. {
  183.     // Get char from buffer, or last one if empty.
  184.     if (!BUFFER_EMPTY(rs, r)) {
  185.         rs->rdport = (rs->rdport & ~0xff) | rs->recv[rs->r_st];
  186.         rs->r_st = (rs->r_st + 1) & BUF_MASK;
  187.     } else {
  188.         rs->rdport = (rs->rdport & ~0xff) |
  189.             rs->recv[(rs->r_st - 1 + BUF_SIZ) & BUF_MASK];
  190.     }
  191.     Update_Flags_And_Ints(rs);
  192.     logger(_L | L_1, "Received char %02X (%c)\n", rs->rdport & 0xff, rs->rdport & 0xff);
  193. }
  194.  
  195. /*    Timer event which periodically checks the RS232 devices for
  196.     activity, reading into buffers and writing from buffers.
  197.     It is not efficient anywhere to call the OS for each status bit
  198.     read, which is why we eat up the buffers the OS is storing for us.     */
  199.  
  200. static void
  201. RS232_Monitor(void)
  202. {
  203.     int         rsidx;
  204.  
  205.     for (rsidx = 0; rsidx < MAX_RS232_DEVS; rsidx++) {
  206.         rs232regs  *rs = &rsregs[rsidx];
  207.  
  208.         // transmit buffered chars.
  209.         Transmit_Chars(rs);
  210.  
  211.         // receive characters from the OS.
  212.         // these are available for reading immediately.
  213.         Receive_Chars(rs);
  214.  
  215.         // update modem lines
  216.         Update_Modem_Lines(rs);
  217.  
  218.         // update status flags and interrupt if needed
  219.         Update_Flags_And_Ints(rs);
  220.     }
  221. }
  222.  
  223. static void
  224. Flush_Buffers(rs232regs * rs)
  225. {
  226.     logger(_L | L_1, "*** Flushing buffers");
  227.     // lose all readable data
  228.     rs->r_st = rs->r_en = 0;
  229.  
  230.     // send all writeable data
  231.     // (don't loop here!)
  232.     Transmit_Chars(rs);
  233.  
  234.     if (!BUFFER_EMPTY(rs, t)) {
  235.         logger(_L | L_1, "*** Transmit buffer was not empty\n");
  236.     }
  237.     rs->t_st = rs->t_en = 0;
  238.     dumprs232(rs);
  239. }
  240.  
  241. #else
  242.  
  243. #define Flush_Buffers(x)
  244.  
  245. #endif
  246.  
  247. /********************************************************************/
  248.  
  249. /*    WRITE BITS  */
  250.  
  251. /*    Load control register handler  
  252.  *
  253.  *    The highest bit set in loadctrl determines which 
  254.  *    write register is active.
  255.  */
  256.  
  257. static int  wrt_reg_offs[] = {
  258.     offsetof(rs232regs, txchar),    //  0
  259.     offsetof(rs232regs, xmitrate),    //  1
  260.     offsetof(rs232regs, rcvrate),    //  2
  261.     offsetof(rs232regs, rcvrate),    //  3
  262.     offsetof(rs232regs, invl),    //  4
  263.     offsetof(rs232regs, invl),    //  5
  264.     offsetof(rs232regs, invl),    //  6
  265.     offsetof(rs232regs, invl),    //  7
  266.     offsetof(rs232regs, ctrl),    //  8
  267.     offsetof(rs232regs, ctrl),    //  9
  268.     offsetof(rs232regs, ctrl),    //  10
  269.     offsetof(rs232regs, ctrl),    //  11
  270.     offsetof(rs232regs, ctrl),    //  12
  271.     offsetof(rs232regs, ctrl),    //  13
  272.     offsetof(rs232regs, ctrl),    //  14
  273.     offsetof(rs232regs, ctrl)    //  15
  274. };
  275.  
  276. #define WRT_REG(rs)    (*(u16 *)((u8 *)rs + wrt_reg_offs[rs->loadctrl&0xf]))
  277.  
  278. /*    
  279.  *    Flag bits for registers multiplexed through loadctrl
  280.  */
  281.  
  282. #define FLAG_TXCHAR(rs)        (1<<(RS_WORDSIZE(rs)-1))
  283. #define FLAG_XMITRATE(rs)    (1<<10)
  284. #define FLAG_RCVRATE(rs)    (1<<10)
  285. #define FLAG_INVL(rs)        (1<<7)
  286. #define FLAG_CTRL(rs)        (1<<7)
  287.  
  288. static void
  289. Calc_BPS_Rate(rs232regs * rs, u16 rate, u32 * bps)
  290. {
  291.     // BPS = 3 MHz / ((CLK4M ? 4 : 3) * 2 * rate x 8*DIV8)
  292.     u32         div;
  293.  
  294.     // input speed
  295.     div = (((rs->ctrl & CTRL_CLK4M) ? 4 : 3) * 2
  296.            * (rate & RATE_MASK) * ((rate & RATE_DIV8) ? 8 : 1));
  297.     if (div == 0)
  298.         *bps = 50;
  299.     else
  300.         *bps = (baseclockhz / div);
  301.  
  302.     logger(_L | L_1, "Calc_BPS_Rate:  *bps = %d\n\n", *bps);
  303. }
  304.  
  305. /*
  306.  *    Multiplexer for registers handled by loadctrl
  307.  *
  308.  */
  309.  
  310. static void
  311. Trigger_Change(rs232regs * rs, int cbit, int dbit)
  312. {
  313.     if ((cbit == 8) || (rs->loadctrl & 8)) {
  314.         if (!dbit || dbit == FLAG_CTRL(rs)) {
  315.             rs->ctrl = rs->wrbits & 0x7ff;
  316.             dumprs232(rs);
  317.             Set_CTRL_Register(rs);
  318.             Flush_Buffers(rs);
  319.             rs->loadctrl &= ~8;
  320.         }
  321.     } else if ((cbit == 4) || (rs->loadctrl & 4)) {
  322.         if (!dbit || dbit == FLAG_INVL(rs)) {
  323.             rs->invl = rs->wrbits & 0xff;
  324.             dumprs232(rs);
  325.             Set_INVL_Register(rs);
  326.             Flush_Buffers(rs);
  327.             rs->loadctrl &= ~4;
  328.         }
  329.     } else if (cbit == 1 || cbit == 2) {
  330.         if ((cbit == 2) || (rs->loadctrl & 2)) {
  331.             if (!dbit || dbit == FLAG_RCVRATE(rs)) {
  332.                 rs->rcvrate = rs->wrbits & 0x7ff;
  333.                 Calc_BPS_Rate(rs, rs->rcvrate, &rs->recvbps);
  334.                 dumprs232(rs);
  335.                 Set_RCVRATE_Register(rs);
  336.                 Flush_Buffers(rs);
  337.                 rs->loadctrl &= ~2;
  338.             }
  339.         }
  340.         if ((cbit == 1) || (rs->loadctrl & 1)) {
  341.             if (!dbit || dbit == FLAG_XMITRATE(rs)) {
  342.                 rs->xmitrate = rs->wrbits & 0x7ff;
  343.                 Calc_BPS_Rate(rs, rs->xmitrate, &rs->xmitbps);
  344.                 dumprs232(rs);
  345.                 Set_XMITRATE_Register(rs);
  346.                 Flush_Buffers(rs);
  347.                 rs->loadctrl &= ~1;
  348.             }
  349.         }
  350.     } else if (!dbit || dbit == FLAG_TXCHAR(rs)) {
  351.         rs->txchar = rs->wrbits & (0xff >> (8 - RS_WORDSIZE(rs)));
  352.         dumprs232(rs);
  353.         Transmit_Char(rs);
  354.     }
  355. }
  356.  
  357. /* 
  358.  *    Writes of low register bits
  359.  */
  360. static      u32
  361. RealRS232_0_10_w(u32 addr, u32 data, u32 num)
  362. {
  363.     u32         bit = 1 << ((addr & 0x1f) >> 1);
  364.  
  365.     SETUP_RS232REGS(rs, addr);
  366.  
  367.     if (bit >= 0x100) {
  368.         logger(_L | L_3, "RealRS232_0_10_w: %d / %d\n", (addr & 0x3f) / 2, data);
  369.     }
  370.  
  371.     rs->rdport &= ~RS_FLAG;
  372.  
  373.     if (data)
  374.         rs->wrbits |= bit;
  375.     else
  376.         rs->wrbits &= ~bit;
  377.  
  378.     if (bit == FLAG_TXCHAR(rs) && rs->loadctrl == 0) {
  379.         rs->txchar = rs->wrbits & (0xff >> (8 - RS_WORDSIZE(rs)));
  380.         dumprs232(rs);
  381.         Transmit_Char(rs);
  382.     }
  383.     return 0;
  384. }
  385.  
  386. /*
  387.  *    Load control register bits
  388.  */
  389. static      u32
  390. RealRS232_11_14_w(u32 addr, u32 data, u32 num)
  391. {
  392.     int         bit = 1 << (((addr & 0x1f) >> 1) - 11);
  393.     u16         old;
  394.  
  395.     SETUP_RS232REGS(rs, addr);
  396.  
  397.     logger(_L | L_3, "RealRS232_11_14_w: %d / %d\n", (addr & 0x3f) / 2, data);
  398.  
  399.     rs->rdport |= RS_FLAG;
  400.  
  401.     old = rs->loadctrl;
  402.     if (data)
  403.         rs->loadctrl |= bit;
  404.     else
  405.         rs->loadctrl &= ~bit;
  406.  
  407.     //  set this register
  408.     Trigger_Change(rs, bit, 0);
  409.     return 0;
  410. }
  411.  
  412.  
  413. /*
  414.  *    Remaining write ports
  415.  *
  416.  */
  417. static      u32
  418. RealRS232_16_21_w(u32 addr, u32 data, u32 num)
  419. {
  420.     u16         old;
  421.     u32         bit = 1 << ((addr & 0x3f) >> 1);
  422.  
  423.     SETUP_RS232REGS(rs, addr);
  424.  
  425.     logger(_L | L_3, "RealRS232_16_21_w: %d / %d\n", (addr & 0x3f) / 2, data);
  426.  
  427.     old = rs->wrport;
  428.     if (data)
  429.         rs->wrport |= bit;
  430.     else
  431.         rs->wrport &= ~bit;
  432.  
  433.     dumprs232(rs);
  434.     Set_Control_Bits(rs, old, bit);
  435.     return 0;
  436. }
  437.  
  438. /*
  439.  *    Read character
  440.  *
  441.  */
  442. static      u32
  443. RealRS232_0_7_r(u32 addr, u32 data, u32 num)
  444. {
  445.     u32         bit = 1 << ((addr & 0xf) >> 1);
  446.     u32         ret;
  447.  
  448.     SETUP_RS232REGS(rs, addr);
  449.  
  450.     if (bit == 1) {
  451.         Receive_Data(rs);
  452.         dumprs232(rs);
  453.     }
  454.  
  455.     ret = !!(rs->rdport & bit);
  456.  
  457.     if (bit >= 0x100) {
  458.         logger(_L | L_3, "RealRS232_0_7_r: %04X / %d\n", addr, ret);
  459.     }
  460.  
  461.     return ret;
  462. }
  463.  
  464. /*
  465.  *    Read status bit
  466.  *
  467.  */
  468. static      u32
  469. RealRS232_9_31_r(u32 addr, u32 data, u32 num)
  470. {
  471.     u32         bit = 1 << ((addr & 0x3f) >> 1);
  472.     u32         ret;
  473.  
  474.     SETUP_RS232REGS(rs, addr);
  475.  
  476.     Read_Status_Bits(rs);
  477.  
  478. #if BUFFERED_RS232
  479.     // force DSR while buffer is nonempty
  480.     if (!BUFFER_EMPTY(rs, r)) {
  481.         rs->rdport |= RS_DSR;
  482.     }
  483. #endif
  484.  
  485.     dumprs232(rs);
  486.  
  487.     ret = !!(rs->rdport & bit);
  488.  
  489.     //  turn off bit once read
  490. //  if (bit == RS_INT || bit == RS_RBINT || bit == RS_XBINT || 
  491. //      bit == RS_TIMINT || bit == RS_DSCINT) 
  492. //      rs->rdport &= ~bit;
  493.  
  494.     logger(_L | L_3, "RealRS232_9_31_r: %d / %d\n", (addr & 0x3f) / 2, ret);
  495.     return ret;
  496. }
  497.  
  498. static      u32
  499. RealRS232_Reset_w(u32 addr, u32 data, u32 base)
  500. {
  501.     SETUP_RS232REGS(rs, addr);
  502.  
  503.     logger(_L | L_3, "RealRS232_Reset_w: %d\n", data);
  504.  
  505.     if (data) {
  506. #if BUFFERED_RS232
  507.         if (rs232_interrupt_tag)
  508.             TM_ResetEvent(rs232_interrupt_tag);
  509. #endif
  510.         memset(rs, 0, sizeof(rs232regs));
  511.         rs->loadctrl = 0xf;
  512.         Set_CTRL_Register(rs);
  513.         Set_INVL_Register(rs);
  514.         Set_RCVRATE_Register(rs);
  515.         Set_XMITRATE_Register(rs);
  516.         Reset_RS232_SysDeps(rs);
  517.         dumprs232(rs);
  518.  
  519. #if BUFFERED_RS232
  520.         if (!rs232_interrupt_tag)
  521.             rs232_interrupt_tag = TM_UniqueTag();
  522.  
  523.         TM_SetEvent(rs232_interrupt_tag, TM_HZ, 0, TM_FUNC | TM_REPEAT,
  524.                     RS232_Monitor);
  525. #endif
  526.     }
  527.     return 0;
  528. }
  529.  
  530. /********************************************************************/
  531.  
  532. mrstruct    dsr_rom_realrs232_handler = {
  533.     realrs232dsr, realrs232dsr, NULL,            /* ROM */
  534.     NULL,
  535.     NULL,
  536.     NULL,
  537.     NULL
  538. };
  539.  
  540. static      u32
  541. RealRS232ROM_w(u32 addr, u32 data, u32 num)
  542. {
  543.     if (data) {
  544. //        logger(_L | L_1, "real RS232 DSR on\n");
  545.         report_status(STATUS_RS232_ACCESS, 0, true);
  546. //      debugger_enable(true);
  547.         dsr_set_active(&realRS232DSR);
  548.  
  549.         SET_AREA_HANDLER(0x4000, 0x2000, &dsr_rom_realrs232_handler);
  550.  
  551.     } else {
  552. //        logger(_L | 0, "real RS232 DSR off\n");
  553.         report_status(STATUS_RS232_ACCESS, 0, false);
  554. //      if (pc<0x2000)
  555. //      debugger_enable(false);
  556.         dsr_set_active(NULL);
  557.         SET_AREA_HANDLER(0x4000, 0x2000, &zero_memory_handler);
  558.     }
  559.     return 0;
  560. }
  561.  
  562.  
  563. /************************************/
  564.  
  565.  
  566. static      vmResult
  567. realrs232_getcrubase(u32 * base)
  568. {
  569.     *base = RS232_CRU_BASE;
  570.     return vmOk;
  571. }
  572.  
  573. static      vmResult
  574. realrs232_filehandler(u32 code)
  575. {
  576.     return vmOk;
  577. }
  578.  
  579. static      vmResult
  580. realrs232_detect(void)
  581. {
  582.     return vmOk;
  583. }
  584.  
  585. static      vmResult
  586. realrs232_init(void)
  587. {
  588.     command_symbol_table *realrs232commands =
  589.         command_symbol_table_new("TI RS232 DSR Options",
  590.                                  "These commands control the TI RS232 emulation",
  591.  
  592.          command_symbol_new("RS232_1",
  593.                             "Give local name for first RS232 port",
  594.                             c_DONT_SAVE,
  595.                             NULL /* action */ ,
  596.                             RET_FIRST_ARG,
  597.                             command_arg_new_string
  598.                             ("filename",
  599.                              "filename or device for current operating system",
  600.                              NULL /* action */ ,
  601.                              ARG_STR(rs232name[0]),
  602.                              NULL /* next */ )
  603.                             ,
  604.  
  605.           command_symbol_new("RS232_2",
  606.                              "Give local name for second RS232 port",
  607.                              c_DONT_SAVE,
  608.                              NULL /* action */ ,
  609.                              RET_FIRST_ARG,
  610.                              command_arg_new_string
  611.                              ("filename",
  612.                               "filename or device for current operating system",
  613.                               NULL /* action */ ,
  614.                               ARG_STR(rs232name[1]),
  615.                               NULL /* next */ )
  616.                              ,
  617.  
  618.            command_symbol_new("RS232DSRFileName",
  619.                               "Name of RS232 DSR ROM image which fits in the CPU address space >4000...>5FFF",
  620.                               c_STATIC,
  621.                               NULL /* action */ ,
  622.                               RET_FIRST_ARG,
  623.                               command_arg_new_string
  624.                               ("file",
  625.                                "name of binary image",
  626.                                NULL /* action */ ,
  627.                                ARG_STR
  628.                                (realrs232filename),
  629.                                NULL /* next */ )
  630.                               ,
  631.  
  632.           NULL /* next */ ))),
  633.  
  634.          NULL /* sub */ ,
  635.  
  636.          NULL    /* next */
  637.         );
  638.  
  639.     command_symbol_table_add_subtable(universe, realrs232commands);
  640.  
  641.     return Init_RS232_SysDeps();
  642. }
  643.  
  644. static struct {
  645.     int         bit;
  646.     crufunc    *func;
  647. } rs232_writers[] = {
  648.     0, RealRS232_0_10_w,
  649.         1, RealRS232_0_10_w,
  650.         2, RealRS232_0_10_w,
  651.         3, RealRS232_0_10_w,
  652.         4, RealRS232_0_10_w,
  653.         5, RealRS232_0_10_w,
  654.         6, RealRS232_0_10_w,
  655.         7, RealRS232_0_10_w,
  656.         8, RealRS232_0_10_w,
  657.         9, RealRS232_0_10_w,
  658.         10, RealRS232_0_10_w,
  659.         11, RealRS232_11_14_w,
  660.         12, RealRS232_11_14_w,
  661.         13, RealRS232_11_14_w,
  662.         14, RealRS232_11_14_w,
  663.         16, RealRS232_16_21_w,
  664.         17, RealRS232_16_21_w,
  665.         18, RealRS232_16_21_w,
  666.         19, RealRS232_16_21_w,
  667.         20, RealRS232_16_21_w,
  668.         21, RealRS232_16_21_w, 31, RealRS232_Reset_w, -1, 0};
  669.  
  670. static struct {
  671.     int         bit;
  672.     crufunc    *func;
  673. } rs232_readers[] = {
  674.     0, RealRS232_0_7_r,
  675.         1, RealRS232_0_7_r,
  676.         2, RealRS232_0_7_r,
  677.         3, RealRS232_0_7_r,
  678.         4, RealRS232_0_7_r,
  679.         5, RealRS232_0_7_r,
  680.         6, RealRS232_0_7_r,
  681.         7, RealRS232_0_7_r,
  682.         9, RealRS232_9_31_r,
  683.         10, RealRS232_9_31_r,
  684.         11, RealRS232_9_31_r,
  685.         12, RealRS232_9_31_r,
  686.         13, RealRS232_9_31_r,
  687.         14, RealRS232_9_31_r,
  688.         15, RealRS232_9_31_r,
  689.         16, RealRS232_9_31_r,
  690.         17, RealRS232_9_31_r,
  691.         19, RealRS232_9_31_r,
  692.         20, RealRS232_9_31_r,
  693.         21, RealRS232_9_31_r,
  694.         22, RealRS232_9_31_r,
  695.         23, RealRS232_9_31_r,
  696.         24, RealRS232_9_31_r,
  697.         25, RealRS232_9_31_r,
  698.         26, RealRS232_9_31_r,
  699.         27, RealRS232_9_31_r,
  700.         28, RealRS232_9_31_r,
  701.         29, RealRS232_9_31_r,
  702.         30, RealRS232_9_31_r, 31, RealRS232_9_31_r, -1, 0};
  703.  
  704. static int
  705. add_rs232_device(int base)
  706. {
  707.     int         idx;
  708.  
  709.     for (idx = 0; rs232_writers[idx].bit >= 0; idx++) {
  710.         if (!cruadddevice(CRU_WRITE,
  711.                           RS232_CRU_BASE + base + rs232_writers[idx].bit * 2,
  712.                           1, rs232_writers[idx].func))
  713.             return 0;
  714.     }
  715.     for (idx = 0; rs232_readers[idx].bit >= 0; idx++) {
  716.         if (!cruadddevice(CRU_READ,
  717.                           RS232_CRU_BASE + base + rs232_readers[idx].bit * 2,
  718.                           1, rs232_readers[idx].func))
  719.             return 0;
  720.     }
  721.     return 1;
  722. }
  723.  
  724. static int
  725. del_rs232_device(int base)
  726. {
  727.     int         idx;
  728.  
  729.     for (idx = 0; rs232_writers[idx].bit >= 0; idx++) {
  730.         if (!crudeldevice(CRU_WRITE,
  731.                           RS232_CRU_BASE + base + rs232_writers[idx].bit * 2,
  732.                           1, rs232_writers[idx].func))
  733.             return 0;
  734.     }
  735.     for (idx = 0; rs232_readers[idx].bit >= 0; idx++) {
  736.         if (!crudeldevice(CRU_READ,
  737.                           RS232_CRU_BASE + base + rs232_readers[idx].bit * 2,
  738.                           1, rs232_readers[idx].func))
  739.             return 0;
  740.     }
  741.     return 1;
  742. }
  743.  
  744. static      vmResult
  745. realrs232_enable(void)
  746. {
  747.     vmResult    res;
  748.  
  749.     logger(_L | L_1, "setting up TI RS232 DSR ROM\n");
  750.     if (0 == loaddsr(romspath, systemromspath, realrs232filename,
  751.                      "TI RS232 DSR ROM", realrs232dsr)) return vmNotAvailable;
  752.  
  753.     res = Enable_RS232_SysDeps();
  754.     if (res != vmOk)
  755.         return vmNotAvailable;
  756.  
  757.     if (cruadddevice(CRU_WRITE, RS232_CRU_BASE, 1, RealRS232ROM_w) &&
  758.         add_rs232_device(0x40) && add_rs232_device(0x80)) {
  759.         return vmOk;
  760.     } else
  761.         return vmNotAvailable;
  762. }
  763.  
  764. static      vmResult
  765. realrs232_disable(void)
  766. {
  767.     Disable_RS232_SysDeps();
  768.     crudeldevice(CRU_WRITE, RS232_CRU_BASE, 1, RealRS232ROM_w);
  769.     del_rs232_device(0x40);
  770.     del_rs232_device(0x80);
  771.     return vmOk;
  772. }
  773.  
  774. static      vmResult
  775. realrs232_restart(void)
  776. {
  777.     return vmOk;
  778. }
  779.  
  780. static      vmResult
  781. realrs232_restop(void)
  782. {
  783.     return vmOk;
  784. }
  785.  
  786. static      vmResult
  787. realrs232_term(void)
  788. {
  789.     Term_RS232_SysDeps();
  790.     return vmOk;
  791. }
  792.  
  793. static vmDSRModule realRS232Module = {
  794.     1,
  795.     realrs232_getcrubase,
  796.     realrs232_filehandler
  797. };
  798.  
  799. vmModule    realRS232DSR = {
  800.     3,
  801.     "TI real-RS232 DSR",
  802.     "dsrRealRS232",
  803.  
  804.     vmTypeDSR,
  805.     vmFlagsNone,
  806.  
  807.     realrs232_detect,
  808.     realrs232_init,
  809.     realrs232_term,
  810.     realrs232_enable,
  811.     realrs232_disable,
  812.     realrs232_restart,
  813.     realrs232_restop,
  814.     {(vmGenericModule *) & realRS232Module}
  815. };
  816.