Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
/********************************************************
* *
* CP/M-68K header file *
* Copyright (c) 1982 by Digital Research, Inc. *
* Structure definitions for BDOS globals *
* and BDOS data structures *
* *
********************************************************/
/**************************************************************************
The BDOS data structures, especially those relating to global variables,
are structured in a way that hopefully will enable this BDOS, in the future,
to easily become a re-entrant multi-tasking file system. Consequently,
the BDOS global variables are divided into two classes. Those that are
truly global, even in the case of multiple tasks using the file system
concurrently, are simply declared as global variables in bdosmain.c.
Only a few "globals" are really global in this sense.
The majority of the "global" variables are actually state variables that
relate to the state of the task using the file system. In CP/M-68K, these
are "global", since there's only one task, but in a multi-thread model they're
not. These type of variables are put into a data structure, with the
intention that in the multi-task environment this structure will be based.
The following declarations take this philosophy into account, and define
a simple structure for the single thread environment while leaving the
possibilities open for the multi-thread environment.
****************************************************************************/
#define snglthrd TRUE
/* TRUE for single-thread environment
FALSE to create based structure for re-entrant model */
#if snglthrd
#define GBL gbls
/* In single thread case, GBL just names
the structure */
#define BSETUP EXTERN struct stvars gbls;
/* and BSETUP defines the extern structure */
#endif
#if ! snglthrd
#define GBL (*statep)
/* If multi-task, state vars are based */
#define BSETUP REG struct stvars *statep; \
statep = &gbls;
/* set up pointer to state variables */
/* This is intended as an example to show the intent */
#endif
/* Note that there are a few critical regions in the file system that must
execute without interruption. They pertain mostly to the manipulation of
the allocation vector. This isn't a problem in a single-thread model, but
must be provided for in a multi-tasking file system. Consequently, the
primitives LOCK and UNLOCK are defined and used where necessary in the
file system. For the single thread model, they are null routines */
#define LOCK /**/
#define UNLOCK /**/
/* Be sure LOCK and UNLOCK are implemented to allow recursive calls to LOCK.
That is, if a process that calls LOCK already owns the lock, let it proceed,
but remember that only the outer-most call to UNLOCK really releases the
file system. */
#define VERSION 0x2022 /* Version number for CP/M-68K */
#define robit 0 /* read-only bit in file type field of fcb */
#define SECLEN 128 /* length of a CP/M sector */
/* File Control Block definition */
struct fcb
{
UBYTE drvcode; /* 0 = default drive, 1..16 are drives A..P */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
UBYTE cur_rec; /* current record field */
UBYTE ran0; /* random record field (3 bytes) */
UBYTE ran1;
UBYTE ran2;
};
/* Declaration of directory entry */
struct dirent
{
UBYTE entry; /* 0 - 15 for user numbers, E5 for empty */
/* the rest are reserved */
UBYTE fname[8]; /* File name (ASCII) */
UBYTE ftype[3]; /* File type (ASCII) */
UBYTE extent; /* Extent number (bits 0..4 used) */
UBYTE s1; /* Reserved */
UBYTE s2; /* Module field (bits 0..5), write flag (7) */
UBYTE rcdcnt; /* Nmbr rcrds in last block, 0..128 */
union
{
UBYTE small[16]; /* 16 block numbers of 1 byte */
WORD big[8]; /* or 8 block numbers of 1 word */
} dskmap;
};
/* Declaration of disk parameter tables */
struct dpb /* disk parameter table */
{
UWORD spt; /* sectors per track */
UBYTE bsh; /* block shift factor */
UBYTE blm; /* block mask */
UBYTE exm; /* extent mask */
UBYTE dpbdum; /* dummy byte for fill */
UWORD dsm; /* max disk size in blocks */
UWORD drm; /* max directory entries */
UWORD dir_al; /* initial allocation for dir */
UWORD cks; /* number dir sectors to checksum */
UWORD trk_off; /* track offset */
};
struct dph /* disk parameter header */
{
UBYTE *xlt; /* pointer to sector translate table */
UWORD hiwater; /* high water mark for this disk */
UWORD dum1; /* dummy (unused) */
UWORD dum2;
UBYTE *dbufp; /* pointer to 128 byte directory buffer */
struct dpb *dpbp; /* pointer to disk parameter block */
UBYTE *csv; /* pointer to check vector */
UBYTE *alv; /* pointer to allocation vector */
};
/* Declaration of structure containing "global" state variables */
struct stvars
{
struct dph *dphp; /* pointer to disk parm hdr for cur disk */
struct dirent *dirbufp; /* pointer for directory buff for process */
/* stored here so that each process can */
/* have a separate dirbuf. */
struct dpb *parmp; /* pointer to disk parameter block for cur */
/* disk. Stored here to save ref calc */
UBYTE *dmaadr; /* Disk dma address */
};

View File

