/* * JR-IDE Project * - (c) 2017 Alan Hightower * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "pimount.h" #pragma data_seg("_TEXT", "CODE"); #pragma code_seg("_TEXT", "CODE"); extern uint16_t get_ds (void); #pragma aux get_ds = \ "mov ax,ds" \ value [ax]; typedef int (*_handler)(void); ctx_t ctx; // Operational context block - resident static union INTPACK far *r; // saved register file from 2Fh entry // Resident helper functions static void _fmemcpy_local (void far *dst, const void far *src, size_t num) { // fastest implementation so far using rep movsw __asm { push es; push ds; push si; push di; mov cx, num; les di, dst; lds si, src; shr cx,1; rep movsw; adc cx,cx; rep movsb; pop di; pop si; pop ds; pop es; } return; } static int _success (void) { r->w.ax = DOS_SUCCESS; r->w.flags &= ~INTR_CF; return 0; } // ***** Function 00h ***** static int _installation_check (void) { r->w.ax = 0x00ff; // installed - generic redirector (PC Tools v8 DRIVEMAP) r->w.flags &= ~INTR_CF; return 0; } // ***** Function 05h ***** static int _chdir (void) { redir_stat_t *arg = (redir_stat_t *) ctx.scratch; _fmemcpy_local (MK_FP(get_ds(), arg->filename_a), ctx.filename1, 128); arg->filename_a_nul = '\0'; arg->statop = REDIR_STAT_ATTR; arg->driveno = ctx.sdb->driveno; _redir_push (REDIR_FEAT_STAT_PUSH); _redir_pull (REDIR_FEAT_STAT_PULL); if (arg->found && (arg->attrib & 0x10)) return _success(); r->w.ax = DOS_PATHNOTFND; return 0; } // ***** Function 0Ch ***** static int _get_diskinfo (void) { redir_info_t *info = (redir_info_t *) ctx.scratch; dlist_t far *drive = (dlist_t far *) MK_FP(r->w.es, r->w.di); if (drive->magic != PIMOUNT_MAGIC) return -1; if (_redir_pull (REDIR_FEAT_GET_STATUS)) return -1; r->w.ax = info->sector_per_cluster; r->w.cx = info->bytes_per_sector; r->w.bx = info->total_clusters; r->w.dx = info->avail_clusters; r->w.flags &= ~INTR_CF; return 0; } // ***** Function 1Ch ***** static int _find_next (void) { redir_nextdir_t *next = (redir_nextdir_t *) ctx.scratch; redir_dentry_t *entry; int i; if ((ctx.sdb->driveno & 0x40) == 0x00) return 0; do { // Check cache(scratch) validity if (ctx.prev_pull != REDIR_FEAT_DIR_NEXT) break; if (next->index == NEXT_DENTRIES) _redir_pull (REDIR_FEAT_DIR_NEXT); entry = &next->entry[next->index]; if (entry->filename[0] == '\0') break; // end of list ctx.sdb->entryno = next->start + next->index; ctx.fdb->attr = entry->attrib; ctx.fdb->mtime = entry->dos_time; ctx.fdb->mdate = entry->dos_date; ctx.fdb->size = entry->size; for (i = 0; i < 11; i++) ctx.fdb->name[i] = entry->filename[i]; next->index++; return _success(); } while (0); // error r->w.ax = DOS_NFILES; return 0; } // ***** Function 1Bh ***** static int _find_first (void) { uint8_t attrmask = ctx.sda[0x24d]; redir_opendir_t *arg = (redir_opendir_t *) ctx.scratch; if (attrmask == _A_VOLID) // Volume Label { ctx.sdb->driveno = ctx.driveno | 0x80; ctx.sdb->entryno = 0; _fmemcpy_local (ctx.sdb->search_mask, ctx.fcbname1, 11); ctx.fdb->attr = _A_VOLID; ctx.fdb->mtime = 0; ctx.fdb->mdate = 0; ctx.fdb->size = 0; ctx.fdb->name[0] = 'J'; ctx.fdb->name[1] = 'R'; ctx.fdb->name[2] = '-'; ctx.fdb->name[3] = 'I'; ctx.fdb->name[4] = 'D'; ctx.fdb->name[5] = 'E'; ctx.fdb->name[6] = '_'; ctx.fdb->name[7] = 'R'; ctx.fdb->name[8] = 'P'; ctx.fdb->name[9] = 'I'; ctx.fdb->name[10] = 'Z'; return _success (); } _fmemcpy_local (MK_FP(get_ds(), arg->filename), ctx.filename1, 128); _fmemcpy_local (MK_FP(get_ds(), arg->mask), ctx.sdb->search_mask, 11); arg->filename_nul = '\0'; arg->mask_nul = '\0'; arg->driveno = ctx.sdb->driveno; arg->attrib_a = attrmask; arg->attrib_b = ctx.sdb->attr_mask; _redir_push (REDIR_FEAT_DIR_FIRST); _fmemcpy_local (ctx.sdb->search_mask, ctx.fcbname1, 11); ctx.sdb->driveno = ctx.driveno | 0xc0; ctx.sdb->attr_mask = attrmask; ctx.sdb->entryno = 0; _redir_pull (REDIR_FEAT_DIR_NEXT); return _find_next (); } // Local (resident) clone of _chain_intr() from // ./owc/src/bld/clib/intel/a/chint086.asm void _chain_prev (void (__interrupt __far *)(void)); #pragma aux _chain_prev = \ "mov cx, ax" \ "mov ax, dx" \ "mov sp, bp" \ "xchg cx, 20[bp]" \ "xchg ax, 22[bp]" \ "pop dx" \ "pop dx" \ "pop es" \ "pop ds" \ "pop di" \ "pop si" \ "pop bp" \ "pop bx" \ "pop bx" \ "pop dx" \ "retf" \ parm [dx ax] \ modify []; // From Ralf's List static const _handler dispatchTable[] = { _installation_check, // 00 : Installation Check NULL, // 01 : Remove Directory NULL, // 02 : NULL, // 03 : Make Directory NULL, // 04 : _chdir, // 05 : Change Directory NULL, // 06 : Close File _success, // 07 : Commit File NULL, // 08 : Read from File NULL, // 09 : Write to File _success, // 0a : Lock Region _success, // 0b : Unlock Region _get_diskinfo, // 0c : Get Disk Information NULL, // 0d : _success, // 0e : Set File Attributes NULL,//_get_file_attrib, // 0f : Get File Attributes and Size NULL, // 10 : NULL, // 11 : Rename File NULL, // 12 : NULL, // 13 : Delete File NULL, // 14 : NULL, // 15 : NULL, // 16 : Open Existing File NULL, // 17 : Create/Truncate File NULL, // 18 : Create/Truncate File w/o CDS NULL, // 19 : Find First File w/o CDS NULL, // 1a : _find_first, // 1b : Find First File _find_next, // 1c : Find Next File NULL, // 1d : Close all Files for Process NULL, // 1e : Do Redirection NULL, // 1f : Printer Setup NULL, // 20 : Flush All Disk Buffers NULL, // 21 : Seek from end of File NULL, // 22 : Process Termination Hook NULL, // 23 : Qualify Remote File Name NULL, // 24 : Turn Off Printer NULL, // 25 : Redirected Printer Mode NULL, // 26 : Remote Printer Echo On/Off NULL, // 27 : NULL, // 28 : NULL, // 29 : NULL, // 2a : NULL, // 2b : NULL, // 2c : Update CB NULL, // 2d : NULL // 2e : Extended Open/Create File }; #define MAX_FUNCTION (int) (sizeof (dispatchTable) / sizeof (dispatchTable[0])) static int _redirect_chain (uint8_t function) { // dlist_t far *sda_drive; if (function == 0) return 0; #if 0 sda_drive = (dlist_t far *) FPDRF(ctx.sda + 0x282); if (sda_drive->magic != PIMOUNT_MAGIC) return 1; if ((ctx.sdb->driveno & 0x1f) != ctx.driveno) return 1; #endif return 0; } void __interrupt redirector (union INTPACK regset) { _asm { push cs pop ds } do { static _handler dispatch; if ((regset.h.ah != 0x11) || (regset.h.al >= MAX_FUNCTION)) break; if (!(dispatch = dispatchTable[regset.h.al])) break; if (_redirect_chain(regset.h.al)) break; r = ®set; // assume failure regset.w.ax = DOS_INVALID_FUNC; regset.w.flags |= INTR_CF; if (dispatch ()) break; return; } while (0); _chain_prev (ctx.prev_handler); return; } // ***** End of RESIDENT segment ***** uint16_t _get_resident_psize (void) { uint16_t bytes; bytes = (uint16_t) _get_resident_psize; bytes += 15; // round up to paragraph (16 bytes) size return bytes >> 4; }