Skip to content

Commit

Permalink
Merge pull request #3382 from cimarronm/device-info-improvements
Browse files Browse the repository at this point in the history
DOS Device Info and Attribute Cleanup
  • Loading branch information
joncampbell123 committed Apr 3, 2022
2 parents c75d0ea + 75b4150 commit 1b5d7f3
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 33 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
0.83.25
-
- Fixed bug where DOS IOCTL would call device control
channel on devices which did not advertise support
for IOCTL (cimarronm)
- Clean up of DOS device and attribute flag usage
(cimarronm)
0.83.24
- Release notes for this version:
https://dosbox-x.com/release-0.83.24.html
Expand Down
35 changes: 35 additions & 0 deletions include/dos_inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,41 @@ void DOS_SetError(uint16_t code);
enum { STDIN=0,STDOUT=1,STDERR=2,STDAUX=3,STDPRN=4};
enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};

namespace DeviceInfoFlags
{
// Device flags
constexpr uint16_t StdIn = 1<<0;
constexpr uint16_t StdOut = 1<<1;
constexpr uint16_t Nul = 1<<2;
constexpr uint16_t Clock = 1<<3;
constexpr uint16_t Special = 1<<4;
constexpr uint16_t Binary = 1<<5;
constexpr uint16_t EofOnInput = 1<<6;
constexpr uint16_t Device = 1<<7;
constexpr uint16_t OpenCloseSupport = 1<<11;
constexpr uint16_t OutputUntilBusy = 1<<13;
constexpr uint16_t IoctlSupport = 1<<14;

// File flags
constexpr uint16_t NotWritten = 1<<6;
constexpr uint16_t NotRemovable = 1<<11;
constexpr uint16_t NoTimeUpdate = 1<<14;
constexpr uint16_t Remote = 1<<15;
}
namespace DeviceAttributeFlags
{
constexpr uint16_t CurrentStdIn = 1<<0;
constexpr uint16_t CurrentStdOut = 1<<1;
constexpr uint16_t CurrentNul = 1<<2;
constexpr uint16_t CurrentClock = 1<<3;
constexpr uint16_t SupportsRemovable = 1<<11;
constexpr uint16_t NonIBM = 1<<13;
constexpr uint16_t SupportsIoctl = 1<<14;
constexpr uint16_t CharacterDevice = 1<<15;

constexpr uint16_t CoreDevicesMask = CurrentStdIn | CurrentStdOut | CurrentNul | CurrentClock;
}