@@ -0,0 +1,91 @@
*****************************************************************
* *
* CP/M-68K Interface Module for the Loader BDOS *
* For "C" version of CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* Version 0.1 -- September 22, 1982 *
* *
*****************************************************************
* Declare Public Routines
.globl _bios1 * 5 BIOS entry points from BDOS
.globl _bios2
.globl _bios3
.globl _bios4
.globl _bios5
.globl _swap * byte swapper
.globl _udiv * unsigned divide routine
* External Routine
.globl _bios
*
* BIOS Interface Routines
*
*
* Note - there are 5 BIOS entry points from the BDOS, labelled BIOS1 -
* BIOS5, depending on the parameters passed.
_bios5:
* For BIOS functions sectran and set exception vector
* Has function number and 2 parameters, a word followed by a long word
move.l 8(sp),d2 * get 2nd parameter (long word)
bra _bios2 * join common routine
_bios4:
* For BIOS function seldsk
* Has function number followed by 2 word parameters
move.w 8(sp),d2 * get 2nd parameter (word)
bra _bios2 * join common routine
_bios3:
* For BIOS function set dma
* Has function number followed by 1 long parameter
move.l 6(sp),d1 * get long word parameter
bra _bios1 * join common routine
_bios2:
* For all BIOS functions with a word parameter
* Word parameter follows function number
move.w 6(sp),d1 * get 1st parameter (word)
_bios1:
* For all BIOS functions that have no parameter other than function number
move.w 4(sp),d0 * get function number
movem.l d3-d7/a3-a6,-(sp)
jsr _bios * do BIOS call
movem.l (sp)+,d3-d7/a3-a6
* * returns value in d0
rts
*
* Utility Subroutines
*
_swap:
* Swap bytes of a word, return swapped value in d0
move.b 5(sp),d0
lsl #8,d0
move.b 4(sp),d0
rts
_udiv:
* Unsigned divide.
* Inputs: Long dividend, unsigned word divisor, address of return structure
* Return: In structure passed, unsigned word quotient, unsigned word remainder
move.l a0, -(sp) * save a0
move.l 14(sp), a0 * get address of return structure
move.l 8(sp), d0 * get dividend
divu 12(sp), d0 * do the divide
move.w d0, (a0)+ * store quotient
swap d0
move.w d0, (a0) * store remainder
move.l (sp)+, a0 * restore a0
rts
.end

View File

@@ -0,0 +1,93 @@
/****************************************************************
* *
* CP/M-68K Loader BDOS Main Routine *
* *
* This is the main routine for the Loader BDOS for *
* CP/M-68K. It has one entry point, _bdos. *
* the assembly language trap handler found in bdosif.s. *
* There are two parameters: a function number (integer) *
* and an information parameter, potentially a long word *
* The BDOS can potentially return a pointer, long word, *
* or word *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
/* Serial Number and Copyright Notice */
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
char *serial = "XXXX-0000-654321";
/* Declare EXTERN functions */
EXTERN WORD seldisk(); /* Select disk */
EXTERN BOOLEAN openfile(); /* Open File */
EXTERN UWORD dirscan(); /* General directory scanning routine */
EXTERN UWORD seqread(); /* Sequential disk read */
/* Declare the "state variables". These are globals for the single-thread
version of the file system, but are put in a structure so they can be
based, with a pointer coming from the calling process */
GLOBAL struct stvars gbls;
/****************************************************************
* *
* _bdos MAIN ROUTINE *
* *
* Called with _bdos(func, info, infop) *
* *
* Where: *
* func is the BDOS function number (d0.w) *
* info is the word parameter (d1.w) *
* infop is the pointer parameter (d1.l) *
* note that info is the word form of infop*
* *
****************************************************************/
UWORD _bdos(func,info,infop)
REG WORD func; /* BDOS function number */
REG UWORD info; /* d1.w word parameter */
REG UBYTE *infop; /* d1.l pointer parameter */
{
switch (func) /* switch on function number */
{
case 2: bconout((UBYTE)info); /* console output */
break;
case 14: return(seldisk(info)); /* select disk */
case 15: infop->drvcode = 0; /* open file */
infop->extent = 0;
infop->s2 = 0;
return(dirscan(openfile, infop));
case 20: infop->drvcode = 0; /* read sequential */
return(seqread(infop));
case 26: GBL.dmaadr = infop; /* set dma address */
break;
default: return(0xffff); /* bad function number */
/* break; */
}; /* end of switch statement */
return(0); /* return the BDOS return value */
} /* end _bdos */

View File

