Subversion Repositories pentevo

Rev

Rev 883 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 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
 
784 DimkaM 22
   open_port = u8(port);
716 lvd 23
 
24
   char portName[11];
25
   _snprintf(portName, _countof(portName), "\\\\.\\COM%d", port);
26
 
784 DimkaM 27
   hPort = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
716 lvd 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
 
784 DimkaM 38
   OvW.hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
39
   OvR.hEvent = CreateEvent(nullptr, TRUE, TRUE, nullptr);
716 lvd 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
   {
784 DimkaM 93
       written = ULONG(OvW.InternalHigh);
716 lvd 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
 
784 DimkaM 105
   int needwrite = int(whead - wtail);
716 lvd 106
   if (needwrite < 0)
107
       needwrite += BSIZE;
108
   if (needwrite && WrReady)
109
   {
110
      if (whead > wtail)
784 DimkaM 111
          memcpy(tempwr, wbuf+wtail, size_t(needwrite));
716 lvd 112
      else
113
      {
114
          memcpy(tempwr, wbuf+wtail, BSIZE-wtail);
115
          memcpy(tempwr+BSIZE-wtail, wbuf, whead);
116
      }
117
 
784 DimkaM 118
      if (WriteFile(hPort, tempwr, DWORD(needwrite), &written, &OvW))
716 lvd 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
   {
784 DimkaM 135
       read = ULONG(OvR.InternalHigh);
716 lvd 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
 
784 DimkaM 149
   int canread = int(rtail - rhead - 1);
716 lvd 150
   if (canread < 0)
151
       canread += BSIZE;
152
   if (canread && RdReady)
153
   {
784 DimkaM 154
      if (ReadFile(hPort, temprd, DWORD(canread), &read, &OvR) && read)
716 lvd 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;
784 DimkaM 170
   if(reg[5] & 0x20)
171
   {
172
       mask |= 2; reg[6] |= 0x10;
173
   }
716 lvd 174
   if (reg[5] & 0x1E) mask |= 4;
175
   // if (mask & reg[1]) cpu.nmi()
176
 
177
   if (mask & 4) reg[2] = 6;
178
   else if (mask & 1) reg[2] = 4;
179
   else if (mask & 2) reg[2] = 2;
180
   else if (mask & 8) reg[2] = 0;
181
   else reg[2] = 1;
182
}
183
 
184
void ISA_MODEM::write(unsigned nreg, unsigned char value)
185
{
186
   DCB dcb;
187
 
188
   if ((1<<nreg) & ((1<<2)|(1<<5)|(1<<6)))
189
       return; // R/O registers
190
 
191
   if (nreg < 2 && (reg[3] & 0x80))
192
   {
193
     div[nreg] = value;
194
     if (GetCommState(hPort, &dcb))
195
     {
196
       if (!divfq)
197
           divfq = 1;
198
       dcb.BaudRate = 115200 / divfq;
199
       SetCommState(hPort, &dcb);
200
     }
201
     return;
202
   }
203
 
204
   if (nreg == 0)
205
   { // THR, write char to output buffer
206
      reg[5] &= ~0x60;
207
      if (((whead+1) & (BSIZE-1)) == wtail)
208
      {
209
/*
210
         printf("write to ful FIFO\n");
211
         reg[5] |= 2; // Overrun error  (������, ���� ��� ������ �� �����, � �� �� ��������)
212
*/
213
      }
214
      else
215
      {
216
         wbuf[whead++] = value;
217
         whead &= (BSIZE-1);
218
         if (((whead+1) & (BSIZE-1)) != wtail)
219
             reg[5] |= 0x60; // Transmitter holding register empty | transmitter empty
220
      }
221
      setup_int();
222
      return;
223
   }
224
 
225
   u8 old = reg[nreg];
226
   reg[nreg] = value;
227
 
228
   if(nreg == 2) // FCR
229
   {
230
       ULONG Flags = 0;
231
       if(value & 2) // RX FIFO reset
232
           Flags |= PURGE_RXCLEAR | PURGE_RXABORT;
233
 
234
       if(value & 4) // TX FIFO reset
235
           Flags |= PURGE_TXCLEAR | PURGE_TXABORT;
236
 
237
       if(Flags)
238
           PurgeComm(hPort, Flags);
239
   }
240
 
241
   // Thu 28 Jul 2005. transfer mode control (code by Alex/AT)
242
 
243
   if (nreg == 3)
244
   {
245
      // LCR set, renew modem config
246
      if (!GetCommState(hPort, &dcb))
247
          return;
248
 
249
      dcb.fBinary = TRUE;
250
      dcb.fParity = (reg[3] & 8)? TRUE : FALSE;
251
      dcb.fOutxCtsFlow = FALSE;
252
      dcb.fOutxDsrFlow = FALSE;
253
      dcb.fDtrControl = DTR_CONTROL_DISABLE;
254
      dcb.fDsrSensitivity = FALSE;
255
      dcb.fTXContinueOnXoff = FALSE;
256
      dcb.fOutX = FALSE;
257
      dcb.fInX = FALSE;
258
      dcb.fErrorChar = FALSE;
259
      dcb.fNull = FALSE;
260
      dcb.fRtsControl = RTS_CONTROL_DISABLE;
261
      dcb.fAbortOnError = FALSE;
262
      dcb.ByteSize = 5 + (reg[3] & 3); // fix by Deathsoft
263
 
264
      static const BYTE parity[] = { ODDPARITY, EVENPARITY, MARKPARITY, SPACEPARITY };
265
      dcb.Parity = (reg[3] & 8) ? parity[(reg[3]>>4) & 3] : NOPARITY;
266
 
267
      if (!(reg[3] & 4)) dcb.StopBits = ONESTOPBIT;
268
      else dcb.StopBits = ((reg[3] & 3) == 1) ? ONE5STOPBITS : TWOSTOPBITS;
269
 
270
      SetCommState(hPort, &dcb);
271
      return;
272
   }
273
 
274
   if (nreg == 4)
275
   {
276
      // MCR set, renew DTR/RTS
277
      if((old ^ reg[4]) & 0x20) // auto rts/cts toggled
278
      {
279
          if (!GetCommState(hPort, &dcb))
280
              return;
281
 
282
          if(reg[4] & 0x20) // auto rts/cts enabled
283
          {
284
              dcb.fOutxCtsFlow = TRUE;
285
              dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
286
          }
287
          else // auto rts/cts disabled
288
          {
289
              dcb.fOutxCtsFlow = FALSE;
290
              dcb.fRtsControl = RTS_CONTROL_DISABLE;
291
          }
292
          SetCommState(hPort, &dcb);
293
      }
294
 
295
      if(!(reg[4] & 0x20)) // auto rts/cts disabled
296
      {
297
          if((old ^ reg[4]) & 1)
298
          {
299
              EscapeCommFunction(hPort, (reg[4] & 1) ? SETDTR : CLRDTR);
300
          }
301
 
302
          if((old ^ reg[4]) & 2)
303
          {
304
              EscapeCommFunction(hPort, (reg[4] & 2) ? SETRTS : CLRRTS);
305
          }
306
      }
307
   }
308
}
309
 
310
unsigned char ISA_MODEM::read(unsigned nreg)
311
{
312
   if (nreg < 2 && (reg[3] & 0x80))
313
       return div[nreg];
314
 
315
   unsigned char result = reg[nreg];
316
 
317
   if (nreg == 0)
318
   { // read char from buffer
730 lvd 319
      if(conf.mem_model == MM_ATM3)result = 0;
716 lvd 320
      if (rhead != rtail)
321
      {
322
           result = reg[0] = rcbuf[rtail++];
323
           rtail &= (BSIZE-1);
324
      }
325
 
326
      if (rhead != rtail)
327
          reg[5] |= 1;
328
      else
329
          reg[5] &= ~1;
330
 
331
      setup_int();
332
   }
333
 
334
   if (nreg == 5)
335
   {
336
       reg[5] &= ~0x0E;
337
       setup_int();
338
   }
339
 
340
   if (nreg == 6)
341
   {
342
       DWORD ModemStatus;
343
       GetCommModemStatus(hPort, &ModemStatus);
344
       u8 r6 = reg[6];
345
       reg[6] &= ~(1 << 4);
346
       reg[6] |= (ModemStatus & MS_CTS_ON) ? (1 << 4): 0;
347
       reg[6] &= ~1;
348
       reg[6] |= ((r6 ^ reg[6]) & (1 << 4)) >> 4;
349
       result = reg[6];
350
   }
351
   return result;
352
}