(with a little help from Arkady)

inthndler.c, chario.c, break.c simplifications and cleanups.
Pass a near pointer to the far pointer that points to the device instead
of an SFT index (in general).
Make cooked_write much faster by only testing for input every 32
characters.
No longer test for ctl_s on syscon if writing to the printer: just
read from the printer which will return zero characters.
Fix reading/writing zero characters by returning "256" (special code).
Adjust interfaces in other files.


git-svn-id: https://svn.code.sf.net/p/freedos/svn/kernel/trunk@683 6ac86273-5f31-0410-b378-82cca8765d1b
This commit is contained in:
Bart Oldeman 2003-09-09 17:43:43 +00:00
parent 8c22873b3e
commit b0e54ff704
7 changed files with 246 additions and 252 deletions

View File

@ -47,9 +47,14 @@ static BYTE *RcsId =
* 1) flag at 40:71 bit 7
* 2) STDIN stream via con_break()
*/
int control_break(void)
int check_handle_break(void)
{
return (CB_FLG & CB_MSK) || con_break();
if (CB_FLG & CB_MSK) {
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
handle_break(&syscon);
}
/* con_break will call handle_break() for CTL_C */
return con_break();
}
/*
@ -61,13 +66,10 @@ int control_break(void)
* 3) decrease the InDOS flag as the kernel drops back to user space
* 4) invoke INT-23 and never come back
*/
void handle_break(int sft_idx)
void handle_break(struct dhdr FAR **pdev)
{
if (CB_FLG & CB_MSK) /* Ctrl-Break pressed */
CB_FLG &= ~CB_MSK; /* reset the ^Break flag */
else /* Ctrl-C pressed */
echo_char_stdin(CTL_C);
KbdFlush(sft_idx); /* Er, this is con_flush() */
echo_char_stdin(CTL_C);
con_flush(pdev);
if (!ErrorMode) /* within int21_handler, InDOS is not incremented */
if (InDOS)
--InDOS; /* fail-safe */

View File

@ -37,17 +37,19 @@ static BYTE *charioRcsId =
#include "globals.h"
STATIC int CharRequest(struct dhdr FAR *dev)
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)
{
charloop:
switch (char_error(&CharReqHdr, dev))
{
for (;;) {
switch (char_error(&CharReqHdr, dev))
{
case ABORT:
case FAIL:
return DE_INVLDACC;
@ -56,147 +58,134 @@ STATIC int CharRequest(struct dhdr FAR *dev)
return 0;
case RETRY:
return 1;
default:
goto charloop;
}
}
}
return 0;
return SUCCESS;
}
long BinaryCharIO(struct dhdr FAR * dev, size_t n, void FAR * bp, unsigned command)
long BinaryCharIO(struct dhdr FAR **pdev, size_t n, void FAR * bp,
unsigned command)
{
int err = SUCCESS;
int err;
do
{
CharReqHdr.r_command = command;
CharReqHdr.r_count = n;
CharReqHdr.r_trans = bp;
} while ((err = CharRequest(dev)) == 1);
err = CharRequest(pdev, command);
} while (err == 1);
return err == SUCCESS ? (long)CharReqHdr.r_count : err;
}
STATIC int CharIO(struct dhdr FAR **pdev, unsigned char ch, unsigned command)
{
int err = (int)BinaryCharIO(pdev, 1, &ch, command);
if (err == 0)
return 256;
if (err < 0)
return err;
return ch;
}
/* STATE FUNCTIONS */
STATIC struct dhdr FAR *idx_to_dev(int sft_idx)
void CharCmd(struct dhdr FAR **pdev, unsigned command)
{
sft FAR *s = idx_to_sft(sft_idx);
if (FP_OFF(s) == (size_t)-1 || (s->sft_mode & SFT_MWRITE) ||
!(s->sft_flags & SFT_FDEVICE))
while (CharRequest(pdev, command) == 1);
}
STATIC int Busy(struct dhdr FAR **pdev)
{
CharCmd(pdev, C_ISTAT);
return CharReqHdr.r_status & S_BUSY;
}
void con_flush(struct dhdr FAR **pdev)
{
CharCmd(pdev, C_IFLUSH);
}
/* if the sft is invalid, then we just monitor syscon */
struct dhdr FAR *sft_to_dev(sft FAR *s)
{
if (FP_OFF(s) == (size_t) -1)
return syscon;
else
return s->sft_dev;
}
/* if sft_idx is invalid, then we just monitor syscon */
STATIC BOOL Busy(int sft_idx)
{
sft FAR *s = idx_to_sft(sft_idx);
if (s->sft_flags & SFT_FDEVICE)
{
struct dhdr FAR *dev = idx_to_dev(sft_idx);
do {
CharReqHdr.r_command = C_ISTAT;
} while(CharRequest(dev) == 1);
if (CharReqHdr.r_status & S_BUSY)
return TRUE;
else
return FALSE;
}
else
return s->sft_posit >= s->sft_size;
return s->sft_dev;
return NULL;
}
BOOL StdinBusy(void)
int StdinBusy(void)
{
return Busy(get_sft_idx(STDIN));
sft FAR *s = get_sft(STDIN);
struct dhdr FAR *dev = sft_to_dev(s);
if (dev)
return Busy(&dev);
return s->sft_posit >= s->sft_size;
}
STATIC void Do_DosIdle_loop(int sft_idx)
STATIC void Do_DosIdle_loop(struct dhdr FAR **pdev)
{
/* the idle loop is only safe if we're using the character stack */
/* the idle loop is only safe if we're using the character stack */
if (user_r->AH < 0xd)
while (Busy(sft_idx))
while (Busy(pdev) && Busy(&syscon))
DosIdle_int();
}
/* get character from the console - this is how DOS gets
CTL_C/CTL_S/CTL_P when outputting */
STATIC int ndread(int sft_idx)
STATIC int ndread(struct dhdr FAR **pdev)
{
struct dhdr FAR *dev = idx_to_dev(sft_idx);
do {
CharReqHdr.r_command = C_NDREAD;
} while(CharRequest(dev) == 1);
CharCmd(pdev, C_NDREAD);
if (CharReqHdr.r_status & S_BUSY)
return -1;
return CharReqHdr.r_ndbyte;
}
STATIC int con_get_char(int sft_idx)
STATIC void con_skip_char(struct dhdr FAR **pdev)
{
unsigned char c;
BinaryCharIO(idx_to_dev(sft_idx), 1, &c, C_INPUT);
if (c == CTL_C)
handle_break(sft_idx);
return c;
if (CharIO(pdev, 0, C_INPUT) == CTL_C)
handle_break(pdev);
}
STATIC void con_hold(int sft_idx)
STATIC void con_hold(struct dhdr FAR **pdev)
{
int c;
if (control_break())
handle_break(-1);
c = ndread(sft_idx);
if (c == CTL_S)
int c = check_handle_break();
if (*pdev != syscon)
c = ndread(pdev);
if (c == CTL_S || c == CTL_C)
{
con_get_char(sft_idx);
Do_DosIdle_loop(sft_idx);
con_skip_char(pdev);
Do_DosIdle_loop(pdev);
/* just wait */
c = con_get_char(sft_idx);
}
if (c == CTL_C)
{
con_get_char(sft_idx);
handle_break(sft_idx);
check_handle_break();
con_skip_char(pdev);
}
}
BOOL con_break(void)
int con_break(void)
{
if (ndread(-1) == CTL_C)
{
con_get_char(-1);
return TRUE;
}
else
return FALSE;
int c = ndread(&syscon);
if (c == CTL_C)
con_skip_char(&syscon);
return c;
}
/* OUTPUT FUNCTIONS */
#ifdef __WATCOMC__
void int29(char c);
#pragma aux int29 = "int 29h" parm[al] modify exact [bx]
#endif
void fast_put_char(char c);
#pragma aux fast_put_char = "int 29h" parm[al] modify exact [bx]
#else
/* writes a character in raw mode; use int29 if possible
for speed */
STATIC int raw_put_char(int sft_idx, int c)
/* writes a character in raw mode using int29 for speed */
STATIC void fast_put_char(unsigned char chr)
{
struct dhdr FAR *dev = idx_to_dev(sft_idx);
unsigned char chr = (unsigned char)c;
if (PrinterEcho)
DosWrite(STDPRN, 1, &chr);
if (dev->dh_attr & ATTR_FASTCON)
{
#if defined(__TURBOC__)
_AL = chr;
__int__(0x29);
#elif defined(__WATCOMC__)
int29(chr);
#elif defined(I86)
asm
{
@ -204,59 +193,79 @@ STATIC int raw_put_char(int sft_idx, int c)
int 0x29;
}
#endif
return 0;
}
c = (int)BinaryCharIO(dev, 1, &chr, C_OUTPUT);
if (c < 0)
return c;
else
return chr;
}
#endif
/* writes a character in cooked mode; maybe with printer echo;
handles TAB expansion */
STATIC int cooked_put_char(int sft_idx, int c)
STATIC int cooked_write_char(struct dhdr FAR **pdev,
unsigned char c,
unsigned char *fast_counter)
{
int err = 0;
unsigned char scrpos = scr_pos;
/* Test for hold char */
con_hold(sft_idx);
unsigned char count = 1;
switch (c)
{
case CR:
scrpos = 0;
break;
case LF:
case BELL:
break;
case BS:
if (scrpos > 0)
scrpos--;
break;
case HT:
do
err = raw_put_char(sft_idx, ' ');
while (err >= 0 && ((++scrpos) & 7));
break;
default:
scrpos++;
if (c == CR)
scrpos = 0;
else if (c == BS) {
if (scrpos > 0)
scrpos--;
} else if (c != LF && c != BELL) {
if (c == HT) {
count = 8 - (scrpos & 7);
c = ' ';
}
scrpos += count;
}
scr_pos = scrpos;
if (c != HT)
err = raw_put_char(sft_idx, c);
return err;
do {
/* if not fast then < 0x80; always check
otherwise check every 32 characters */
if (*fast_counter <= 0x80)
/* Test for hold char and ctl_c */
con_hold(pdev);
*fast_counter += 1;
*fast_counter &= 0x9f;
if (PrinterEcho)
DosWrite(STDPRN, 1, &c);
if (*fast_counter & 0x80)
{
fast_put_char(c);
}
else
{
int err = CharIO(pdev, c, C_OUTPUT);
if (err < 0)
return err;
}
} while (--count > 0);
return SUCCESS;
}
long cooked_write(int sft_idx, size_t n, char FAR *bp)
long cooked_write(struct dhdr FAR **pdev, size_t n, char FAR *bp)
{
size_t xfer;
int err = SUCCESS;
for (xfer = 0; err >= SUCCESS && xfer < n && *bp != CTL_Z; bp++, xfer++)
err = cooked_put_char(sft_idx, *bp);
return err < SUCCESS ? (long)err : xfer;
size_t xfer = 0;
unsigned char fast_counter;
/* bit 7 means fastcon; low 5 bits count number of characters */
fast_counter = ((*pdev)->dh_attr & ATTR_FASTCON) << 3;
for (xfer = 0; xfer < n; xfer++)
{
int err;
unsigned char c = *bp++;
if (c == CTL_Z)
break;
err = cooked_write_char(pdev, c, &fast_counter);
if (err < 0)
return err;
}
return xfer;
}
/* writes character for disk file or device */
@ -276,13 +285,13 @@ void write_char_stdout(int c)
/* this is for handling things like ^C, mostly used in echoed input */
STATIC int echo_char(int c, int sft_idx)
{
int out = c;
if (iscntrl(c) && c != HT && c != LF && c != CR)
{
write_char('^', sft_idx);
write_char(c + '@', sft_idx);
out += '@';
}
else
write_char(c, sft_idx);
write_char(out, sft_idx);
return c;
}
@ -300,28 +309,28 @@ STATIC void destr_bs(int sft_idx)
/* READ FUNCTIONS */
STATIC int raw_get_char(int sft_idx, BOOL check_break)
STATIC int raw_get_char(struct dhdr FAR **pdev, BOOL check_break)
{
unsigned char c;
int err;
Do_DosIdle_loop(sft_idx);
Do_DosIdle_loop(pdev);
if (check_break)
con_hold(sft_idx);
err = (int)BinaryCharIO(idx_to_dev(sft_idx), 1, &c, C_INPUT);
return err < 0 ? err : c;
{
con_hold(pdev);
Do_DosIdle_loop(pdev);
}
return CharIO(pdev, 0, C_INPUT);
}
long cooked_read(int sft_idx, size_t n, char FAR *bp)
long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp)
{
unsigned xfer = 0;
int c;
while(n--)
{
c = raw_get_char(sft_idx, TRUE);
c = raw_get_char(pdev, TRUE);
if (c < 0)
return c;
if (c == 256)
break;
*bp++ = c;
xfer++;
if (bp[-1] == CTL_Z)
@ -333,10 +342,10 @@ long cooked_read(int sft_idx, size_t n, char FAR *bp)
unsigned char read_char(int sft_idx, BOOL check_break)
{
unsigned char c;
sft FAR *s = idx_to_sft(sft_idx);
struct dhdr FAR *dev = sft_to_dev(idx_to_sft(sft_idx));
if ((FP_OFF(s) == (size_t) -1) || (s->sft_flags & SFT_FDEVICE))
return raw_get_char(sft_idx, check_break);
if (dev)
return (unsigned char)raw_get_char(&dev, check_break);
DosRWSft(sft_idx, 1, &c, XFR_READ);
return c;
@ -352,18 +361,6 @@ unsigned char read_char_stdin(BOOL check_break)
return read_char(get_sft_idx(STDIN), check_break);
}
void KbdFlush(int sft_idx)
{
struct dhdr FAR *dev = idx_to_dev(sft_idx);
do {
CharReqHdr.r_unit = 0;
CharReqHdr.r_status = 0;
CharReqHdr.r_command = C_IFLUSH;
CharReqHdr.r_length = sizeof(request);
} while (CharRequest(dev) == 1);
}
/* reads a line (buffered, called by int21/ah=0ah, 3fh) */
void read_line(int sft_in, int sft_out, keyboard FAR * kp)
{

View File

@ -230,10 +230,12 @@ long DosRWSft(int sft_idx, size_t n, void FAR * bp, int mode)
/* Do a device transfer if device */
if (s->sft_flags & SFT_FDEVICE)
{
struct dhdr FAR *dev = s->sft_dev;
/* Now handle raw and cooked modes */
if (s->sft_flags & SFT_FBINARY)
{
long rc = BinaryCharIO(s->sft_dev, n, bp,
long rc = BinaryCharIO(&dev, n, bp,
mode == XFR_READ ? C_INPUT : C_OUTPUT);
if (mode == XFR_WRITE && rc > 0 && (s->sft_flags & SFT_FCONOUT))
{
@ -266,7 +268,7 @@ long DosRWSft(int sft_idx, size_t n, void FAR * bp, int mode)
if (mode==XFR_READ)
{
long rc;
/* Test for eof and exit */
/* immediately if it is */
if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL))
@ -275,21 +277,21 @@ long DosRWSft(int sft_idx, size_t n, void FAR * bp, int mode)
if (s->sft_flags & SFT_FCONIN)
rc = read_line_handle(sft_idx, n, bp);
else
rc = cooked_read(sft_idx, n, bp);
rc = cooked_read(&dev, n, bp);
if (*(char *)bp == CTL_Z)
s->sft_flags &= ~SFT_FEOF;
return rc;
}
else
{
/* reset EOF state (set to no EOF) */
/* reset EOF state (set to no EOF) */
s->sft_flags |= SFT_FEOF;
/* if null just report full transfer */
if (s->sft_flags & SFT_FNUL)
return n;
else
return cooked_write(sft_idx, n, bp);
return cooked_write(&dev, n, bp);
}
}
@ -1399,13 +1401,13 @@ struct dhdr FAR *IsDevice(const char FAR * fname)
for (i = 0; i < FNAME_SIZE; i++)
{
char c1 = froot[i];
unsigned char c1 = (unsigned char)froot[i];
if (c1 == '.' || c1 == '\0')
{
/* check if remainder of device name consists of spaces or nulls */
for (; i < FNAME_SIZE; i++)
{
char c2 = dhp->dh_name[i];
unsigned char c2 = dhp->dh_name[i];
if (c2 != ' ' && c2 != '\0')
break;
}

View File

@ -429,6 +429,9 @@ VOID fputbyte(VOID FAR *, UBYTE);
/*#define is_leap_year(y) ((y) & 3 ? 0 : (y) % 100 ? 1 : (y) % 400 ? 0 : 1) */
/* ^Break handling */
#ifdef __WATCOMC__
#pragma aux (cdecl) spawn_int23 aborts;
#endif
void ASMCFUNC spawn_int23(void); /* procsupt.asm */
GLOBAL BYTE ReturnAnyDosVersionExpected;

View File

@ -373,7 +373,6 @@ VOID ASMCFUNC int21_service(iregs FAR * r)
#define FP_DS_DX (MK_FP(lr.DS, lr.DX))
#define FP_ES_DI (MK_FP(lr.ES, lr.DI))
#define CLEAR_CARRY_FLAG() r->FLAGS &= ~FLG_CARRY
#define SET_CARRY_FLAG() r->FLAGS |= FLG_CARRY
@ -407,23 +406,8 @@ dispatch:
/* Check for Ctrl-Break */
switch (lr.AH)
{
default:
if (!break_ena)
break;
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (control_break())
handle_break(-1);
}
if (break_ena || (lr.AH >= 1 && lr.AH <= 5) || (lr.AH >= 8 && lr.AH <= 0x0b))
check_handle_break;
/* The dispatch handler */
switch (lr.AH)
@ -436,13 +420,16 @@ dispatch:
/* Read Keyboard with Echo */
case 0x01:
DOS_01:
lr.AL = read_char_stdin(TRUE);
write_char_stdout(lr.AL);
break;
/* Display Character */
case 0x02:
write_char_stdout(lr.DL);
DOS_02:
lr.AL = lr.DL;
write_char_stdout(lr.AL);
break;
/* Auxiliary Input */
@ -461,27 +448,28 @@ dispatch:
/* Direct Console I/O */
case 0x06:
DOS_06:
if (lr.DL != 0xff)
write_char_stdout(lr.DL);
else if (StdinBusy())
{
lr.AL = 0x00;
r->FLAGS |= FLG_ZERO;
}
else
{
r->FLAGS &= ~FLG_ZERO;
lr.AL = read_char_stdin(FALSE);
}
goto DOS_02;
lr.AL = 0x00;
r->FLAGS |= FLG_ZERO;
if (StdinBusy())
break;
r->FLAGS &= ~FLG_ZERO;
lr.AL = read_char_stdin(FALSE);
break;
/* Direct Console Input */
case 0x07:
DOS_07:
lr.AL = read_char_stdin(FALSE);
break;
/* Read Keyboard Without Echo */
case 0x08:
DOS_08:
lr.AL = read_char_stdin(TRUE);
break;
@ -501,35 +489,34 @@ dispatch:
/* Buffered Keyboard Input */
case 0x0a:
DOS_0A:
read_line(get_sft_idx(STDIN), get_sft_idx(STDOUT), FP_DS_DX);
break;
/* Check Stdin Status */
case 0x0b:
lr.AL = 0xFF;
if (StdinBusy())
lr.AL = 0x00;
else
lr.AL = 0xFF;
break;
/* Flush Buffer, Read Keyboard */
case 0x0c:
KbdFlush(get_sft_idx(STDIN));
{
struct dhdr FAR *dev = sft_to_dev(get_sft(STDIN));
if (dev)
con_flush(&dev);
switch (lr.AL)
{
case 0x01:
case 0x06:
case 0x07:
case 0x08:
case 0x0a:
lr.AH = lr.AL;
goto dispatch;
default:
lr.AL = 0x00;
break;
case 0x01: goto DOS_01;
case 0x06: goto DOS_06;
case 0x07: goto DOS_07;
case 0x08: goto DOS_08;
case 0x0a: goto DOS_0A;
}
lr.AL = 0x00;
break;
}
/* Reset Drive */
case 0x0d:
@ -1819,45 +1806,43 @@ struct int2f12regs {
extern short AllocateHMASpace (size_t lowbuffer, size_t highbuffer);
/* WARNING: modifications in `r' are used outside of int2F_12_handler()
* On input r.ax==0x12xx, 0x4A01 or 0x4A02
*/
VOID ASMCFUNC int2F_12_handler(struct int2f12regs r)
{
UWORD function = r.ax & 0xff;
/* dont use
/* dont use
QueryFreeHMASpace(&p);
here; DS !=SS
*/
if ((r.ax & 0xff00) == 0x4a00)
{
size_t wantedBytes = r.bx;
r.bx = 0;
r.es = FP_SEG(firstAvailableBuf);
r.di = FP_OFF(firstAvailableBuf);
size_t wantedBytes, offs;
if (function != 1 && function != 2)
return;
wantedBytes = r.bx;
r.es = r.di = 0xffff;
r.bx = 0;
if (FP_SEG(firstAvailableBuf) != 0xffff)
{
return;
}
if (r.ax == 0x4a01)
{
r.bx = 0 - FP_OFF(firstAvailableBuf);
return;
}
if (r.ax == 0x4a02)
offs = FP_OFF(firstAvailableBuf);
r.di = offs;
if (function == 0x02)
{
if (wantedBytes > 0 - FP_OFF(firstAvailableBuf))
{
r.bx = 0;
return;
}
if (wantedBytes > ~offs)
return;
AllocateHMASpace(FP_OFF(firstAvailableBuf),
FP_OFF(firstAvailableBuf)+wantedBytes);
firstAvailableBuf += wantedBytes;
return;
r.bx = wantedBytes;
}
return;
}
if (function > 0x31)

View File

@ -48,23 +48,28 @@ UWORD dskxfer(COUNT dsk, ULONG blkno, VOID FAR * buf, UWORD numblocks,
/* *** End of change */
/* break.c */
int control_break(void);
void handle_break(int sft_idx);
#ifdef __WATCOMC__
#pragma aux handle_break aborts;
#endif
int check_handle_break(void);
void handle_break(struct dhdr FAR **pdev);
/* chario.c */
long BinaryCharIO(struct dhdr FAR * dev, size_t n, void FAR * bp, unsigned command);
struct dhdr FAR *sft_to_dev(sft FAR *sft);
long BinaryCharIO(struct dhdr FAR **pdev, size_t n, void FAR * bp,
unsigned command);
int echo_char_stdin(int c);
BOOL con_break(void);
BOOL StdinBusy(void);
void KbdFlush(int sft_idx);
int con_break(void);
int StdinBusy(void);
void con_flush(struct dhdr FAR **pdev);
unsigned char read_char(int sft_idx, BOOL check_break);
unsigned char read_char_stdin(BOOL check_break);
long cooked_read(int sft_idx, size_t n, char FAR *bp);
long cooked_read(struct dhdr FAR **pdev, size_t n, char FAR *bp);
void read_line(int sft_in, int sft_out, keyboard FAR * kp);
size_t read_line_handle(int sft_idx, size_t n, char FAR * bp);
void write_char(int c, int sft_idx);
void write_char_stdout(int c);
long cooked_write(int sft_idx, size_t n, char FAR *bp);
long cooked_write(struct dhdr FAR **pdev, size_t n, char FAR *bp);
sft FAR *get_sft(UCOUNT);

View File

@ -74,7 +74,7 @@ UWORD DaysFromYearMonthDay(UWORD Year, UWORD Month, UWORD DayOfMonth)
/* common - call the clock driver */
void ExecuteClockDriverRequest(BYTE command)
{
BinaryCharIO(clock, sizeof(struct ClockRecord), &ClkRecord, command);
BinaryCharIO(&clock, sizeof(struct ClockRecord), &ClkRecord, command);
}
void DosGetTime(struct dostime *dt)