@@ -0,0 +1,208 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk Read/Write Module *
* *
* This module contains functions to perform sequential *
* or random access read or write to the disk for CP/M-68K *
* *
* It includes the following external functions: *
* *
* seqread() - sequential disk read *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
/* External function definitions */
EXTERN UWORD rdsec(); /* disk read routine */
EXTERN WORD swap(); /* assembly language byte swapper */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
/**********************************************************/
/* First, some utility functions used by seqio and ranio */
/**********************************************************/
/******************************
* FCB block number routines *
******************************/
WORD blkindx(fcbp)
/* return index into fcb disk map */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG WORD i;
REG WORD blkshf;
BSETUP
dparmp = GBL.parmp;
blkshf = dparmp->bsh;
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
}
UWORD blknum(fcbp, index, wrdfcb)
/* return block number in fcb indicated by index */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words? */
{
if (wrdfcb)
return( swap(fcbp->dskmap.big[index]) );
else return( UBWORD(fcbp->dskmap.small[index]) );
}
/*********************
* disk read routine *
*********************/
UWORD do_io(block, rcrd)
UWORD block; /* block number */
UBYTE rcrd; /* record number */
{
LONG lsec;
REG struct dpb *dparmp;
BSETUP
dparmp = GBL.parmp; /* init dpb pointer */
lsec = ((LONG)block << (dparmp->bsh)) +
(LONG)(rcrd & (dparmp->blm));
return( rdsec(lsec, GBL.dmaadr) );
}
/*******************************************
* routine for crossing extent boundaries *
*******************************************/
WORD new_ext(fcbp)
/* If sequential I/O, open the next extent */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG UBYTE mod; /* module number */
REG UBYTE ext; /* extent number */
BSETUP
mod = (fcbp->s2) & 0x3f;
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
if (ext >= 32)
{
ext = 0;
mod += 1;
}
if (mod >= 64) return(6); /* past maximum file size */
if ( mod == ((fcbp->s2) & 0x3f) )
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
{ /* we're in same logical extent */
fcbp->extent = ext;
return(0);
}
/* Extent or Module numbers don't match */
/* Close the old extent and open a new one */
fcbp->s2 = mod;
fcbp->extent = ext;
if ( dirscan(openfile, fcbp) >= 255 ) /* open new extent */
return(4); /* reading unwritten extent */
return(0);
}
/************************************
* Routine to calculate the maximum *
* extent number of an FCB in a *
* extent-folded environment *
************************************/
UWORD calcext(fcbp)
REG struct fcb *fcbp;
{
REG UWORD i;
REG BYTE *p;
BSETUP
i = 15;
p = &(fcbp->dskmap.small[16]);
do
{
if (*--p) break;
i -= 1;
} while (i);
/* Now i contains the index of the last non-zero block in the FCB */
if ((GBL.parmp)->dsm > 255) i >>= 1;
i >>= 7 - ((GBL.parmp)->bsh);
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
}
/*********************************
* Routine to get the actual *
* record count of the currently *
* active logical extent of a FCB *
*********************************/
UWORD get_rc(fcbp)
REG struct fcb *fcbp;
{
REG UWORD ext;
ext = calcext(fcbp); /* find last active extent in fcb */
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
/* if this is the last active fcb, return fcb's rc */
else if (ext > fcbp->extent) return(128);
/* if the fcb has more extents past this one, then */
/* the current one is logically full */
else return (0);
/* if we seeked past the last active extent, rc = 0 */
}
/************************
* seqread entry point *
************************/
UWORD seqread(fcbp)
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
{
REG UWORD block; /* block number from fcb */
REG WORD index; /* index into disk map of fcb */
REG WORD parm; /* parameter to do-io */
REG WORD bigfile; /* file system is in word mode */
BSETUP
bigfile = ((GBL.parmp)->dsm) & ~0xff;
if (fcbp->cur_rec == 128)
{ /* time to try next extent */
if ( new_ext(fcbp) )
return(1); /* if can't open new extent, error */
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
}
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
return(1); /* this is end of file */
index = blkindx(fcbp); /* get index into fcb disk map */
block = blknum(fcbp, index, bigfile);
if ( ! block) /* no data allocated at that position */
return(1); /* reading unwritten data */
return( do_io(block, (fcbp->cur_rec)++) );
}

View File

@@ -0,0 +1,45 @@
/********************************************************
* *
* BIOS definitions for CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* This include file simply defines the BIOS calls *
* *
********************************************************/
EXTERN UBYTE bios1(); /* used for character I/O functions */
EXTERN bios2(); /* parm1 is word, no return value */
EXTERN bios3(); /* used for set dma only */
/* parm1 is a pointer, no return */
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
/* words, returns a pointer to dph */
EXTERN UWORD bios5(); /* for sectran and set exception */
#define bwboot() bios1(1) /* warm boot */
#define bconstat() bios1(2) /* console status */
#define bconin() bios1(3) /* console input */
#define bconout(parm) bios2(4,parm) /* console output parm */
#define blstout(parm) bios2(5,parm) /* list device output */
#define bpun(parm) bios2(6,parm) /* punch char output */
#define brdr() bios1(7) /* reader input */
#define bhome() bios1(8) /* recalibrate drive */
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
/* select disk and return info */
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
#define bsetdma(parm) bios3(12,parm) /* set dma address */
#define bread() bios1(13) /* read sector from disk */
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
#define blistst() bios1(15) /* list device status */
#define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
/* sector translate */
#define bgetseg() bios1(18) /* get memory segment tbl */
#define bgetiob() bios1(19) /* get I/O byte */
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
#define bflush() bios1(21) /* flush buffers */
#define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
/* set exception vector */

View File

@@ -0,0 +1,59 @@
***************************************
* Information to go on the 256 byte *
* boot sector of an ExorMacs *
***************************************
.text
.dc.l $4000 * starting stack pointer
.dc.l start * starting program counter
.dc.w 1 * garbage
.dc.w 1 * length of SAT
.dc.l 2 * secondary directory start
.dc.l 0 * primary directory PSN list start
.dc.l 0 * start of boot loader
.dc.w 26 * length of boot loader
.dc.l $0 * boot execution address
.dc.l $0 * boot load address
.dc.b '9/30' * generation date
.dc.b 'CP/M-68K of 9/30/82 ' * volume descriptor
.dc.b '0020' * version/revision
.dc.w $0a484 * checksum (god help us)
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $0f1e2d3c * diagnostic test pattern
.dc.l $4b5a6978
.dc.l $8796a5b4
.dc.l $c3d2e1f0
.dc.l $4f8f0f07 * diagnostic test pattern
.dc.l $0b0d0e06
.dc.l $0a0c0408
.dc.l $04020100
.dc.l 00, 00, 00, 00 * diagnostic test pattern
.dc.l 0 * diagnostic test area directory
.dc.l 0 * start of dump area
.dc.w 0 * length of dump area
.dc.l 0 * start of sector lockout table
.dc.w 0 * length of sector lockout table
.dc.l 0,0,0,0,0,0,0 * unused, reserved
.dc.l 0,0,0,0,0,0
.dc.l 0,0,0,0,0,0,0
.dc.l 0,0,0,0,0,0
.dc.b 'EXORMACS' * let's hear it for Motorola
*
* end of volume id
*
* begin boot info proper
*
.ds.b $300 * skip over exception vectors
.even
start: move #$2700,sr
move.l #$8,a0
move.w #253,d0
exlp: move.l #expdef,(a0)+
dbf d0,exlp
jmp grunt
expdef: rte
grunt: move #$2000,sr
.end

View File

