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 #ifndef DOSBOX_SERIALPORT_H 00021 #define DOSBOX_SERIALPORT_H 00022 00023 #ifndef DOSBOX_DOSBOX_H 00024 #include "dosbox.h" 00025 #endif 00026 #ifndef DOSBOX_INOUT_H 00027 #include "inout.h" 00028 #endif 00029 #ifndef DOSBOX_TIMER_H 00030 #include "timer.h" 00031 #endif 00032 #ifndef DOSBOX_DOS_INC_H 00033 #include "dos_inc.h" 00034 #endif 00035 #ifndef DOSBOX_PROGRAMS_H 00036 #include "programs.h" 00037 #endif 00038 00039 // set this to 1 for serial debugging in release mode 00040 #define SERIAL_DBG_FORCED 1 00041 00042 #if (C_DEBUG || SERIAL_DBG_FORCED) 00043 #define SERIAL_DEBUG 1 00044 #endif 00045 00046 #if SERIAL_DEBUG 00047 #include "hardware.h" 00048 #endif 00049 00050 // Serial port interface 00051 00052 class MyFifo { 00053 public: 00054 MyFifo(Bitu maxsize_) { 00055 maxsize=size=maxsize_; 00056 pos=used=0; 00057 data=new Bit8u[size]; 00058 } 00059 ~MyFifo() { 00060 if (data != NULL) { 00061 delete[] data; 00062 data = NULL; 00063 } 00064 } 00065 INLINE Bitu getFree(void) { 00066 return size-used; 00067 } 00068 bool isEmpty() { 00069 return used==0; 00070 } 00071 bool isFull() { 00072 return (size-used)==0; 00073 } 00074 00075 INLINE Bitu getUsage(void) { 00076 return used; 00077 } 00078 void setSize(Bitu newsize) 00079 { 00080 size=newsize; 00081 pos=used=0; 00082 } 00083 void clear(void) { 00084 pos=used=0; 00085 data[0]=0; 00086 } 00087 00088 bool addb(Bit8u _val) { 00089 Bitu where=pos+used; 00090 if (where>=size) where-=size; 00091 if(used>=size) { 00092 // overwrite last byte 00093 if(where==0) where=size-1; 00094 else where--; 00095 data[where]=_val; 00096 return false; 00097 } 00098 data[where]=_val; 00099 used++; 00100 return true; 00101 } 00102 Bit8u getb() { 00103 if (!used) return data[pos]; 00104 Bitu where=pos; 00105 used--; 00106 if(used) pos++; 00107 if (pos>=size) pos-=size; 00108 return data[where]; 00109 } 00110 Bit8u getTop() { 00111 Bitu where=pos+used; 00112 if (where>=size) where-=size; 00113 if(used>=size) { 00114 if(where==0) where=size-1; 00115 else where--; 00116 } 00117 return data[where]; 00118 } 00119 00120 Bit8u probeByte() { 00121 return data[pos]; 00122 } 00123 private: 00124 Bit8u * data; 00125 Bitu maxsize,size,pos,used; 00126 }; 00127 00128 class CSerial { 00129 public: 00130 00131 #if SERIAL_DEBUG 00132 FILE * debugfp; 00133 bool dbg_modemcontrol; // RTS,CTS,DTR,DSR,RI,CD 00134 bool dbg_serialtraffic; 00135 bool dbg_register; 00136 bool dbg_interrupt; 00137 bool dbg_aux; 00138 void log_ser(bool active, char const* format,...); 00139 #endif 00140 00141 static bool getBituSubstring(const char* name,Bitu* data, CommandLine* cmd); 00142 00143 bool InstallationSuccessful;// check after constructing. If 00144 // something was wrong, delete it right away. 00145 00146 // Constructor takes com port number (0-3) 00147 CSerial(Bitu id, CommandLine* cmd); 00148 00149 virtual ~CSerial(); 00150 00151 IO_ReadHandleObject ReadHandler[8]; 00152 IO_WriteHandleObject WriteHandler[8]; 00153 00154 float bytetime; // how long a byte takes to transmit/receive in milliseconds 00155 void changeLineProperties(); 00156 Bitu idnumber; 00157 00158 void setEvent(Bit16u type, float duration); 00159 void removeEvent(Bit16u type); 00160 void handleEvent(Bit16u type); 00161 virtual void handleUpperEvent(Bit16u type)=0; 00162 00163 // defines for event type 00164 #define SERIAL_TX_LOOPBACK_EVENT 0 00165 #define SERIAL_THR_LOOPBACK_EVENT 1 00166 #define SERIAL_ERRMSG_EVENT 2 00167 00168 #define SERIAL_TX_EVENT 3 00169 #define SERIAL_RX_EVENT 4 00170 #define SERIAL_POLLING_EVENT 5 00171 #define SERIAL_THR_EVENT 6 00172 #define SERIAL_RX_TIMEOUT_EVENT 7 00173 00174 #define SERIAL_BASE_EVENT_COUNT 7 00175 00176 #define COMNUMBER idnumber+1 00177 00178 Bitu irq; 00179 00180 // CSerial requests an update of the input lines 00181 virtual void updateMSR()=0; 00182 00183 // Control lines from prepherial to serial port 00184 bool getDTR(); 00185 bool getRTS(); 00186 00187 bool getRI(); 00188 bool getCD(); 00189 bool getDSR(); 00190 bool getCTS(); 00191 00192 void setRI(bool value); 00193 void setDSR(bool value); 00194 void setCD(bool value); 00195 void setCTS(bool value); 00196 00197 // From serial port to prepherial 00198 // set output lines 00199 virtual void setRTSDTR(bool rts, bool dtr)=0; 00200 virtual void setRTS(bool val)=0; 00201 virtual void setDTR(bool val)=0; 00202 00203 // Register access 00204 void Write_THR(Bit8u data); 00205 void Write_IER(Bit8u data); 00206 void Write_FCR(Bit8u data); 00207 void Write_LCR(Bit8u data); 00208 void Write_MCR(Bit8u data); 00209 // Really old hardware seems to have the delta part of this register writable 00210 void Write_MSR(Bit8u val); 00211 void Write_SPR(Bit8u data); 00212 void Write_reserved(Bit8u data, Bit8u address); 00213 00214 Bitu Read_RHR(); 00215 Bitu Read_IER(); 00216 Bitu Read_ISR(); 00217 Bitu Read_LCR(); 00218 Bitu Read_MCR(); 00219 Bitu Read_LSR(); 00220 Bitu Read_MSR(); 00221 Bitu Read_SPR(); 00222 00223 // If a byte comes from loopback or prepherial, put it in here. 00224 void receiveByte(Bit8u data); 00225 void receiveByteEx(Bit8u data, Bit8u error); 00226 00227 // depratched 00228 // connected device checks, if port can receive data: 00229 bool CanReceiveByte(); 00230 00231 // when THR was shifted to TX 00232 void ByteTransmitting(); 00233 00234 // When done sending, notify here 00235 void ByteTransmitted(); 00236 00237 // Transmit byte to prepherial 00238 virtual void transmitByte(Bit8u val, bool first)=0; 00239 00240 // switch break state to the passed value 00241 virtual void setBreak(bool value)=0; 00242 00243 // change baudrate, number of bits, parity, word length al at once 00244 virtual void updatePortConfig(Bit16u divider, Bit8u lcr)=0; 00245 00246 void Init_Registers(); 00247 00248 bool Putchar(Bit8u data, bool wait_dsr, bool wait_cts, Bitu timeout); 00249 bool Getchar(Bit8u* data, Bit8u* lsr, bool wait_dsr, Bitu timeout); 00250 00251 DOS_Device* mydosdevice; 00252 00253 void registerDOSDevice(); 00254 void unregisterDOSDevice(); 00255 00256 private: 00257 00258 // I used this spec: st16c450v420.pdf 00259 00260 void ComputeInterrupts(); 00261 00262 // a sub-interrupt is triggered 00263 void rise(Bit8u priority); 00264 00265 // clears the pending sub-interrupt 00266 void clear(Bit8u priority); 00267 00268 #define ERROR_PRIORITY 4 // overrun, parity error, frame error, break 00269 #define RX_PRIORITY 1 // a byte has been received 00270 #define TX_PRIORITY 2 // tx buffer has become empty 00271 #define MSR_PRIORITY 8 // CRS, DSR, RI, DCD change 00272 #define TIMEOUT_PRIORITY 0x10 00273 #define NONE_PRIORITY 0 00274 00275 Bit8u waiting_interrupts; // these are on, but maybe not enabled 00276 00277 // 16C550 00278 // read/write name 00279 00280 Bit16u baud_divider; 00281 #define RHR_OFFSET 0 // r Receive Holding Register, also LSB of Divisor Latch (r/w) 00282 // Data: whole byte 00283 #define THR_OFFSET 0 // w Transmit Holding Register 00284 // Data: whole byte 00285 Bit8u IER; // r/w Interrupt Enable Register, also MSB of Divisor Latch 00286 #define IER_OFFSET 1 00287 00288 bool irq_active; 00289 00290 #define RHR_INT_Enable_MASK 0x1 00291 #define THR_INT_Enable_MASK 0x2 00292 #define Receive_Line_INT_Enable_MASK 0x4 00293 #define Modem_Status_INT_Enable_MASK 0x8 00294 00295 Bit8u ISR; // r Interrupt Status Register 00296 #define ISR_OFFSET 2 00297 00298 #define ISR_CLEAR_VAL 0x1 00299 #define ISR_FIFOTIMEOUT_VAL 0xc 00300 #define ISR_ERROR_VAL 0x6 00301 #define ISR_RX_VAL 0x4 00302 #define ISR_TX_VAL 0x2 00303 #define ISR_MSR_VAL 0x0 00304 public: 00305 Bit8u LCR; // r/w Line Control Register 00306 private: 00307 #define LCR_OFFSET 3 00308 // bit0: word length bit0 00309 // bit1: word length bit1 00310 // bit2: stop bits 00311 // bit3: parity enable 00312 // bit4: even parity 00313 // bit5: set parity 00314 // bit6: set break 00315 // bit7: divisor latch enable 00316 00317 00318 #define LCR_BREAK_MASK 0x40 00319 #define LCR_DIVISOR_Enable_MASK 0x80 00320 #define LCR_PORTCONFIG_MASK 0x3F 00321 00322 #define LCR_PARITY_NONE 0x0 00323 #define LCR_PARITY_ODD 0x8 00324 #define LCR_PARITY_EVEN 0x18 00325 #define LCR_PARITY_MARK 0x28 00326 #define LCR_PARITY_SPACE 0x38 00327 00328 #define LCR_DATABITS_5 0x0 00329 #define LCR_DATABITS_6 0x1 00330 #define LCR_DATABITS_7 0x2 00331 #define LCR_DATABITS_8 0x3 00332 00333 #define LCR_STOPBITS_1 0x0 00334 #define LCR_STOPBITS_MORE_THAN_1 0x4 00335 00336 // Modem Control Register 00337 // r/w 00338 #define MCR_OFFSET 4 00339 bool dtr; // bit0: DTR 00340 bool rts; // bit1: RTS 00341 bool op1; // bit2: OP1 00342 bool op2; // bit3: OP2 00343 bool loopback; // bit4: loop back enable 00344 00345 #define MCR_DTR_MASK 0x1 00346 #define MCR_RTS_MASK 0x2 00347 #define MCR_OP1_MASK 0x4 00348 #define MCR_OP2_MASK 0x8 00349 #define MCR_LOOPBACK_Enable_MASK 0x10 00350 public: 00351 Bit8u LSR; // r Line Status Register 00352 private: 00353 00354 #define LSR_OFFSET 5 00355 00356 #define LSR_RX_DATA_READY_MASK 0x1 00357 #define LSR_OVERRUN_ERROR_MASK 0x2 00358 #define LSR_PARITY_ERROR_MASK 0x4 00359 #define LSR_FRAMING_ERROR_MASK 0x8 00360 #define LSR_RX_BREAK_MASK 0x10 00361 #define LSR_TX_HOLDING_EMPTY_MASK 0x20 00362 #define LSR_TX_EMPTY_MASK 0x40 00363 00364 #define LSR_ERROR_MASK 0x1e 00365 00366 // error printing 00367 bool errormsg_pending; 00368 Bitu framingErrors; 00369 Bitu parityErrors; 00370 Bitu overrunErrors; 00371 Bitu txOverrunErrors; 00372 Bitu overrunIF0; 00373 Bitu breakErrors; 00374 00375 00376 // Modem Status Register 00377 // r 00378 #define MSR_OFFSET 6 00379 bool d_cts; // bit0: deltaCTS 00380 bool d_dsr; // bit1: deltaDSR 00381 bool d_ri; // bit2: deltaRI 00382 bool d_cd; // bit3: deltaCD 00383 bool cts; // bit4: CTS 00384 bool dsr; // bit5: DSR 00385 bool ri; // bit6: RI 00386 bool cd; // bit7: CD 00387 00388 #define MSR_delta_MASK 0xf 00389 #define MSR_LINE_MASK 0xf0 00390 00391 #define MSR_dCTS_MASK 0x1 00392 #define MSR_dDSR_MASK 0x2 00393 #define MSR_dRI_MASK 0x4 00394 #define MSR_dCD_MASK 0x8 00395 #define MSR_CTS_MASK 0x10 00396 #define MSR_DSR_MASK 0x20 00397 #define MSR_RI_MASK 0x40 00398 #define MSR_CD_MASK 0x80 00399 00400 Bit8u SPR; // r/w Scratchpad Register 00401 #define SPR_OFFSET 7 00402 00403 00404 // For loopback purposes... 00405 Bit8u loopback_data; 00406 void transmitLoopbackByte(Bit8u val, bool value); 00407 00408 // 16C550 (FIFO) 00409 public: // todo remove 00410 MyFifo* rxfifo; 00411 private: 00412 MyFifo* txfifo; 00413 MyFifo* errorfifo; 00414 Bitu errors_in_fifo; 00415 Bitu rx_interrupt_threshold; 00416 Bitu fifosize; 00417 Bit8u FCR; 00418 bool sync_guardtime; 00419 #define FIFO_STATUS_ACTIVE 0xc0 // FIFO is active AND works ;) 00420 #define FIFO_ERROR 0x80 00421 #define FCR_ACTIVATE 0x01 00422 #define FCR_CLEAR_RX 0x02 00423 #define FCR_CLEAR_TX 0x04 00424 #define FCR_OFFSET 2 00425 #define FIFO_FLOWCONTROL 0x20 00426 }; 00427 00428 extern CSerial* serialports[]; 00429 const Bit8u serial_defaultirq[] = { 4, 3, 4, 3 }; 00430 const Bit16u serial_baseaddr[] = {0x3f8,0x2f8,0x3e8,0x2e8}; 00431 const char* const serial_comname[]={"COM1","COM2","COM3","COM4"}; 00432 00433 // the COM devices 00434 00435 class device_COM : public DOS_Device { 00436 public: 00437 // Creates a COM device that communicates with the num-th parallel port, i.e. is LPTnum 00438 device_COM(class CSerial* sc); 00439 virtual ~device_COM(); 00440 bool Read(Bit8u * data,Bit16u * size); 00441 bool Write(const Bit8u * data,Bit16u * size); 00442 bool Seek(Bit32u * pos,Bit32u type); 00443 bool Close(); 00444 Bit16u GetInformation(void); 00445 private: 00446 CSerial* sclass; 00447 }; 00448 00449 #endif