gsplus/src/scc_windriver.c
2016-02-04 00:37:39 -06:00

275 lines
6.0 KiB
C

/*
GSPLUS - Advanced Apple IIGS Emulator Environment
Copyright (C) 2016 - Dagen Brock
Based on the KEGS emulator written by and Copyright (C) 2003 Kent Dickey
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* This file contains the Win32 COM1/COM2 calls */
#include "defc.h"
#include "scc.h"
#ifdef __CYGWIN__
#include <Windows.h>
#include <NspAPI.h>
#endif
#ifdef UNDER_CE
#define vsnprintf _vsnprintf
#endif
extern Scc scc_stat[2];
extern word32 g_c025_val;
#ifdef _WIN32
int
scc_serial_win_init(int port)
{
COMMTIMEOUTS commtimeouts;
TCHAR str_buf[8];
Scc *scc_ptr;
HANDLE host_handle;
int state;
int ret;
scc_ptr = &(scc_stat[port]);
scc_ptr->state = 0; /* mark as failed */
#ifdef UNICODE
wsprintf(&str_buf[0], _T("COM%d"), port+1);
#else
sprintf(&str_buf[0], "COM%d", port+1);
#endif
host_handle = CreateFile(&str_buf[0], GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
scc_ptr->host_handle = host_handle;
scc_ptr->host_handle2 = malloc(sizeof(DCB));
printf("scc_socket_init %d called, host_handle: %p\n", port,
host_handle);
if(host_handle == INVALID_HANDLE_VALUE) {
scc_ptr->host_handle = 0;
return 0;
}
scc_serial_win_change_params(port);
commtimeouts.ReadIntervalTimeout = MAXDWORD;
commtimeouts.ReadTotalTimeoutMultiplier = 0;
commtimeouts.ReadTotalTimeoutConstant = 0;
commtimeouts.WriteTotalTimeoutMultiplier = 0;
commtimeouts.WriteTotalTimeoutConstant = 10;
ret = SetCommTimeouts(host_handle, &commtimeouts);
if(ret == 0) {
printf("setcommtimeout ret: %d\n", ret);
}
state = 2; /* raw serial */
scc_ptr->state = state;
return state;
}
void
scc_serial_win_change_params(int port)
{
DCB *dcbptr;
HANDLE host_handle;
Scc *scc_ptr;
int ret;
scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle;
dcbptr = (DCB*)scc_ptr->host_handle2; // OG Added cast
if(host_handle == 0) {
return;
}
ret = GetCommState(host_handle, dcbptr);
if(ret == 0) {
printf("getcomm port%d ret: %d\n", port, ret);
}
#if 1
printf("dcb.baudrate: %d, bytesize:%d, stops:%d, parity:%d\n",
(int)dcbptr->BaudRate, (int)dcbptr->ByteSize,
(int)dcbptr->StopBits, (int)dcbptr->Parity);
printf("dcb.binary: %d, ctsflow: %d, dsrflow: %d, dtr: %d, dsr: %d\n",
(int)dcbptr->fBinary,
(int)dcbptr->fOutxCtsFlow,
(int)dcbptr->fOutxDsrFlow,
(int)dcbptr->fDtrControl,
(int)dcbptr->fDsrSensitivity);
printf("dcb.txonxoff:%d, outx:%d, inx: %d, null: %d, rts: %d\n",
(int)dcbptr->fTXContinueOnXoff,
(int)dcbptr->fOutX,
(int)dcbptr->fInX,
(int)dcbptr->fNull,
(int)dcbptr->fRtsControl);
printf("dcb.fAbortOnErr:%d, fParity:%d\n", (int)dcbptr->fAbortOnError,
(int)dcbptr->fParity);
#endif
dcbptr->fAbortOnError = 0;
dcbptr->BaudRate = scc_ptr->baud_rate;
dcbptr->ByteSize = scc_ptr->char_size;
dcbptr->StopBits = ONESTOPBIT;
switch((scc_ptr->reg[4] >> 2) & 0x3) {
case 2: // 1.5 stop bits
dcbptr->StopBits = ONE5STOPBITS;
break;
case 3: // 2 stop bits
dcbptr->StopBits = TWOSTOPBITS;
break;
}
dcbptr->Parity = NOPARITY;
switch((scc_ptr->reg[4]) & 0x3) {
case 1: // Odd parity
dcbptr->Parity = ODDPARITY;
break;
case 3: // Even parity
dcbptr->Parity = EVENPARITY;
break;
}
dcbptr->fNull = 0;
dcbptr->fDtrControl = DTR_CONTROL_ENABLE;
dcbptr->fDsrSensitivity = 0;
dcbptr->fOutxCtsFlow = 0;
dcbptr->fOutxDsrFlow = 0;
dcbptr->fParity = 0;
dcbptr->fInX = 0;
dcbptr->fOutX = 0;
dcbptr->fRtsControl = RTS_CONTROL_ENABLE;
ret = SetCommState(host_handle, dcbptr);
if(ret == 0) {
printf("SetCommState ret: %d, new baud: %d\n", ret,
(int)dcbptr->BaudRate);
}
}
void
scc_serial_win_fill_readbuf(int port, int space_left, double dcycs)
{
byte tmp_buf[256];
Scc *scc_ptr;
HANDLE host_handle;
DWORD bytes_read;
DWORD i;
int ret;
scc_ptr = &(scc_stat[port]);
host_handle = scc_ptr->host_handle;
if(host_handle == 0) {
return;
}
/* Try reading some bytes */
space_left = MIN(256, space_left);
ret = ReadFile(host_handle, tmp_buf, space_left, &bytes_read, NULL);
if(ret == 0) {
printf("ReadFile ret 0\n");
}
if(ret && (bytes_read > 0)) {
for(i = 0; i < bytes_read; i++) {
scc_add_to_readbuf(port, tmp_buf[i], dcycs);
}
}
}
void
scc_serial_win_empty_writebuf(int port)
{
Scc *scc_ptr;
HANDLE host_handle;
int rdptr;
int wrptr;
int done;
word32 err_code;
DWORD bytes_written;
int ret;
int len;
scc_ptr = &(scc_stat[port]);
//printf("win_empty_writebuf, host_handle: %d\n", scc_ptr->host_handle);
host_handle = scc_ptr->host_handle;
if(host_handle == 0) {
return;
}
/* Try writing some bytes */
done = 0;
while(!done) {
rdptr = scc_ptr->out_rdptr;
wrptr = scc_ptr->out_wrptr;
if(rdptr == wrptr) {
//printf("...rdptr == wrptr\n");
done = 1;
break;
}
len = wrptr - rdptr;
if(len < 0) {
len = SCC_OUTBUF_SIZE - rdptr;
}
if(len > 32) {
len = 32;
}
if(len <= 0) {
done = 1;
break;
}
bytes_written = 1;
ret = WriteFile(host_handle, &(scc_ptr->out_buf[rdptr]), len,
&bytes_written, NULL);
printf("WriteFile ret: %d, bytes_written:%d, len:%d\n", ret,
(int)bytes_written, len);
err_code = (word32)-1;
if(ret == 0) {
err_code = (word32)GetLastError();
printf("WriteFile ret:0, err_code: %08x\n", err_code);
}
if(ret == 0 || (bytes_written == 0)) {
done = 1;
break;
} else {
rdptr = rdptr + bytes_written;
if(rdptr >= SCC_OUTBUF_SIZE) {
rdptr = rdptr - SCC_OUTBUF_SIZE;
}
scc_ptr->out_rdptr = rdptr;
}
}
}
#endif