| Close | Back |
/* CODE TO OPEN THE DOOR. */
# include "dos.h"
# include "stdio.h"
# include "ctype.h"
# include "conio.h"
struct IoctlOutputDataBlockHeader
{
unsigned char commandCode;
};
void initializeIoctlOutputDataBlockHeader(
struct IoctlOutputDataBlockHeader* i, unsigned char
code)
{
i->commandCode = code;
}
enum IoctlOutputCodes
{
EJECT_DISK = 0,
LOCK_UNLOCK_DOOR = 1,
RESET_DRIVE = 2,
AUDIO_CHANNEL_CONTROL = 3,
CLOSE_TRAY = 5
};
struct RequestHeader
{
unsigned char length;
unsigned char unit;
unsigned char commandCode;
unsigned int status;
unsigned char unused[ 8 ];
};
struct IoctlOutputHeader
{
struct RequestHeader base;
unsigned char mediaDescriptor;
void far* transferAddress;
unsigned int byteCount;
unsigned int sectorNumber;
void far* volumeIdPtr;
};
enum CommandCodes
{
INIT = 0,
IOCTL_INPUT = 3,
INPUT_FLUSH = 7,
OUTPUT_FLUSH = 11,
IOCTL_OUTPUT = 12,
DEVICE_OPEN = 13,
DEVICE_CLOSE = 14,
READ_LONG = 128,
READ_LONG_PREFETCH = 130,
SEEK = 131,
PLAY_AUDIO = 132,
STOP_AUDIO = 133,
WRITE_LONG = 134,
WRITE_LONG_VERIFY = 135,
RESUME_AUDIO = 136
};
void initializeRequestHeader(struct RequestHeader*
r,
unsigned int length, unsigned char subunit, enum
CommandCodes code)
{
r->length = length;
r->unit = subunit;
r->commandCode = code;
r->status = 0; // not necessary, but sets status to a known value
}
void initializeIoctlOutputHeader(struct
IoctlOutputHeader* i,
void far* data, unsigned int dataLength, unsigned
char subunit)
{
initializeRequestHeader(&i->base, sizeof(struct
IoctlOutputHeader), subunit, IOCTL_OUTPUT);
i->mediaDescriptor = 0;
i->transferAddress = data;
i->byteCount = dataLength;
i->sectorNumber = 0;
i->volumeIdPtr = (void far*)0;
}
void callDevice(char drive, void* data)
{
struct SREGS s;
union REGS r;
s.es = FP_SEG(data);
r.x.bx = FP_OFF(data);
r.x.ax = 0x1510;
if (isupper(drive))
{
r.x.cx = drive - 'A';
}
else if (islower(drive))
{
r.x.cx = drive - 'a';
}
else
{
r.x.cx = (unsigned char)drive;
}
int86x(0x2F, &r, &r, &s);
}
unsigned int getStatus(struct RequestHeader* r)
{
return r->status;
}
char* getErrorCode(unsigned int status)
{
char* result = 0;
if (status & 0x8000)
{
switch (status & 0x00FF)
{
case 0:
result = "write-protect violation";
break;
case 1:
result = "unknown unit";
break;
case 2:
result = "drive not ready";
break;
case 3:
result = "unknown command";
break;
case 4:
result = "CRC error";
break;
case 5:
result = "bad drive request structure length";
break;
case 6:
result = "seek error";
break;
case 7:
result = "unknown media";
break;
case 8:
result = "sector not found";
break;
case 9:
result = "printer out of paper";
break;
case 10:
result = "write fault";
break;
case 11:
result = "read fault";
break;
case 12:
result = "general failure";
break;
case 14:
result = "media unavailable";
break;
case 15:
result = "invalid disk change";
break;
default:
result = "undocumented error code";
break;
}
}
return result;
}
int isBusy(unsigned int status)
{
return (status & 0x0200) ? 1 : 0;
}
struct Eject
{
struct IoctlOutputDataBlockHeader base;
};
void initializeEject(struct Eject* e)
{
initializeIoctlOutputDataBlockHeader(&(e->base),
EJECT_DISK);
}
int eject(char drive, unsigned char subunit)
{
struct Eject e;
struct IoctlOutputHeader i;
unsigned int status;
char* error;
initializeEject(&e);
initializeIoctlOutputHeader(&i, (void far*)&e,
sizeof(struct Eject), subunit);
callDevice(drive, (void far*)&i);
status = getStatus(&i.base);
error = getErrorCode(status);
if (error)
{
printf("Error ejecting disk: %s\n", error);
return 0;
}
if (isBusy(status))
{
printf("Device busy\n");
return 0;
}
return 1;
}
void main()
{
struct Eject e;
clrscr();
initializeEject(&e);
eject('g',3);
}