@@ -0,0 +1,174 @@
/****************************************************************
* *
* CP/M-68K Loader *
* *
* This is the main routine for the CP/M-68K Loader. *
* It has one entry point, ldcpm, which is called from *
* the assembly language routine called startld found in *
* ldrif.s. startld just sets up the stack. *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#define ALCYON TRUE /* TRUE if compiling with the ALCYON 68K C compiler */
#define SECLEN 128 /* CP/M sector length */
/* Declare EXTERN functions */
EXTERN WORD _bdos(); /* Loader BDOS entry point */
EXTERN startld(); /* Assembly routine to set up stack & retry */
EXTERN BYTE *bios1(); /* bios entry point for get segment table */
EXTERN move(); /* general purpose byte mover */
#define conout(ch) _bdos(2,ch)
#define seldsk(dsk) _bdos(14,dsk)
#define open(fcbp) _bdos(15,0,fcbp)
#define read(fcbp) _bdos(20,0,fcbp)
#define setdma(p) _bdos(26,0,p)
/* Define the data structures used in ldcpm */
struct fcb
{
UBYTE drvcode; /* drive code, must be 0 for loader BDOS */
/* (auto disk select not supported) */
UBYTE fname[11]; /* includes file name and type fields */
UBYTE sys_info[4]; /* ex, s1, s2, rc. These are don't cares */
UBYTE dskmap[16]; /* disk map, also a don't care */
UBYTE cur_rec; /* current record field */
};
struct hdr
{
WORD magic; /* magic number. We only recognize 0x601a */
LONG size[5]; /* sizes of code, data, bss, sym tbl, stack */
BYTE *tstart; /* start address of text segment */
WORD rlbflg; /* relocation bits suppressed flag */
};
struct segtbl
{ /* memory segment table from LDRBIOS */
WORD entrys; /* number of segments, must be 1 */
BYTE *start; /* low memory address */
LONG length; /* length of segment */
};
/**********************/
/* Global Variables */
/**********************/
BYTE buffer[SECLEN]; /* 128 byte dma buffer to read program headers */
/* We need 2 FCB's: one to read CPM.SYS and one to read BIOS.SYS */
/* Unfortunately, due to a bug in the Alcyon compiler, we can't initialize */
/* them in a straightforward way. So: */
#if ALCYON
struct fcb cpmfcb =
{ 0x0043, 0x504d, 0x2020, 0x2020, 0x2053, 0x5953, /* drive, name, and type */
0,0,0,0,0,0,0,0,0,0,0 /* the rest of the fcb */
};
#else
struct fcb cpmfcb =
{ (BYTE)0 /* drive code */
'CPM SYS', /* file name */
0,0,0,0,0,0,0,0,0,0 /* the rest of the fcb */
0,0,0,0,0,0,0,0,0,0,0
};
#endif
/**************************/
/* Utility Routines */
/**************************/
pstring(p)
/* print string */
REG BYTE *p;
{
while (*p) conout(*p++);
}
badload(errtype)
/* Load failed. Print message and try again */
REG WORD errtype;
{
REG WORD i;
switch (errtype)
{
case 0: pstring("\r\nBoot error.");
startld();
case 1: pstring("\n\rOpen or Read error on ");
break;
case 2: pstring("\n\rBad file format on ");
}
pstring("CPM.SYS");
startld();
}
/********************
* load subroutine *
********************/
BYTE *load(fcbp)
/* load the file pointed to by fcbp and return pointer to load point */
REG struct fcb *fcbp;
{
REG BYTE *p;
REG struct hdr *hp;
REG LONG length;
setdma( buffer );
if ( open(fcbp) >= 255 ) badload(1);
fcbp->cur_rec = 0;
if ( read(fcbp) ) badload(1);
hp = buffer;
if ( (hp->magic != 0x601a) || ! (hp->rlbflg) )
badload(2);
p = hp->tstart;
length = hp->size[0] + hp->size[1];
move(&buffer[sizeof *hp], p, SECLEN - (sizeof *hp));
/* move the first record minus header to load point */
p += SECLEN - (sizeof *hp);
length -= SECLEN - (sizeof *hp);
while (length > 0L)
{
setdma(p);
if ( read(fcbp) ) badload(1);
p += SECLEN;
length -= SECLEN;
}
return(hp->tstart);
}
/***************************
* ldcpm main routine *
***************************/
ldcpm()
{
WORD (*gocpm)();
if (seldsk(0)) badload(0);
gocpm = load(&cpmfcb); /* load the CP/M system */
pstring("\r\n\nCP/M-68K(tm) Version 1.2 Alpha 8/21/83 ");
pstring("\n\rCopyright (c) 1982 Digital Research, Inc.\r\n\n");
(*gocpm)(); /* jump to the CCP */
}

View File

@@ -0,0 +1,16 @@
e:vax BDOSDEF.H r
e:vax BDOSIF.S r
e:vax BDOSMAIN.C r
e:vax BDOSREAD.C r
e:vax BIOSDEF.H r
e:vax BOOTER.S r
e:vax CPMLDR.C r
e:vax DSKUTIL.C r
e:vax FILEIO.C r
e:vax IOSYS.C r
e:vax LDRBIOS.S r
e:vax LDRIF.S r
e:vax MAKE.SUB r
e:vax PKTIO.H r
e:vax PUTBOOT.S r
e:vax STDIO.H r

View File

