home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
packet
/
cbbs60so.arc
/
MBIBM.C
< prev
next >
Wrap
Text File
|
1989-01-25
|
11KB
|
609 lines
/*
* MBIBM.C - 1/25/88 - System dependent functions.
* For standard IBM PC, under MS-DOS 3.1 or later
*
* Uses calls thru int 14h to drivers that replace the regular
* interrupt 14h drivers.
* Uses brkoff and brkon to disable/enable ctrl-brk by VE3GYQ
* - VE3GYQ and NK6K
*
*/
#include "mb.h"
#include <time.h>
#include <dos.h>
/*
* INT14 function codes.
*/
#define SER_OUT 1 /* Character out serial port */
#define SER_IN 2 /* Character in from serial port */
#define SER_STAT 3 /* Check status of serial port */
#define SER_INQ 4 /* Verify driver loaded */
#define SET_BUSY 8 /* Set port busy flag */
#define CLR_BUSY 9 /* Clear port busy flag */
#define PP_FLAG 10 /* Store port flag in bios */
#define PC_FLAG 11 /* Store command flag in bios */
#define GP_FLAG 12 /* Retreive port flag */
#define GC_FLAG 13 /* Retreive command flag */
#define GCMD 14 /* Get command from bios */
#define PCMD 15 /* Store command in bios */
/*
* INT21 Functions codes.
*/
#define SETDATE 0x2b
#define SETTIME 0x2d
#define SETDTA 0x1a
#define GETDTA 0x2f
#define GETFRE 0x36
#define SRCFST 0x4e
#define SRCNXT 0x4f
#define DV_PAUSE 0x1000 /* Relinquish control to other */
#define DV_BEGINC 0x101B /* Begin DV critical region */
#define DV_ENDC 0x101C /* End critical region */
char l_date[7], l_time[5];
long time();
static union REGS inreg, outreg, ingive, outgive;
char pt_flag = 0;
char bios_call;
#define CMDPORT 15 /* Port for passing commands */
/*
* Initialize the serial I/O system.
* Ports are initialized by loading driver and then running mbmode.
*/
ioinit()
{
brkoff(); /* disable DOS ctrl-brk fn */
}
dosinit()
{
if (s_flag & s_dv)
{
ingive.x.ax = DV_PAUSE;
bios_call = 0x15;
printf ("Set for DESQview.\n");
}
}
iooff()
{
brkon(); /* restore DOS ctrl-brk fn */
}
/*
* Switch out of the current window.
*/
switchw()
{
if (s_flag & s_dv)
int86(bios_call, &ingive, &outgive);
}
/*
* Set the current I/O device.
*/
ioport(pp)
PORTS *pp;
{
port = pp;
}
breakport()
{
inreg.x.dx = port->idn;
inreg.h.ah = 7;
int86( 0x14, &inreg, &outreg);
}
isdcd()
{
switch (port->dev)
{
case p_tnc:
case p_serial:
inreg.x.dx = port->idn;
inreg.h.ah = SER_STAT;
int86( 0x14, &inreg, &outreg );
return (0x80 & outreg.h.al);
default: return true;
}
}
/*
* Suspend multitasking permitting only calling task to
* continue execution.
*/
begin_lock()
{
inreg.x.ax = DV_BEGINC;
int86(0x15, &inreg, &outreg);
}
/*
* Resume multitasking.
*/
end_lock()
{
inreg.x.ax = DV_ENDC;
int86(0x15, &inreg, &outreg);
}
/*
* Mark all the ports in this window as busy.
*/
setbusy()
{
inreg.h.ah = SET_BUSY;
inreg.x.dx = CMDPORT;
inreg.h.al = window;
int86(0x14, &inreg, &outreg);
}
/*
* Mark all the ports in this window as idle.
*/
clrbusy()
{
inreg.h.ah = CLR_BUSY;
inreg.x.dx = CMDPORT;
inreg.h.al = window;
int86(0x14, &inreg, &outreg);
}
/*
* Store the port flag in the bios. Port flag bits set
* indicate that the corresponding port is initialized
* in a window.
*/
putp_flag(c)
byte c;
{
inreg.h.ah = PP_FLAG;
inreg.x.dx = CMDPORT;
inreg.h.al = c;
int86(0x14, &inreg, &outreg);
}
/*
* Store the command flag in the bios. Command flag bits set
* indicate that the corresponding port has a command waiting
* for it to process.
*/
putc_flag(c)
byte c;
{
inreg.h.ah = PC_FLAG;
inreg.x.dx = CMDPORT;
inreg.h.bl = c;
int86(0x14, &inreg, &outreg);
}
/*
* Get the port flag from the bios. Port flag bits set
* indicate that the corresponding port is initialized
* in a window.
*/
byte getp_flag()
{
inreg.h.ah = GP_FLAG;
inreg.x.dx = CMDPORT;
int86(0x14, &inreg, &outreg);
return outreg.h.al;
}
/*
* Get the command flag from the bios. Command flag bits set
* indicate that the corresponding port has a command waiting
* for it to process.
*/
getc_flag()
{
inreg.h.ah = GC_FLAG;
inreg.x.dx = CMDPORT;
int86(0x14, &inreg, &outreg);
c_flag = outreg.h.bl;
b_flag = outreg.h.bh;
}
/*
* Recover two characters from the bios storage area for use
* as commands. Port->line will contain these on return.
*/
getcomd()
{
inreg.h.ah = GCMD;
inreg.x.dx = CMDPORT;
int86(0x14, &inreg, &outreg);
port->opt1 = outreg.h.bl;
port->opt2 = outreg.h.bh;
}
/*
* Pass a two character command to the bios storage area.
*/
putcomd(c1, c2)
char c1, c2;
{
inreg.h.ah = PCMD;
inreg.x.dx = CMDPORT;
inreg.h.bl = c1;
inreg.h.bh = c2;
int86(0x14, &inreg, &outreg);
}
/*
* Return character from the current port.
*/
char inchar()
{
register char ch;
if (port->dev is p_console)
{ ch = bdos(7, 0, 0);if (ch is '\020') pt_flag = !pt_flag; }
else
{
inreg.h.ah = SER_IN;
inreg.x.dx = port->idn;
int86(0x14, &inreg, &outreg);
ch = (0x00ff & outreg.h.al);
}
if (ch is del) ch = '\b';
if (port->dev is p_console) return ch;
/*
* Input did not come from the console.
* Echo the input to the console.
*/
if (!(port->ec)) return ch;
if (ch isnt ctl_g)
{
bdos(2, ch, 0);
if (ch is '\r') bdos(2, '\n', 0);
}
return ch;
}
/*
* Return non-zero if a character waits at current input.
*/
instat()
{
register int st;
if (port->dev is p_console) st = kbstat();
else
{
inreg.x.dx = port->idn;
inreg.h.ah = SER_STAT;
int86(0x14, &inreg, &outreg);
st = 0x01 & outreg.h.ah;
}
if (!st) if (s_flag & s_dv)
if (port->flags & p_give)
int86(bios_call, &ingive, &outgive);
return st;
}
outi(ch)
char ch;
{
inreg.x.dx = port->idn;
inreg.h.ah = SER_STAT;
/*
* Check if cts on and xmtr rgstr empty.
* Else maybe give some time to other DV windows.
*/
int86(0x14, &inreg, &outreg);
while((0x2010 & outreg.x.ax) isnt 0x2010)
{
/*
if (s_flag & s_dv)
if (port->flags & p_give) int86(bios_call, &ingive, &outgive);
*/
int86(0x14, &inreg, &outreg);
}
/*
* Stuff the character out the port.
*/
inreg.h.ah = SER_OUT;
inreg.h.al = ch;
int86(0x14, &inreg, &outreg);
}
/*
* Put the character out the current port,
* echo to console if the current port is not the console.
* Note special handling of end-of-line character.
*/
outchar(ch)
char ch;
{
if (ch is '\r') return;
if (ch is '\n') ch = '\r';
/*
* Put it out to the console, if it is going there.
*/
if ((port->dev is p_console) or port->ec)
{
bdos(2, ch, 0);
if (ch is '\r') bdos(2,'\n',0);
if (pt_flag) { bdos(5,ch,0); if(ch is '\r') bdos(5,'\n',0); }
}
/*
* If the port is the console, nothing more to do.
*/
if (port->dev is p_console) return;
/*
* Stuff this byte out the port.
*/
outi(ch);
if (ch is '\r') if (port->flags & p_lf) outi('\n');
}
outstr(cp)
char *cp;
{
while(*cp) outchar(*cp++);
}
/*
* Set the clock.
* fld[1] has the date string.
* fld[2] has the time string.
*/
settime()
{
inreg.h.ah = SETTIME;
inreg.h.ch = two(port->fld[2]); /* Hour */
inreg.h.cl = two(port->fld[2]+2); /* Minute */
inreg.x.dx = 0; /* Seconds and hundredths */
intdos(&inreg, &outreg);
inreg.h.ah = SETDATE;
inreg.h.dl = two(port->fld[1]+4); /* Day */
inreg.h.dh = two(port->fld[1]+2); /* Month */
inreg.x.cx = 1900 + two(port->fld[1]); /* Year */
intdos(&inreg, &outreg);
}
two(cp)
char *cp;
{
return (10 * (*cp - '0') + (*(cp + 1) - '0'));
}
/*
* Fill the globals "l_date", "l_time", and "dt" with
* the current date and time by reading the system clock.
* l_time is HHMM, l_date is YYMMDD.
* dt has the format of a directory item date/time.
*/
curtim()
{
struct tm *ct;
long ltime;
time(<ime);
ct = localtime(<ime);
sprintf(l_time, "%02d%02d", ct->tm_hour, ct->tm_min);
sprintf(l_date, "%02d%02d%02d", ct->tm_year, ct->tm_mon + 1, ct->tm_mday);
/* month returned by localtime is 0-11 */
}
/*
* Check a timer.
*/
chktmr(l)
long l;
{
long cur;
time(&cur);
if (cur > l) return false;
return true;
}
/*
* Set a timer.
*/
settmr(l, i)
long *l;
int i;
{
long cur;
time(&cur);
*l = cur + (long)i;
}
/*
* Wait a bit.
*/
wait(sec)
int sec;
{
long l;
settmr(&l, sec);
while (chktmr(l)) if (s_flag & s_dv)
int86(bios_call, &ingive, &outgive);
}
/*
* Directory access routines.
*/
#define d_dir 0x10
/*
* A directory item.
*/
typedef struct
{
char res[21];
char attr;
int time;
int date;
word sizel;
word sizeh;
char name[13];
} FCB;
static int olddta;
static FCB fcb;
/*
* Open directory, return first item.
*/
diropen(cp, p, dirdef)
char *cp;
DIRDEF *dirdef;
DIRENT *p;
{
long csize;
/*
* Save DOS current buffer.
*/
inreg.h.ah = GETDTA;
intdos(&inreg, &outreg);
olddta = outreg.x.bx;
/*
* Point DOS at local buffer.
*/
inreg.h.ah = SETDTA;
inreg.x.dx = (int)&fcb;
intdos(&inreg, &outreg);
/*
* Get disk free space.
*/
inreg.h.ah = GETFRE;
if (*(cp + 1) is ':') inreg.h.dl = toupper(*cp) - 'A' + 1; else inreg.h.dl = 0;
intdos(&inreg, &outreg);
/*
* Compute device size.
* ax = sectors / cluster
* bx = available clusters
* cx = bytes / sector
* dx = total cluster / drive
*/
csize = (long)outreg.x.ax * (long)outreg.x.cx;
dirdef->size = (int)((csize * (long)outreg.x.dx + 1023l) / 1024l);
dirdef->free = (int)((csize * (long)outreg.x.bx + 1023l) / 1024l);
/*
* Get the first directory entry.
*/
if (port->flds is 1) strcat(cp, "*.*");
if (port->mode & (local | sysop)) inreg.x.cx = d_dir; else inreg.x.cx = 0;
inreg.x.dx = (int)cp;
inreg.h.ah = SRCFST;
while (true)
{
if (intdos(&inreg, &outreg))
{
p->size = -1;
inreg.h.ah = SETDTA;
inreg.x.dx = olddta;
intdos(&inreg, &outreg);
return false;
}
if (dodir(p)) return true;
inreg.h.ah = SRCNXT;
}
}
/*
* Return second and succeding directory entries.
*/
dirnext(p, dirdef)
DIRENT *p;
DIRDEF *dirdef;
{
inreg.h.ah = SRCNXT;
while(true)
{
if (intdos(&inreg, &outreg))
{
p->size = -1;
inreg.h.ah = SETDTA;
inreg.x.dx = olddta;
intdos(&inreg, &outreg);
return;
}
if (dodir(p)) return;
}
}
dodir(p)
DIRENT *p;
{
strcpy(p->name, fcb.name);
if (fcb.attr & d_dir)
{
if (match(p->name, ".")) return false;
if (match(p->name, "..")) return false;
strcat(p->name, "\\");
}
p->size = (int)((65536l * (long)fcb.sizeh + (long)fcb.sizel + 1023l) / 1024l);
return true;
}