STATIC int CharRequest(struct dhdr FAR **pdev, unsigned command) { struct dhdr FAR *dev = *pdev; CharReqHdr.r_command = command; CharReqHdr.r_unit = 0; CharReqHdr.r_status = 0; CharReqHdr.r_length = sizeof(request); execrh(&CharReqHdr, dev); if (CharReqHdr.r_status & S_ERROR) { for (;;) { switch (char_error(&CharReqHdr, dev)) { case ABORT: case FAIL: return DE_INVLDACC; case CONTINUE: CharReqHdr.r_count = 0; return 0; case RETRY: return 1; } } } return SUCCESS; }
COUNT DosSetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp) { DosGetDate((BYTE FAR *) & DayOfWeek, (BYTE FAR *) & Month, (BYTE FAR *) & DayOfMonth, (COUNT FAR *) & Year); ClkRecord.clkHours = *hp; ClkRecord.clkMinutes = *mp; ClkRecord.clkSeconds = *sp; ClkRecord.clkHundredths = *hdp; YearsSince1980 = Year - 1980; ClkRecord.clkDays = DayOfMonth - 1 + days[is_leap_year(Year)][Month - 1] + ((YearsSince1980) * 365) + ((YearsSince1980 + 3) / 4); ClkReqHdr.r_length = sizeof(request); ClkReqHdr.r_command = C_OUTPUT; ClkReqHdr.r_count = sizeof(struct ClockRecord); ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); ClkReqHdr.r_status = 0; execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); if (ClkReqHdr.r_status & S_ERROR) return char_error(&ClkReqHdr, (struct dhdr FAR *)clock); return SUCCESS; }
UCOUNT BinaryCharIO(struct dhdr FAR * dev, UCOUNT n, void FAR * bp, unsigned command, COUNT *err) { *err = SUCCESS; FOREVER { CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = command; CharReqHdr.r_count = n; CharReqHdr.r_trans = bp; CharReqHdr.r_status = 0; execrh(&CharReqHdr, dev); if (CharReqHdr.r_status & S_ERROR) { charloop: switch (char_error(&CharReqHdr, dev)) { case ABORT: case FAIL: *err = DE_INVLDACC; return 0; case CONTINUE: break; case RETRY: continue; default: goto charloop; } } break; } return CharReqHdr.r_count; }
VOID DosGetTime(BYTE FAR * hp, BYTE FAR * mp, BYTE FAR * sp, BYTE FAR * hdp) { ClkReqHdr.r_length = sizeof(request); ClkReqHdr.r_command = C_INPUT; ClkReqHdr.r_count = sizeof(struct ClockRecord); ClkReqHdr.r_trans = (BYTE FAR *) (&ClkRecord); ClkReqHdr.r_status = 0; execrh((request FAR *) & ClkReqHdr, (struct dhdr FAR *)clock); if (ClkReqHdr.r_status & S_ERROR) return; *hp = ClkRecord.clkHours; *mp = ClkRecord.clkMinutes; *sp = ClkRecord.clkSeconds; *hdp = ClkRecord.clkHundredths; }
UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if (hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } /* If this is not opened and it's not a write */ /* another error */ if (s->sft_count == 0 || (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR))) { *err = DE_ACCESS; return 0; } if (s->sft_flags & SFT_FSHARED) { ReadCount = Remote_RW(REM_WRITE, n, bp, s, err); if (err) { return ReadCount; } else return 0; } /* Do a device write if device */ if (s->sft_flags & SFT_FDEVICE) { request rq; /* set to no EOF */ s->sft_flags &= ~SFT_FEOF; /* if null just report full transfer */ if (s->sft_flags & SFT_FNUL) { *err = SUCCESS; return n; } /* Now handle raw and cooked modes */ if (s->sft_flags & SFT_FBINARY) { rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = n; rq.r_trans = (BYTE FAR *) bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) { char_error(&rq, s->sft_dev); } else { if (s->sft_flags & SFT_FCONOUT) { WORD cnt = rq.r_count; while (cnt--) { switch (*bp++) { case CR: scr_pos = 0; break; case LF: case BELL: break; case BS: --scr_pos; break; default: ++scr_pos; } } } *err = SUCCESS; return rq.r_count; } } else { REG WORD c, cnt = n, spaces_left = 0, next_pos, xfer = 0; static BYTE space = ' '; start: if (cnt-- == 0) goto end; if (*bp == CTL_Z) goto end; if (s->sft_flags & SFT_FCONOUT) { switch (*bp) { case CR: next_pos = 0; break; case LF: case BELL: next_pos = scr_pos; break; case BS: next_pos = scr_pos ? scr_pos - 1 : 0; break; case HT: spaces_left = 8 - (scr_pos & 7); next_pos = scr_pos + spaces_left; goto output_space; default: next_pos = scr_pos + 1; } } rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = 1; rq.r_trans = bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) char_error(&rq, s->sft_dev); goto post; output_space: rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = 1; rq.r_trans = &space; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) char_error(&rq, s->sft_dev); --spaces_left; post: if (spaces_left) goto output_space; ++bp; ++xfer; if (s->sft_flags & SFT_FCONOUT) scr_pos = next_pos; if (break_ena && control_break()) { handle_break(); goto end; } goto start; end: *err = SUCCESS; return xfer; } } else /* a block write */ { COUNT rc; ReadCount = writeblock(s->sft_status, bp, n, &rc); if (rc < SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } *err = SUCCESS; return 0; }
/* * The `force_binary' parameter is a hack to allow functions 0x01, 0x06, 0x07, * and function 0x40 to use the same code for performing reads, even though the * two classes of functions behave quite differently: 0x01 etc. always do * binary reads, while for 0x40 the type of read (binary/text) depends on what * the SFT says. -- ror4 */ UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err, BOOL force_binary) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if (hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } /* If not open or write permission - exit */ if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE)) { *err = DE_INVLDACC; return 0; } /* * Do remote first or return error. * must have been opened from remote. */ if (s->sft_flags & SFT_FSHARED) { ReadCount = Remote_RW(REM_READ, n, bp, s, err); if (err) { *err = SUCCESS; return ReadCount; } else return 0; } /* Do a device read if device */ if (s->sft_flags & SFT_FDEVICE) { request rq; /* First test for eof and exit */ /* immediately if it is */ if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL)) { s->sft_flags &= ~SFT_FEOF; *err = SUCCESS; return 0; } /* Now handle raw and cooked modes */ if (force_binary || (s->sft_flags & SFT_FBINARY)) { rq.r_length = sizeof(request); rq.r_command = C_INPUT; rq.r_count = n; rq.r_trans = (BYTE FAR *) bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) { char_error(&rq, s->sft_dev); } else { *err = SUCCESS; return rq.r_count; } } else if (s->sft_flags & SFT_FCONIN) { kb_buf.kb_size = LINESIZE - 1; kb_buf.kb_count = 0; sti((keyboard FAR *) & kb_buf); fbcopy((BYTE FAR *) kb_buf.kb_buf, bp, kb_buf.kb_count); *err = SUCCESS; return kb_buf.kb_count; } else { *bp = _sti(); *err = SUCCESS; return 1; } } else /* a block read */ { COUNT rc; ReadCount = readblock(s->sft_status, bp, n, &rc); if (rc != SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } *err = SUCCESS; return 0; }
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err) { sft FAR *s; struct dpb FAR *dpbp; BYTE FAR *pBuffer = MK_FP(r->DS, r->DX); COUNT nMode; /* Test that the handle is valid */ switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: /* Get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: if (r->BL > nblkdev) { *err = DE_INVLDDRV; return 0; } else { /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ if (r->BL == 0) dpbp = &blk_devices[default_drive]; else dpbp = &blk_devices[r->BL - 1]; } break; case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (!r->DX) NetRetry = r->DX; break; default: *err = DE_INVLDFUNC; return 0; } switch (r->AL) { case 0x00: /* Get the flags from the SFT */ r->DX = r->AX = s->sft_flags; /* Test for file and network SFT. These return a 0 in */ /* the AH register. */ if ((s->sft_flags & SFT_FSHARED) || !(s->sft_flags & SFT_FDEVICE)) { r->AH = 0; } break; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(s->sft_flags & SFT_FDEVICE)) { *err = DE_INVLDFUNC; return 0; } /* Set it to what we got in the DL register from the */ /* user. */ r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if ((s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL))) { if (s->sft_dev->dh_attr & SFT_FIOCTL) { CharReqHdr.r_unit = 0; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) return char_error(&CharReqHdr, s->sft_dev); if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } break; } } *err = DE_INVLDFUNC; return 0; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if ((dpbp->dpb_device->dh_attr & ATTR_IOCTL) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { *err = DE_INVLDFUNC; return 0; } CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (r->AL == 0x08) { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { goto IoCharCommon; } r->AL = 0; break; case 0x08: if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } *err = DE_INVLDFUNC; return 0; case 0x09: r->DX = dpbp->dpb_device->dh_attr; break; case 0x0a: r->DX = s->sft_dcb->dpb_device->dh_attr; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { if (r->BL == 0) r->BL = default_drive; CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) *err = DE_ACCESS; else *err = SUCCESS; return 0; } *err = DE_INVLDFUNC; return 0; default: *err = DE_INVLDFUNC; return 0; } *err = SUCCESS; return 0; }
UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mode) { register struct dpb FAR *dpbp = get_dpb(dsk); if (dpbp == NULL) { return 0x0201; /* illegal command */ } #if TOM #define KeyboardShiftState() (*(BYTE FAR *)(MK_FP(0x40,0x17))) if (KeyboardShiftState() & 0x01) { printf("dskxfer:%s %x - %lx %u\n", mode == DSKWRITE ? "write" : "read", dsk, blkno, numblocks); if ((KeyboardShiftState() & 0x03) == 3) dumpBufferCache(); } #endif for (;;) { IoReqHdr.r_length = sizeof(request); IoReqHdr.r_unit = dpbp->dpb_subunit; switch (mode) { case DSKWRITE: if (verify_ena) { IoReqHdr.r_command = C_OUTVFY; break; } /* else fall through */ case DSKWRITEINT26: IoReqHdr.r_command = C_OUTPUT; break; case DSKREADINT25: case DSKREAD: IoReqHdr.r_command = C_INPUT; break; default: return 0x0100; /* illegal command */ } IoReqHdr.r_status = 0; IoReqHdr.r_meddesc = dpbp->dpb_mdb; IoReqHdr.r_count = numblocks; if ((dpbp->dpb_device->dh_attr & ATTR_HUGE) || blkno >= MAXSHORT) { IoReqHdr.r_start = HUGECOUNT; IoReqHdr.r_huge = blkno; } else IoReqHdr.r_start = (UWORD)blkno; /* * Some drivers normalise transfer address so HMA transfers are disastrous! * Then transfer block through xferbuf (DiskTransferBuffer doesn't work!) * (But this won't work for multi-block HMA transfers... are there any?) */ if (FP_SEG(buf) >= 0xa000 && numblocks == 1 && bufloc != LOC_CONV) { IoReqHdr.r_trans = deblock_buf; if (mode == DSKWRITE) fmemcpy(deblock_buf, buf, SEC_SIZE); execrh((request FAR *) & IoReqHdr, dpbp->dpb_device); if (mode == DSKREAD) fmemcpy(buf, deblock_buf, SEC_SIZE); } else { IoReqHdr.r_trans = (BYTE FAR *) buf; execrh((request FAR *) & IoReqHdr, dpbp->dpb_device); } if ((IoReqHdr.r_status & (S_ERROR | S_DONE)) == S_DONE) break; /* INT25/26 (_SEEMS_ TO) return immediately with 0x8002, if drive is not online,... normal operations (DIR) wait for ABORT/RETRY other condition codes not tested */ if (mode >= DSKWRITEINT26) return (IoReqHdr.r_status); loop: switch (block_error(&IoReqHdr, dpbp->dpb_unit, dpbp->dpb_device, mode)) { case ABORT: case FAIL: return (IoReqHdr.r_status); case RETRY: continue; case CONTINUE: break; default: goto loop; } break; } /* retry loop */ /* *** Changed 9/4/00 BER */ return 0; /* Success! Return 0 for a successful operation. */ /* End of change */ }
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err) { sft FAR *s; struct dpb FAR *dpbp; BYTE FAR *pBuffer = MK_FP(r->DS, r->DX); COUNT nMode; switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: if ((s = get_sft(r->BX)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: if (r->BL > nblkdev) { *err = DE_INVLDDRV; return 0; } else { if (r->BL == 0) dpbp = &blk_devices[default_drive]; else dpbp = &blk_devices[r->BL - 1]; } break; case 0x0b: break; default: *err = DE_INVLDFUNC; return 0; } switch (r->AL) { case 0x00: r->DX = r->AX = s->sft_flags; if ((s->sft_flags & SFT_FSHARED) || !(s->sft_flags & SFT_FDEVICE)) { r->AH = 0; } break; case 0x01: if (!(s->sft_flags & SFT_FDEVICE)) { *err = DE_INVLDFUNC; return 0; } r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if (!(s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL))) { if (s->sft_dev->dh_attr & SFT_FIOCTL) { CharReqHdr.r_unit = 0; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) return char_error(&CharReqHdr, s->sft_dev); if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } break; } } *err = DE_INVLDFUNC; return 0; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if (!(dpbp->dpb_device->dh_attr & ATTR_IOCTL) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { *err = DE_INVLDFUNC; return 0; } CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (r->AL == 0x08) { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { goto IoCharCommon; } r->AL = 0; break; case 0x08: if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } *err = DE_INVLDFUNC; return 0; case 0x09: r->DX = dpbp->dpb_device->dh_attr; break; case 0x0a: r->DX = s->sft_dcb->dpb_device->dh_attr; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if (!(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { if (r->BL == 0) r->BL = default_drive; CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) *err = DE_ACCESS; else *err = SUCCESS; return 0; } *err = DE_INVLDFUNC; return 0; default: *err = DE_INVLDFUNC; return 0; } *err = SUCCESS; return 0; }
COUNT DosDevIOctl(iregs FAR * r) { sft FAR *s; struct dpb FAR *dpbp; COUNT nMode; /* commonly used, shouldn't harm to do front up */ CharReqHdr.r_length = sizeof(request); CharReqHdr.r_trans = MK_FP(r->DS, r->DX); CharReqHdr.r_status = 0; CharReqHdr.r_count = r->CX; /* Test that the handle is valid */ switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: /* Get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) return DE_INVLDHNDL; break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ /* JT Fixed it */ CharReqHdr.r_unit = ( r->BL == 0 ? default_drive : r->BL - 1); if (CharReqHdr.r_unit >= lastdrive) return DE_INVLDDRV; else { /* cdsp = &CDSp->cds_table[CharReqHdr.r_unit]; */ dpbp = CDSp->cds_table[CharReqHdr.r_unit].cdsDpb; } break; case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (!r->DX) NetRetry = r->DX; break; default: return DE_INVLDFUNC; } switch (r->AL) { case 0x00: /* Get the flags from the SFT */ if (s->sft_flags & SFT_FDEVICE) r->AX = (s->sft_dev->dh_attr & 0xff00) | s->sft_flags_lo; else r->AX = s->sft_flags; /* Undocumented result, Ax = Dx seen using Pcwatch */ r->DX = r->AX; break; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(s->sft_flags & SFT_FDEVICE)) return DE_INVLDFUNC; /* Set it to what we got in the DL register from the */ /* user. */ r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if ((s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x02 ) && (s->sft_dev->dh_attr & SFT_FIOCTL)) || ((r->AL == 0x03 ) && (s->sft_dev->dh_attr & SFT_FIOCTL)) || ((r->AL == 0x10) && (s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && (s->sft_dev->dh_attr & ATTR_GENIOCTL))) { CharReqHdr.r_unit = 0; CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_DEVICE; } if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } else if (r->AL == 0x02 || r->AL == 0x03) { r->AX = CharReqHdr.r_count; } else if (r->AL == 0x0c || r->AL == 0x10) { r->AX = CharReqHdr.r_status; } break; } return DE_INVLDFUNC; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if(!dpbp) { return DE_INVLDDRV; } if ( ((r->AL == 0x04 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) || ((r->AL == 0x05 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { return DE_INVLDFUNC; } CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_DEVICE; } if (r->AL == 0x08) { r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else if (r->AL == 0x04 || r->AL == 0x05) { r->AX = CharReqHdr.r_count; } else if (r->AL == 0x0d || r->AL == 0x11) { r->AX = CharReqHdr.r_status; } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0xFF : 0; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { nMode = C_OSTAT; goto IoCharCommon; } r->AL = 0; break; case 0x08: if(!dpbp) { return DE_INVLDDRV; } if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } return DE_INVLDFUNC; case 0x09: if(CDSp->cds_table[CharReqHdr.r_unit].cdsFlags & CDSNETWDRV) { r->DX = ATTR_REMOTE ; r->AX = S_DONE|S_BUSY; } else { if(!dpbp) { return DE_INVLDDRV; } /* Need to add subst bit 15 */ r->DX = dpbp->dpb_device->dh_attr; r->AX = S_DONE|S_BUSY; } break; case 0x0a: r->DX = s->sft_flags; r->AX = 0; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if(!dpbp) { return DE_INVLDDRV; } if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_ACCESS; } else { r->AL = CharReqHdr.r_unit; return SUCCESS; } } return DE_INVLDFUNC; default: return DE_INVLDFUNC; } return SUCCESS; }
/* Changed to UWORD 9/4/00 BER */ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks, COUNT mode) /* End of change */ { /* REG struct dpb *dpbp = &blk_devices[dsk]; */ REG struct dpb FAR *dpbp = CDSp->cds_table[dsk].cdsDpb; if ((UCOUNT)dsk >= lastdrive ) { return 0x0201; /* illegal command */ } if (!(CDSp->cds_table[dsk].cdsFlags & CDSPHYSDRV)) { return 0x0201; /* illegal command */ } #if TOM #define KeyboardShiftState() (*(BYTE FAR *)(MK_FP(0x40,0x17))) if (KeyboardShiftState() & 0x01) { printf("dskxfer:%s %x - %lx %u\n", mode == DSKWRITE ? "write" : "read", dsk, blkno, numblocks); if ((KeyboardShiftState() & 0x03) == 3) dumpBufferCache(); } #endif for (;;) { IoReqHdr.r_length = sizeof(request); IoReqHdr.r_unit = dpbp->dpb_subunit; switch(mode) { case DSKWRITE : if (verify_ena) { IoReqHdr.r_command = C_OUTVFY; break; } /* else fall through */ case DSKWRITEINT26: IoReqHdr.r_command = C_OUTPUT; break; case DSKREADINT25: case DSKREAD : IoReqHdr.r_command = C_INPUT; break; default: return 0x0100; /* illegal command */ } IoReqHdr.r_status = 0; IoReqHdr.r_meddesc = dpbp->dpb_mdb; IoReqHdr.r_trans = (BYTE FAR *) buf; IoReqHdr.r_count = numblocks; if (blkno >= MAXSHORT) { IoReqHdr.r_start = HUGECOUNT; IoReqHdr.r_huge = blkno; } else IoReqHdr.r_start = blkno; execrh((request FAR *) & IoReqHdr, dpbp->dpb_device); if (!(IoReqHdr.r_status & S_ERROR) && (IoReqHdr.r_status & S_DONE)) break; /* INT25/26 (_SEEMS_ TO) return immediately with 0x8002, if drive is not online,... normal operations (DIR) wait for ABORT/RETRY other condition codes not tested */ if (mode >= DSKWRITEINT26) return (IoReqHdr.r_status); /* Changed 9/4/00 BER return (IoReqHdr.r_status); */ /* Skip the abort, retry, fail code...it needs fixed...BER */ /* End of change */ loop: switch (block_error(&IoReqHdr, dpbp->dpb_unit, dpbp->dpb_device)) { case ABORT: case FAIL: return (IoReqHdr.r_status); case RETRY: continue; case CONTINUE: break; default: goto loop; } } /* retry loop */ /* *** Changed 9/4/00 BER */ return 0; /* Success! Return 0 for a successful operation. */ /* End of change */ }
int DosDevIOctl(lregs * r) { struct dhdr FAR *dev; if (r->AL > 0x11) return DE_INVLDFUNC; switch (r->AL) { case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (r->DX) NetRetry = r->DX; return SUCCESS; case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: case 0x10: { sft FAR *s; unsigned flags; /* Test that the handle is valid and */ /* get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) return DE_INVLDHNDL; flags = s->sft_flags; switch (r->AL) { case 0x00: /* Get the flags from the SFT */ if (flags & SFT_FDEVICE) r->AX = (flags & 0xff) | (s->sft_dev->dh_attr & 0xff00); else r->AX = flags; /* Undocumented result, Ax = Dx seen using Pcwatch */ r->DX = r->AX; return SUCCESS; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(flags & SFT_FDEVICE)) return DE_INVLDFUNC; /* RBIL says this is only for DOS < 6, but MSDOS 7.10 */ /* returns this as well... and some buggy program relies*/ /* on it :( */ if (r->DH != 0) return DE_INVLDDATA; /* Undocumented: AL should get the old value */ r->AL = s->sft_flags_lo; /* Set it to what we got in the DL register from the */ /* user. */ s->sft_flags_lo = SFT_FDEVICE | r->DL; return SUCCESS; case 0x0a: r->DX = flags; r->AX = 0; return SUCCESS; } if (!(flags & SFT_FDEVICE)) { if (r->AL == 0x06) r->AL = s->sft_posit >= s->sft_size ? 0 : 0xFF; else if (r->AL == 0x07) r->AL = 0; else return DE_INVLDFUNC; return SUCCESS; } dev = s->sft_dev; CharReqHdr.r_unit = 0; break; } default: /* block IOCTL: 4, 5, 8, 9, d, e, f, 11 */ { struct dpb FAR *dpbp; unsigned attr; /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ /* JT Fixed it */ /* NDN feeds the actual ASCII drive letter to this function */ dpbp = get_dpb((r->BL & 0x1f) == 0 ? default_drive : (r->BL & 0x1f) - 1); if (dpbp) { CharReqHdr.r_unit = dpbp->dpb_subunit; dev = dpbp->dpb_device; attr = dev->dh_attr; } else { if (r->AL != 9) return DE_INVLDDRV; dev = NULL; attr = ATTR_REMOTE; } switch (r->AL) { case 0x09: { /* note from get_dpb() */ /* that if cdsp == NULL then dev must be NULL too */ struct cds FAR *cdsp = get_cds1(r->BL & 0x1f); if (cdsp == NULL) return DE_INVLDDRV; if (cdsp->cdsFlags & CDSSUBST) attr |= ATTR_SUBST; r->AX = S_DONE | S_BUSY; r->DX = attr; return SUCCESS; } case 0x0d: if ((r->CX & ~(0x486B-0x084A)) == 0x084A) { /* 084A/484A, 084B/484B, 086A/486A, 086B/486B */ r->AX = 0; /* (lock/unlock logical/physical volume) */ /* simulate success for MS-DOS 7+ SCANDISK etc. --LG */ return SUCCESS; } /* fall through */ default: /* 0x04, 0x05, 0x08, 0x0e, 0x0f, 0x11 */ break; } break; } } { unsigned testattr = ATTR_QRYIOCTL; if (r->AL<=0x0f) testattr = ATTR_GENIOCTL; if (r->AL<=0x08) testattr = ATTR_EXCALLS; if (r->AL<=0x07) testattr = 0xffff; if (r->AL<=0x05) testattr = ATTR_IOCTL; if (!(dev->dh_attr & testattr)) return DE_INVLDFUNC; } CharReqHdr.r_command = cmd[r->AL]; if (r->AL == 0x0C || r->AL == 0x0D || r->AL >= 0x10) /* generic or query */ { CharReqHdr.r_cat = r->CH; /* category (major) code */ CharReqHdr.r_fun = r->CL; /* function (minor) code */ CharReqHdr.r_si = r->SI; /* contents of SI and DI */ CharReqHdr.r_di = r->DI; CharReqHdr.r_io = MK_FP(r->DS, r->DX); /* parameter block */ } else { CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = MK_FP(r->DS, r->DX); } CharReqHdr.r_length = sizeof(request); CharReqHdr.r_status = 0; execrh(&CharReqHdr, dev); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_ACCESS; } if (r->AL <= 0x05) /* 0x02, 0x03, 0x04, 0x05 */ r->AX = CharReqHdr.r_count; else if (r->AL <= 0x07) /* 0x06, 0x07 */ r->AX = (CharReqHdr.r_status & S_BUSY) ? 0000 : 0x00ff; else if (r->AL == 0x08) /* 0x08 */ r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; else if (r->AL == 0x0e || r->AL == 0x0f) /* 0x0e, 0x0f */ r->AL = CharReqHdr.r_unit; else /* 0x0c, 0x0d, 0x10, 0x11 */ r->AX = CharReqHdr.r_status; return SUCCESS; }