Subversion Repositories pentevo

Rev

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