/* CODE TO CLOSE THE DOOR. */ # include "stdio.h" # include "conio.h" # include "dos.h" #include "ctype.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 CloseTray { struct IoctlOutputDataBlockHeader base; }; void initializeCloseTray(struct CloseTray* ct) { initializeIoctlOutputDataBlockHeader(&(ct->base), CLOSE_TRAY); } int closeTray(char drive, unsigned char subunit) { struct CloseTray ct; struct IoctlOutputHeader i; unsigned int status; char* error; initializeCloseTray(&ct); initializeIoctlOutputHeader(&i, (void far*)&ct, sizeof(struct CloseTray), subunit); callDevice(drive, (void far*)&i); status = getStatus(&i.base); error = getErrorCode(status); if (error) { printf("Error closing tray: %s\n", error); return 0; } if (isBusy(status)) { printf("Device busy\n"); return 0; } return 1; } void main(void) { clrscr(); closeTray('g',3); }