Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5.  
  6. #include "util.h"
  7.  
  8. void ISA_MODEM::open(int port)
  9. {
  10.    if (open_port == port)
  11.        return;
  12.    whead = wtail = rhead = rtail = 0;
  13.    if (hPort && hPort != INVALID_HANDLE_VALUE)
  14.    {
  15.        CloseHandle(hPort);
  16.        CloseHandle(OvW.hEvent);
  17.        CloseHandle(OvR.hEvent);
  18.    }
  19.    if (port < 1 || port > 255)
  20.        return;
  21.  
  22.    open_port = port;
  23.  
  24.    char portName[11];
  25.    _snprintf(portName, _countof(portName), "\\\\.\\COM%d", port);
  26.  
  27.    hPort = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
  28.    if (hPort == INVALID_HANDLE_VALUE)
  29.    {
  30.       errmsg("can't open modem on %s", portName); err_win32();
  31.       conf.modem_port = open_port = 0;
  32.       return;
  33.    }
  34.  
  35.    memset(&OvW, 0, sizeof(OvW));
  36.    memset(&OvR, 0, sizeof(OvR));
  37.  
  38.    OvW.hEvent = CreateEvent(0, TRUE, TRUE, 0);
  39.    OvR.hEvent = CreateEvent(0, TRUE, TRUE, 0);
  40.  
  41.    COMMTIMEOUTS times;
  42.    times.ReadIntervalTimeout = MAXDWORD;
  43.    times.ReadTotalTimeoutMultiplier = 0;
  44.    times.ReadTotalTimeoutConstant = 0;
  45.    times.WriteTotalTimeoutMultiplier = 0;
  46.    times.WriteTotalTimeoutConstant = 0;
  47.    SetCommTimeouts(hPort, &times);
  48.  
  49. #if 0
  50.    DCB dcb;
  51.    if (GetCommState(hPort, &dcb)) {
  52.       printf(
  53.        "modem state:\n"
  54.        "rate=%d\n"
  55.        "parity=%d, OutxCtsFlow=%d, OutxDsrFlow=%d, DtrControl=%d, DsrSensitivity=%d\n"
  56.        "TXContinueOnXoff=%d, OutX=%d, InX=%d, ErrorChar=%d\n"
  57.        "Null=%d, RtsControl=%d, AbortOnError=%d, XonLim=%d, XoffLim=%d\n"
  58.        "ByteSize=%d, Parity=%d, StopBits=%d\n"
  59.        "XonChar=#%02X, XoffChar=#%02X, ErrorChar=#%02X, EofChar=#%02X, EvtChar=#%02X\n\n",
  60.        dcb.BaudRate,
  61.        dcb.fParity, dcb.fOutxCtsFlow, dcb.fOutxDsrFlow, dcb.fDtrControl, dcb.fDsrSensitivity,
  62.        dcb.fTXContinueOnXoff, dcb.fOutX, dcb.fInX, dcb.fErrorChar,
  63.        dcb.fNull, dcb.fRtsControl, dcb.fAbortOnError, dcb.XonLim, dcb.XoffLim,
  64.        dcb.ByteSize, dcb.Parity, dcb.StopBits,
  65.        (BYTE)dcb.XonChar, (BYTE)dcb.XoffChar, (BYTE)dcb.ErrorChar, (BYTE)dcb.EofChar, (BYTE)dcb.EvtChar);
  66.    }
  67. #endif
  68. }
  69.  
  70. void ISA_MODEM::close()
  71. {
  72.    if (!hPort || hPort == INVALID_HANDLE_VALUE)
  73.        return;
  74.    CloseHandle(hPort);
  75.    hPort = INVALID_HANDLE_VALUE;
  76.    open_port = 0;
  77.    CloseHandle(OvW.hEvent);
  78.    CloseHandle(OvR.hEvent);
  79. }
  80.  
  81. void ISA_MODEM::io()
  82. {
  83.    if (!hPort || hPort == INVALID_HANDLE_VALUE)
  84.        return;
  85.  
  86.    static u8 tempwr[BSIZE];
  87.    static u8 temprd[BSIZE];
  88.  
  89.    DWORD written = 0;
  90.    bool WrReady = false;
  91.    if(WaitForSingleObject(OvW.hEvent, 0) == WAIT_OBJECT_0)
  92.    {
  93.        written = OvW.InternalHigh;
  94.        OvW.InternalHigh = 0;
  95.        wtail = (wtail+written) & (BSIZE-1);
  96. /*
  97.        if(written)
  98.        {
  99.            printf("write complete: %d\n", written);
  100.        }
  101. */
  102.        WrReady = true;
  103.    }
  104.  
  105.    int needwrite = whead - wtail;
  106.    if (needwrite < 0)
  107.        needwrite += BSIZE;
  108.    if (needwrite && WrReady)
  109.    {
  110.       if (whead > wtail)
  111.           memcpy(tempwr, wbuf+wtail, needwrite);
  112.       else
  113.       {
  114.           memcpy(tempwr, wbuf+wtail, BSIZE-wtail);
  115.           memcpy(tempwr+BSIZE-wtail, wbuf, whead);
  116.       }
  117.  
  118.       if (WriteFile(hPort, tempwr, needwrite, &written, &OvW))
  119.       {
  120.       // printf("\nsend: "); dump1(temp, written);
  121.       // printf("writen : %d, %d\n", needwrite, written);
  122.       }
  123.       else
  124.       {
  125.       // printf("write pending : %d, %d\n", needwrite, written);
  126.       }
  127.    }
  128.    if (((whead+1) & (BSIZE-1)) != wtail)
  129.        reg[5] |= 0x60;
  130.  
  131.    bool RdReady = false;
  132.    DWORD read = 0;
  133.    if(WaitForSingleObject(OvR.hEvent, 0) == WAIT_OBJECT_0)
  134.    {
  135.        read = OvR.InternalHigh;
  136.        OvR.InternalHigh = 0;
  137.        if(read)
  138.        {
  139.           for (unsigned i = 0; i < read; i++)
  140.           {
  141.               rcbuf[rhead++] = temprd[i];
  142.               rhead &= (BSIZE-1);
  143.           }
  144.        }
  145.  
  146.        RdReady = true;
  147.    }
  148.  
  149.    int canread = rtail - rhead - 1;
  150.    if (canread < 0)
  151.        canread += BSIZE;
  152.    if (canread && RdReady)
  153.    {
  154.       if (ReadFile(hPort, temprd, canread, &read, &OvR) && read)
  155.       {
  156. //printf("\nrecv: "); dump1(temp, read);
  157.       }
  158.    }
  159.    if (rhead != rtail)
  160.        reg[5] |= 1;
  161.  
  162.    setup_int();
  163. }
  164.  
  165. void ISA_MODEM::setup_int()
  166. {
  167.    reg[6] &= ~0x10;
  168.  
  169.    unsigned char mask = reg[5] & 1;
  170.    if (reg[5] & 0x20) mask |= 2, reg[6] |= 0x10;
  171.    if (reg[5] & 0x1E) mask |= 4;
  172.    // if (mask & reg[1]) cpu.nmi()
  173.  
  174.    if (mask & 4) reg[2] = 6;
  175.    else if (mask & 1) reg[2] = 4;
  176.    else if (mask & 2) reg[2] = 2;
  177.    else if (mask & 8) reg[2] = 0;
  178.    else reg[2] = 1;
  179. }
  180.  
  181. void ISA_MODEM::write(unsigned nreg, unsigned char value)
  182. {
  183.    DCB dcb;
  184.  
  185.    if ((1<<nreg) & ((1<<2)|(1<<5)|(1<<6)))
  186.        return; // R/O registers
  187.  
  188.    if (nreg < 2 && (reg[3] & 0x80))
  189.    {
  190.      div[nreg] = value;
  191.      if (GetCommState(hPort, &dcb))
  192.      {
  193.        if (!divfq)
  194.            divfq = 1;
  195.        dcb.BaudRate = 115200 / divfq;
  196.        SetCommState(hPort, &dcb);
  197.      }
  198.      return;
  199.    }
  200.  
  201.    if (nreg == 0)
  202.    { // THR, write char to output buffer
  203.       reg[5] &= ~0x60;
  204.       if (((whead+1) & (BSIZE-1)) == wtail)
  205.       {
  206. /*
  207.          printf("write to ful FIFO\n");
  208.          reg[5] |= 2; // Overrun error  (╬°шсър, ¤ЄюЄ сшЄ Єюы№ъю эр яЁшхь, р эх эр яхЁхфрўє)
  209. */
  210.       }
  211.       else
  212.       {
  213.          wbuf[whead++] = value;
  214.          whead &= (BSIZE-1);
  215.          if (((whead+1) & (BSIZE-1)) != wtail)
  216.              reg[5] |= 0x60; // Transmitter holding register empty | transmitter empty
  217.       }
  218.       setup_int();
  219.       return;
  220.    }
  221.  
  222.    u8 old = reg[nreg];
  223.    reg[nreg] = value;
  224.  
  225.    if(nreg == 2) // FCR
  226.    {
  227.        ULONG Flags = 0;
  228.        if(value & 2) // RX FIFO reset
  229.            Flags |= PURGE_RXCLEAR | PURGE_RXABORT;
  230.  
  231.        if(value & 4) // TX FIFO reset
  232.            Flags |= PURGE_TXCLEAR | PURGE_TXABORT;
  233.  
  234.        if(Flags)
  235.            PurgeComm(hPort, Flags);
  236.    }
  237.  
  238.    // Thu 28 Jul 2005. transfer mode control (code by Alex/AT)
  239.  
  240.    if (nreg == 3)
  241.    {
  242.       // LCR set, renew modem config
  243.       if (!GetCommState(hPort, &dcb))
  244.           return;
  245.  
  246.       dcb.fBinary = TRUE;
  247.       dcb.fParity = (reg[3] & 8)? TRUE : FALSE;
  248.       dcb.fOutxCtsFlow = FALSE;
  249.       dcb.fOutxDsrFlow = FALSE;
  250.       dcb.fDtrControl = DTR_CONTROL_DISABLE;
  251.       dcb.fDsrSensitivity = FALSE;
  252.       dcb.fTXContinueOnXoff = FALSE;
  253.       dcb.fOutX = FALSE;
  254.       dcb.fInX = FALSE;
  255.       dcb.fErrorChar = FALSE;
  256.       dcb.fNull = FALSE;
  257.       dcb.fRtsControl = RTS_CONTROL_DISABLE;
  258.       dcb.fAbortOnError = FALSE;
  259.       dcb.ByteSize = 5 + (reg[3] & 3); // fix by Deathsoft
  260.  
  261.       static const BYTE parity[] = { ODDPARITY, EVENPARITY, MARKPARITY, SPACEPARITY };
  262.       dcb.Parity = (reg[3] & 8) ? parity[(reg[3]>>4) & 3] : NOPARITY;
  263.  
  264.       if (!(reg[3] & 4)) dcb.StopBits = ONESTOPBIT;
  265.       else dcb.StopBits = ((reg[3] & 3) == 1) ? ONE5STOPBITS : TWOSTOPBITS;
  266.  
  267.       SetCommState(hPort, &dcb);
  268.       return;
  269.    }
  270.  
  271.    if (nreg == 4)
  272.    {
  273.       // MCR set, renew DTR/RTS
  274.       if((old ^ reg[4]) & 0x20) // auto rts/cts toggled
  275.       {
  276.           if (!GetCommState(hPort, &dcb))
  277.               return;
  278.  
  279.           if(reg[4] & 0x20) // auto rts/cts enabled
  280.           {
  281.               dcb.fOutxCtsFlow = TRUE;
  282.               dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
  283.           }
  284.           else // auto rts/cts disabled
  285.           {
  286.               dcb.fOutxCtsFlow = FALSE;
  287.               dcb.fRtsControl = RTS_CONTROL_DISABLE;
  288.           }
  289.           SetCommState(hPort, &dcb);
  290.       }
  291.  
  292.       if(!(reg[4] & 0x20)) // auto rts/cts disabled
  293.       {
  294.           if((old ^ reg[4]) & 1)
  295.           {
  296.               EscapeCommFunction(hPort, (reg[4] & 1) ? SETDTR : CLRDTR);
  297.           }
  298.  
  299.           if((old ^ reg[4]) & 2)
  300.           {
  301.               EscapeCommFunction(hPort, (reg[4] & 2) ? SETRTS : CLRRTS);
  302.           }
  303.       }
  304.    }
  305. }
  306.  
  307. unsigned char ISA_MODEM::read(unsigned nreg)
  308. {
  309.    if (nreg < 2 && (reg[3] & 0x80))
  310.        return div[nreg];
  311.  
  312.    unsigned char result = reg[nreg];
  313.  
  314.    if (nreg == 0)
  315.    { // read char from buffer
  316.       if (rhead != rtail)
  317.       {
  318.            result = reg[0] = rcbuf[rtail++];
  319.            rtail &= (BSIZE-1);
  320.       }
  321.  
  322.       if (rhead != rtail)
  323.           reg[5] |= 1;
  324.       else
  325.           reg[5] &= ~1;
  326.  
  327.       setup_int();
  328.    }
  329.  
  330.    if (nreg == 5)
  331.    {
  332.        reg[5] &= ~0x0E;
  333.        setup_int();
  334.    }
  335.  
  336.    if (nreg == 6)
  337.    {
  338.        DWORD ModemStatus;
  339.        GetCommModemStatus(hPort, &ModemStatus);
  340.        u8 r6 = reg[6];
  341.        reg[6] &= ~(1 << 4);
  342.        reg[6] |= (ModemStatus & MS_CTS_ON) ? (1 << 4): 0;
  343.        reg[6] &= ~1;
  344.        reg[6] |= ((r6 ^ reg[6]) & (1 << 4)) >> 4;
  345.        result = reg[6];
  346.    }
  347.    return result;
  348. }
  349.