@@ -0,0 +1,109 @@
/****************************************************************
* *
* CP/M-68K Loader BDOS Disk Utilities Module *
* *
* This module contains the miscellaneous utilities *
* for manipulating the disk in CP/M-68K. Included are: *
* *
* dirscan() - general purpose dir scanning *
* dir_rd() - read directory sector *
* rdsec() - read/write disk sector *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "pktio.h" /* Packet I/O definitions */
/* declare external functions and variables */
EXTERN UWORD do_phio(); /* external physical disk I/O routine */
/**********************
* read/write routine *
**********************/
UWORD rdsec(secnum, dma)
/* General disk sector read routine */
/* It simply sets up a I/O packet and sends it to do_phio */
LONG secnum; /* logical sector number to read/write */
UBYTE *dma; /* dma address */
{
struct iopb rwpkt;
BSETUP
rwpkt.iofcn = (BYTE)read;
rwpkt.ioflags = (BYTE)0;
rwpkt.devadr = secnum; /* sector number */
rwpkt.xferadr = dma; /* dma address */
/* parameters that are currently not used by do_phio
rwpkt.devnum = GBL.curdsk;
rwpkt.devtype = disk;
rwpkt.xferlen = 1;
*/
rwpkt.infop = GBL.dphp; /* pass ptr to dph */
return(do_phio(&rwpkt));
}
/***************************
* directory read routine *
***************************/
UWORD dir_rd(secnum)
WORD secnum;
{
BSETUP
return( rdsec((LONG)secnum, GBL.dirbufp) );
}
/************************
* dirscan entry point *
************************/
UWORD dirscan(funcp, fcbp)
BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
{
REG UWORD i; /* loop counter */
REG struct dpb *dparmp; /* pointer to disk parm block */
REG UWORD dirsec; /* sector number we're working on */
BSETUP
dparmp = GBL.parmp; /* init ptr to dpb */
for ( i = 0 ; i <= dparmp->drm ; i++ )
{ /* main directory scanning loop */
if ( ! (i & 3) )
{ /* inside loop happens when we need to
read another directory sector */
dirsec = i >> 2;
if (dir_rd(dirsec)) /* read the directory sector */
return(0xffff);
}
if ( (*funcp)(fcbp, (GBL.dirbufp) + (i&3), i) )
/* call function with parms of (1) fcb ptr,
(2) pointer to directory entry, and
(3) directory index */
return(i & 3); /* return directory code */
}
return(255);
}

View File

@@ -0,0 +1,129 @@
/****************************************************************
* *
* 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: *
* *
* seldisk() - select disk *
* openfile() - open file *
* move() - general purpose byte mover *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.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 do_phio(); /* packet disk i/o handler */
EXTERN UWORD swap(); /* assembly language byte swapper */
/************************
* seldisk entry point *
************************/
WORD seldisk(dsknum)
REG UBYTE dsknum; /* disk number to select */
{
struct iopb selpkt;
REG UWORD *p; /* scratch pointer */
REG WORD i;
BSETUP
if (UBWORD(dsknum) > 15) return(0xffff);
selpkt.iofcn = sel_info;
selpkt.devnum = dsknum;
selpkt.ioflags = 0;
do_phio(&selpkt); /* actually do the disk select */
if ((GBL.dphp = selpkt.infop) == NULL)
return(0xffff);
GBL.dirbufp = (GBL.dphp)->dbufp;
/* set up GBL copies of dir_buf and dpb ptrs */
GBL.parmp = (GBL.dphp)->dpbp;
return(0);
}
/*******************************
* 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;
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;
}
return(rtn);
}

View File

@@ -0,0 +1,67 @@
/****************************************************************
* *
* CP/M-68K BDOS Disk I/O System Module *
* *
* This module translates from the packet oriented I/O *
* passed from the other BDOS modules into BIOS calls. *
* *
* It includes only one external entry point:
* do_phio() - do physical i/o *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "pktio.h" /* Packet I/O definitions */
#include "biosdef.h" /* Declarations for BIOS entry points */
EXTERN udiv(); /* Assembly language unsigned divide routine */
/* in bdosif.s. It's used because Alcyon C */
/* can't do / or % without an external */
/************************
* do_phio entry point *
************************/
UWORD do_phio(iop)
REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
{
REG struct dph *hdrp; /* pointer to disk parameter header */
REG struct dpb *dparmp; /* pointer to disk parameter block */
struct
{ /* structure for results of external divide */
UWORD iotrk;
UWORD iosect;
} iopdiv;
LOCK /* lock the disk system while doing physical i/o */
switch (iop->iofcn)
{
case sel_info:
iop->infop = bseldsk(iop->devnum, iop->ioflags);
break;
case read:
hdrp = iop->infop;
dparmp = hdrp->dpbp;
udiv( iop->devadr, dparmp->spt, &iopdiv );
bsettrk( iopdiv.iotrk + dparmp->trk_off );
bsetsec( bsectrn( iopdiv.iosect, hdrp->xlt ) );
bsetdma(iop->xferadr);
return(bread());
}
UNLOCK
return(0);
}

View File

