mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
Upload
Digital Research
This commit is contained in:
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/fileio.c
Normal file
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/fileio.c
Normal file
@@ -0,0 +1,659 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS File I/O Module *
|
||||
* *
|
||||
* This module contains all file handling BDOS functions *
|
||||
* except for read and write for CP/M-68K. Included are: *
|
||||
* *
|
||||
* seldsk() - select disk *
|
||||
* openfile() - open file *
|
||||
* close_fi() - close file *
|
||||
* search() - search for first/next file match *
|
||||
* create() - create file *
|
||||
* delete() - delete file *
|
||||
* rename() - rename file *
|
||||
* set_attr() - set file attributes *
|
||||
* getsize() - get file size *
|
||||
* setran() - set random record field *
|
||||
* free_sp() - get disk free space *
|
||||
* move() - general purpose byte mover *
|
||||
* *
|
||||
* *
|
||||
* Compiled with Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
/* declare external fucntions */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN UWORD error(); /* disk error routine */
|
||||
EXTERN UWORD ro_err(); /* read-only file error routine */
|
||||
EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
EXTERN clraloc(); /* clear bit in allocation vector */
|
||||
EXTERN setaloc(); /* set bit in allocation vector */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dir_wr(); /* directory write routine */
|
||||
EXTERN tmp_sel(); /* temporary select disk routine */
|
||||
EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
|
||||
EXTERN UWORD udiv(); /* unsigned divide routine */
|
||||
|
||||
|
||||
/* declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of disks in critical state */
|
||||
|
||||
|
||||
/************************************
|
||||
* This function passed to dirscan *
|
||||
* from seldsk (below) *
|
||||
************************************/
|
||||
|
||||
BOOLEAN alloc(fcbp, dirp, dirindx)
|
||||
/* Set up allocation vector for directory entry pointed to by dirp */
|
||||
|
||||
struct fcb *fcbp; /* not used in this function */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory for *dirp */
|
||||
{
|
||||
REG WORD i; /* loop counter */
|
||||
BSETUP
|
||||
|
||||
if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
|
||||
{
|
||||
(GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
|
||||
i = 0;
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
do setaloc( UBWORD(dirp->dskmap.small[i++]) );
|
||||
while (i <= 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
do setaloc(swap(dirp->dskmap.big[i++]));
|
||||
while (i <= 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* seldsk entry point *
|
||||
************************/
|
||||
|
||||
seldsk(dsknum)
|
||||
|
||||
REG UBYTE dsknum; /* disk number to select */
|
||||
|
||||
{
|
||||
struct iopb selpkt;
|
||||
REG WORD i;
|
||||
UWORD j;
|
||||
REG UBYTE logflag;
|
||||
BSETUP
|
||||
|
||||
logflag = ~(log_dsk >> dsknum) & 1;
|
||||
if ((GBL.curdsk != dsknum) || logflag)
|
||||
{ /* if not last used disk or not logged on */
|
||||
selpkt.iofcn = sel_info;
|
||||
GBL.curdsk = (selpkt.devnum = dsknum);
|
||||
if (UBWORD(dsknum) > 15) error(2);
|
||||
selpkt.ioflags = logflag ^ 1;
|
||||
do
|
||||
{
|
||||
do_phio(&selpkt); /* actually do the disk select */
|
||||
if ( (GBL.dphp = selpkt.infop) != NULL ) break;
|
||||
} while ( ! error(3) );
|
||||
|
||||
GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
/* set up GBL copies of dir_buf and dpb ptrs */
|
||||
GBL.parmp = (GBL.dphp)->dpbp;
|
||||
}
|
||||
if (logflag)
|
||||
{ /* if disk not previously logged on, do it now */
|
||||
LOCK /* must lock the file system while messing with alloc vec */
|
||||
i = (GBL.parmp)->dsm;
|
||||
do clraloc(i); while (i--); /* clear the allocation vector */
|
||||
i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
|
||||
4 * (((GBL.parmp)->blm) + 1), &j);
|
||||
/* calculate nmbr of directory blks */
|
||||
if (j) i++; /* round up */
|
||||
do setaloc(--i); while (i); /* alloc directory blocks */
|
||||
dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
|
||||
log_dsk |= 1 << dsknum; /* mark disk as logged in */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* General purpose byte mover *
|
||||
*******************************/
|
||||
|
||||
move(p1, p2, i)
|
||||
|
||||
REG BYTE *p1;
|
||||
REG BYTE *p2;
|
||||
REG WORD i;
|
||||
{
|
||||
while (i--)
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* General purpose filename matcher *
|
||||
*************************************/
|
||||
|
||||
BOOLEAN match(p1, p2, chk_ext)
|
||||
|
||||
REG UBYTE *p1;
|
||||
REG UBYTE *p2;
|
||||
BOOLEAN chk_ext;
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
i = 12;
|
||||
do
|
||||
{
|
||||
temp = (*p1 ^ '?');
|
||||
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
return(FALSE);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
if (chk_ext)
|
||||
{
|
||||
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
return(FALSE);
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* openfile entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN openfile(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx;
|
||||
|
||||
{
|
||||
REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
{
|
||||
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
move(dirp, fcbp, sizeof *dirp);
|
||||
/* copy dir entry into user's fcb */
|
||||
fcbp->extent = fcb_ext;
|
||||
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* flush buffers routine */
|
||||
/*************************/
|
||||
|
||||
UWORD flushit()
|
||||
{
|
||||
REG UWORD rtn; /* return code from flush buffers call */
|
||||
struct iopb flushpkt; /* I/O packet for flush buffers call */
|
||||
|
||||
flushpkt.iofcn = flush;
|
||||
while ( rtn = do_phio(&flushpkt) )
|
||||
if ( error(1) ) break;
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* file close routine for dirscan *
|
||||
*********************************/
|
||||
|
||||
BOOLEAN close(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE *fp;
|
||||
REG UBYTE *dp;
|
||||
REG UWORD fcb_ext;
|
||||
REG UWORD dir_ext;
|
||||
BSETUP
|
||||
|
||||
if ( match(fcbp, dirp, TRUE) )
|
||||
{ /* Note that FCB merging is done here as a final
|
||||
confirmation that disks haven't been swapped */
|
||||
LOCK
|
||||
fp = &(fcbp->dskmap.small[0]);
|
||||
dp = &(dirp->dskmap.small[0]);
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{ /* Small disk map merge routine */
|
||||
i = 16;
|
||||
do
|
||||
{
|
||||
if (*dp)
|
||||
{
|
||||
if (*fp)
|
||||
{
|
||||
if (*dp != *fp) goto badmerge;
|
||||
}
|
||||
else *fp = *dp;
|
||||
}
|
||||
else *dp = *fp;
|
||||
fp += 1;
|
||||
dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
else
|
||||
{ /* Large disk map merge routine */
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (*(UWORD *)dp)
|
||||
{
|
||||
if (*(UWORD *)fp)
|
||||
{
|
||||
if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
|
||||
}
|
||||
else *(UWORD *)fp = *(UWORD *)dp;
|
||||
}
|
||||
else *(UWORD *)dp = *(UWORD *)fp;
|
||||
(UWORD *)fp += 1;
|
||||
(UWORD *)dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
/* Disk map merging complete */
|
||||
fcb_ext = calcext(fcbp); /* calc max extent for fcb */
|
||||
dir_ext = (UWORD)(dirp->extent) & 0x1f;
|
||||
if ( (fcb_ext > dir_ext) ||
|
||||
((fcb_ext == dir_ext) &&
|
||||
(UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
|
||||
/* if fcb points to larger file than dirp */
|
||||
{
|
||||
dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
|
||||
dirp->extent = (BYTE)fcb_ext;
|
||||
}
|
||||
dirp->s1 = fcbp->s1;
|
||||
if ( (dirp->ftype[robit]) & 0x80) ro_err(fcbp,dirindx);
|
||||
/* read-only file error */
|
||||
dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
|
||||
dir_wr(dirindx >> 2);
|
||||
UNLOCK
|
||||
return(TRUE);
|
||||
|
||||
badmerge:
|
||||
UNLOCK
|
||||
ro_dsk |= (1 << GBL.curdsk);
|
||||
return(FALSE);
|
||||
}
|
||||
else return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* close_fi entry point *
|
||||
************************/
|
||||
|
||||
UWORD close_fi(fcbp)
|
||||
|
||||
struct fcb *fcbp; /* pointer to fcb for file to close */
|
||||
{
|
||||
flushit(); /* first, flush the buffers */
|
||||
if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
|
||||
don't need to do physical close */
|
||||
return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* search entry point *
|
||||
************************/
|
||||
|
||||
/* First two functions for dirscan */
|
||||
|
||||
BOOLEAN alltrue(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
BOOLEAN matchit(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(match(p1, p2, TRUE));
|
||||
}
|
||||
|
||||
|
||||
/* search entry point */
|
||||
UWORD search(fcbp, dsparm, p)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to search */
|
||||
REG UWORD dsparm; /* parameter to pass through to dirscan */
|
||||
UBYTE *p; /* pointer to pass through to tmp_sel */
|
||||
|
||||
{
|
||||
REG UWORD rtn; /* return value */
|
||||
BSETUP
|
||||
|
||||
if (fcbp->drvcode == '?')
|
||||
{
|
||||
seldsk(GBL.dfltdsk);
|
||||
rtn = dirscan(alltrue, fcbp, dsparm);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_sel(p); /* temporarily select disk */
|
||||
if (fcbp->extent != '?') fcbp->extent = 0;
|
||||
fcbp->s2 = 0;
|
||||
rtn = dirscan(matchit, fcbp, dsparm);
|
||||
}
|
||||
move( GBL.dirbufp, GBL.dmaadr, SECLEN);
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* create entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN create(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to create */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = ((dirp->entry) == 0xe5) )
|
||||
{
|
||||
p = &(fcbp->rcdcnt);
|
||||
i = 17;
|
||||
do
|
||||
{ /* clear fcb rcdcnt and disk map */
|
||||
*p++ = 0;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
|
||||
dir_wr(dirindx >> 2); /* write the directory sector */
|
||||
if ( dirindx > (GBL.dphp)->hiwater )
|
||||
(GBL.dphp)->hiwater = dirindx;
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* delete entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN delete(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
dirp->entry = 0xe5;
|
||||
LOCK
|
||||
dir_wr(dirindx >> 2);
|
||||
/* Now free up the space in the allocation vector */
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
i = 16;
|
||||
do clraloc(UBWORD(dirp->dskmap.small[--i]));
|
||||
while (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 8;
|
||||
do clraloc(swap(dirp->dskmap.big[--i]));
|
||||
while (i);
|
||||
}
|
||||
UNLOCK
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* rename entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN rename(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p; /* general purpose pointers */
|
||||
REG BYTE *q;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
p = &(fcbp->dskmap.small[1]);
|
||||
q = &(dirp->fname[0]);
|
||||
i = 11;
|
||||
do
|
||||
{
|
||||
*q++ = *p++ & 0x7f;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* set_attr entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN set_attr(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
move(&fcbp->fname[0], &dirp->fname[0], 11);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* utility routine used by *
|
||||
* setran and getsize *
|
||||
****************************/
|
||||
|
||||
LONG extsize(fcbp)
|
||||
/* Return size of extent pointed to by fcbp */
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
return( ((LONG)(fcbp->extent & 0x1f) << 7)
|
||||
| ((LONG)(fcbp->s2 & 0x3f) << 12) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* setran entry point *
|
||||
************************/
|
||||
|
||||
setran(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG random;
|
||||
|
||||
random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
|
||||
/* compute random record field */
|
||||
fcbp->ran0 = random.b2;
|
||||
fcbp->ran1 = random.b1;
|
||||
fcbp->ran2 = random.b0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* fsize is a funtion for dirscan */
|
||||
/* passed from getsize */
|
||||
/**********************************/
|
||||
|
||||
BOOLEAN fsize(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG temp;
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
|
||||
/* compute file size */
|
||||
fcbp->ran0 = temp.b2;
|
||||
fcbp->ran1 = temp.b1;
|
||||
fcbp->ran2 = temp.b0;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
/************************
|
||||
* getsize entry point *
|
||||
************************/
|
||||
|
||||
getsize(fcbp)
|
||||
/* get file size */
|
||||
REG struct fcb *fcbp; /* pointer to fcb to get file size for */
|
||||
|
||||
{
|
||||
LONG maxrcd;
|
||||
LONG temp;
|
||||
REG WORD dsparm;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
|
||||
maxrcd = 0;
|
||||
dsparm = 0;
|
||||
temp = 0;
|
||||
while ( dirscan(fsize, fcbp, dsparm) < 255 )
|
||||
{ /* loop until no more matches */
|
||||
temp.b2 = fcbp->ran0;
|
||||
temp.b1 = fcbp->ran1;
|
||||
temp.b0 = fcbp->ran2;
|
||||
if (temp > maxrcd) maxrcd = temp;
|
||||
dsparm = 1;
|
||||
}
|
||||
fcbp->ran0 = maxrcd.b2;
|
||||
fcbp->ran1 = maxrcd.b1;
|
||||
fcbp->ran2 = maxrcd.b0;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* free_sp entry point *
|
||||
************************/
|
||||
|
||||
free_sp(dsknum)
|
||||
|
||||
UBYTE dsknum; /* disk number to get free space of */
|
||||
{
|
||||
REG LONG records;
|
||||
REG UWORD *alvec;
|
||||
REG UWORD bitmask;
|
||||
REG UWORD alvword;
|
||||
REG WORD i;
|
||||
BSETUP
|
||||
|
||||
seldsk(dsknum); /* select the disk */
|
||||
records = (LONG)0; /* initialize the variables */
|
||||
alvec = (GBL.dphp)->alv;
|
||||
bitmask = 0;
|
||||
for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
|
||||
{
|
||||
if ( ! bitmask)
|
||||
{
|
||||
bitmask = 0x8000;
|
||||
alvword = ~(*alvec++);
|
||||
}
|
||||
if ( alvword & bitmask)
|
||||
records += (LONG)( ((GBL.parmp)->blm) + 1 );
|
||||
bitmask >>= 1;
|
||||
}
|
||||
*(LONG *)GBL.dmaadr = records; /* move # records to DMA address */
|
||||
}
|
Reference in New Issue
Block a user