/* Routines for File Class */
void DOS_SetupFiles (void);
bool DOS_ReadFile(uint16_t entry,uint8_t * data,uint16_t * amount, bool fcb = false);
Expand Down
21 changes: 12 additions & 9 deletions src/dos/dev_con.h
Original file line number Diff line number Diff line change
Expand Up @@ -1324,8 +1324,11 @@ bool device_CON::Close() {
extern bool dos_con_use_int16_to_detect_input;

uint16_t device_CON::GetInformation(void) {
static constexpr auto deviceWord = DeviceInfoFlags::Device | DeviceInfoFlags::Special | DeviceInfoFlags::StdIn |
DeviceInfoFlags::StdOut;

if (dos_con_use_int16_to_detect_input || IS_PC98_ARCH) {
uint16_t ret = 0x80D3; /* No Key Available */
uint16_t ret = deviceWord | DeviceInfoFlags::EofOnInput; /* No Key Available */

/* DOSBox-X behavior: Use INT 16h AH=0x11 Query keyboard status/preview key.
* The reason we do this is some DOS programs actually rely on hooking INT 16h
Expand All @@ -1345,9 +1348,9 @@ uint16_t device_CON::GetInformation(void) {
* Since Scandisk is using INT 21h AH=0x0B to query STDIN during this time,
* this implementation is a good "halfway" compromise in that this call
* will trigger the INT 16h AH=0x11 hook it relies on. */
if (readcache || dev_con_pos < dev_con_max) return 0x8093; /* key available */
if (readcache || dev_con_pos < dev_con_max) return deviceWord; /* key available */

if (DOS_BreakConioFlag) return 0x8093; /* key available */
if (DOS_BreakConioFlag) return deviceWord; /* key available */

uint16_t saved_ax = reg_ax;

Expand All @@ -1369,9 +1372,9 @@ uint16_t device_CON::GetInformation(void) {
* so that Read() returns it immediately instead of doing this conversion itself.
* This way we never block when we SAID a key was available that gets ignored. */
if (CommonPC98ExtScanConversionToReadBuf(reg_ah))
ret = 0x8093; /* Key Available */
ret = deviceWord; /* Key Available */
else
ret = 0x80D3; /* No Key Available */
ret = deviceWord | DeviceInfoFlags::EofOnInput; /* No Key Available */

/* need to consume the key. if it generated anything it will be returned to Read()
* through dev_con_readbuf[] */
Expand All @@ -1384,7 +1387,7 @@ uint16_t device_CON::GetInformation(void) {
INT16_Handler_Wrap();
}
else {
ret = 0x8093; /* Key Available */
ret = deviceWord; /* Key Available */
}
}

Expand All @@ -1396,8 +1399,8 @@ uint16_t device_CON::GetInformation(void) {
uint16_t head=mem_readw(BIOS_KEYBOARD_BUFFER_HEAD);
uint16_t tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL);

if ((head==tail) && !readcache) return 0x80D3; /* No Key Available */
if (readcache || real_readw(0x40,head)) return 0x8093; /* Key Available */
if ((head==tail) && !readcache) return deviceWord | DeviceInfoFlags::EofOnInput; /* No Key Available */
if (readcache || real_readw(0x40,head)) return deviceWord; /* Key Available */

/* remove the zero from keyboard buffer */
uint16_t start=mem_readw(BIOS_KEYBOARD_BUFFER_START);
Expand All @@ -1407,7 +1410,7 @@ uint16_t device_CON::GetInformation(void) {
mem_writew(BIOS_KEYBOARD_BUFFER_HEAD,head);
}

return 0x80D3; /* No Key Available */
return deviceWord | DeviceInfoFlags::EofOnInput; /* No Key Available */
}

device_CON::device_CON() {
Expand Down
20 changes: 12 additions & 8 deletions src/dos/dos_devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ uint16_t DOS_ExtDevice::CallDeviceFunction(uint8_t command, uint8_t length, uint
}

bool DOS_ExtDevice::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
if(ext.attribute & 0x4000) {
if(ext.attribute & DeviceAttributeFlags::SupportsIoctl) {
// IOCTL INPUT
if((CallDeviceFunction(3, 26, (uint16_t)(bufptr >> 4), (uint16_t)(bufptr & 0x000f), size) & 0x8000) == 0) {
*retcode = real_readw(dos.dcp, 18);
Expand All @@ -94,7 +94,7 @@ bool DOS_ExtDevice::ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t
}

bool DOS_ExtDevice::WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) {
if(ext.attribute & 0x4000) {
if(ext.attribute & DeviceAttributeFlags::SupportsIoctl) {
// IOCTL OUTPUT
if((CallDeviceFunction(12, 26, (uint16_t)(bufptr >> 4), (uint16_t)(bufptr & 0x000f), size) & 0x8000) == 0) {
*retcode = real_readw(dos.dcp, 18);
Expand Down Expand Up @@ -148,8 +148,12 @@ bool DOS_ExtDevice::Seek(uint32_t * pos,uint32_t type) {
}

uint16_t DOS_ExtDevice::GetInformation(void) {
// bit9=1 .. ExtDevice
return (ext.attribute & 0xc07f) | 0x0080 | EXT_DEVICE_BIT;
uint16_t ret = EXT_DEVICE_BIT;
if (ext.attribute & DeviceAttributeFlags::CharacterDevice) ret |= DeviceInfoFlags::Device;
if (ext.attribute & DeviceAttributeFlags::SupportsIoctl) ret |= DeviceInfoFlags::IoctlSupport;
if (ext.attribute & DeviceAttributeFlags::SupportsRemovable) ret |= DeviceInfoFlags::OpenCloseSupport;
ret |= ext.attribute & DeviceAttributeFlags::CoreDevicesMask;
return ret;
}

uint8_t DOS_ExtDevice::GetStatus(bool input_flag) {
Expand Down Expand Up @@ -248,7 +252,7 @@ class device_NUL : public DOS_Device {
return true;
}
virtual bool Close() { return true; }
virtual uint16_t GetInformation(void) { return 0x8084; }
virtual uint16_t GetInformation(void) { return DeviceInfoFlags::Device | DeviceInfoFlags::Nul; }
virtual bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
virtual bool WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode) { (void)bufptr; (void)size; (void)retcode; return false; }
};
Expand Down Expand Up @@ -283,7 +287,7 @@ class device_PRN : public DOS_Device {
return true;
}
uint16_t GetInformation(void) {
return 0x80A0;
return DeviceInfoFlags::Device | DeviceInfoFlags::Binary;
}
bool Close() {
return false;
Expand Down Expand Up @@ -608,7 +612,7 @@ class device_CLIP : public DOS_Device {
return true;
}
uint16_t GetInformation(void) {
return 0x80E0;
return DeviceInfoFlags::Device | DeviceInfoFlags::EofOnInput | DeviceInfoFlags::Binary;
}
};

Expand Down Expand Up @@ -645,7 +649,7 @@ uint8_t DOS_Device::GetStatus(bool input_flag) {
if(info & EXT_DEVICE_BIT) {
return Devices[devnum]->GetStatus(input_flag);
}
return (info & 0x40) ? 0x00 : 0xff;
return (info & DeviceInfoFlags::EofOnInput) ? 0x00 : 0xff;
}

DOS_File::DOS_File(const DOS_File& orig) : flags(orig.flags), open(orig.open), attr(orig.attr),
Expand Down
16 changes: 9 additions & 7 deletions src/dos/dos_ioctl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ bool DOS_IOCTL(void) {
}
switch(reg_al) {
case 0x00: /* Get Device Information */
if (Files[handle]->GetInformation() & 0x8000) { //Check for device
if (Files[handle]->GetInformation() & DeviceInfoFlags::Device) { //Check for device
reg_dx=Files[handle]->GetInformation() & ~EXT_DEVICE_BIT;
} else {
uint8_t hdrive=Files[handle]->GetDrive();
Expand All @@ -633,7 +633,7 @@ bool DOS_IOCTL(void) {
hdrive=2; // defaulting to C:
}
/* return drive number in lower 5 bits for block devices */
reg_dx=(Files[handle]->GetInformation()&0xffe0)|hdrive;
reg_dx = (Files[handle]->GetInformation()&0xffe0) | (hdrive&0x1f);
}
reg_ax=reg_dx; //Destroyed officially
return true;
Expand All @@ -642,7 +642,7 @@ bool DOS_IOCTL(void) {
DOS_SetError(DOSERR_DATA_INVALID);
return false;
} else {
if (Files[handle]->GetInformation() & 0x8000) { //Check for device
if (Files[handle]->GetInformation() & DeviceInfoFlags::Device) { //Check for device
reg_al=(uint8_t)(Files[handle]->GetInformation() & 0xff);
} else {
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
Expand All @@ -651,7 +651,8 @@ bool DOS_IOCTL(void) {
}
return true;
case 0x02: /* Read from Device Control Channel */
if (Files[handle]->GetInformation() & 0xc000) {
if (Files[handle]->GetInformation() & (DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport) ==
DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport) {
/* is character device with IOCTL support */
PhysPt bufptr=PhysMake(SegValue(ds),reg_dx);
uint16_t retcode=0;
Expand All @@ -663,7 +664,8 @@ bool DOS_IOCTL(void) {
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
return false;
case 0x03: /* Write to Device Control Channel */
if (Files[handle]->GetInformation() & 0xc000) {
if (Files[handle]->GetInformation() & (DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport) ==
DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport) {
/* is character device with IOCTL support */
PhysPt bufptr=PhysMake(SegValue(ds),reg_dx);
uint16_t retcode=0;
Expand All @@ -675,7 +677,7 @@ bool DOS_IOCTL(void) {
DOS_SetError(DOSERR_FUNCTION_NUMBER_INVALID);
return false;
case 0x06: /* Get Input Status */
if (Files[handle]->GetInformation() & 0x8000) { //Check for device
if (Files[handle]->GetInformation() & DeviceInfoFlags::Device) { //Check for device
reg_al = ((DOS_Device*)(Files[handle]))->GetStatus(true);
} else { // FILE
uint32_t oldlocation=0;
Expand Down Expand Up @@ -781,6 +783,6 @@ bool DOS_IOCTL(void) {
bool DOS_GetSTDINStatus(void) {
uint32_t handle=RealHandle(STDIN);
if (handle==0xFF) return false;
if (Files[handle] && (Files[handle]->GetInformation() & 64)) return false;
if (Files[handle] && (Files[handle]->GetInformation() & DeviceInfoFlags::EofOnInput)) return false;
return true;
}
5 changes: 4 additions & 1 deletion src/dos/dos_mscdex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1371,7 +1371,10 @@ class device_MSCDEX : public DOS_Device {
}
bool Seek(uint32_t * /*pos*/,uint32_t /*type*/){return false;}
bool Close(){return false;}
uint16_t GetInformation(void){return 0xc880;}
uint16_t GetInformation(void)
{
return DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport | DeviceInfoFlags::OpenCloseSupport;
}
bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
bool WriteToControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
// private:
Expand Down
2 changes: 1 addition & 1 deletion src/dos/drive_local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2735,7 +2735,7 @@ bool localFile::Close() {
}

uint16_t localFile::GetInformation(void) {
return read_only_medium?0x40:0;
return read_only_medium ? DeviceInfoFlags::NotWritten : 0;
}


Expand Down
2 changes: 1 addition & 1 deletion src/dos/drive_virtual.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ bool Virtual_File::Close(){


uint16_t Virtual_File::GetInformation(void) {
return 0x40; // read-only drive
return DeviceInfoFlags::NotWritten; // read-only drive
}


Expand Down
2 changes: 1 addition & 1 deletion src/gui/sdlmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ bool CheckQuit(void) {
return systemmessagebox("Quit DOSBox-X warning","You are currently running a guest system.\nAre you sure to quit anyway now?","yesno", "question", 1);
if (warn == "autofile")
for (uint8_t handle = 0; handle < DOS_FILES; handle++) {
if (Files[handle] && (Files[handle]->GetName() == NULL || strcmp(Files[handle]->GetName(), "CON")) && (Files[handle]->GetInformation()&0x8000) == 0)
if (Files[handle] && (Files[handle]->GetName() == NULL || strcmp(Files[handle]->GetName(), "CON")) && (Files[handle]->GetInformation()&DeviceInfoFlags::Device) == 0)
return systemmessagebox("Quit DOSBox-X warning","It may be unsafe to quit from DOSBox-X right now\nbecause one or more files are currently open.\nAre you sure to quit anyway now?","yesno", "question", 1);
}
else if (RunningProgram&&strcmp(RunningProgram, "DOSBOX-X")&&strcmp(RunningProgram, "COMMAND")&&strcmp(RunningProgram, "4DOS"))
Expand Down
4 changes: 2 additions & 2 deletions src/hardware/parport/parport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ bool device_LPT::Close() {
uint16_t device_LPT::GetInformation(void) {
#if C_PRINTER
if (parallelPortObjects[num] && parallelPortObjects[num]->parallelType == PARALLEL_TYPE_PRINTER)
return 0x8040;
return DeviceInfoFlags::Device | DeviceInfoFlags::EofOnInput | DeviceInfoFlags::Binary;
#endif
return 0x80A0;
return DeviceInfoFlags::Device | DeviceInfoFlags::Binary;
}

const char* lptname[]={"LPT1","LPT2","LPT3","LPT4","LPT5","LPT6","LPT7","LPT8","LPT9"};
Expand Down
2 changes: 1 addition & 1 deletion src/hardware/serialport/serialport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ bool device_COM::Close() {
}

uint16_t device_COM::GetInformation(void) {
return 0x80A0;
return DeviceInfoFlags::Device | DeviceInfoFlags::Binary;
}

device_COM::device_COM(class CSerial* sc) {
Expand Down
5 changes: 4 additions & 1 deletion src/ints/ems.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,10 @@ class device_EMM : public DOS_Device {
}
bool Seek(uint32_t * /*pos*/,uint32_t /*type*/){return false;}
bool Close(){return false;}
uint16_t GetInformation(void){return 0xc0c0;}
uint16_t GetInformation(void)
{
return DeviceInfoFlags::Device | DeviceInfoFlags::IoctlSupport;
}
bool ReadFromControlChannel(PhysPt bufptr,uint16_t size,uint16_t * retcode);
bool WriteToControlChannel(PhysPt /*bufptr*/,uint16_t /*size*/,uint16_t * /*retcode*/){return true;}
private:
Expand Down

0 comments on commit 1b5d7f3

Please sign in to comment.