@@ -0,0 +1,288 @@
*****************************************************************
* *
* CP/M-68K Loader BIOS *
* Basic Input/Output Subsystem *
* For ERG 68000 with Tarbell floppy disk controller *
* *
*****************************************************************
.globl _bios * declare external entry point
_bios:
cmpi #nfuncs,d0
bge nogood
lsl #2,d0 * multiply bios function by 4
movea.l 6(pc,d0),a0 * get handler address
jsr (a0) * call handler
nogood:
rts
biosbase:
.dc.l nogood
.dc.l nogood
.dc.l constat
.dc.l conin
.dc.l conout
.dc.l nogood
.dc.l nogood
.dc.l nogood
.dc.l home
.dc.l seldsk
.dc.l settrk
.dc.l setsec
.dc.l setdma
.dc.l read
.dc.l nogood
.dc.l nogood
.dc.l sectran
.dc.l setdma
.dc.l getseg
.dc.l nogood
.dc.l nogood
.dc.l nogood
.dc.l setexc
nfuncs=(*-biosbase)/4
constat: move.b $ffff01,d0 * get status byte
andi.w #2,d0 * data available bit on?
beq noton * branch if not
moveq.l #$1,d0 * set result to true
rts
noton: clr.l d0 * set result to false
rts
conin: bsr constat * see if key pressed
tst d0
beq conin * wait until key pressed
move.b $ffff00,d0 * get key
and.l #$7f,d0 * clear all but low 7 bits
rts
conout: move.b $ffff01,d0 * get status
and.b #$1,d0 * check for transmitter buffer empty
beq conout * wait until our port has aged...
move.b d1,$ffff00 * and output it
rts * and exit
*
* Disk Handlers for Tarbell 1793 floppy disk controller
*
maxdsk = 2 * this BIOS supports 2 floppy drives
dphlen = 26 * length of disk parameter header
iobase = $00fffff8 * Tarbell floppy disk port base address
dcmd = iobase * output port for command
dstat = iobase * input status port
dtrk = iobase+1 * disk track port
dsect = iobase+2 * disk sector port
ddata = iobase+3 * disk data port
dwait = iobase+4 * input port to wait for op finished
dcntrl = iobase+4 * output control port for drive selection
home: clr.b track
rts
seldsk:
* select disk A
clr.b seldrv * select drive A
clr.b selcode * select code is 00 for drv 0, $10 for drv 1
move.l #dph0,d0
selrtn: rts
settrk: move.b d1,track
rts
setsec: move.b d1,sector
rts
sectran:
* translate sector in d1 with translate table pointed to by d2
* result in d0
movea.l d2,a0
ext.l d1
move.b #0(a0,d1),d0
ext.l d0
rts
setdma:
move.l d1,dma
rts
read:
* Read one sector from requested disk, track, sector to dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
rretry:
bsr setup
ori #$88,d3 * OR read command with head load bit
move.b d3,dcmd * output it to FDC
rloop: btst #7,dwait
beq rdone * if end of read, exit
move.b ddata,(a0)+ * else, move next byte of data
bra rloop
rdone:
bsr rstatus * get FDC status
bne rerror
clr.l d0
rts
rerror: bsr errchk * go to error handler
subq.b #1,errcnt
bne rretry
move.l #$ffffffff,d0
rts
setup:
* common read and write setup code
* select disk, set track, set sector were all deferred until now
move.b #$d0,dcmd * clear controller, get status
move.b curdrv,d3
cmp.b seldrv,d3
bne newdrive * if drive not selected, do it
move.b track,d3
cmp.b oldtrk,d3
bne newtrk * if not on right track, do it
clr.l d3 * if head already loaded, no head load delay
btst #5,dstat * if head unloaded, treat as new disk
bne sexit
newdrive:
move.b selcode,dcntrl * select the drive
move.b seldrv,curdrv
newtrk:
bsr chkseek * seek to correct track if required
moveq #4,d3 * force head load delay
sexit:
move.b sector,dsect * set up sector number
move.b track,dtrk * set up track number
move.l dma,a0 * dma address to a0
rts
errchk:
btst.b #4,d7
bne chkseek * if record not found error, reseek
rts
chkseek:
* check for correct track, seek if necessary
bsr readid * find out what track we're on
beq chks1 * if read id ok, skip restore code
restore:
* home the drive and reseek to correct track
move.b #$0B,dcmd * restore command to command port
rstwait:
btst #7,dwait
bne rstwait * loop until restore completed
btst #2,dstat
beq restore * if not at track 0, try again
clr.l d3 * track number returned in d3 from readid
chks1:
move.b d3,dtrk * update track register in FDC
move.b track,oldtrk * update oldtrk
cmp.b track,d3 * are we at right track?
beq chkdone * if yes, exit
move.b track,ddata * else, put desired track in data reg of FDC
move.b #$18,dcmd * and issue a seek command
chks2: btst #7,dwait
bne chks2 * loop until seek complete
move.b dstat,d3 * read status to clear FDC
chkdone:
rts
readid:
* read track id, return track number in d3
move.b #$c4,dcmd * issue read id command
move.b dwait,d7 * wait for intrq
move.b ddata,d3 * track byte to d3
rid2:
btst #7,dwait
beq rstatus * wait for intrq
move.b ddata,d7 * read another byte
bra rid2 * and loop
rstatus:
move.b dstat,d7
andi.b #$9d,d7 * set condition codes
rts
getseg:
move.l #memrgn,d0 * return address of mem region table
rts
setexc:
andi.l #$ff,d1 * do only for exceptions 0 - 255
lsl #2,d1 * multiply exception number by 4
movea.l d1,a0
move.l (a0),d0 * return old vector value
move.l d2,(a0) * insert new vector
rts
.data
seldrv: .dc.b $ff * drive requested by seldsk
curdrv: .dc.b $ff * currently selected drive
track: .dc.b 0 * track requested by settrk
oldtrk: .dc.b 0 * track we were on
sector: .dc.w 0
dma: .dc.l 0
selcode: .dc.b 0 * drive select code
errcnt: .dc.b 10 * retry counter
memrgn: .dc.w 1 * 1 memory region
.dc.l $18000 * load the system at 18000 hex
.dc.l $8000
* disk parameter headers
dph0: .dc.l xlt
.dc.w 0 * dummy
.dc.w 0
.dc.w 0
.dc.l dirbuf * ptr to directory buffer
.dc.l dpb * ptr to disk parameter block
.dc.l 0 * ptr to check vector
.dc.l 0 * ptr to allocation vector
* disk parameter block
dpb: .dc.w 26 * sectors per track
.dc.b 3 * block shift
.dc.b 7 * block mask
.dc.b 0 * extent mask
.dc.b 0 * dummy fill
.dc.w 242 * disk size
.dc.w 63 * 64 directory entries
.dc.w $c000 * directory mask
.dc.w 16 * directory check size
.dc.w 2 * track offset
* sector translate table
xlt: .dc.b 1, 7,13,19
.dc.b 25, 5,11,17
.dc.b 23, 3, 9,15
.dc.b 21, 2, 8,14
.dc.b 20,26, 6,12
.dc.b 18,24, 4,10
.dc.b 16,22
.bss
dirbuf: .ds.b 128 * directory buffer
.end

