/***************************************************************************** * FILE: rmlib.c * * * * DESC: * * - Interface to Real Mode calls * * * * Copyright (C) 1993,1994 * * Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld * * email: rainer@mathematik.uni-bielefeld.de * * * *****************************************************************************/ #include "DPMI.H" #include "PROCESS.H" #include "START32.H" #include "CDOSX32.H" #include "RMLIB.H" #include "DOSERRNO.H" #define LV_WORD *(WORD *)& unsigned rm_bios_read_keybrd(unsigned mode) { TRANSLATION tr; unsigned key; LV_WORD tr.eax = mode << 8; tr.sp = tr.ss = 0; tr.flags = 0x3200; tr.cs = cs16real; tr.ds = cs16real; SimulateRMint(0x16, 0, 0, &tr); key = (unsigned) (tr.eax & 0xFFFF); if ((tr.flags & 64) && (mode == 0x01 || mode == 0x11)) return 0; else return key; } #ifdef __EMX__ #define SET_SEG_OFF(pointer, seg, off) \ { seg = (((unsigned) (pointer) & ~0xFFF) >> 4) + ds16real; \ off = (unsigned) (pointer) & 0xFFF; } #else /* 16 bit compiler */ #define SET_SEG_OFF(pointer, seg, off) \ { seg = ds16real; off = (WORD) (pointer) ;} #endif #ifdef __EMX__ #define SET_SEG_OFF_64(pointer, seg, off) \ { seg = (((unsigned) (pointer) & ~0xFFFF) >> 4) + ds16real; \ off = (unsigned) (pointer) & 0xFFFF; } #else /* 16 bit compiler */ #define SET_SEG_OFF_64(pointer, seg, off) \ { seg = ds16real; off = (WORD) (pointer) ;} #endif unsigned emx_errno; static int call_rm_dos(TRANSLATION *ts) { ts->flags = 0x3200; ts->cs = cs16real; SET_SEG_OFF_64(real_mode_stack, ts->ss, ts->sp); /* DPMI-Call to Real-Mode DOS */ SimulateRMint(0x21, 0, 0, ts); /* return Carry-bit */ if (ts->flags & 1) { _doserrno = (unsigned) ts->eax & 0xFFFF; emx_errno = doserror_to_errno(_doserrno); return -1; } else return (int) (ts->eax & 0xFFFF); } /* ********** DISK OPERATIONS ********** */ /* ** AH = 0x0E ** DL = drive (a=0,b=1,c=2) ** return: AL max drive */ int rm_setdrive(WORD drive) { TRANSLATION ts; LV_WORD ts.eax = 0x0E00; LV_WORD ts.edx = drive; return (call_rm_dos(&ts) & 0xFF); } /* ** AH = 0x19 ** return: AL this drive (a=0,b=1,c=2) */ int rm_getdrive(void) { TRANSLATION ts; LV_WORD ts.eax = 0x1900; return (call_rm_dos(&ts) & 0xFF); } /* ** AH = 0x1A ** DS:DX dta address */ void rm_setdta(void *buf) { TRANSLATION ts; LV_WORD ts.eax = 0x1A00; SET_SEG_OFF(buf, ts.ds, ts.edx); call_rm_dos(&ts); } /* ********** DATE/TIME OPERATIONS ********** */ /* ** AH = 0x2A ** return: CX=year DX=month/day */ void rm_getdate(struct dos_date * dd) { TRANSLATION ts; LV_WORD ts.eax = 0x2A00; call_rm_dos(&ts); dd->ddate_year = (WORD) ts.ecx; dd->ddate_month = (BYTE) ((WORD) ts.edx >> 8); dd->ddate_day = (BYTE) ts.edx; dd->ddate_dayofweek = (BYTE) ts.eax; } /* ** AH = 0x2B ** CX = year ** DX = month/day */ int rm_setdate(struct dos_date * dd) { TRANSLATION ts; LV_WORD ts.eax = 0x2B00; LV_WORD ts.ecx = (WORD) dd->ddate_year; LV_WORD ts.edx = ((WORD) dd->ddate_month << 8) | dd->ddate_day; call_rm_dos(&ts); if ((ts.eax & 0xFF) == 0xFF) return -1; else return 0; } /* ** AH = 0x2C ** return CX=hour/min DX=sec/hsec */ void rm_gettime(struct dos_time * dt) { TRANSLATION ts; LV_WORD ts.eax = 0x2C00; call_rm_dos(&ts); dt->dtime_hour = (BYTE) ((WORD) ts.ecx >> 8); dt->dtime_minutes = (BYTE) ts.ecx; dt->dtime_seconds = (BYTE) ((WORD) ts.edx >> 8); dt->dtime_hsec = (BYTE) ts.edx; } /* ** AH = 0x2D ** CX = hour/min ** DX = sec/hsec */ int rm_settime(struct dos_time * dt) { TRANSLATION ts; LV_WORD ts.eax = 0x2D00; LV_WORD ts.ecx = ((WORD) dt->dtime_hour << 8) | dt->dtime_minutes; LV_WORD ts.edx = ((WORD) dt->dtime_seconds << 8) | dt->dtime_hsec; call_rm_dos(&ts); if ((ts.eax & 0xFF) == 0xFF) return -1; else return 0; } /* ********** DIRECTORY OPERATIONS ********** */ /* ** AH = 0x3B ** DS:DX name (64 bytes) */ int rm_chdir(char *name) { TRANSLATION ts; LV_WORD ts.eax = 0x3B00; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x43 ; AL = 0 ** DS:DX name ** return CX: attr */ int rm_getfattr(char *name, WORD * attr) { TRANSLATION ts; LV_WORD ts.eax = 0x4300; SET_SEG_OFF(name, ts.ds, ts.edx); if (call_rm_dos(&ts) == -1) return -1; else { *attr = (WORD) ts.ecx; return 0; } } int rm_access(char *name, WORD mode) { WORD attr; if (rm_getfattr(name, &attr) == -1) return -1; if ((attr & 1) && (mode & 2)) /* RDONLY and try WRITE access */ return -1; else return 0; } /* ** AH = 0x43 ; AL = 1 ** CX = attr ** DS:DX name */ int rm_setfattr(char *name, WORD attr) { TRANSLATION ts; LV_WORD ts.eax = 0x4301; LV_WORD ts.ecx = attr; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x47 ** DS:SI name */ int rm_getcwd(WORD drive, char *name) { TRANSLATION ts; LV_WORD ts.eax = 0x4700; LV_WORD ts.edx = drive; SET_SEG_OFF(name, ts.ds, ts.esi); return call_rm_dos(&ts); } /* ** AH = 0x4E ** CX = attr ** DS:DX name */ int rm_findfirst(char *name, WORD attr, struct find_t * ft) { TRANSLATION ts; rm_setdta(ft); LV_WORD ts.eax = 0x4E00; LV_WORD ts.ecx = attr; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ********** FILE HANDLE OPERATIONS ********** */ /* ** AH = 0x3C ** CX = attr ** DS:DX = name ** return: AX fileno */ int rm_creat(char *name, WORD attr) { TRANSLATION ts; LV_WORD ts.eax = 0x3C00; LV_WORD ts.ecx = attr; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x3D ** AL = mode ** DS:DX = name ** return: AX fileno */ int rm_open(char *name, WORD modes) { TRANSLATION ts; LV_WORD ts.eax = 0x3D00 | modes; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x3E ** BX = file handle ** return: -1 on error */ int rm_close(WORD handle) { TRANSLATION ts; LV_WORD ts.eax = 0x3E00; LV_WORD ts.ebx = handle; if (call_rm_dos(&ts) == -1) return -1; else return 0; } /* ** AH = 0x3F ** BX = handle ** CX = bytes ** DS:DX = buf ** return: AX bytes */ int rm_read(WORD handle, void *buf, WORD bytes) { TRANSLATION ts; LV_WORD ts.eax = 0x3F00; LV_WORD ts.ebx = (WORD) handle; LV_WORD ts.ecx = (WORD) bytes; SET_SEG_OFF(buf, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x40 ** BX = handle ** CX = bytes ** DS:DX = buf ** return: AX bytes */ int rm_write(WORD handle, void *buf, WORD bytes) { TRANSLATION ts; LV_WORD ts.eax = 0x4000; LV_WORD ts.ebx = (WORD) handle; LV_WORD ts.ecx = (WORD) bytes; SET_SEG_OFF(buf, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AH = 0x42 ** AL = orgin ** BX = handle ** CX:DX = pos ** return: new pos */ long rm_lseek(WORD handle, DWORD offset, WORD orgin) { TRANSLATION ts; LV_WORD ts.eax = 0x4200 | orgin; LV_WORD ts.ebx = (WORD) handle; LV_WORD ts.ecx = (WORD) (offset >> 16); LV_WORD ts.edx = (WORD) offset; if (call_rm_dos(&ts) == -1) return -1L; else return (ts.edx << 16) | (ts.eax & 0xFFFF); } /* ** AH = 0x45 ** BX = handle ** return: AX new handle */ int rm_dup(WORD handle) { TRANSLATION ts; LV_WORD ts.eax = 0x4500; LV_WORD ts.ebx = handle; return call_rm_dos(&ts); } /* ** AH = 0x46 ** BX = handle ** CX = new handle ** return: -1 on error */ int rm_dup2(WORD handle, WORD newhandle) { TRANSLATION ts; LV_WORD ts.eax = 0x4600; LV_WORD ts.ebx = handle; LV_WORD ts.ecx = newhandle; return call_rm_dos(&ts); } /* ** AX = 0x5700 ** BX = handle ** return: CX:DX */ int rm_getftime(WORD handle, WORD * date, WORD * time) { TRANSLATION ts; LV_WORD ts.eax = 0x5700; LV_WORD ts.ebx = handle; if (call_rm_dos(&ts) == -1) return -1; else { *date = (WORD) ts.edx; *time = (WORD) ts.ecx; return 0; } } /* ** AX = 0x5701 ** BX = handle ** CX:DX = time/date */ int rm_setftime(WORD handle, WORD date, WORD time) { TRANSLATION ts; LV_WORD ts.eax = 0x5701; LV_WORD ts.ebx = handle; LV_WORD ts.ecx = time; LV_WORD ts.edx = date; return call_rm_dos(&ts); } /* ** AH = 0x5B ** CX = attr ** DS:DX = name ** return: AX fileno */ int rm_creatnew(char *name, WORD attr) { TRANSLATION ts; LV_WORD ts.eax = 0x5B00; LV_WORD ts.ecx = attr; SET_SEG_OFF(name, ts.ds, ts.edx); return call_rm_dos(&ts); } /* ** AX = 0x67 ** BX = handles */ int rm_sethandles(WORD handles) { TRANSLATION ts; LV_WORD ts.eax = 0x6700; LV_WORD ts.ebx = handles; return call_rm_dos(&ts); } /* ********** IOCTL OPERATIONS ********** */ /* ** AH = 0x44 ; AL = 0 ** BX = handle */ int rm_ioctl_getattr(WORD handle) { TRANSLATION ts; LV_WORD ts.eax = 0x4400; LV_WORD ts.ebx = handle; if (call_rm_dos(&ts) == -1) return -1; else return (WORD) ts.edx; } int rm_isatty(WORD handle) { int i = rm_ioctl_getattr(handle); if (i == -1) return 0; else return i & 128; } /* ** AH = 0x44 ; AL = 01 ** BX = handle ** DX = mode */ int rm_ioctl_setattr(WORD handle, WORD mode) { TRANSLATION ts; LV_WORD ts.eax = 0x4401; LV_WORD ts.ebx = handle; LV_WORD ts.edx = mode; if (call_rm_dos(&ts) == -1) return -1; else return 0; } /* ** AH = 0x44 ; AL = 06 ** BX = handle */ int rm_ioctl_select_in(WORD handle) { TRANSLATION ts; LV_WORD ts.eax = 0x4406; LV_WORD ts.ebx = handle; if (call_rm_dos(&ts) == -1) return 0; return ((BYTE)ts.eax == 0xFF) ? 1 : 0; } /* ** AH = 0x44 ; AL = 09 ** BL = drive ** ret: 1/0 remote or -1 */ int rm_ioctl_remotedrive(BYTE drive) { TRANSLATION ts; LV_WORD ts.eax = (WORD) 0x4409; LV_WORD ts.ebx = (WORD) drive; if (call_rm_dos(&ts) == -1) return -1; else return (int) (ts.edx & 0x1000) >> 12; } /* ********** PROCESS CONTROL ********** */ /* ** AX = 0x4B00 ** DS:DX = name ** ES:BX = exec block ** ret: -1 on error */ int rm_exec(char *name, struct execb * eb) { TRANSLATION ts; LV_WORD ts.eax = 0x4B00; SET_SEG_OFF(name, ts.ds, ts.edx); SET_SEG_OFF(eb, ts.es, ts.ebx); return call_rm_dos(&ts); } /* ** AX = 0x4D00 ** ret: exit value */ int rm_get_exit_status(void) { TRANSLATION ts; LV_WORD ts.eax = 0x4D00; return call_rm_dos(&ts); }