DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #include "config.h" 00021 #include "setup.h" 00022 00023 #if C_DIRECTLPT 00024 00025 /* Linux version */ 00026 #if defined (LINUX) 00027 00028 #include "parport.h" 00029 #include "directlpt_linux.h" 00030 #include "callback.h" 00031 #include <linux/ppdev.h> 00032 #include <sys/ioctl.h> 00033 #include <sys/types.h> 00034 00035 #include <errno.h> 00036 #include <fcntl.h> 00037 #include <SDL.h> 00038 00039 CDirectLPT::CDirectLPT (Bitu nr, Bit8u initIrq, CommandLine* cmd) 00040 :CParallel (cmd, nr, initIrq) { 00041 InstallationSuccessful = false; 00042 interruptflag=true; // interrupt disabled 00043 00044 std::string str; 00045 00046 if(!cmd->FindStringBegin("realport:",str,false)) { 00047 LOG_MSG("parallel%d: realport parameter missing.",(int)nr+1); 00048 return; 00049 } 00050 porthandle = open(str.c_str(), O_RDWR ); 00051 if(porthandle == -1) { 00052 LOG_MSG("parallel%d: Could not open port %s.",(int)nr+1,str.c_str()); 00053 if (errno == 2) LOG_MSG ("The specified port does not exist."); 00054 else if(errno==EBUSY) LOG_MSG("The specified port is already in use."); 00055 else if(errno==EACCES) LOG_MSG("You are not allowed to access this port."); 00056 else LOG_MSG("Errno %d occurred.",errno); 00057 return; 00058 } 00059 00060 if(ioctl( porthandle, PPCLAIM, NULL ) == -1) { 00061 LOG_MSG("parallel%d: failed to claim port.",(int)nr+1); 00062 return; 00063 } 00064 // TODO check return value 00065 00066 // go for it 00067 ack_polarity=false; 00068 initialize(); 00069 00070 InstallationSuccessful = true; 00071 } 00072 00073 CDirectLPT::~CDirectLPT () { 00074 if(porthandle > 0) close(porthandle); 00075 } 00076 00077 bool CDirectLPT::Putchar(Bit8u val) 00078 { 00079 //LOG_MSG("putchar: %x",val); 00080 00081 // check if printer online and not busy 00082 // PE and Selected: no printer attached 00083 Bit8u sr=Read_SR(); 00084 //LOG_MSG("SR: %x",sr); 00085 if((sr&0x30)==0x30) 00086 { 00087 LOG_MSG("putchar: no printer"); 00088 return false; 00089 } 00090 // error 00091 if(sr&0x20) 00092 { 00093 LOG_MSG("putchar: paper out"); 00094 return false; 00095 } 00096 if((sr&0x08)==0) 00097 { 00098 LOG_MSG("putchar: printer error"); 00099 return false; 00100 } 00101 00102 Write_PR(val); 00103 // busy 00104 Bitu timeout = 10000; 00105 Bitu time = timeout+SDL_GetTicks(); 00106 00107 while(SDL_GetTicks()<time) { 00108 // wait for the printer to get ready 00109 for(int i = 0; i < 500; i++) { 00110 // do NOT run into callback_idle unless we have to (speeds things up) 00111 sr=Read_SR(); 00112 if(sr&0x80) break; 00113 } 00114 if(sr&0x80) break; 00115 CALLBACK_Idle(); 00116 } 00117 if(SDL_GetTicks()>=time) { 00118 LOG_MSG("putchar: busy timeout"); 00119 return false; 00120 } 00121 // strobe data out 00122 // I hope this creates a sufficient long pulse... 00123 // (I/O-Bus at 7.15 MHz will give some delay) 00124 00125 for(int i = 0; i < 5; i++) Write_CON(0xd); // strobe on 00126 Write_CON(0xc); // strobe off 00127 00128 #if PARALLEL_DEBUG 00129 log_par(dbg_putchar,"putchar 0x%2x",val); 00130 if(dbg_plainputchar) fprintf(debugfp,"%c",val); 00131 #endif 00132 00133 return true; 00134 } 00135 Bitu CDirectLPT::Read_PR() { 00136 Bitu retval; 00137 ioctl(porthandle, PPRDATA, &retval); 00138 return retval; 00139 } 00140 Bitu CDirectLPT::Read_COM() { 00141 Bitu retval; 00142 ioctl(porthandle, PPRCONTROL, &retval); 00143 return retval; 00144 } 00145 Bitu CDirectLPT::Read_SR() { 00146 Bitu retval; 00147 ioctl(porthandle, PPRSTATUS, &retval); 00148 return retval; 00149 } 00150 00151 void CDirectLPT::Write_PR(Bitu val){ 00152 ioctl(porthandle, PPWDATA, &val); 00153 } 00154 void CDirectLPT::Write_CON(Bitu val) { 00155 ioctl(porthandle, PPWCONTROL, &val); 00156 } 00157 void CDirectLPT::Write_IOSEL(Bitu val) { 00158 // switches direction old-style TODO 00159 if((val==0xAA)||(val==0x55)) LOG_MSG("TODO implement IBM-style direction switch"); 00160 } 00161 void CDirectLPT::handleUpperEvent(Bit16u type) { (void)type; } 00162 #endif 00163 #endif