View File

@@ -0,0 +1,46 @@
*****************************************
* Assembly Language Interface Routine *
* for the CP/M-68K loader, cpmldr *
* *
* It has one entry point: _startld *
* It sets up the stack and jumps to *
* _ldcpm *
*****************************************
.globl _startld * public entry point
.globl ldr * label for library search
.globl _bios * external references
.globl _ldcpm
.globl _bios1 * library search
.globl _dirscan * " "
.globl _seqread * " "
.text
ldr:
_startld:
lea stack,sp
clr.l d0
jsr _bios * init the BIOS
move #22,d0
move #8,d1
move.l #privexc,d2
jsr _bios * set exception for privilege violation
ori #$2000,sr * set supervisor state
* if in user mode, will generate priv violation
lea stack,sp
bra _ldcpm
privexc:
ori.w #$2000,(sp)
rte
.bss
.ds.l 256
stack: .ds.w 1
.end

View File

@@ -0,0 +1,62 @@
$2cp68 bdosmain.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 bdosmain.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 bdosmain.s
era bdosmain.s
$2cp68 bdosread.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 bdosread.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 bdosread.s
era bdosread.s
$2cp68 cpmldr.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 cpmldr.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 cpmldr.s
era cpmldr.s
$2cp68 dskutil.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 dskutil.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 dskutil.s
era dskutil.s
$2cp68 fileio.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 fileio.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 fileio.s
era fileio.s
$2cp68 iosys.c $1x.i
$2c068 $1x.i $1x.1 $1x.2 $1x.3
era $1x.i
$2c168 $1x.1 $1x.2 iosys.s
era $1x.1
era $1x.2
$2as68 -l -u -s 0$1 -f $1 iosys.s
era iosys.s
$2as68 -f $1 -s 0$1 -l -u bdosif.s
$2as68 -f $1 -s 0$1 -l -u booter.s
$2as68 -f $1 -s 0$1 -l -u ldrif.s
$2ar68 rvf $1 ldrlib ldrif.o cpmldr.o bdosif.o dskutil.o fileio.o bdosread.o
$2ar68 rvf $1 ldrlib bdosmain.o iosys.o
era *.o

View File

@@ -0,0 +1,57 @@
/********************************************************
* *
* CP/M-68K header file *
* Copyright (c) 1982 by Digital Research, Inc. *
* Structure definitions for doing I/O in packets *
* *
********************************************************/
/* May use this information structure instead of disk parameter header and
disk parameter block in future, but for now it's unused
struct dskinfo
{
UBYTE *dbuffp;
UBYTE *csv;
UBYTE *alv;
UBYTE blksize;
UBYTE didummy;
UWORD dskmax;
UWORD dirmax;
UWORD chksize;
};
*/
struct iopb
{
UBYTE iofcn; /* function number, see defines below */
UBYTE ioflags; /* used for login flag and write flag */
UBYTE devtype; /* device type, see defines below */
/* currently unused */
UBYTE devnum; /* device number, or, devtype and devnum
taken together form int device number */
LONG devadr; /* item nmbr on device to start xfer at */
/* note -- item is sector for disks, byte for char devs */
UWORD xferlen; /* number items to transfer */
UBYTE *xferadr; /* memory address to xfer to/from */
struct dph *infop; /* pointer to disk parameter header */
/* return parm for fcn 0, input for rest */
};
/* Definitions for iofcn, the function number */
#define sel_info 0 /* select and return info on device */
#define read 1
#define write 2
#define flush 3
#define status 4 /* not currently used */
/* Definitions for devtype, the device type */
/* This field not currently used */
#define console 0
#define printer 1
#define disk 2
#define memory 3 /* gets TPA boundaries */
#define redir 4 /* read/write IOByte */
#define exc_vec 5 /* set exception vector */

View File

