DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/dos/dos_devices.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include <string.h>
00021 #include "dosbox.h"
00022 #include "callback.h"
00023 #include "regs.h"
00024 #include "mem.h"
00025 #include "bios.h"
00026 #include "dos_inc.h"
00027 #include "support.h"
00028 #include "parport.h"
00029 #include "drives.h" //Wildcmp
00030 /* Include all the devices */
00031 
00032 #include "dev_con.h"
00033 
00034 
00035 DOS_Device * Devices[DOS_DEVICES] = {NULL};
00036 
00037 class device_NUL : public DOS_Device {
00038 public:
00039         device_NUL() { SetName("NUL"); };
00040         virtual bool Read(Bit8u * data,Bit16u * size) {
00041         (void)data; // UNUSED
00042                 *size = 0; //Return success and no data read. 
00043 //              LOG(LOG_IOCTL,LOG_NORMAL)("%s:READ",GetName());
00044                 return true;
00045         }
00046         virtual bool Write(const Bit8u * data,Bit16u * size) {
00047         (void)data; // UNUSED
00048         (void)size; // UNUSED
00049 //              LOG(LOG_IOCTL,LOG_NORMAL)("%s:WRITE",GetName());
00050                 return true;
00051         }
00052         virtual bool Seek(Bit32u * pos,Bit32u type) {
00053         (void)type;
00054         (void)pos;
00055 //              LOG(LOG_IOCTL,LOG_NORMAL)("%s:SEEK",GetName());
00056                 return true;
00057         }
00058         virtual bool Close() { return true; }
00059         virtual Bit16u GetInformation(void) { return 0x8084; }
00060         virtual bool ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
00061         virtual bool WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
00062 };
00063 
00064 class device_PRN : public DOS_Device {
00065 public:
00066         device_PRN() {
00067                 SetName("PRN");
00068         }
00069         bool Read(Bit8u * data,Bit16u * size) {
00070         (void)data; // UNUSED
00071         (void)size; // UNUSED
00072                 DOS_SetError(DOSERR_ACCESS_DENIED);
00073                 return false;
00074         }
00075         bool Write(const Bit8u * data,Bit16u * size) {
00076                 for(int i = 0; i < 3; i++) {
00077                         // look up a parallel port
00078                         if(parallelPortObjects[i] != NULL) {
00079                                 // send the data
00080                                 for (Bit16u j=0; j<*size; j++) {
00081                                         if(!parallelPortObjects[i]->Putchar(data[j])) return false;
00082                                 }
00083                                 return true;
00084                         }
00085                 }
00086                 return false;
00087         }
00088         bool Seek(Bit32u * pos,Bit32u type) {
00089         (void)type; // UNUSED
00090                 *pos = 0;
00091                 return true;
00092         }
00093         Bit16u GetInformation(void) {
00094                 return 0x80A0;
00095         }
00096         bool Close() {
00097                 return false;
00098         }
00099 };
00100 
00101 bool DOS_Device::Read(Bit8u * data,Bit16u * size) {
00102         return Devices[devnum]->Read(data,size);
00103 }
00104 
00105 bool DOS_Device::Write(const Bit8u * data,Bit16u * size) {
00106         return Devices[devnum]->Write(data,size);
00107 }
00108 
00109 bool DOS_Device::Seek(Bit32u * pos,Bit32u type) {
00110         return Devices[devnum]->Seek(pos,type);
00111 }
00112 
00113 bool DOS_Device::Close() {
00114         return Devices[devnum]->Close();
00115 }
00116 
00117 Bit16u DOS_Device::GetInformation(void) { 
00118         return Devices[devnum]->GetInformation();
00119 }
00120 
00121 bool DOS_Device::ReadFromControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { 
00122         return Devices[devnum]->ReadFromControlChannel(bufptr,size,retcode);
00123 }
00124 
00125 bool DOS_Device::WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcode) { 
00126         return Devices[devnum]->WriteToControlChannel(bufptr,size,retcode);
00127 }
00128 
00129 DOS_File::DOS_File(const DOS_File& orig) {
00130         flags=orig.flags;
00131         time=orig.time;
00132         date=orig.date;
00133         attr=orig.attr;
00134         refCtr=orig.refCtr;
00135         open=orig.open;
00136         hdrive=orig.hdrive;
00137         name=0;
00138         if(orig.name) {
00139                 name=new char [strlen(orig.name) + 1];strcpy(name,orig.name);
00140         }
00141 }
00142 
00143 DOS_File & DOS_File::operator= (const DOS_File & orig) {
00144         flags=orig.flags;
00145         time=orig.time;
00146         date=orig.date;
00147         attr=orig.attr;
00148         refCtr=orig.refCtr;
00149         open=orig.open;
00150         hdrive=orig.hdrive;
00151         if(name) {
00152                 delete [] name; name=0;
00153         }
00154         if(orig.name) {
00155                 name=new char [strlen(orig.name) + 1];strcpy(name,orig.name);
00156         }
00157         return *this;
00158 }
00159 
00160 Bit8u DOS_FindDevice(char const * name) {
00161         /* should only check for the names before the dot and spacepadded */
00162         char fullname[DOS_PATHLENGTH];Bit8u drive;
00163 //      if(!name || !(*name)) return DOS_DEVICES; //important, but makename does it
00164         if (!DOS_MakeName(name,fullname,&drive)) return DOS_DEVICES;
00165 
00166         char* name_part = strrchr(fullname,'\\');
00167         if(name_part) {
00168                 *name_part++ = 0;
00169                 //Check validity of leading directory.
00170                 if(!Drives[drive]->TestDir(fullname)) return DOS_DEVICES;
00171         } else name_part = fullname;
00172    
00173         char* dot = strrchr(name_part,'.');
00174         if(dot) *dot = 0; //no ext checking
00175 
00176         static char com[5] = { 'C','O','M','1',0 };
00177         static char lpt[5] = { 'L','P','T','1',0 };
00178         // AUX is alias for COM1 and PRN for LPT1
00179         // A bit of a hack. (but less then before).
00180         // no need for casecmp as makename returns uppercase
00181         if (strcmp(name_part, "AUX") == 0) name_part = com;
00182         if (strcmp(name_part, "PRN") == 0) name_part = lpt;
00183 
00184         /* loop through devices */
00185         for(Bit8u index = 0;index < DOS_DEVICES;index++) {
00186                 if (Devices[index]) {
00187                         if (WildFileCmp(name_part,Devices[index]->name)) return index;
00188                 }
00189         }
00190         return DOS_DEVICES;
00191 }
00192 
00193 
00194 void DOS_AddDevice(DOS_Device * adddev) {
00195 //Caller creates the device. We store a pointer to it
00196 //TODO Give the Device a real handler in low memory that responds to calls
00197         if (adddev == NULL) E_Exit("DOS_AddDevice with null ptr");
00198         for(Bitu i = 0; i < DOS_DEVICES;i++) {
00199                 if (Devices[i] == NULL){
00200 //                      LOG_MSG("DOS_AddDevice %s (%p)\n",adddev->name,(void*)adddev);
00201                         Devices[i] = adddev;
00202                         Devices[i]->SetDeviceNumber(i);
00203                         return;
00204                 }
00205         }
00206         E_Exit("DOS:Too many devices added");
00207 }
00208 
00209 void DOS_DelDevice(DOS_Device * dev) {
00210 // We will destroy the device if we find it in our list.
00211 // TODO:The file table is not checked to see the device is opened somewhere!
00212         if (dev == NULL) E_Exit("DOS_DelDevice with null ptr");
00213         for (Bitu i = 0; i <DOS_DEVICES;i++) {
00214                 if (Devices[i] == dev) { /* NTS: The mainline code deleted by matching names??? Why? */
00215 //                      LOG_MSG("DOS_DelDevice %s (%p)\n",dev->name,(void*)dev);
00216                         delete Devices[i];
00217                         Devices[i] = 0;
00218                         return;
00219                 }
00220         }
00221 
00222         /* hm. unfortunately, too much code in DOSBox assumes that we delete the object.
00223          * prior to this fix, failure to delete caused a memory leak */
00224         LOG_MSG("WARNING: DOS_DelDevice() failed to match device object '%s' (%p). Deleting anyway\n",dev->name,(void*)dev);
00225         delete dev;
00226 }
00227 
00228 void update_pc98_function_row(bool enable);
00229 
00230 void DOS_ShutdownDevices(void) {
00231         for (Bitu i=0;i < DOS_DEVICES;i++) {
00232                 if (Devices[i] != NULL) {
00233 //                      LOG_MSG("DOS: Shutting down device %s (%p)\n",Devices[i]->name,(void*)Devices[i]);
00234                         delete Devices[i];
00235                         Devices[i] = NULL;
00236                 }
00237         }
00238 
00239     /* NTS: CON counts as a device */
00240     if (IS_PC98_ARCH) update_pc98_function_row(false);
00241 }
00242 
00243 // INT 29h emulation needs to keep track of CON
00244 DOS_Device *DOS_CON = NULL;
00245 
00246 void DOS_SetupDevices(void) {
00247         DOS_Device * newdev;
00248         newdev=new device_CON(); DOS_CON = newdev;
00249         DOS_AddDevice(newdev);
00250         DOS_Device * newdev2;
00251         newdev2=new device_NUL();
00252         DOS_AddDevice(newdev2);
00253         DOS_Device * newdev3;
00254         newdev3=new device_PRN();
00255         DOS_AddDevice(newdev3);
00256 }
00257