@@ -0,0 +1,194 @@
*********************************************************
* *
* Program to Write Boot Tracks for CP/M-68K (tm) *
* *
* Copyright Digital Research 1982 *
* *
*********************************************************
*
*
*
prntstr = 9 BDOS Functions
dseldsk = 14
open = 15
readseq = 20
dsetdma = 26
*
seldsk = 9 BIOS Functions
settrk = 10
setsec = 11
isetdma = 12
write = 14
sectran = 16
flush = 21
*
bufcnt = $80
bufsize = $80*bufcnt
*
.text
*
start: link a6,#0
move.l 8(a6),a0 base page address
lea $5c(a0),a1
move.l a1,fcb
clr.b hflag
add #$81,a0 first character of command tail
scan: cmpi.b #$20,(a0)+ skip over blanks
beq scan
sub.l #1,a0
scan1: tst.b (a0)
beq erxit
cmpi.b #$2d,(a0)+ check for -H flag
bne nohyph
cmpi.b #$48,(a0)+
bne erxit
tst.b hflag
bne erxit
move.b #$ff,hflag
sub.l #$24,fcb change to 2nd default fcb
bra scan
nohyph: cmpi.b #$20,(a0)
bne scan1
scan2: cmpi.b #$20,(a0)+
beq scan2
cmpi.b #$61,-(a0) get disk letter
blt upper upshift
sub #$20,(a0)
upper: cmpi.b #$41,(a0) compare with range A - P
blt erxit
cmpi.b #$50,(a0)
bgt erxit
move.b (a0),d0
ext.w d0 put disk letter into range 0 - 15
sub.w #$41,d0
move.w d0,dsk
*
* open file to copy
*
move.w #open,d0
move.l fcb,d1
trap #2
cmpi.w #$00ff,d0
bne openok
move.l #opnfl,d1
jmp erx
openok: move.l fcb,a0
clr.b 32(a0)
*
* read
*
move.l #buf,d2
clr.w count
rloop: move.w #dsetdma,d0
move.l d2,d1
trap #2
move.w #readseq,d0
move.l fcb,d1
trap #2
tst.w d0
bne wrtout
add.l #128,d2
add.w #1,count
cmpi.w #bufcnt,count
bgt bufoflx
bra rloop
*
* write
*
wrtout: move.w #seldsk,d0 select the disk
move.w dsk,d1
clr.b d2
trap #3
tst.l d0 check for select error
beq selerx
move.l d0,a0
move.l 14(a0),a0 get DPB address
move.w (a0),spt get sectors per track
move.w 14(a0),off get offset
clr.w trk start at trk 0
move.w #1,sect start at sector 1
lea buf,a0
tst.b hflag
bne wrt1
cmpi.w #$601a,(a0)
bne wrt1
add.l #28,a0
wrt1: move.l a0,bufp
*
wloop: tst.w count
beq exit
move.w sect,d1 check for end-of-track
cmp.w spt,d1
ble sok
move.w #1,sect advance to new track
move.w trk,d0
add.w #1,d0
move.w d0,trk
cmp.w off,d0
bge oflex
sok: move.w #settrk,d0 set the track
move.w trk,d1
trap #3
move.w sect,d1 set sector
move.w #setsec,d0
trap #3
move.w #isetdma,d0 set up dma address for write
move.l bufp,d1
trap #3
move.w #write,d0 and write
clr.w d1
trap #3
tst.w d0 check for write error
bne wrterx
add #1,sect increment sector number
sub #1,count
add.l #128,bufp
bra wloop
*
exit: move.w #flush,d0 exit location - flush bios buffers
trap #3
unlk a6
rts and exit to CCP
*
erxit: move.l #erstr,d1 miscellaneous errors
erx: move.w #prntstr,d0 print error message and exit
trap #2
bra exit
*
selerx: move.l #selstr,d1 disk select error
bra erx
wrterx: move.l #wrtstr,d1 disk write error
bra erx
bufoflx: move.l #bufofl,d1 buffer overflow
bra erx
oflex: move.l #trkofl,d1
bra erx
*
*
.bss
*
.even
*
buf: .ds.b bufsize+128
*
fcb: .ds.l 1 fcb address
spt: .ds.w 1 sectors per track
sect: .ds.w 1 current sector
trk: .ds.w 1 current track
dsk: .ds.w 1 selected disk
off: .ds.w 1 1st track of non-boot area
count: .ds.w 1
bufp: .ds.l 1
hflag: .ds.b 1
*
.data
*
erstr: .dc.b 'Invalid Command Line',13,10,'$'
selstr: .dc.b 'Select Error',13,10,'$'
wrtstr: .dc.b 'Write Error',13,10,'$'
opnfl: .dc.b 'Cannot Open Source File',13,10,'$'
bufofl: .dc.b 'Buffer Overflow',13,10,'$'
trkofl: .dc.b 'Too Much Data for System Tracks',13,10,'$'
*
*
.end

View File

@@ -0,0 +1,68 @@
/*****************************************************************************
*
* C P / M C H E A D E R F I L E
* -----------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This is an include file for assisting the user to write portable
* programs for C.
*
*****************************************************************************/
#define ALCYON 1 /* using Alcyon compiler */
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define BOOLEAN char /* 2 valued (true/false) */
#define WORD short /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG unsigned long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
/***************************/
#ifdef ALCYON
#define UBYTE char
#define UBWORD(a) ((UWORD)a & 0xff)
/* Unsigned byte to word cast */
#else
#define UBYTE unsigned char /* Unsigned byte */
#define UBWORD(a) (UWORD)a
#endif
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL (BYTE *)0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
/****************************************************************************/
/* */
/* M A C R O S */
/* ----------- */
/* */
/* Define some stuff as macros .... */
/* */
/****************************************************************************/
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
/*************************** end of stdio.h *********************************/

View File

@@ -0,0 +1,16 @@
$ boot
$ !
$ ! VMS procedure for building ldrlib with cross tools
$ !
$ set noon
$ cc68 bdosmain
$ cc68 bdosread
$ cc68 cpmldr
$ cc68 dskutil
$ cc68 fileio
$ cc68 iosys
$ as68 -l -u bdosif.s
$ as68 -l -u ldrif.s
$ del ldrlib.;*
$ ar68 rv ldrlib ldrif.o cpmldr.o bdosif.o dskutil.o fileio.o bdosread.o
$ ar68 rv ldrlib bdosmain.o iosys.o

View File

@@ -0,0 +1,20 @@
$ set noon
$ vsend BDOSDEF.H
$ vsend BDOSIF.S
$ vsend BDOSMAIN.C
$ vsend BDOSREAD.C
$ vsend BIOSDEF.H
$ vsend BOOTER.S
$ vsend CPMLDR.C
$ vsend DSKUTIL.C
$ vsend FILEIO.C
$ vsend IOSYS.C
$ vsend LDRBIOS.S
$ vsend LDRIF.S
$ vsend LDRLIB.
$ vsend MAKE.SUB
$ vsend PKTIO.H
$ vsend PUTBOOT.S
$ vsend STDIO.H
$ vsend VMAKE.COM
$ vsend done