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,9 @@
A collection of C sources for CP/M-68K, apparently for versions 1.01, 1.02, 1.02a, and 1.03.
There are some BIOS/BDOS/CCP sources in here, but all seem to be revisions of version 1.1 of the OS.
The bulk of the code looks like revisions of Alcyon C (compiler, assembler, linker and libraries). As far as I can see, this compiler emits 68K assembler and should run under CP/M-68K, REGULUS, VMS on a VAX and Unix on a PDP-11.
Reading v101/doc/ and v102a/doc/ makes interesting trivia:
1. "The Pascal version of CP/M-68K..." (cpm0706.rno)
2. "Allows up to 8Gb of on-line disk(ette) storage" (pdd.rno)
3. "CP/M-68K Alpha Release III 2/15/84" (a3.rno)

View File

@@ -0,0 +1,14 @@
#define ARMAG "!<arch>\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
};

View File

@@ -0,0 +1,752 @@
/*
Copyright 1981
Alcyon Corporation
8474 Commerce Av.
San Diego, Ca. 92121
*/
#include "machine.h"
#include "iobuf.h"
#include "cout.h"
#define BLKSIZE 512
char buff[BLKSIZE]={0};
/* flags for cp1file*/
#define IEVEN 1
#define OEVEN 2
#define WHDR 4
#define DIR 0100000
#define CHR 040000
#define BLK 020000
#define ROWN 0400
#define WOWN 0200
#define XOWN 0100
#define RGRP 040
#define WGRP 020
#define XGRP 010
#define ROTH 04
#define WOTH 02
#define XOTH 01
#define LIBMAGIC 0177545
#define LNAMLEN 14
struct lib2hdr {
char l2fname[LNAMLEN];
long l2modti;
char l2userid;
char l2gid;
short l2fimode;
long l2fsize;
short l2junk;
} libhd={0};
struct {
int f_devnum;
int f_inum;
int f_fimode;
char f_nlinks;
char f_userid;
char f_gid;
char f_size0;
int f_size1;
int f_addr[8];
long f_acti;
long f_modti;
};
short libmagic LIBMAGIC;
int rflg=0, dflg=0, xflg=0, tflg=0, vflg=0;
int uflg=0;
int pflg=0;
int areof=0;
int arfd=0;
int tempfd=0;
int aflg=0, bflg=0;
int psflg=0;
int matchflg=0;
char *psname=0;
char *arname=0,tempname[80]={0,0,0};
/************************/
#ifdef UNIX /* */
char *dname="/tmp/"; /* UNIX */
#else /* CP/M and VMS */
char *dname=""; /* Disk Name */
#endif /************************/
#ifdef UNIX /* */
char *tname="arXXXXXX"; /* Unix temp file name */
#else /* CP/M and VMS */
char *tname="ar68.tmp"; /* Temp file name */
#endif /************************/
long lseek();
long fixlong();
long filesize();
int endit();
int (*docom)()=0;
int replace();
int delete();
int extract();
int tell();
#ifdef JUNK
long mklong();
#endif
int print();
#ifdef VAX
struct {
short loword;
short hiword;
};
#endif
#ifdef PDP11
struct {
short loword;
short hiword;
};
#endif
#ifdef MC68000
struct {
short hiword;
short loword;
};
#endif
main(argc,argv)
char **argv;
{
register char *p1, *p2;
register char **ap;
register int i;
register long l;
register long k;
long kk;
if(argc < 3) {
usage:
error("usage: ar68 drtwx[abiv][f d:] [opmod] archive obmod1 [obmod2] ... [>filespec]\n");
endit();
}
/* signal(1,endit); */
ap = &argv[1];
p1 = *ap++;
i = argc-3;
while(*p1) {
switch(*p1++) {
case 'r':
rflg++;
docom = replace;
break;
case 'a':
aflg++;
psname = *ap++;
i--;
break;
/* These options removed because they don't work!
case 'b':
case 'i':
bflg++;
i--;
psname = *ap++;
break;
*/
case 'd':
dflg++;
docom = delete;
break;
case 'x':
xflg++;
docom = extract;
break;
case 't':
tflg++;
docom = tell;
break;
case 'w':
pflg++;
docom = print;
break;
case 'v':
vflg++;
break;
case 'f': /* Drive for temp files */
dname = *ap++; /* Set proper disk name */
break;
default:
error("invalid option flag: %c\n",*--p1);
endit();
}
}
uflg = rflg+dflg;
if((uflg+xflg+tflg+pflg) != 1) {
error("one and only one of drtwx flags required\n");
endit();
}
psflg = aflg+bflg;
if(psflg > 1) {
error("only one of abi flags allowed\n");
endit();
}
strcat (tempname,dname); /* Form 1st part of string */
strcat (tempname,tname); /* Add in file name */
#ifdef UNIX /* For UNIX, make temp file*/
mktemp(tempname);
#endif
arname = *ap++;
arfd = openar(arname,rflg);
if(i==0 && tflg) {
listall();
endit();
}
if(i<=0)
goto usage;
if( xflg == 0 ) {
if((tempfd=creat(tempname,0644,1)) < 0) {
error("cannot create %s\n",tempname);
endit();
}
if(write(tempfd,&libmagic,sizeof libmagic) != sizeof libmagic)
{
error("temp file write error\n");
endit();
}
}
while(i) {
excom(*ap++);
i--;
}
excom(0L); /*end of arg list*/
if (xflg == 0)
{
k = lseek(tempfd,0L,1); /* Fetch file size */
#ifndef UNIX
l = lseek(tempfd,0L,0); /* Rewind temp file */
if (l < 0) /* Error? */
{
printf("seek error on %s\n",tempname);
exit(-1);
}
#else
close(tempfd);
if((tempfd=open(tempname,0,1)) < 0)
{
printf("Cannot re-open %s\n",tempname);
exit(-1);
}
#endif
close(arfd); /* Close input file */
unlink(arname); /* Delete the file */
arfd=creat(arname,0666,1); /* Create the file again*/
if(arfd < 0) /* Error? */
{
printf("Unable to re-create %s -- archive is in %s\n",
arname,tempname);
exit(-1);
}
i = 1; /* Klutz */
while (i > 0 && k > 0) /* Copy the file back */
{
i = (k > BLKSIZE) ? BLKSIZE : k;
i = read(tempfd,buff,i);
if(i < 0)
{
printf("Read error on %s\n",tempname);
exit(-1);
}
else if (i > 0)
{
if(write(arfd,buff,i) != i)
{
printf("Write error on %s\n",arname);
exit (-1);
}
}
k -= i;
}
kk = 0;
write(arfd,&kk,sizeof(k)); /* Put 0 on end of file */
close (tempfd);
unlink(tempname);
}
endit();
}
openar(arp,crfl)
char *arp;
{
register i;
int ib;
if((i=open(arp,2,1)) < 0) { /*does not exist*/
areof = 1;
if((i = creat(arp,0666,1)) < 0)
{
printf("Cannot Create %s\n",arname);
exit(-1);
}
else
return(i);
}
if(read(i,&ib,sizeof libmagic) != sizeof libmagic || ib != LIBMAGIC) {
notar:
error("not archive format: %s\n",arp);
endit();
}
return(i);
}
/* execute one command -- call with filename or 0*/
excom(ap)
char *ap;
{
register char *p;
if(p=ap)
{
if(p[1] == ':') /* CP/M Drive number */
p += 2; /* Bump to file name */
}
if((p) && (matchflg==0)) { /*look thru archive for file name*/
while(areof==0 && nextar()) { /*get next ar file header*/
if(streq(p,&libhd.l2fname[0]))
break;
if(psflg && streq(psname,&libhd.l2fname[0])) {
break;
}
skcopy(uflg); /*skip or copy*/
}
}
(*docom)(ap); /*exec requested command*/
}
tell(ap)
char *ap;
{
register char *p;
register i;
register char *p1;
if(ap==0)
endit();
if(vflg) { /*long list*/
pmode(libhd.l2fimode);
printf(" %d/%d %6ld ",libhd.l2userid,libhd.l2gid,
libhd.l2fsize);
/* p1 = ctime(&libhd.l2modti);
p1[24] = '\0';
p1 =+ 4;
printf(" %s ",p1); */
}
pfname();
skcopy(0);
}
pfname()
{
printf("%.14s\n",libhd.l2fname);
}
replace(ap)
char *ap;
{
register i;
int ifd;
register long l;
register char *p1;
if( ap == 0 ) {
if( bflg && areof == 0 ) {
l = -(sizeof libhd);
lseek(arfd,l,1);
}
cprest();
return;
}
if((ifd=open(ap,0,1)) < 0) {
error("cannot open %s\n",ap);
endit();
}
if(areof && psflg) {
error("%s not in library\n",psname);
endit();
}
if((bflg|aflg) && matchflg==0) { /*copy archive file before appending*/
if(aflg)
skcopy(1);
matchflg++;
}
p1 = (ap[1] == ':') ? ap + 2 : ap; /* Drive name */
copystr(p1,&libhd.l2fname[0],LNAMLEN);
if(areof|aflg) {
inform('a');
}
else if(bflg) {
inform('i');
}
else {
inform('r');
skcopy(0); /*skip old copy*/
}
p1 = buff;
libhd.l2modti = 0;
libhd.l2userid = 0;
libhd.l2gid = 0;
libhd.l2fimode = 0666;
libhd.l2fsize = filesize(&ifd,ap);
cp1file(ifd,tempfd,WHDR+OEVEN,ap,tempname);
close(ifd);
}
struct iobuf ssbuf={0};
long filesize(fdp,fname)
int *fdp;
char *fname;
{
struct hdr tcout;
register long size;
register short *p;
register int i;
close(*fdp);
if( fopen(fname,&ssbuf,1) < 0 )
error("cannot open %s\n",fname);
p = &tcout;
for( i = 0; i < (sizeof tcout)/2; i++ )
*p++ = getw(&ssbuf);
close(ssbuf.fildes);
if( tcout.ch_magic != MAGIC )
error("not object file: %s\n",fname);
size = tcout.ch_tsize + tcout.ch_dsize;
if( tcout.ch_rlbflg == 0 )
size =+ size;
size =+ tcout.ch_ssize;
if( (*fdp=open(fname,0,1)) < 0 )
error("cannot reopen %s\n",fname);
size =+ sizeof tcout;
#ifndef UNIX
size = ((size+3)/4)*4; /*turkey round-up to long for VAX*/
#endif
return(size);
}
struct { char byt1; char byt2; char byt3; char byt4; };
long fixlong(l)
long l;
{
long tl;
tl.byt1 = l.byt4;
tl.byt2 = l.byt3;
tl.byt3 = l.byt2;
tl.byt4 = l.byt1;
return(tl);
}
fixshort(i)
int i;
{
int ti;
ti.byt1 = i.byt2;
ti.byt2 = i.byt1;
}
delete(ap)
char *ap;
{
if(ap==0) {
cprest();
return;
}
inform('d');
skcopy(0);
}
extract(ap)
char *ap;
{
register ofd;
register long l;
register i;
if(ckafile(ap))
return;
if((ofd=creat(ap,0666)) < 0) {
error("cannot create %s\n",ap);
endit();
}
inform('x');
cp1file(arfd,ofd,IEVEN,arname,ap);
close(ofd);
}
print(ap)
char *ap;
{
if(ckafile(ap))
return;
cp1file(arfd,1,IEVEN,arname,"std output");
}
endit()
{
exit();
}
/* list all file in the library*/
listall()
{
while(nextar()) {
tell(-1);
}
}
/*read next ar file header into libhd*/
nextar()
{
if( read(arfd,&libhd,sizeof libhd) != sizeof libhd ||
libhd.l2fname[0] == '\0' ) {
areof++;
return(0);
}
return(1);
}
/* call with cpflag=0 for skip, cpflag=1 for copy*/
skcopy(cpflag)
{
register long l;
register int i;
if(areof)
return;
l = libhd.l2fsize;
if(l&1)
l++;
if(cpflag) {
inform('c');
cp1file(arfd,tempfd,WHDR+OEVEN+IEVEN,arname,tempname);
}
else {
if(lseek(arfd,l,1) < 0) {
error("seek error on library\n");
endit();
}
}
}
#ifdef JUNK
char *mktemp(ap)
char *ap;
{
register char *p;
register i,j;
/* i = getpid(); /*process id*/
/* p = ap;
while(*p)
p++;
for(j=0; j<5; j++) {
*--p = ((i&7) + '0');
i =>> 3;
}
*/ return(ap);
}
#endif
streq(s1, s2)
char *s1, *s2;
{
register char *p1, *p2;
p1 = s1;
p2 = s2;
while(*p1++ == *p2)
if(*p2++ == 0)
return(1);
return(0);
}
int m1[] { 1, ROWN, 'r', '-' };
int m2[] { 1, WOWN, 'w', '-' };
int m3[] { 1, XOWN, 'x', '-' };
int m4[] { 1, RGRP, 'r', '-' };
int m5[] { 1, WGRP, 'w', '-' };
int m6[] { 1, XGRP, 'x', '-' };
int m7[] { 1, ROTH, 'r', '-' };
int m8[] { 1, WOTH, 'w', '-' };
int m9[] { 1, XOTH, 'x', '-' };
int *m[] { m1, m2, m3, m4, m5, m6, m7, m8, m9};
pmode(aflg1)
{
register int **mp;
for (mp = &m[0]; mp < &m[9];)
select(*mp++,aflg1);
}
select(pairp,flg)
int *pairp;
int flg;
{
register int n, *ap, f;
ap = pairp;
f = flg;
n = *ap++;
while (--n>=0 && (f&*ap++)==0)
ap++;
putchar(*ap);
}
inform(cc)
char cc;
{
if(vflg) {
putchar(cc);
putchar(' ');
pfname();
}
}
copystr(ap1,ap2,alen)
char *ap1, *ap2;
{
register char *p1, *p2;
register len;
p1 = ap1;
p2 = ap2;
len = alen;
while(len) {
if(!(*p2++ = *p1++))
break;
len--;
}
while(--len > 0)
*p2++ = '\0';
}
#ifdef JUNK
long mklong(ai1,ai2)
{
long l;
l.hiword = ai1;
l.loword = ai2;
return(l);
}
#endif
cprest()
{
while(areof==0 && nextar())
skcopy(1); /*copy rest of library*/
}
cp1file(ifd,ofd,aflags,iname,oname)
char *iname, *oname;
{
register i;
register int j;
register long l;
register flags;
flags = aflags;
if(flags&WHDR) {
if(write(ofd,&libhd,sizeof libhd) != sizeof libhd) {
iwrerr:
error("write error on %s\n",oname);
endit();
}
}
for( l = libhd.l2fsize; l > BLKSIZE; l =- BLKSIZE ) {
if((i=read(ifd,buff,BLKSIZE)) != BLKSIZE) {
irderr:
error("read error on %s\n",iname);
endit();
}
if(write(ofd,buff,BLKSIZE) != BLKSIZE) {
goto iwrerr;
}
}
if( l > 0 ) {
i = l;
if((j=read(ifd,buff,i)) != i)
goto irderr;
if(flags&OEVEN) {
if(i&1) {
buff[i] = '\0';
i++;
}
}
if(write(ofd,buff,i) != i)
goto iwrerr;
}
if(flags&IEVEN)
if(l&1)
read(ifd,buff,1);
}
ckafile(ap)
char *ap;
{
if(ap==0)
endit();
if(areof) {
error("%s not in archive file\n",ap);
return(1);
}
return(0);
}
error(x1,x2,x3,x4,x5,x6)
int x1, x2, x3, x4, x5, x6;
{
printf(x1,x2,x3,x4,x5,x6);
if( tempfd ) {
close(tempfd);
unlink(tempname);
}
exit();
}

View File

@@ -0,0 +1,13 @@
#define HDSIZE (sizeof couthd) /**.o file header size*/
struct hdr {
short ch_magic; /*c.out magic number 060016 = $600E*/
long ch_tsize; /*text size*/
long ch_dsize; /*data size*/
long ch_bsize; /*bss size*/
long ch_ssize; /*symbol table size*/
long ch_stksize; /*stack size*/
long ch_entry; /*entry point*/
short ch_rlbflg; /*relocation bits suppressed flag*/
} couthd={0};
#define MAGIC 0x601a /* bra .+26 instruction*/

View File

@@ -0,0 +1,101 @@
/****************************************************************************/
/* */
/* C P M . H */
/* --------- */
/* */
/* This file contains CP/M specific definitions for the v6 library */
/* for the Alcyon assembler / linker. */
/* */
/* "stdio.h" must be included BEFORE this file. */
/* */
/****************************************************************************/
/*
* Cp/m FCB definition
*/
struct xfcb /****************************/
{ /* */
BYTE drive; /* Disk drive field */
BYTE fname[8]; /* File name */
BYTE ftype[3]; /* File type */
BYTE extent; /* Current extent number */
BYTE s1,s2; /* "system reserved" */
BYTE reccnt; /* Record counter */
BYTE resvd[16]; /* More "system reserved" */
LONG record; /* Note -- we overlap the */
/* current record field to */
/* make this useful. */
}; /****************************/
#define SECSIZ 128 /* # bytes / CP/M sector */
/****************************/
/****************************************************************************/
/* */
/* Channel Control Block (CCB) */
/* */
/* One CCB is allocated (statically) for each of the 16 possible open */
/* files under C (including STDIN, STDOUT, STDERR). Permanent data */
/* regarding the channel is kept here. */
/* */
/* */
/****************************************************************************/
struct ccb /************************************/
{ /* */
BYTE flags; /* Flags byte */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct xfcb fcb; /* File FCB */
BYTE buffer[SECSIZ]; /* Read / write buffer */
}; /************************************/
#define MAXFILE 16 /* Maximum # files */
extern struct ccb _iob[MAXFILE]; /* Declare storage */
/* Flags word bit definitions */
/************************************/
#define OPENED 1 /* Channel is OPEN */
#define ISTTY 2 /* Channel open to TTT */
#define ISLPT 4 /* Channel open to LPT */
#define ISREAD 8 /* Channel open readonly */
#define ISASCII 16 /* ASCII file attached */
#define ATEOF 32 /* End of file encountered */
#define DIRTY 64 /* Buffer needs writing */
/************************************/
/****************************************************************************/
/* */
/* B D O S F u n c t i o n D e f i n i t i o n s */
/* ------------------------------------------------- */
/* */
/* Following are BDOS function definitions used by the C runtime */
/* library. */
/* */
/****************************************************************************/
/****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
/****************************/
/****************************************************************************/
/* Other CP/M definitions */
/****************************************************************************/
#define TERM "CON:" /* Console file name */
#define LIST "LST:" /* List device file name */
#define EOFCHAR 0x1a /* End of file character-^Z */
/****************************/

View File

@@ -0,0 +1,135 @@
/*
* Kludge hex dump routine for 68K
*/
#include <stdio.h>
#include <cpm.h>
#include "machine.h"
#include <ctype.h>
main(argc,argv)
int argc;
char **argv;
{
char buffer[128]; /* Sector buffer */
int sector; /* Sector number */
long filaddr; /* File address */
int offset; /* Sector Offset */
register i,j,k,l,m; /* Temps. */
int fd; /* File descriptor */
if(argc < 2 || argc > 3) /* Only 1 file, please! */
{
printf("Usage: dump [-shhhhhh] file\n");
exit();
}
i = 1;
filaddr= 0; /* Zero file address */
if(*argv[1] == '-')
{
decode(argv[1],&filaddr); /* Get hex file addr */
i=2;
}
if((fd=openb(argv[i],READ)) < 0) /* Try to open file */
{
printf("Unable to open \"%s\"\n",argv[i]);
exit();
}
sector = filaddr >> 7; /* Zero sector count */
filaddr &= ~15; /* Round request down */
lseek(fd,filaddr,0); /* Do the seek */
m = (128 - (filaddr & 127)); /* # bytes in sector */
while((l=read(fd,buffer,m)) > 0) /* Until EOF */
{
l = (l + 15) / 16; /* Number of lines */
offset = filaddr & 127; /* Starting Offset */
for(i=0; i<l; i++) /* 8 lines / sector */
{
printf("%04x %02x (%06lx): ",sector,offset,filaddr);
for(j=0; j<16; j++) /* 16 bytes / line */
{
#ifdef VAX
printf(" %02x%02x",(buffer[i*16+j+1])&0xff,
(buffer[i*16+j]&0xff));
#endif
#ifdef PDP11
printf(" %02x%02x",(buffer[i*16+j+1])&0xff,
(buffer[i*16+j])&0xff);
#endif
#ifdef MC68000
printf(" %02x%02x",(buffer[i*16+j])&0xff,
(buffer[i*16+j+1]&0xff));
#endif
j++;
}
printf(" *");
for(j=0; j<16; j++) /* Now ASCII */
{
k = buffer[i*16+j] & 0x7f;
if ((k < ' ') || (k == 0x7f)) k= '.';
printf("%c",k);
}
printf("*\n");
filaddr += 16; /* Bump up file address*/
offset += 16; /* and offset */
}
sector++; /* Increment sector count*/
m = 128; /* # bytes to read next */
for(j=0; j<128; j++)
buffer[j] = 0;
}
printf("\n*** E O F ***\n");
}
/****************************************************************************/
/* */
/* D e c o d e F u n c t i o n */
/* ------------------------------ */
/* */
/* Routine "decode" is called to process the relocation base argument */
/* from the command line. */
/* */
/* Calling sequence: */
/* */
/* ret = decode(string,&address); */
/* */
/* Where: */
/* string -> argument string (usually argv[1]) */
/* &address -> long word to receive converted value */
/* */
/* ret = 0 if successful conversion */
/* = -1 if anything amiss */
/* */
/****************************************************************************/
WORD decode(string,addr) /* */
/* */
REG BYTE *string; /* -> Command argument */
LONG *addr; /* = return value */
{ /****************************/
REG LONG a; /* Temp return value */
REG BYTE c; /* Temp character */
/* */
if(*string++ != '-' || *string++ != 's')/* Check for valid switch */
return(FAILURE); /* quit if NFG */
/* */
a = 0; /* Zero out accumulator */
/* */
while(*string) /* Until no more chars */
{ /* */
c = toupper(*string) & 0177; /* Pick up next char */
if (c >= '0' && c <= '9') /* Digit */
a = (a << 4) + c - '0'; /* Un-ASCIIfy */
else if (c >= 'A' && c <= 'F') /* Hex */
a = (a << 4) + c - 'A'+ 10; /* Un-ASCIIfy */
else /* Bad character */
return(FAILURE); /* So long, sucker!! */
string++; /* Increment pointer */
} /* */
*addr = a; /* Store result */
return(SUCCESS); /* Return all ok */
} /****************************/

View File

@@ -0,0 +1,238 @@
/****************************************************************************
*
* C R U N T I M E G R E P R O U T I N E
* -------------------------------------------
* Copyright 1983 by Digital Research Inc. All rights reserved.
*
* The routine "grep" searches for an ascii character pattern in
* a series of files. "Grep" allows the following options:
*
* OPTION FUNCTION
* ------ --------
* -v Print only lines not matching the pattern
* -c Print only a count of the lines
* -n Print with line numbers
* -s Write out the sector number in which the pattern was found
* -l Write out a list of the files in which the pattern was found
* -y Do not distinguish between upper & lower case
*
* Calling Sequence:
*
* grep(options,expression,files);
*
* Where:
*
* options Is a pointer to a string of options
* expression Is a pointer to the search pattern
* files Is an array of pointers to filenames
*
*****************************************************************************/
/****************************/
/* INCLUDE FILES */
/****************************/
#include <stdio.h> /* standard I/O library */
#include <portab.h> /* CP/M portability defines */
#include <ctype.h> /* char type definitions */
/****************************/
/* GLOBAL VARIABLES */
/****************************/
GLOBAL BYTE __match = TRUE; /* Print Matching lines only*/
GLOBAL BYTE __count = FALSE; /* Just count the lines */
GLOBAL BYTE __num = FALSE; /* Print line #'s */
GLOBAL BYTE __sector = FALSE; /* Display the sector */
GLOBAL BYTE __list = FALSE; /* Display only a file list */
GLOBAL BYTE __nocase = FALSE; /* Distinguish between cases*/
GLOBAL FILE *fstream; /* file stream ptr */
GLOBAL BYTE line[129]; /* line buffer */
GLOBAL BYTE line1[129]; /* Temp line buffer */
GLOBAL BYTE first = TRUE; /* used on the list option */
GLOBAL UWORD numfound = 0; /* number of lines found */
/****************************/
/* FUNCTIONS */
/****************************/
FILE *fopenb(); /* returns a ptr to a file */
/****************************/
/* MAIN */
main(argc,argv) /* Entry point */
WORD argc; /* = # args */
BYTE **argv; /* -> args */
{ /****************************/
BYTE *options; /* Option pointer */
BYTE *expression; /* -> expression */
BYTE **files; /* -> files */
/* */
if(argc < 2) /* Must have at least 2 */
{ /* */
usage: printf("Usage: grep [-options] pattern files\n");
exit(); /* */
} /****************************/
/* */
options = "-ny"; /* Set up option */
if(*argv[1] == '-') /* Options specified? */
{ /* */
options = argv[1]; /* Yes, use them */
if(argc < 3) goto usage; /* check for valid args */
expression = argv[2]; /* -> Pattern */
files = &argv[3]; /* -> file list */
} /****************************/
else { /* No options */
expression = argv[1]; /* Expression */
files = &argv[2]; /* file list */
} /****************************/
return(grep(options,expression,files)); /* Call the real function */
} /* */
/****************************/
grep(options,expression,files) /* */
REG BYTE *options; /* option list */
REG BYTE *expression; /* pattern to search for */
BYTE *files[]; /* array of files */
{ /* */
REG BYTE *p; /* temp pointer */
REG UWORD patt_cnt; /* pattern counter */
REG UWORD char_cnt; /* character count */
REG UWORD line_cnt; /* line count */
REG UWORD i; /* counter */
UWORD length; /* length of pattern */
BYTE found; /* set if pattern is found */
/* */
/* */
if(*options != '-') /* Legal option list? */
{ /* */
fprintf(stderr,"GREP--Illegal option list: %s\n",options); /* */
exit(-1); /* Just quit */
} /****************************/
while(*options) /* if found ........ */
{ /* */
switch(*++options) /* */
{ /* */
case 'v' : __match = FALSE; /* print non-matching lines */
break; /* */
case 'c' : __count = TRUE; /* print a count of lines */
break; /* */
case 'n' : __num = TRUE; /* number the lines */
break; /* */
case 's' : __sector= TRUE; /* print sector number */
break; /* */
case 'l' : __list = TRUE; /* list the files */
break; /* */
case 'y' : __nocase= TRUE; /* no case distinction */
/*break;*/ /* */
} /* */
} /* */
/****************************/
if(__list) /* list option has priority */
{ /* over these..... */
__count = FALSE; /* */
__num = FALSE; /* */
__sector = FALSE; /* */
} /* */
else /* */
if(__count) /* count option has priority*/
{ /* over these..... */
__num = FALSE; /* */
__sector = FALSE; /* */
} /* */
else /* */
if(__num) /* num option has priority */
__sector = FALSE; /* over the sector option */
if(__nocase) /* if no case destinction */
{ /* */
p = expression; /* */
while(*p) /* change expression to */
{ /* */
*p = toupper(*p); /* upper case letters */
p++; /* */
} /* */
} /* */
length = strlen(expression); /* count the characters in */
/* the pattern to match */
while(*files) /* search all the files */
{ /* */
if((fstream = fopenb(*files,"r")) != NULL)/*try to open the file */
{ /* */
char_cnt = 0; /* initialize char count */
line_cnt = 0; /* initialize line # count */
numfound = 0; /* initialize # found */
first = TRUE; /* initialize for list */
if(!__list && !__count) /* if these options are not */
{ /* ON then print the file- */
printf("\nFILE: %s\n",*files); /* name before each search */
printf("----\n"); /* */
} /* */
while(!feof(fstream)) /* go until end of file */
{ /* */
found = FALSE; patt_cnt = 0; /* */
p = expression; /* */
fgets(line1,129,fstream); /* read a line */
/****************************/
for(i = 0;line1[i];i++) /* */
if(__nocase) /* Translate? */
line[i] = toupper(line1[i]);/* */
else /* Don't translate */
line[i] = line1[i]; /* Just copy */
/****************************/
i = 0; /* */
while(line[i]) /* scan until a NULL */
{ /* */
char_cnt++; /* bump the char count */
if(line[i] == *p) /* check pattern */
{ /* */
p++; /* look for next char */
patt_cnt++; /* we found a character */
if(patt_cnt == length) /* Have we found the end ? */
{ /* */
found = TRUE; /* set a flag */
p = expression; /* */
patt_cnt = 0; /* */
} /* */
} /* */
else /* */
{ /* */
p = expression; /* reset the pattern ptr */
patt_cnt = 0; /* start the count over */
} /* */
i++; /* check next character */
} /* */
line[i-1] = NULL; /* mask out extra LF */
line_cnt++; /* bump the line count */
prtline(found,char_cnt,line_cnt,files);/*then print routine */
} /* */
if(__count) /* is count option ON ? */
printf("\n%s: %d",*files,numfound);/*print a count of # fnd */
} /* */
files++; /* go to next file */
} /* */
} /****************************/
/* PRINT ROUTINE */
prtline(found,char_cnt,line_cnt,files) /****************************/
BYTE found; /* does line contain pattern*/
UWORD char_cnt; /* number of chars searched */
UWORD line_cnt; /* number of lines searched */
BYTE *files[]; /* current file */
{ /****************************/
if((__match && found) || /* have we a line ? */
(!__match && !found)) /* */
{ /* */
numfound++; /* count the # lines found */
if(__count) return; /* nothing to do */
if(__list) /* if the list option */
{ /* */
if(first) /* FIRST pattern found ? */
printf("\n%s",*files); /* print the filename */
first = FALSE; /* turn off flag */
return; /* and return.. */
} /* */
if(__sector) /* do we print the sector# ?*/
{ /* */
printf("\n%d",char_cnt/128);/* divide count by 128 */
return; /* */
} /* */
if(__num) /* do we print a line # ? */
{ /* */
printf("%5d: ",line_cnt); /* */
} /* otherwise..... */
fputs(line1,stdout); /* just print the line */
} /* */
} /****************************/

View File

@@ -0,0 +1,6 @@
struct iobuf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};

View File

@@ -0,0 +1,111 @@
/*
* Fix library files on CP/M - 68k
*/
#define LNAMLEN 14
#define LIBMAGIC 0177545
struct lib2hdr {
char fname[LNAMLEN]; /* Original file name */
long modti; /* Modification (unused) */
char userid; /* User id */
char gid;
short fimode;
long fsize; /* file size (Swap words here */
short junk; /* Unused */
} header;
struct {
short hiword; /* PDP-11 is */
short loword; /* backwards */
};
long lseek();
main(argc,argv)
int argc;
char **argv;
{
short i,j; /* Temps */
long seekaddr; /* Seek pointer */
long writeaddr; /* Write seek pointer */
short fd; /* File descriptor for I/O */
short ofd; /* File descriptor for output */
short magic; /* Lib magic word */
char buffer[30000]; /* I/O Buffer for file */
if(argc != 3)
{
printf ("File count wrong\n");
exit();
}
if((fd=open(argv[1],0,1)) < 0)
{
printf("Open failure on %s\n",argv[1]);
exit();
}
if((ofd=creat(argv[2],1,1)) < 0)
{
printf("Cannot create %s\n",argv[2]);
exit();
}
if(read(fd,&magic,2) != 2)
{
printf("Read error\n");
exit();
}
if(magic != LIBMAGIC)
{
printf("Not archive format: %s\n",argv[1]);
exit();
}
if(write(ofd,&magic,2) != 2)
{
printf("Write error\n");
exit();
}
while(1)
{
if(read(fd,&header,(sizeof header)-2) != (sizeof header)-2)
{
printf("Read error at file offset %lx\n",writeaddr);
exit();
}
for(i=0; i<LNAMLEN; i+=2)
{
j = header.fname[i];
header.fname[i] = header.fname[i+1];
header.fname[i+1] = j;
}
header.modti = 0L;
header.userid = 0;
header.gid = 0;
header.fimode = 0777;
header.junk = 0;
printf("File %14s: %ld bytes\n",&header.fname[0],header.fsize);
if(write(ofd,&header,(sizeof header)) != (sizeof header))
{
printf("Write error\n");
exit();
}
if(header.fsize > 30000)
{
printf("File size error\n");
exit();
}
if(read(fd,&buffer[0],header.fsize.loword) != header.fsize.loword)
{
printf("Read error\n");
exit();
}
if(write(ofd,&buffer[0],header.fsize.loword) != header.fsize.loword)
{
printf("Write error\n");
exit();
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* Fix library files on CP/M - 68k
*/
#define LNAMLEN 14
#define LIBMAGIC 0177545
struct lib2hdr {
char fname[LNAMLEN]; /* Original file name */
long modti; /* Modification (unused) */
char userid; /* User id */
char gid;
short fimode;
long fsize; /* file size (Swap words here */
short junk; /* Unused */
} header;
struct {
short hiword; /* PDP-11 is */
short loword; /* backwards */
};
long lseek();
main(argc,argv)
int argc;
char **argv;
{
short i,j; /* Temps */
long seekaddr; /* Seek pointer */
long writeaddr; /* Write seek pointer */
short fd; /* File descriptor for I/O */
short ofd; /* File descriptor for output */
short magic; /* Lib magic word */
char buffer[30000]; /* I/O Buffer for file */
if(argc != 3)
{
printf ("File count wrong\n");
exit();
}
if((fd=open(argv[1],0,1)) < 0)
{
printf("Open failure on %s\n",argv[1]);
exit();
}
if((ofd=creat(argv[2],1,1)) < 0)
{
printf("Cannot create %s\n",argv[2]);
exit();
}
if(read(fd,&magic,2) != 2)
{
printf("Read error\n");
exit();
}
if(magic != LIBMAGIC)
{
printf("Not archive format: %s\n",argv[1]);
exit();
}
if(write(ofd,&magic,2) != 2)
{
printf("Write error\n");
exit();
}
while(1)
{
if(read(fd,&header,(sizeof header)-2) != (sizeof header)-2)
{
printf("Read error at file offset %lx\n",writeaddr);
exit();
}
for(i=0; i<LNAMLEN; i+=2)
{
j = header.fname[i];
header.fname[i] = header.fname[i+1];
header.fname[i+1] = j;
}
header.modti = 0L;
header.userid = 0;
header.gid = 0;
header.fimode = 0777;
header.junk = 0;
printf("File %14s: %ld bytes\n",&header.fname[0],header.fsize);
if(write(ofd,&header,(sizeof header)) != (sizeof header))
{
printf("Write error\n");
exit();
}
if(header.fsize > 30000)
{
printf("File size error\n");
exit();
}
if(read(fd,&buffer[0],header.fsize.loword) != header.fsize.loword)
{
printf("Read error\n");
exit();
}
if(write(ofd,&buffer[0],header.fsize.loword) != header.fsize.loword)
{
printf("Write error\n");
exit();
}
}
}

View File

@@ -0,0 +1,63 @@
$ num
AR68.C
AR68.lis
$ num
DUMP.C
DUMP.lis
$ num
GREP.C
GREP.lis
$ num
LIBFIX.C
LIBFIX.lis
$ num
LO68.C
LO68.lis
$ num
LO68INIT.C
LO68INIT.lis
$ num
NM68.C
NM68.lis
$ num
NUXI.C
NUXI.lis
$ num
PRTOBJ.C
PRTOBJ.lis
$ num
RELOC.C
RELOC.lis
$ num
SENDC68.C
SENDC68.lis
$ num
SIZE68.C
SIZE68.lis
$ num
TEST.C
TEST.lis
$ num
AR.H
AR.lst
$ num
COUT.H
COUT.lst
$ num
CPM.H
CPM.lst
$ num
IOBUF.H
IOBUF.lst
$ num
LO68.H
LO68.lst
$ num
MACHINE.H
MACHINE.lst
$ num
SENDC68.H
SENDC68.lst
$ num
STDIO.H
STDIO.lst

View File

@@ -0,0 +1,63 @@
$ num
AR68.C
AR68.lis
$ num
DUMP.C
DUMP.lis
$ num
GREP.C
GREP.lis
$ num
LIBFIX.C
LIBFIX.lis
$ num
LO68.C
LO68.lis
$ num
LO68INIT.C
LO68INIT.lis
$ num
NM68.C
NM68.lis
$ num
NUXI.C
NUXI.lis
$ num
PRTOBJ.C
PRTOBJ.lis
$ num
RELOC.C
RELOC.lis
$ num
SENDC68.C
SENDC68.lis
$ num
SIZE68.C
SIZE68.lis
$ num
TEST.C
TEST.lis
$ num
AR.H
AR.lst
$ num
COUT.H
COUT.lst
$ num
CPM.H
CPM.lst
$ num
IOBUF.H
IOBUF.lst
$ num
LO68.H
LO68.lst
$ num
MACHINE.H
MACHINE.lst
$ num
SENDC68.H
SENDC68.lst
$ num
STDIO.H
STDIO.lst

View File

@@ -0,0 +1,36 @@
$ num
AR68.C
AR68.lis
$ num
LO68.C
LO68.lis
$ num
LO68INIT.C
LO68INIT.lis
$ num
NMC68.C
NMC68.lis
$ num
PRTOBJ.C
PRTOBJ.lis
$ num
SENDC68.C
SENDC68.lis
$ num
SIZE68.C
SIZE68.lis
$ num
AR.H
AR.lis
$ num
COUT.H
COUT.lis
$ num
IOBUF.H
IOBUF.lis
$ num
LO68.H
LO68H.lis
$ num
SENDC68.H
SENDC68H.lis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
/*
Copyright 1981
Alcyon Corporation
8474 Commerce Av.
San Diego, Ca. 92121
*/
#include "machine.h"
/* format of a symbol entry in the main table*/
#define SEEKREL 1 /*relative seek flag*/
#define SYNAMLEN 8
struct symtab {
char name[SYNAMLEN]; /*symbol name*/
short flags; /*bit flags*/
long vl1; /*symbol value*/
char *tlnk; /*table link*/
};
struct symtab *symptr;
#define OSTSIZE 14 /*entry length on object file without tlnk*/
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYDA 0002000 /*DATA based relocatable*/
# define SYTX 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
#ifdef VAX
struct {
short loword;
short hiword;
};
#endif
#ifdef PDP11
struct {
short loword;
short hiword;
};
#endif
#ifdef MC68000
struct {
short hiword;
short loword;
};
#endif
/* parameters that define the main table*/
#define SZMT 300 /*initial size of the main table*/
/*must be large enough to initialize*/
#define ICRSZMT 100 /*add to main table when run out*/
int cszmt; /*current size of main table*/
char *bmte; /*beginning of main table*/
char *emte; /*end of main table*/
/*initial reference table for externals*/
# define SZIRT 64
char *eirt[SZIRT];
char *saveirt[SZIRT];
/*initial reference table for globals*/
char *girt[SZIRT];
char *savgirt[SZIRT];
char **pirt;
char *lmte; /*last entry in main table*/
char *savlmte;
#define AREGLO 8
#define AREGHI 15
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
#define EXTREL 6 /* relative mode on external variable*/
#define BUFSIZE 512
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf ibuf;
struct buf tbuf;
struct buf obuf;
struct buf rbuf;
struct buf rtbuf;
struct buf rdbuf;
int sflag; /*remove symbol table*/
long textbase;
long database;
long bssbase;
long textsize;
long datasize;
long bsssize;
long stacksize;
long textstart;
long datastart;
long bssstart;
char *ifilname; /*points to name of current input file*/
#define NFILE 256 /*max # files we can process*/
char *fsymp[NFILE]; /*points to first symbol for each .o file*/
char **firstsym; /*points to entry in fsymp*/
int extmatch; /*matched an external in a library entry*/
int noload; /*dont load this lib file flag*/
#define NLIB 16 /*max # libraries to process*/
int lbfictr[NLIB]; /*counts files loaded from one library*/
int *libfctr; /*points to lbfictr*/
long lbfioff[NFILE]; /*each file offset in library*/
long *libptr; /*points to lbfioff*/
#define LIB1MAGIC 0177555
#define LIB2MAGIC 0xffffff65
#define LIB1HDSIZE 16
#define LIB2HDSIZE 26
struct libhdr {
char l1fname[8];
long l1modti;
char l1userid;
char l1fimode;
short l1fsize;
};
struct lib2hdr {
char l2fname[14];
long l2modti;
char l2userid;
char l2gid;
short l2fimode;
long l2fsize;
short l2junk;
} *lib2hd;
#define ARMAG "!<arch>\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
} lib3_hdr;
#define LIB3MAGIC 0x3c21
#define LIB3HDSIZE (sizeof lib3_hdr)
int libhdsize;
long libhd[20]; /*length is max lib head size*/
int undflg;
char dafnc;
int pass2;
long stlen;
int Xflag;
int Dflag;
int Bflag;
int Zflag;
struct symtab *etextptr;
struct symtab *edataptr;
struct symtab *endptr;
char *lastdup;
char rtfnc;
char rdfnc;
int saverbits;

View File

@@ -0,0 +1,185 @@
/*
Copyright 1981
Alcyon Corporation
8474 Commerce Av.
San Diego, Ca. 92121
*/
/* format of a symbol entry in the main table*/
#define SEEKREL 1 /*relative seek flag*/
#define SYNAMLEN 8
struct symtab {
char name[SYNAMLEN]; /*symbol name*/
short flags; /*bit flags*/
long vl1; /*symbol value*/
char *tlnk; /*table link*/
};
struct symtab *symptr =0;
#define OSTSIZE 14
/*entry length on object file without tlnk*/
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYDA 0002000 /*DATA based relocatable*/
# define SYTX 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
struct {
short loword;
short hiword;
};
/* parameters that define the main table*/
#define SZMT 300 /*initial size of the main table*/
/*must be large enough to initialize*/
#define ICRSZMT 100 /*add to main table when run out*/
int cszmt =0;
char *bmte =0;
char *emte =0;
/*initial reference table for externals*/
# define SZIRT 64
char *eirt[SZIRT] ={0};
char *saveirt[SZIRT] ={0};
/*initial reference table for globals*/
char *girt[SZIRT] ={0};
char *savgirt[SZIRT] ={0};
char **pirt =0;
char *lmte =0;
char *savlmte =0;
#define AREGLO 8
#define AREGHI 15
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
#define EXTREL 6 /* relative mode on external variable*/
#define BUFSIZE 512
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf ibuf ={0};
struct buf tbuf ={0};
struct buf obuf ={0};
struct buf rbuf ={0};
struct buf rtbuf ={0};
struct buf rdbuf ={0};
int sflag =0;
long textbase =0;
long database =0;
long bssbase =0;
long textsize =0;
long datasize=0;
long bsssize =0;
long stacksize =0;
long textstart =0;
long datastart =0;
long bssstart =0;
char *ifilname =0;
#define NFILE 256 /*max # files we can process*/
char *fsymp[NFILE] ={0};
char **firstsym =0;
int extmatch =0;
int noload =0;
#define NLIB 16 /*max # libraries to process*/
int lbfictr[NLIB] ={0};
int *libfctr =0;
long lbfioff[NFILE] ={0};
long *libptr =0;
#define LIB1MAGIC 0177555
#define LIB2MAGIC 0177545
#define LIB1HDSIZE 16
#define LIB2HDSIZE 26
struct libhdr {
char l1fname[8];
long l1modti;
char l1userid;
char l1fimode;
int l1fsize;
};
struct lib2hdr {
char l2fname[14];
long l2modti;
char l2userid;
char l2gid;
int l2fimode;
long l2fsize;
};
#define ARMAG "!<arch>\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
} lib3_hdr ={0};
#define LIB3MAGIC 0x3c21
#define LIB3HDSIZE (sizeof lib3_hdr)
int libhdsize =0;
long libhd[20] ={0};
int undflg =0;
char dafnc =0;
int pass2 =0;
long stlen =0;
int Xflag =0;
int Dflag =0;
int Bflag =0;
int Zflag =0;
struct symtab *etextptr =0;
struct symtab *edataptr =0;
struct symtab *endptr =0;
char *lastdup =0;
char rtfnc =0;
char rdfnc =0;
int saverbits =0;

View File

@@ -0,0 +1,185 @@
/*
Copyright 1981
Alcyon Corporation
8474 Commerce Av.
San Diego, Ca. 92121
*/
/* format of a symbol entry in the main table*/
#define SEEKREL 1 /*relative seek flag*/
#define SYNAMLEN 8
struct symtab {
char name[SYNAMLEN]; /*symbol name*/
short flags; /*bit flags*/
long vl1; /*symbol value*/
char *tlnk; /*table link*/
};
struct symtab *symptr =0;
#define OSTSIZE 14
/*entry length on object file without tlnk*/
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYDA 0002000 /*DATA based relocatable*/
# define SYTX 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
struct {
short loword;
short hiword;
};
/* parameters that define the main table*/
#define SZMT 300 /*initial size of the main table*/
/*must be large enough to initialize*/
#define ICRSZMT 100 /*add to main table when run out*/
int cszmt =0;
char *bmte =0;
char *emte =0;
/*initial reference table for externals*/
# define SZIRT 64
char *eirt[SZIRT] ={0};
char *saveirt[SZIRT] ={0};
/*initial reference table for globals*/
char *girt[SZIRT] ={0};
char *savgirt[SZIRT] ={0};
char **pirt =0;
char *lmte =0;
char *savlmte =0;
#define AREGLO 8
#define AREGHI 15
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
#define EXTREL 6 /* relative mode on external variable*/
#define BUFSIZE 512
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf ibuf ={0};
struct buf tbuf ={0};
struct buf obuf ={0};
struct buf rbuf ={0};
struct buf rtbuf ={0};
struct buf rdbuf ={0};
int sflag =0;
long textbase =0;
long database =0;
long bssbase =0;
long textsize =0;
long datasize=0;
long bsssize =0;
long stacksize =0;
long textstart =0;
long datastart =0;
long bssstart =0;
char *ifilname =0;
#define NFILE 256 /*max # files we can process*/
char *fsymp[NFILE] ={0};
char **firstsym =0;
int extmatch =0;
int noload =0;
#define NLIB 16 /*max # libraries to process*/
int lbfictr[NLIB] ={0};
int *libfctr =0;
long lbfioff[NFILE] ={0};
long *libptr =0;
#define LIB1MAGIC 0177555
#define LIB2MAGIC 0177545
#define LIB1HDSIZE 16
#define LIB2HDSIZE 26
struct libhdr {
char l1fname[8];
long l1modti;
char l1userid;
char l1fimode;
int l1fsize;
};
struct lib2hdr {
char l2fname[14];
long l2modti;
char l2userid;
char l2gid;
int l2fimode;
long l2fsize;
};
#define ARMAG "!<arch>\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
} lib3_hdr ={0};
#define LIB3MAGIC 0x3c21
#define LIB3HDSIZE (sizeof lib3_hdr)
int libhdsize =0;
long libhd[20] ={0};
int undflg =0;
char dafnc =0;
int pass2 =0;
long stlen =0;
int Xflag =0;
int Dflag =0;
int Bflag =0;
int Zflag =0;
struct symtab *etextptr =0;
struct symtab *edataptr =0;
struct symtab *endptr =0;
char *lastdup =0;
char rtfnc =0;
char rdfnc =0;
int saverbits =0;

View File

@@ -0,0 +1 @@
$clink ar68,lib:klutz/lib ar68

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
#define PDP11 1 /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
#define UNIX 1 /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
#define MC68000 1 /* 68000 version */
/*#define VAX 1*/ /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
#define CPM 1 /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
/*#define VMS 1*/ /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
#define VAX 1 /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
#define VMS 1 /* VMS Operating System*/

View File

@@ -0,0 +1,10 @@
/*
* Use this file to determine what kind of machine you want the
* Alcyon stuff to run on ....
*/
/*#define MC68000 1*/ /* 68000 version */
#define VAX 1 /* VAX Version */
/*#define PDP11 1*/ /* PDP-11 Version*/
/*#define CPM 1*/ /* CP/M Operating System*/
/*#define UNIX 1*/ /* UNIX Operating System*/
#define VMS 1 /* VMS Operating System*/

View File

@@ -0,0 +1,13 @@
$ set def [steve.cpm68k.asmlink]
$ set noon
$ copy machine.68k machine.h
$ purge machine.h
$ delete *.o;*
$ cc68 ar68
$ cc68 lo68
$ cc68 nm68
$ cc68 prtobj
$ cc68 sendc68
$ cc68 reloc
$ cc68 dump
$ @reload

View File

@@ -0,0 +1,10 @@
cc -c *.c
cc -o ar68 ar68.o ../lib/libx.a
cc -o dump dump.o ../lib/libx.a
cc -o lo68 lo68.o ../lib/libx.a
cc -o nm68 nm68.o ../lib/libx.a
cc -o nuxi nuxi.o ../lib/libx.a
cc -o prtobj prtobj.o ../lib/libx.a
cc -o reloc reloc.o ../lib/libx.a
cc -o sendc68 sendc68.o ../lib/libx.a
cc -o size68 size68.o ../lib/libx.a

View File

@@ -0,0 +1,104 @@
$1pip d:=*.h[g6
$1pip machine.h=machine.68k
$1pip d:=e:as68symb.dat[g0
$1pip d:=lib6.a[g5
$1pip d:=clib[g6
$1pip d:=s.o[g6
$1pip d:=w.o[g6
$1cp68 ar68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic ar68.s -l
$1as68 -f $1 -l -u ar68.s
era $1x.i
era $1x.ic
era $1x.st
era ar68.s
$1cp68 lo68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic lo68.s -l
$1as68 -f $1 -l -u lo68.s
era $1x.i
era $1x.ic
era $1x.st
era lo68.s
$1cp68 dump.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic dump.s -l
$1as68 -f $1 -l -u dump.s
era $1x.i
era $1x.ic
era $1x.st
era dump.s
$1cp68 nm68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic nm68.s -l
$1as68 -f $1 -l -u nm68.s
era $1x.i
era $1x.ic
era $1x.st
era nm68.s
$1cp68 prtobj.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic prtobj.s -l
$1as68 -f $1 -l -u prtobj.s
era $1x.i
era $1x.ic
era $1x.st
era prtobj.s
$1cp68 reloc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic reloc.s -l
$1as68 -f $1 -l -u reloc.s
era $1x.i
era $1x.ic
era $1x.st
era reloc.s
$1cp68 sendc68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic sendc68.s -l
$1as68 -f $1 -l -u sendc68.s
era $1x.i
era $1x.ic
era $1x.st
era sendc68.s
$1cp68 size68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic size68.s -l
$1as68 -f $1 -l -u size68.s
era $1x.i
era $1x.ic
era $1x.st
era size68.s
$1cp68 grep.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic grep.s -l
$1as68 -f $1 -l -u grep.s
era $1x.i
era $1x.ic
era $1x.st
era grep.s
$1lo68 -r -s -o lo68.rel s.o lo68.o lib6.a
$1lo68 -r -s -o ar68.rel s.o ar68.o lib6.a
$1lo68 -r -s -o dump.rel -unofloat s.o dump.o clib
$1lo68 -r -s -o nm68.rel s.o nm68.o lib6.a
$1lo68 -r -s -o prtobj.rel s.o prtobj.o lib6.a
$1lo68 -r -s -o reloc.rel -unofloat s.o reloc.o clib
$1lo68 -r -s -o sendc68.rel s.o sendc68.o lib6.a
$1lo68 -r -s -o size68.rel s.o size68.o lib6.a
$1lo68 -r -s -o grep.rel -unofloat w.o grep.o clib
era *.o
era clib
era lib6.a
era as68symb.dat

View File

@@ -0,0 +1,99 @@
$1pip d:=*.h[g6
$1pip machine.h=machine.68k
$1pip d:=as68symb.dat[g0
$1pip d:=lib6.a[g5
$1pip d:=clib[g6
$1pip d:=s.o[g6
$1pip d:=w.o[g6
$1cp68 ar68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic ar68.s -l
$1as68 -f $1 -l -u ar68.s
era $1x.i
era $1x.ic
era $1x.st
era ar68.s
$1cp68 lo68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic lo68.s -l
$1as68 -f $1 -l -u lo68.s
era $1x.i
era $1x.ic
era $1x.st
era lo68.s
$1cp68 dump.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic dump.s -l
$1as68 -f $1 -l -u dump.s
era $1x.i
era $1x.ic
era $1x.st
era dump.s
$1cp68 nm68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic nm68.s -l
$1as68 -f $1 -l -u nm68.s
era $1x.i
era $1x.ic
era $1x.st
era nm68.s
$1cp68 prtobj.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic prtobj.s -l
$1as68 -f $1 -l -u prtobj.s
era $1x.i
era $1x.ic
era $1x.st
era prtobj.s
$1cp68 reloc.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic reloc.s -l
$1as68 -f $1 -l -u reloc.s
era $1x.i
era $1x.ic
era $1x.st
era reloc.s
$1cp68 sendc68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic sendc68.s -l
$1as68 -f $1 -l -u sendc68.s
era $1x.i
era $1x.ic
era $1x.st
era sendc68.s
$1cp68 size68.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic size68.s -l
$1as68 -f $1 -l -u size68.s
era $1x.i
era $1x.ic
era $1x.st
era size68.s
$1cp68 grep.c $1x.i
$1c068 $1x.i $1x.ic $1x.st
$1c168 $1x.ic grep.s -l
$1as68 -f $1 -l -u grep.s
era $1x.i
era $1x.ic
era $1x.st
era grep.s
$1lo68 -r -s -o lo68.rel s.o lo68.o lib6.a
$1lo68 -r -s -o ar68.rel s.o ar68.o lib6.a
$1lo68 -r -s -o dump.rel -unofloat s.o dump.o clib
$1lo68 -r -s -o nm68.rel s.o nm68.o lib6.a
$1lo68 -r -s -o prtobj.rel s.o prtobj.o lib6.a
$1lo68 -r -s -o reloc.rel -unofloat s.o reloc.o clib
$1lo68 -r -s -o sendc68.rel s.o sendc68.o lib6.a
$1lo68 -r -s -o size68.rel s.o size68.o lib6.a
$1lo68 -r -s -o grep.rel -unofloat w.o grep.o clib

View File

@@ -0,0 +1,12 @@
$ set noon
$ cx lo68
$ cx lo68init
$ clink lo68,lo68init,lib:klutz/lib lo68
$ cx nmc68
$ clink nmc68,lib:klutz/lib nmc68
$ cx prtobj
$ clink prtobj,lo68init,lib:klutz/lib prtobj
$ cx sendc68
$ clink sendc68,lib:klutz/lib sendc68
$ cx ar68
$ clink ar68,lib:klutz/lib ar68

View File

@@ -0,0 +1,114 @@
#include "cout.h"
#include "sendc68.h"
#define MAGIC1 MAGIC+1
int hdsize=0;
int loctr=0;
int pflg=0;
int syno=0;
int symflg;
extern int fout;
long lseek();
main(argc,argv)
char **argv;
{
long l,l1;
register i,j,k;
if(argc<2) {
printf("Usage: nm68 objectfile\n");
exit();
}
hdsize = HDSIZE;
fout = dup(1);
i = 1;
openfile(argv[i]);
l = couthd.ch_tsize+couthd.ch_dsize+hdsize;
lseek(ibuf.fildes,l,0);
ibuf.nunused = 0;
l1 = couthd.ch_ssize;
syno = 0;
while(l1) {
syno++;
for(i=0; i<8; i++) /* Print Symbol name*/
{
k = getc(&ibuf) & 0377;
if (k < ' ') k = ' '; /* Filter ctrl chars*/
putchar(k);
}
putchar((char)'\t');
j = getw(&ibuf); /*flags*/
l.hiword = getw(&ibuf);
l.loword = getw(&ibuf);
printf("%8lx",l);
prtflags(j);
l1 -= OSTSIZE;
}
myflush();
}
prtflags(af)
{
register f;
f = af;
if(f&SYEQ)
printf(" equ");
if(f&SYGL)
printf(" global");
if(f&SYER)
printf(" reg");
if(f&SYXR)
printf(" external");
if(f&SYDA)
printf(" data");
else if(f&SYTX)
printf(" text");
else if(f&SYBS)
printf(" bss");
else
printf(" abs");
putchar((char)'\n');
}
openfile(ap)
char *ap;
{
register char *p;
p = ap;
if((ibuf.fildes=fopen(p,&ibuf,1)) < 0) {
printf("unable to open %s\n",p);
exit();
}
ifilname = p; /*point to current file name for error msgs*/
if(read(ibuf.fildes,&couthd,2) != 2) {
printf("read error on file: %s\n",ifilname);
exit();
}
ibuf.nunused = 0;
lseek(ibuf.fildes,0L,0);
readhdr(); /*read file header*/
}
readhdr()
{
register int i;
register short *p;
p = &couthd;
for(i=0; i<HDSIZE/2; i++)
*p++ = getw(&ibuf);
if(couthd.ch_magic != MAGIC) {
if(couthd.ch_magic==MAGIC1) {
hdsize =+ 8;
}
else {
printf("file format error: %s\n",ifilname);
exit();
}
}
}

View File

@@ -0,0 +1,132 @@
#include "cout.h"
#include "sendc68.h"
#include <stdio.h>
#define MAGIC1 MAGIC+1
int hdsize=0;
int input=0;
int loctr=0;
int pflg=0;
int syno=0;
int symflg;
long lseek();
main(argc,argv)
char **argv;
{
long l,l1;
register i,j,k;
BYTE *buffer;
if(argc<2) {
printf("Usage: nm68 filename\n");
exit();
}
hdsize = HDSIZE;
i = 1;
openfile(argv[1]); /* Open input file */
if (couthd.ch_ssize > 65534L)
{
printf("nm68: Too many symbols\n");
exit(-1);
}
i = couthd.ch_ssize;
if((buffer=malloc(i)) == NULL)
{
printf("nm68: Insufficient memory\n");
exit(-1);
}
l = couthd.ch_tsize+couthd.ch_dsize+hdsize;
lseek(ibuf.fildes,l,0);
if(read(input,buffer,i) != i)
{
printf("nm68: Input read error\n");
exit(-1);
}
/*
* Ok, now the symbol table is in memory. Sort it and print it.
*/
l1 = couthd.ch_ssize;
syno = 0;
while(l1) {
syno++;
for(i=0; i<8; i++) /* Print Symbol name*/
{
k = getc(&ibuf) & 0377;
if (k < ' ') k = ' '; /* Filter ctrl chars*/
putchar(k);
}
putchar((char)'\t');
j = getw(&ibuf); /*flags*/
l.hiword = getw(&ibuf);
l.loword = getw(&ibuf);
printf("%8lx",l);
prtflags(j);
l1 -= OSTSIZE;
}
myflush();
}
prtflags(af)
{
register f;
f = af;
if(f&SYEQ)
printf(" equ");
if(f&SYGL)
printf(" global");
if(f&SYER)
printf(" reg");
if(f&SYXR)
printf(" external");
if(f&SYDA)
printf(" data");
else if(f&SYTX)
printf(" text");
else if(f&SYBS)
printf(" bss");
else
printf(" abs");
putchar((char)'\n');
}
openfile(ap)
char *ap;
{
register char *p;
p = ap;
if((ibuf.fildes=fopen(p,&ibuf,1)) < 0) {
printf("unable to open %s\n",p);
exit();
}
ifilname = p; /*point to current file name for error msgs*/
if(read(ibuf.fildes,&couthd,2) != 2) {
printf("read error on file: %s\n",ifilname);
exit();
}
ibuf.nunused = 0;
lseek(ibuf.fildes,0L,0);
readhdr(); /*read file header*/
}
readhdr()
{
register int i;
register short *p;
p = &couthd;
for(i=0; i<HDSIZE/2; i++)
*p++ = getw(&ibuf);
if(couthd.ch_magic != MAGIC) {
if(couthd.ch_magic==MAGIC1) {
hdsize =+ 8;
}
else {
printf("file format error: %s\n",ifilname);
exit();
}
}
}

View File

@@ -0,0 +1,76 @@
#include "cout.h"
long lseek();
main(argc,argv)
int argc;
char **argv;
{
register i,j,c,d;
long symseek; /* Symbol table seek addr */
int symlength; /* Symbol length (bytes) */
char symbuf[30000]; /* Symbol table buffer */
int fd; /* File descriptor */
if((fd=open(argv[1],2,1)) < 0) /* Open input file */
{
printf("Cannot open %s\n",argv[1]); /* Can't */
exit(); /* Just quit */
} /****************************/
if((i=read(fd,&couthd,HDSIZE)) != HDSIZE) /* Read file header */
{ /* Can't */
printf("Header read error\n"); /* Print message */
exit(); /* Then quit */
} /****************************/
symseek=couthd.ch_tsize+couthd.ch_dsize+HDSIZE;
if(couthd.ch_magic != MAGIC)
{
if(couthd.ch_magic == (MAGIC+1))
{
symseek += 8;
}
else
{
printf("File format error\n");
exit();
}
}
symlength = lseek(fd,symseek,0); /* Seek to sym begin */
if(symlength != symseek) /* OK? */
{
printf("Seek error\n"); /*No, quit */
exit(); /* */
}
symlength = couthd.ch_ssize; /* Fetch symbol length */
if(read(fd,&symbuf[0],symlength) != symlength)
{
printf("Symbol table read error\n");
}
for(i=0; i < symlength; i+=14)
{
for(j=0; j < 8; j+=2)
{
c = symbuf[j+i];
d = symbuf[j+i+1];
symbuf[j+i] = d;
symbuf[j+i+1] = c;
}
}
if(lseek(fd,symseek,0) != symseek)
{
printf("Seek error\n");
exit();
}
if(write(fd,&symbuf[0],symlength) != symlength)
{
printf("Symbol table write error\n");
exit();
}
close(fd);
exit(0);
}

View File

@@ -0,0 +1,192 @@
#include "cout.h"
#include "lo68.h"
#define LIBMAGIC 0177545
int loctr=0;
int pflg=0;
int syno=0;
int symflg=0;
extern int fout;
char *reloc[] {
"DABS",
"DRELOC",
"TRELOC",
"BRELOC",
"EXTVAR",
"LUPPER",
"NOTUSED",
"INSABS" };
long lseek();
main(argc,argv)
char **argv;
{
long l,l1;
register i,j;
if(argc<2) {
printf("Usage: prtobj [-] objectfile\n");
exit();
}
fout = dup(1);
i = 1;
if(*argv[1] == '-') {
i++;
symflg++;
}
pass2 = 1;
openfile(argv[i]);
if(couthd.ch_rlbflg == 0) { /*relocation bits there*/
l = couthd.ch_tsize+couthd.ch_dsize+couthd.ch_ssize+HDSIZE; /*ptr to relocation bits*/
longseek(l,&rbuf,3);
}
printf("file name: %s\n",argv[i]);
l = couthd.ch_tsize;
printf("text size = %9ld = %08lx hex\n",l,l);
l = couthd.ch_dsize;
printf("data size = %9ld = %08lx hex\n",l,l);
l = couthd.ch_bsize;
printf("bss size = %9ld = %08lx hex\n",l,l);
l = couthd.ch_ssize;
printf("symbol size = %9ld = %08lx hex\n",l,l);
l = couthd.ch_stksize;
printf("stack size = %9ld = %08lx hex\n",l,l);
loctr = couthd.ch_entry;
printf("entry point = %9ld = %08lx hex\n",loctr,loctr);
if(symflg) {
l = couthd.ch_tsize+couthd.ch_dsize+HDSIZE;
longseek(l,&ibuf,3);
goto dosyms;
}
l1 = couthd.ch_tsize;
printf("TEXT:\n");
mloop:
for(l=0; l<l1; l=+ 2) {
i = getw(&ibuf);
if(couthd.ch_rlbflg==0)
j = getw(&rbuf);
else
j = DABS;
printf("%08x %04x %s",loctr,((int)i)&0xffff,reloc[j&7]);
if((j&7) == EXTVAR)
printf(" ext# %5d\n",(j>>3)&017777);
else
putchar('\n');
loctr =+ 2;
}
if(pflg==0) {
printf("\nDATA:\n");
l1 = couthd.ch_dsize;
pflg++;
goto mloop;
}
dosyms:
printf("\nSYMBOLS:\n");
l1 = couthd.ch_ssize;
syno = 0;
while(l1) {
printf("%4d ",syno);
syno++;
for(i=0; i<8; i++)
putchar((int)getc(&ibuf)); /*symbol name*/
putchar((int)'\t');
j = getw(&ibuf); /*flags*/
l.hiword = getw(&ibuf);
l.loword = getw(&ibuf);
printf("%04x%04x",((int)l.hiword)&0xffff,
((int)l.loword)&0xffff);
prtflags(j);
l1 =- OSTSIZE;
}
myflush();
}
prtflags(af)
{
register f;
f = af;
if(f&SYEQ)
printf(" equ");
if(f&SYGL)
printf(" global");
if(f&SYER)
printf(" equreg");
if(f&SYXR)
printf(" external");
if(f&SYDA)
printf(" data");
else if(f&SYTX)
printf(" text");
else if(f&SYBS)
printf(" bss");
else
printf(" abs");
putchar((int)'\n');
}
openfile(ap)
char *ap;
{
register char *p;
p = ap;
if((ibuf.fildes=open(p,0,1)) < 0) {
printf("unable to open %s\n",p);
exit();
}
ifilname = p; /*point to current file name for error msgs*/
if(read(ibuf.fildes,&couthd,2) != 2) {
printf("read error on file: %s\n",ifilname);
exit();
}
ibuf.nunused = 0;
if(couthd.ch_magic != LIBMAGIC) {
lseek(ibuf.fildes,0L,0);
readhdr(); /*read file header*/
}
if(pass2) { /*need file descrptr for reloc bits*/
rbuf.fildes = open(p,0,1);
rbuf.nunused = 0;
}
}
doseek(afd,aoff,apnam)
{
if(lseek(afd,(long)aoff,apnam) < 0) {
printf("seek error on file %s\n",ifilname);
exit();
}
}
readhdr()
{
register int i;
register short *p;
p = &couthd;
for(i=0; i<HDSIZE/2; i++)
*p++ = getw(&ibuf);
if(couthd.ch_magic != MAGIC) {
printf("file format error: %s\n",ifilname);
exit();
}
}
longseek(al,bp,pn)
long al;
struct buf *bp;
{
long l;
register b,o;
l = al>>9;
b = l.loword; /*block #*/
o = al.loword&0777; /*offset in block*/
doseek(bp->fildes,b,pn); /*seek to block*/
doseek(bp->fildes,o,SEEKREL); /*do offset*/
bp->nunused = 0; /*input buff empty*/
}

View File

@@ -0,0 +1 @@
$ clink as680,as681,as682,as683,as684,as685,as68inits,lib:klutz/lib as68/debug

View File

@@ -0,0 +1,33 @@
$ set def [steve.cpm68k.asmlink]
$ set noon
$ assign [-.asc] asc:
$ conv :== $bin:conv
$ lo68 -r -s -o ar68.out lib:startup.o ar68.o lib:lib6.a
$ conv
ar68.out
asc:ar68.asc
$ lo68 -r -s -o lo68.out lib:startup.o lo68.o lib:lib6.a
$ conv
lo68.out
asc:lo68.asc
$ lo68 -r -s -o nm68.out lib:startup.o nm68.o lib:lib6.a
$ conv
nm68.out
asc:nm68.asc
$ lo68 -r -s -o prtobj.out lib:startup.o prtobj.o lib:lib6.a
$ conv
prtobj.out
asc:prtobj.asc
$ lo68 -r -s -o sendc68.out lib:startup.o sendc68.o lib:lib6.a
$ conv
sendc68.out
asc:sendc68.asc
$ lo68 -r -s -o reloc.out lib:startup.o reloc.o lib:clib68.a
$ conv
reloc.out
asc:reloc.asc
$ lo68 -r -s -o dump.out lib:startup.o dump.o lib:lib6.a
$ conv
dump.out
asc:dump.asc
$ ! end

View File

@@ -0,0 +1,434 @@
/****************************************************************************/
/* */
/* R e l o c P r o g r a m */
/* ------------------------- */
/* */
/* This program is used to relocate an Alcyon format load module into */
/* an absolute module using the minimum disk space possible. The */
/* relocation information, symbol table, and trailing zeros in the */
/* data segment are deleted. */
/* */
/* Invokation: */
/* */
/* A>reloc -bhhhhhh in.68k out.68k */
/* */
/* Where: */
/* hhhhhh Is the desired new base address (TPA + 100) in hex */
/* in.68k Is the input file */
/* out.68k Is the output file */
/* */
/****************************************************************************/
#include <stdio.h>
#include <ctype.h>
/****************************************************************************/
/* */
/* The following code defines the organization of a "long" variable on */
/* either the VAX (11) or 68000. This allows us to use "getw" on the */
/* separate parts of the long and to recombine them for 32-bit */
/* arithmetic operations. */
/* */
/****************************************************************************/
#include "machine.h"
#ifdef UNIX
#include <portab.h>
#endif
#ifdef VAX /****************************/
struct { /* low word first on VAX */
WORD loword; /* */
WORD hiword; /* */
}; /****************************/
#endif
#ifdef PDP11 /****************************/
struct { /* low word first on PDP11 */
WORD loword; /* */
WORD hiword; /* */
}; /****************************/
#endif
#ifdef MC68000 /****************************/
struct { /* */
WORD hiword; /* High word first on 68K */
WORD loword; /* */
}; /****************************/
#endif
#ifdef UNIX /****************************/
#define fopenb fopen /* Not in UNIX library */
#endif /****************************/
/****************************************************************************/
/* */
/* Relocation bit definitions */
/* */
/* Note that this program is intended only for load module files. Any */
/* references to external symbols or relative references are illegal. */
/* */
/****************************************************************************/
/* */
#define DABS 0 /* Data absolute */
#define DRELOC 1 /* Data segment relative */
#define TRELOC 2 /* Text segment relative */
#define BRELOC 3 /* BSS segment relative */
#define EXTVAL 4 /* External variable */
#define LUPPER 5 /* Upper word of long */
#define EXTREL 6 /* External relative symbol */
#define INSABS 7 /* 1st word of instruction */
/****************************/
/****************************************************************************/
/* */
/* G l o b a l D a t a */
/* */
/****************************************************************************/
/* */
BYTE *ifname=0; /* -> Input filename */
BYTE *ofname=0; /* -> Output filename */
LONG base=0; /* New relocation base */
FILE *fopenb(); /* File open procedure */
LONG ftell(); /* File offset procedure */
#ifdef CPM /* Only defined with CP/M */
EXTERN BYTE _start; /* Start of program */
#endif /* */
/****************************/
#include "cout.h" /* Output header area */
/****************************/
/****************************************************************************/
/* */
/* M a i n P r o c e d u r e */
/* --------------------------- */
/* */
/* Here we get things started: */
/* */
/* 1). Get relocation base */
/* 2). Open input and output files */
/* 3). Determine data area (new) size */
/* */
/* Any errors here are fatal, and cause program termination. */
/* */
/****************************************************************************/
VOID main(argc,argv)
/****************************/
DEFAULT argc; /* Int var from RTL startup */
BYTE **argv; /* -> Arg strings */
{ /****************************/
REG LONG i,l; /* Temps */
REG FILE *ifp,*ofp,*rfp; /* File pointers */
/* */
if(argc != 4 && argc != 3) /* Gotta have right format */
usage(); /* Print out nasty message */
/****************************/
if(argc == 4) /* "-bxxxx" form */
{ /****************************/
if(decode(argv[1], &base) == FAILURE) /* Convert to binary */
{ /* */
printf("Illegal option: %s\n", /* Print offending option */
argv[1]); /* */
usage(); /* Print reminder messages */
} /****************************/
ifname = argv[2]; /* -> Input file name */
ofname = argv[3]; /* -> Output file name */
} else /* Default form */
{ /* */
#ifdef CPM /* On CP/M, */
base = &_start; /* Use start of reloc itself*/
#else /****************************/
base = 0x500; /* 500H is default */
#endif /* */
ifname = argv[1]; /* -> Input filename */
ofname = argv[2]; /* -> Output filename */
} /****************************/
/* */
if((base & 1) != 0) /* In range? */
{ /* no */
printf("Illegal base address=%lx\n", /* print */
base); /* message */
exit(-1); /* And quit */
} /****************************/
/* */
if((ifp=fopenb(ifname,"r")) == NULL) /* Try to open input */
{ /* */
printf("Cannot open %s\n",ifname); /* Complain */
exit(-1); /* & quit */
} /****************************/
/* */
if((ofp=fopenb(ofname,"w")) == NULL) /* Try to create output */
{ /* */
printf("Cannot create %s\n",ifname); /* Complain */
exit(-1); /* & quit */
} /****************************/
/****************************************************************************/
/* */
/* Now read the file header and compute the new data segment size ... */
/* */
/****************************************************************************/
/* */
i = fread(&couthd,1,(sizeof couthd), /* Do the read */
ifp); /* */
if(i != (sizeof couthd)) /* Did it work?? */
{ /* */
printf("Read error on %s\n",ifname); /* No, complain */
exit(-1); /* and quit */
} /****************************/
/* */
if(couthd.ch_magic != MAGIC) /* Valid file? */
{ /* */
printf("File format error: %s\n", /* Print nasty message */
ifname); /* */
exit(-1); /* Quit */
} /****************************/
/* */
l = couthd.ch_tsize + sizeof couthd; /* Seek address for data */
fseek(ifp,l,0); /* Seek to data start */
/* */
i = couthd.ch_dsize; /* Fetch data size */
l = ftell(ifp); /* l <= new data end addr */
/* */
while (i > 0) /* Until all data examined */
{ /* */
if(getw(ifp) != 0) /* This data word = 0? */
l = ftell(ifp); /* No, record seek address */
i -= 2; /* Down count */
} /****************************/
/****************************************************************************/
/* */
/* Open the file a second time, and perform the proper seeks to align */
/* one copy of the open file to the beginning of the text segment, and */
/* the other copy to the beginning of the relocation information */
/* */
/****************************************************************************/
/* */
if((rfp=fopenb(ifname,"r")) == NULL) /* Try to open again */
{ /* */
printf("Cannot re-open %s\n",ifname); /* Print nasty message */
exit(-1); /* and quit */
} /****************************/
fseek(ifp,(LONG)(sizeof couthd),0); /* Seek to text beginning */
fseek(rfp,(LONG)(sizeof couthd) + /* Seek to */
couthd.ch_tsize+couthd.ch_dsize + /* relocation */
couthd.ch_ssize, 0); /* info*/
/****************************/
reloc(ifp,rfp,ofp,l); /* Do relocation */
} /****************************/
/****************************************************************************/
/* */
/* U s a g e F u n c t i o n */
/* --------------------------- */
/* */
/* Routine "usage" is used to print out an error message when the */
/* program is invoked in an improper manner. */
/* */
/* Calling Sequence: */
/* */
/* usage(); */
/* */
/* No return is made, "exit()" is called to go back to the O/S. */
/* */
/****************************************************************************/
VOID usage()
{
printf("Usage: reloc [-bhhhhhh] input output\n");
printf(" where: hhhhhh is new base address\n");
printf(" (TPA+100 is default base address)\n");
printf(" input is relocatable file\n");
printf(" output is absolute file\n");
exit(-1);
}
/****************************************************************************/
/* */
/* D e c o d e F u n c t i o n */
/* ------------------------------ */
/* */
/* Routine "decode" is called to process the relocation base argument */
/* from the command line. */
/* */
/* Calling sequence: */
/* */
/* ret = decode(string,&address); */
/* */
/* Where: */
/* string -> argument string (usually argv[1]) */
/* &address -> long word to receive converted value */
/* */
/* ret = 0 if successful conversion */
/* = -1 if anything amiss */
/* */
/****************************************************************************/
WORD decode(string,addr) /* */
/* */
REG BYTE *string; /* -> Command argument */
LONG *addr; /* = return value */
{ /****************************/
REG LONG a; /* Temp return value */
REG BYTE c; /* Temp character */
/* */
if(*string++ != '-' || *string++ != 'b')/* Check for valid switch */
return(FAILURE); /* quit if NFG */
/* */
a = 0; /* Zero out accumulator */
/* */
while(*string) /* Until no more chars */
{ /* */
c = *string & 0177; /* Pick up next char */
if (c >= '0' && c <= '9') /* Digit */
a = (a << 4) + c - '0'; /* Un-ASCIIfy */
else if (c >= 'A' && c <= 'F') /* Hex */
a = (a << 4) + c - 'A'+ 10; /* Un-ASCIIfy */
else if (c >= 'a' && c <= 'f') /* Lower case hex */
a = (a << 4) + c - 'a'+ 10; /* Un-ASCII it */
else /* Bad character */
return(FAILURE); /* So long, sucker!! */
string++; /* Increment pointer */
} /* */
*addr = a; /* Store result */
return(SUCCESS); /* Return all ok */
} /****************************/
/****************************************************************************/
/* */
/* R e l o c F u n c t i o n */
/* --------------------------- */
/* */
/* Function "reloc" is called to perform the relocation operation and */
/* write the output file simultaneously. */
/* */
/* Calling Sequence: */
/* */
/* reloc(ifp,rfp,ofp,length); */
/* */
/* Where: */
/* */
/* ifp Is the input stream pointer (positioned at text) */
/* rfp Is a stream pointer positioned at relocation bits */
/* ofp Is a stream pointer for the output file */
/* length Is the total length of the output file */
/* */
/****************************************************************************/
VOID reloc(ifp,rfp,ofp,length) /* */
/* */
REG FILE *ifp; /* -> Text information */
REG FILE *rfp; /* -> Relocation info */
REG FILE *ofp; /* -> Output file */
LONG length; /* = # bytes in the file */
{ /****************************/
struct hdr x; /* Duplicate header */
REG LONG bytes; /* File offset */
LONG j; /* Temp for long relocation */
REG WORD r; /* Relocation word */
REG WORD k; /* Temp data word */
WORD longf; /* Long relocation flag */
WORD z; /* Temp for error codes */
LONG bias; /* Relocation bias */
/* */
bias = base - couthd.ch_entry; /* Compute relocation bias */
/* */
/************************************************* */
/* */
/* Prepare and write the new file header in structure "x". */
/* */
/************************************************* */
/* */
x.ch_magic = MAGIC; /* Magic word */
x.ch_tsize = couthd.ch_tsize; /* Text size */
j = sizeof couthd + couthd.ch_tsize + /* Compute number of bytes */
couthd.ch_dsize - length; /* moved from data to bss */
x.ch_dsize = couthd.ch_dsize - j; /* New data size */
x.ch_bsize = couthd.ch_bsize + j; /* New bss size */
x.ch_ssize = 0; /* No symbols */
x.ch_stksize = 0; /* No stack */
x.ch_entry = base; /* New base address */
x.ch_rlbflg = -1; /* No relocation bits */
/****************************/
if(fwrite(&x,1,sizeof x,ofp) != /* Do the write */
sizeof x) /* */
{ /* Here if failed */
printf("Write error on %s\n",ofname); /* print message */
exit(-1); /* Quit */
} /****************************/
/****************************************************************************/
/* */
/* Here begins the actual file relocation procedure. Read a word */
/* from the relocation bits and from the file together. If long, */
/* read another word from each. Perform indicated relocation. */
/* */
/****************************************************************************/
/* */
bytes = 0; /* No bytes written yet ... */
length -= sizeof(couthd); /* Just program, please... */
while (bytes < length) /* until we are done */
{ /****************************/
k = getw(ifp); /* get next text/data word */
r = getw(rfp); /* get next relocation word */
/****************************/
if ((r & ~7) != 0) /* Check for validity */
badrel(r,bytes); /* Not valid, quit */
/* */
if(r == LUPPER) /* Doing a long? */
{ /* */
j.hiword = k; /* Yes, get another word */
j.loword = getw(ifp); /* From both */
r = getw(rfp); /* streams */
longf = 2; /* Set flag */
} /****************************/
else /* Not a long */
{ /* */
j.loword = k; /* Put in low order word */
j.hiword = 0; /* Make top part 0 */
longf = 0; /* Clear flag */
} /****************************/
switch (r) /* Now do indicated reloc */
{ /* */
case TRELOC: /* If relocatable, */
case DRELOC: /* relocate */
case BRELOC: /* */
j += bias; /* Add in bias */
case DABS: /* If not relocatable, */
case INSABS: /* don't */
break; /****************************/
default: /* Any others illegal */
badrel(r,bytes); /* Print message */
} /****************************/
if(longf == 0 && j.hiword !=0) /* 16-bit overflow? */
{ /* */
printf("16-bit overflow at %ld\n", /* Print out message */
bytes); /* with offset */
exit(-1); /* */
} /****************************/
if(longf != 0) /* Long? */
putw(j.hiword,ofp); /* yes, output high */
#ifndef UNIX /* A bug in UNIX RTL!! */
if((z=putw(j.loword,ofp)) != j.loword) /* Check for write error */
{ /* */
printf("Write error on %s ",ofname); /* Had one, */
printf("Offset = %lx data= %x err =%x\n", /* */
bytes,j.loword,z); /* Print out message */
exit(-1); /* & quit */
} /****************************/
#else /* Just output and pray... */
putw(j.loword,ofp); /* Output low word */
#endif /****************************/
bytes += 2 + longf; /* Increment byte count */
/* */
} /* End while loop */
} /* End reloc procedure */
/****************************/
VOID badrel(r,offset) /* Print bad reloc message */
/* */
WORD r; /* Relocation bits */
LONG offset; /* File offset */
{ /****************************/
printf("Illegal reloc = %x at %lx\n", /* Print error message */
r,offset); /* */
exit(-1); /* quit */
} /****************************/

View File

@@ -0,0 +1,26 @@
$ set noon
$ vsend AR68.C
$ vsend DUMP.C
$ vsend GREP.C
$ vsend LIBFIX.C
$ vsend LO68.C
$ vsend LO68INIT.C
$ vsend NM68.C
$ vsend NUXI.C
$ vsend PRTOBJ.C
$ vsend RELOC.C
$ vsend SENDC68.C
$ vsend SIZE68.C
$ vsend TEST.C
$ vsend AR.H
$ vsend COUT.H
$ vsend CPM.H
$ vsend IOBUF.H
$ vsend LO68.H
$ vsend SENDC68.H
$ vsend MAKE.SUB
$ vsend MACHINE.11
$ vsend MACHINE.68K
$ vsend MACHINE.H
$ vsend MACHINE.VAX
$ vsend done

View File

@@ -0,0 +1,211 @@
#include "cout.h"
#include "sendc68.h"
/* this program reads a c.out format binary file and converts*/
/* it to the absolute ASCII load format acceptable by MACSBUG*/
/* and then sends it down the standard output file*/
#define MAGIC1 MAGIC+1
long lseek();
long datastart=0;
long bssstart=0;
long loctr=0;
extern int fout;
int pflg=0;
#define RBLEN 32 /*number of bytes per S1 record*/
int bcnt=RBLEN;
char cksum=0;
int syno=0;
char *ofn=0;
int ofd=0;
int noclear=0;
main(argc,argv)
char **argv;
{
long l,l1;
register i,j;
if(argc<2) {
printf("Usage: sendc68 [-] commandfile [outputfile]\n");
exit();
}
i = 1;
if(*argv[1] == '-') {
noclear++;
i++;
}
openfile(argv[i++]);
if(argc>i) {
ofn = argv[i]; /*tty device name*/
if((ofd=creat(ofn,0666,0)) < 0) {
printf("unable to create %s\n",ofn);
exit();
}
}
else {
ofd = dup(1); /*standard output file*/
}
fout = ofd; /*use buffered output*/
l1 = couthd.ch_tsize;
loctr = couthd.ch_entry;
mloop:
for(l=0; l<l1; l=+ 2) {
i = getw(&ibuf);
outword(i);
loctr =+ 2;
}
if(couthd.ch_magic==MAGIC1) {
while(bcnt != RBLEN) /*fill out the last S1 buffer*/
outword(0);
loctr = datastart;
}
l1 = couthd.ch_dsize;
for(l=0; l<l1; l=+ 2) {
i = getw(&ibuf);
outword(i);
loctr =+ 2;
}
if(noclear==0) {
if(couthd.ch_magic==MAGIC1) {
while(bcnt != RBLEN) /*fill out the last S1 buffer*/
outword(0);
loctr = bssstart;
}
l1 = couthd.ch_bsize; /*size of bss*/
while(l1 > 0) {
outword(0); /*clear the bss*/
l1 =- 2;
loctr =+ 2;
}
}
while(bcnt != RBLEN) /*fill out the last S1 buffer*/
outword(0);
printf("S9030000FC\n");
myflush();
}
openfile(ap)
char *ap;
{
register char *p;
p = ap;
if((ibuf.fildes=open(p,0,1)) < 0) {
printf("unable to open %s\n",p);
exit();
}
ifilname = p; /*point to current file name for error msgs*/
if(read(ibuf.fildes,&couthd,2) != 2) {
printf("read error on file: %s\n",ifilname);
exit();
}
ibuf.nunused = 0;
lseek(ibuf.fildes,0L,0);
readhdr(); /*read file header*/
}
readhdr()
{
register int i;
register short *p;
p = &couthd;
for(i=0; i<HDSIZE/2; i++)
*p++ = getw(&ibuf);
if(couthd.ch_magic != MAGIC) {
if(couthd.ch_magic==MAGIC1) {
#ifdef VAX
datastart.loword = getw(&ibuf);
datastart.hiword = getw(&ibuf);
bssstart.loword = getw(&ibuf);
bssstart.hiword = getw(&ibuf);
#endif
#ifdef PDP11
datastart.loword = getw(&ibuf);
datastart.hiword = getw(&ibuf);
bssstart.loword = getw(&ibuf);
bssstart.hiword = getw(&ibuf);
#endif
#ifdef MC68000
datastart.hiword = getw(&ibuf);
datastart.loword = getw(&ibuf);
bssstart.hiword = getw(&ibuf);
bssstart.loword = getw(&ibuf);
#endif
}
else {
printf("file format error: %s\n",ifilname);
exit();
}
}
}
longseek(al,bp,pn)
long al;
struct buf *bp;
{
if(lseek(bp->fildes,al,0) < 0) {
printf("seek error on file %s\n",ifilname);
exit();
}
bp->nunused = 0; /*input buff empty*/
}
outword(i)
register i;
{
if(bcnt==RBLEN) { /*beginning of record*/
cksum = 0;
if(loctr.hiword) {
printf("S2");
hexby(RBLEN+4);
hexby(loctr.hiword);
}
else {
printf("S1");
hexby(RBLEN+3); /*byte count*/
}
hexwd(loctr.loword);
}
hexwd(i);
bcnt =- 2;
if(bcnt==0) {
hexby(-cksum-1);
putchar('\n');
bcnt = RBLEN;
}
}
hexwd(i)
{
hexby((i>>8)&0xff);
hexby(i&0xff);
}
hexby(c)
{
cksum =+ c;
outhex((c>>4)&017);
outhex(c&017);
}
outhex(x)
{
if(x>=0 && x<=9)
putchar(x+'0');
else if(x>=10 && x<=15)
putchar(x-10+'A');
else
exit();
}

View File

@@ -0,0 +1,87 @@
/* format of a symbol entry in the main table*/
#include "machine.h"
#define SEEKREL 1 /*relative seek flag*/
#define OSTSIZE 14 /*symbol table entry length on object file*/
/* without table link*/
# define STESIZE 18 /*byte length of symbol table entry*/
struct symtab {
char name[8]; /*symbol name*/
short flags; /*bit flags*/
long vl1; /*symbol value*/
char *tlnk; /*table link*/
};
struct symtab *symptr;
/* flags for symbols*/
# define SYDF 0100000 /*defined*/
# define SYEQ 0040000 /*equated*/
# define SYGL 0020000 /*global - entry or external*/
# define SYER 0010000 /*equated register*/
# define SYXR 0004000 /*external reference*/
# define SYDA 0002000 /*DATA based relocatable*/
# define SYTX 0001000 /*TEXT based relocatable*/
# define SYBS 0000400 /*BSS based relocatable*/
struct irts {
char *irle; /*ptr to last entry in chain*/
char *irfe; /*ptr to first entry in chain*/
};
#ifdef VAX
struct {
short loword;
short hiword;
};
#endif
#ifdef PDP11
struct {
short loword;
short hiword;
};
#endif
#ifdef MC68000
struct {
short hiword;
short loword;
};
#endif
#ifdef VAX
struct {
char lobyte;
char hibyte;
};
#endif
#ifdef PDP11
struct {
char lobyte;
char hibyte;
};
#endif
#ifdef MC68000
struct {
char hibyte;
char lobyte;
};
#endif
/* relocation bit definitions:*/
#define RBMASK 07 /*tells type of relocation*/
#define INSABS 7 /*first word of instr -- absolute*/
#define DABS 0 /*data word absolute*/
#define TRELOC 2 /* TEXT relocatable*/
#define DRELOC 1 /* DATA relocatable*/
#define BRELOC 3 /* BSS relocatable*/
#define EXTVAR 4 /* ref to external variable*/
#define LUPPER 5 /* upper word of long*/
struct buf{
int fildes;
int nunused;
char *xfree;
char buff[512];
};
struct buf ibuf={0};
char *ifilname=0;

View File

@@ -0,0 +1,103 @@
#include "cout.h"
#define MAGIC1 MAGIC+1
int fd=0;
char *fn = {"c.out"};
main(argc,argv)
char **argv;
{
register i,j;
long l;
i = 1;
if(argc<2)
goto dodef;
for(i=1; i<argc; i++) {
fn = argv[i];
dodef:
if((fd=open(fn,0,1)) < 0) {
printf("unable to open %s\n",fn);
exit();
}
if((j=read(fd,&couthd,HDSIZE)) != HDSIZE) {
printf("read error on %s\n",fn);
exit();
}
if(couthd.ch_magic!=MAGIC && couthd.ch_magic!=MAGIC1) {
printf("File format error: %s\n",fn);
exit();
}
printf("%s:",fn);
l = couthd.ch_tsize+couthd.ch_dsize+couthd.ch_bsize;
ldec(couthd.ch_tsize);
putchar('+');
ldec(couthd.ch_dsize);
putchar('+');
ldec(couthd.ch_bsize);
putchar('=');
ldec(l);
printf(" (");
lhex(l);
printf(" ) stack size = ");
ldec(couthd.ch_stksize);
putchar('\n');
if(couthd.ch_magic == MAGIC1) {
read(fd,&l,4);
printf("data start=");
lhex(l);
read(fd,&l,4);
printf(" bss start=");
lhex(l);
putchar('\n');
}
}
}
char ostr[80] = {0};
lhex(al)
long al;
{
register i;
register char *p;
register j;
p = &ostr[80];
*--p = 0;
for(i=0; i<8; i++) {
j = al&017;
if(j<10)
j =+ '0';
else
j =+ 'A'-10;
*--p = j;
al =>> 4;
if(al == 0)
break;
}
printf("%s",p);
}
ldec(al)
long al;
{
register i;
register char *p;
register j;
p = &ostr[80];
*--p = 0;
for(i=0; i<10; i++) {
j = al%10;
j =+ '0';
*--p = j;
al =/ 10;
if(al == 0)
break;
}
printf("%s",p);
}

View File

@@ -0,0 +1,80 @@
/*****************************************************************************
*
* C P / M C H E A D E R F I L E
* -----------------------------------
*
* This is the standard include file for the CP/M-68K assembler / linker
* kludge package.
*
*****************************************************************************/
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define UBYTE unsigned char /* Unsigned byte */
#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 */
/***************************/
/* Open Mode Definitions */
/************************************/
#define READ 0 /* Open for READ only */
#define WRITE 1 /* Open for WRITE only */
#define IO 2 /* Open for READ and WRITE */
#define UPDATE 2 /* Same as IO */
/************************************/
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FILE struct ccb /* Define FILE pointer */
#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 0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
#define STDIN 0 /* File */
#define STDOUT 1 /* numbers */
#define STDERR 2 /* for std i/o */
/****************************************************************************/
/* */
/* M A C R O S */
/* ----------- */
/* */
/* Define some stuff as macros .... */
/* */
/****************************************************************************/
#define stdin (&_iob[0]) /* Standard input channel */
#define stdout (&_iob[1]) /* Standard output channel */
#define stderr (&_iob[2]) /* Standard error channel */
#define fileno(p) p->chan /* File # of a channel */
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
#define isalpha(c) (islower(c)||isupper(c)) /* true if "c" a letter */
#define isdigit(c) ('0' <= (c) && (c) <= '9') /* Ascii only!! */
#define islower(c) ('a' <= (c) && (c) <= 'z') /* Ascii only!! */
#define isupper(c) ('A' <= (c) && (c) <= 'Z') /* Ascii only!! */
#define iswhite(c) ((c) <= ' ' || 0177<= (c)) /* Is control / funny char */
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
#define tolower(c) (isupper(c) ? ((c)+040):(c)) /* translate to lower case */
#define toupper(c) (islower(c) ? ((c)-040):(c)) /* translate to upper case */
#define isatty(x) (((x)->flags & ISTTY) == 0 ? FALSE : TRUE)

View File

@@ -0,0 +1,6 @@
main()
{
long i;
for(i = -1L; i < 0; i--)
printf("i = %8lx\n",i);
}

View File

@@ -0,0 +1,10 @@
$ set def [steve.cpm68k.asmlink]
$ copy machine.vax machine.h
$ purge machine.h
$ cx ar68
$ cx lo68
$ cx lo68init
$ cx nm68
$ cx prtobj
$ cx sendc68
$ @vrelink

View File

@@ -0,0 +1,7 @@
$ delete ar68.exe;*,as68.exe;*,lo68.exe;*,nm68.exe;*,prtobj.exe;*
$ delete sendc68.exe;*
$ clink ar68,lib:klutz/lib ar68
$ clink lo68,lo68init,lib:klutz/lib lo68
$ clink nm68,lib:klutz/lib nm68
$ clink prtobj,lo68init,lib:klutz/lib prtobj
$ clink sendc68,lib:klutz/lib sendc68

View File

@@ -0,0 +1,174 @@
/********************************************************
* *
* 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. This type of variables is 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 arbit 2 /* archive 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
{
UBYTE kbchar; /* One byte keyboard type-ahead buffer */
UBYTE delim; /* Delimiter for function 9 */
BOOLEAN lstecho; /* True if echoing console output to lst: */
BOOLEAN echodel; /* Echo char when getting <del> ? */
UWORD column; /* CRT column number for expanding tabs */
UBYTE *chainp; /* Used for chain to program call */
UBYTE curdsk; /* Currently selected disk */
UBYTE dfltdsk; /* Default disk (last selected by fcn 14) */
UBYTE user; /* Current user number */
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 */
UWORD srchpos; /* position in directory for search next */
UBYTE *dmaadr; /* Disk dma address */
struct fcb *srchp; /* Pointer to search FCB for function 17 */
UBYTE *excvec[18]; /* Array of exception vectors */
};
/* Console buffer structure declaration */
struct conbuf
{
UBYTE maxlen; /* Maximum length from calling routine */
UBYTE retlen; /* Length actually found by BDOS */
UBYTE cbuf[]; /* Console data */
};

View File

@@ -0,0 +1,154 @@
*****************************************************************
* *
* CP/M-68K Basic Disk Operating System interface module *
* For "C" version of CP/M-68K *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
* Version 0.2 -- September 22, 1982 *
* *
*****************************************************************
* Declare Public Routines
.globl _bios1 * 6 BIOS entry points from BDOS
.globl _bios2
.globl _bios3
.globl _bios4
.globl _bios5
.globl _bios6
.globl _traphnd * trap #2 handler
.globl _swap * byte swapper
.globl _udiv * unsigned divide routine
* Declare external routines
.globl __bdos * BDOS entry point in bdosmain
* The following external references were put in just to make sure that all
* the BDOS modules were referenced, so we could put them in a library
.globl _constat * references conbdos.o
.globl _dirscan * references dskutil.o
.globl _create * references fileio.o
.globl _bdosrw * references bdosrw.o
biosf = 50
setsupf = 62
_traphnd:
*
* first save the registers and
* check for functions handled by assembly language routines
*
cmpi #setsupf,d0
beq setsup
movem.l d1-d7/a0-a6,-(sp)
cmpi #biosf,d0
beq bioscall
*
* function number is passed in D0
* byte and word pararmeters are passed in D1.W
* address parameters are passed in D1.L
*
move.l d1,-(a7)
move.w d1,-(a7)
move.w d0,-(a7)
jsr __bdos * call BDOS
*
* now restore the regs
*
ext.l d0
addq #8,sp * fix up the stack
bdone:
movem.l (sp)+,a0-a6/d1-d7
rte * return from trap call
*
* direct BIOS call function
*
bioscall:
move.l d1,a0 * get address of CPB
move.w (a0)+,d0
movem.l (a0)+,d1-d2
trap #3
bra bdone
*
* Set supervisor mode procedure
*
setsup:
ori #$2000,(sp) * turn on supervisor bit in SR
rte
*
* BIOS Interface Routines
*
*
* Note - there are 6 BIOS entry points from the BDOS, labelled BIOS1 -
* BIOS6, 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)
_bios6:
_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)
* * save C register variables
trap #3 * do BIOS call
* * returns value in d0
movem.l (sp)+,d3-d7/a3-a6
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 routine
* returns unsigned quotient in D0.W
* UWORD udiv( divisor, dividend, remp )
*
* REG LONG divisor;
* UWORD dividend;
* UWORD *remp /* pointer to remainder (returned) */
move.l 4(sp), d0 * get dividend
divu 8(sp), d0 * do the divide
movea.l 10(sp),a0
swap d0
move.w d0, (a0) * store remainder
clr.w d0
swap d0 * word quotient in d0
rts
.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,304 @@
/****************************************************************
* *
* CP/M-68K BDOS Main Routine *
* *
* This is the main routine for the BDOS for CP/M-68K *
* It has one entry point, _bdos, which is called from *
* the assembly language trap handler found in bdosif.s. *
* The parameters are a function number (integer) and an *
* information parameter (which is passed from bdosif as *
* both an integer and a pointer).
* The BDOS can potentially return a pointer, long word, *
* or word *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
/* Declare EXTERN functions */
EXTERN warmboot(); /* Warm Boot function */
EXTERN BOOLEAN constat(); /* Console status */
EXTERN UBYTE conin(); /* Console Input function */
EXTERN tabout(); /* Console output with tab expansion */
EXTERN UBYTE rawconio(); /* Raw console I/O */
EXTERN prt_line(); /* Print line until delimiter */
EXTERN readline(); /* Buffered console read */
EXTERN seldsk(); /* Select disk */
EXTERN BOOLEAN openfile(); /* Open File */
EXTERN UWORD close_fi(); /* Close File */
EXTERN UWORD search(); /* Search first and next fcns */
EXTERN UWORD dirscan(); /* General directory scanning routine */
EXTERN UWORD bdosrw(); /* Sequential and Random disk read/write */
EXTERN BOOLEAN create(); /* Create file */
EXTERN BOOLEAN delete(); /* Delete file */
EXTERN BOOLEAN rename(); /* Rename file */
EXTERN BOOLEAN set_attr(); /* Set file attributes */
EXTERN getsize(); /* Get File Size */
EXTERN setran(); /* Set Random Record */
EXTERN free_sp(); /* Get Disk Free Space */
EXTERN UWORD flushit(); /* Flush Buffers */
EXTERN UWORD pgmld(); /* Program Load */
EXTERN UWORD setexc(); /* Set Exception Vector */
EXTERN set_tpa(); /* Get/Set TPA Limits */
EXTERN move(); /* general purpose byte mover */
/* Declare "true" global variables; i.e., those which will pertain to the
entire file system and thus will remain global even when this becomes
a multi-tasking file system */
GLOBAL UWORD log_dsk; /* 16-bit vector of logged in drives */
GLOBAL UWORD ro_dsk; /* 16-bit vector of read-only drives */
GLOBAL UWORD crit_dsk; /* 16-bit vector of drives in "critical"
state. Used to control dir checksums */
GLOBAL BYTE *tpa_lp; /* TPA lower boundary (permanent) */
GLOBAL BYTE *tpa_lt; /* TPA lower boundary (temporary) */
GLOBAL BYTE *tpa_hp; /* TPA upper boundary (permanent) */
GLOBAL BYTE *tpa_ht; /* TPA upper boundary (temporary) */
/* 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;
struct tempstr
{
UBYTE tempdisk;
BOOLEAN reselect;
struct fcb *fptr;
};
/****************************************************************
* *
* _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 */
{
REG UWORD rtnval;
LOCAL struct tempstr temp;
BSETUP
temp.reselect = FALSE;
temp.fptr = infop;
rtnval = 0;
switch (func) /* switch on function number */
{
case 0: warmboot(0); /* warm boot function */
/* break; */
case 1: return((UWORD)conin()); /* console input function */
/* break; */
case 2: tabout((UBYTE)info); /* console output with */
break; /* tab expansion */
case 3: return((UWORD)brdr()); /* get reader from bios */
/* break; */
case 4: bpun((UBYTE)info); /* punch output to bios */
break;
case 5: blstout((UBYTE)info); /* list output from bios */
break;
case 6: return((UWORD)rawconio(info)); /* raw console I/O */
/* break; */
case 7: return(bgetiob()); /* get i/o byte */
/* break; */
case 8: bsetiob(info); /* set i/o byte function */
break;
case 9: prt_line(infop); /* print line function */
break;
case 10: readline(infop); /* read buffered con input */
break;
case 11: return((UWORD)constat()); /* console status */
/* break; */
case 12: return(VERSION); /* return version number */
/* break; */
case 13: log_dsk = 0; /* reset disk system */
ro_dsk = 0;
crit_dsk= 0;
GBL.curdsk = 0xff;
GBL.dfltdsk = 0;
break;
case 14: seldsk((UBYTE)info); /* select disk */
GBL.dfltdsk = (UBYTE)info;
break;
case 15: tmp_sel(&temp); /* open file */
infop->extent = 0;
infop->s2 = 0;
rtnval = dirscan(openfile, infop, 0);
break;
case 16: tmp_sel(&temp); /* close file */
rtnval = close_fi(infop);
break;
case 17: GBL.srchp = infop; /* search first */
rtnval = search(infop, 0, &temp);
break;
case 18: infop = GBL.srchp; /* search next */
temp.fptr = infop;
rtnval = search(infop, 1, &temp);
break;
case 19: tmp_sel(&temp); /* delete file */
rtnval = dirscan(delete, infop, 2);
break;
case 20: tmp_sel(&temp); /* read sequential */
rtnval = bdosrw(infop, TRUE, 0);
break;
case 21: tmp_sel(&temp); /* write sequential */
rtnval = bdosrw(infop, FALSE, 0);
break;
case 22: tmp_sel(&temp); /* create file */
infop->extent = 0;
infop->s1 = 0;
infop->s2 = 0;
infop->rcdcnt = 0;
/* Zero extent, S1, S2, rcrdcnt. create zeros rest */
rtnval = dirscan(create, infop, 8);
break;
case 23: tmp_sel(&temp); /* rename file */
rtnval = dirscan(rename, infop, 2);
break;
case 24: return(log_dsk); /* return login vector */
/* break; */
case 25: return(UBWORD(GBL.dfltdsk)); /* return current disk */
/* break; */
case 26: GBL.dmaadr = infop; /* set dma address */
break;
/* No function 27 -- Get Allocation Vector */
case 28: ro_dsk |= 1<<GBL.dfltdsk; /* set disk read-only */
break;
case 29: return(ro_dsk); /* get read-only vector */
/* break; */
case 30: tmp_sel(&temp); /* set file attributes */
rtnval = dirscan(set_attr, infop, 2);
break;
case 31: if (GBL.curdsk != GBL.dfltdsk) seldsk(GBL.dfltdsk);
move( (GBL.parmp), infop, sizeof *(GBL.parmp) );
break; /* return disk parameters */
case 32: if ( (info & 0xff) <= 15 ) /* get/set user number */
GBL.user = (UBYTE)info;
return(UBWORD(GBL.user));
/* break; */
case 33: tmp_sel(&temp); /* random read */
rtnval = bdosrw(infop, TRUE, 1);
break;
case 34: tmp_sel(&temp); /* random write */
rtnval = bdosrw(infop, FALSE, 1);
break;
case 35: tmp_sel(&temp); /* get file size */
getsize(infop);
break;
case 36: tmp_sel(&temp); /* set random record */
setran(infop);
break;
case 37: info = ~info; /* reset drive */
log_dsk &= info;
ro_dsk &= info;
crit_dsk &= info;
break;
case 40: tmp_sel(&temp); /* write random with 0 fill */
rtnval = bdosrw(infop, FALSE, 2);
break;
case 46: free_sp(info); /* get disk free space */
break;
case 47: GBL.chainp = GBL.dmaadr; /* chain to program */
warmboot(0); /* terminate calling program */
/* break; */
case 48: return( flushit() ); /* flush buffers */
/* break; */
case 59: return(pgmld(infop,GBL.dmaadr)); /* program load */
/* break; */
case 61: return(setexc(infop)); /* set exception vector */
/* break; */
case 63: set_tpa(infop); /* get/set TPA limits */
break;
default: return(-1); /* bad function number */
/* break; */
}; /* end of switch statement */
if (temp.reselect) infop->drvcode = temp.tempdisk;
/* if reselected disk, restore it now */
return(rtnval); /* return the BDOS return value */
} /* end _bdos */
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
REG struct tempstr *temptr;
{
REG struct fcb *fcbp;
REG UBYTE tmp_dsk;
BSETUP
fcbp = temptr->fptr; /* get local copy of fcb pointer */
tmp_dsk = (temptr->tempdisk = fcbp->drvcode);
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
fcbp->drvcode = GBL.user;
temptr->reselect = TRUE;
}

View File

@@ -0,0 +1,307 @@
/****************************************************************
* *
* CP/M-68K BDOS Miscellaneous Module *
* *
* This module contains miscellaneous loose ends for *
* CP/M-68K. Included are: *
* *
* bdosinit() - BDOS initialization routine *
* called from CCP for system init *
* warmboot() - BDOS warm boot exit routine *
* error() - BDOS error printing routine *
* ro_err() - BDOS read-only file error routine *
* setexc() - BDOS set exception vector *
* set_tpa() - BDOS get/set TPA limits *
* serial # and copyright notice, machine readable *
* *
* *
* Configured for Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
/* serial # and copyright notice */
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright (c) 1983, Digital Research";
char *serial="XXXX-0000-654321";
/* Declare external functions */
EXTERN conout(); /* Console Output function */
EXTERN UBYTE conin(); /* Console Input function */
EXTERN prt_line(); /* Print String function */
EXTERN UWORD _bdos(); /* BDOS main routine */
EXTERN UBYTE *traphndl(); /* assembly language trap handler */
EXTERN initexc(); /* init the exception handler in */
/* exceptn.s */
EXTERN UWORD dirscan(); /* Directory scanning routine */
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
EXTERN UWORD dir_rd(); /* Read directory sector 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 critical disks */
EXTERN BYTE *tpa_lt; /* TPA lower limit (temporary) */
EXTERN BYTE *tpa_lp; /* TPA lower limit (permanent) */
EXTERN BYTE *tpa_ht; /* TPA upper limit (temporary) */
EXTERN BYTE *tpa_hp; /* TPA upper limit (permanent) */
EXTERN BOOLEAN submit; /* external variables from CCP */
EXTERN BOOLEAN morecmds;
#define trap2v 34 /* trap 2 vector number */
#define ctrlc 3 /* control-c */
/********************************
* bdos initialization routine *
********************************/
bdosinit()
/* Initialize the File System */
{
REG struct
{
WORD nmbr;
BYTE *low;
LONG length;
} *segp;
BSETUP
bsetvec(trap2v, &traphndl); /* set up trap vector */
GBL.kbchar = 0; /* initialize the "global" variables */
GBL.delim = '$';
GBL.lstecho = FALSE;
GBL.echodel = TRUE;
GBL.chainp = NULL;
_bdos(13); /* reset disk system function */
segp = bgetseg(); /* get pointer to memory segment table */
tpa_lt = tpa_lp = segp->low;
tpa_ht = tpa_hp = tpa_lp + segp->length;
initexc( &(GBL.excvec[0]) );
}
/************************
* warmboot entry point *
************************/
warmboot(parm)
/* Warm Boot the system */
WORD parm; /* 1 to reset submit flag */
{
BSETUP
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
/* note that this code is specifically for a single-
thread system. It won't work in a multi-task sys */
ro_dsk = 0;
crit_dsk = 0;
if (parm)
submit = morecmds = FALSE;
GBL.curdsk = 0xff; /* set current disk to "unknown" */
tpa_lt = tpa_lp;
tpa_ht = tpa_hp;
initexc( &(GBL.excvec[0]) );
bwboot();
}
/*************************/
/* disk error handlers */
/*************************/
prt_err(p)
/* print the error message */
BYTE *p;
{
BSETUP
prt_line(p);
prt_line(" error on drive $");
conout(GBL.curdsk + 'A');
}
abrt_err(p)
/* print the error message and always abort */
BYTE *p;
{
prt_err(p);
warmboot(1);
}
ext_err(cont,p)
/* print the error message, and allow for retry, abort, or ignore */
REG BOOLEAN cont; /* Boolean for whether continuing is allowed */
BYTE *p; /* pointer to error message */
{
REG UBYTE ch;
prt_err(p);
do
{
prt_line("\n\rDo you want to: Abort (A), Retry (R)$");
if (cont) prt_line(", or Continue with bad data (C)$");
prt_line("? $");
ch = conin() & 0x5f;
prt_line("\r\n$");
switch ( ch )
{
case ctrlc: warmboot(1);
case 'A': warmboot(1);
case 'C': if (cont) return(1);
break;
case 'R': return(0);
}
} while (TRUE);
}
/********************************/
/* Read-only File Error Routine */
/********************************/
ro_err(fcbp,dirindx)
/* File R/O error */
REG struct fcb *fcbp;
WORD dirindx;
{
REG BYTE *p;
REG UWORD i;
REG UBYTE ch;
p = (BYTE *)fcbp;
prt_line("CP/M Disk file error: $");
i = 8;
do conout(*++p & 0x7f); while (--i);
conout('.');
i = 3;
do conout(*++p & 0x7f); while (--i);
prt_line(" is read-only.$");
do
{
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
ch = conin() & 0x5f;
prt_line("\r\n$");
switch ( ch )
{
case ctrlc: warmboot(1);
case 'A': warmboot(1);
case 'C': fcbp->ftype[robit] &= 0x7f;
dirscan(set_attr, fcbp, 2);
return(dir_rd(dirindx >> 2));
} /* Reset the directory buffer !!!! */
} while (TRUE);
}
/************************
* error entry point *
************************/
error(errnum)
/* Print error message, do appropriate response */
UWORD errnum; /* error number */
{
BSETUP
prt_line("\r\nCP/M Disk $");
switch (errnum)
{
case 0: return( ext_err(TRUE,"read$") );
/* break; */
case 1: return( ext_err(TRUE,"write$") );
/* break; */
case 2: abrt_err("select$");
/* break; */
case 3: return( ext_err(FALSE,"select$") );
/* break; */
case 4: abrt_err("change$");
/* break; */
}
}
/*****************************
* set exception entry point *
*****************************/
setexc(epbp)
/* Set Exception Vector */
REG struct
{
WORD vecnum;
BYTE *newvec;
BYTE *oldvec;
} *epbp;
{
REG WORD i;
BSETUP
i = epbp->vecnum-2;
if ( i==32 || i==33) return(-1);
if ( (30 <= i) && (i <= 37) ) i -= 20;
else if ( (i < 0) || (i > 9) ) return(255);
epbp->oldvec = GBL.excvec[i];
GBL.excvec[i] = epbp->newvec;
return(0);
}
/*****************************
* get/set TPA entry point *
*****************************/
set_tpa(p)
/* Get/Set TPA Limits */
REG struct
{
UWORD parms;
BYTE *low;
BYTE *high;
} *p;
#define set 1
#define sticky 2
{
if (p->parms & set)
{
tpa_lt = p->low;
tpa_ht = p->high;
if (p->parms & sticky)
{
tpa_lp = tpa_lt;
tpa_hp = tpa_ht;
}
}
else
{
p->low = tpa_lt;
p->high = tpa_ht;
}
}

View File

@@ -0,0 +1,314 @@
/****************************************************************
* *
* 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: *
* *
* bdosrw() - sequential and random disk I/O *
* *
* *
* Compiled with Alcyon C on the VAX *
* *
****************************************************************/
#include "bdosinc.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
/* External function definitions */
EXTERN UWORD rdwrt(); /* disk read/write routine */
EXTERN WORD getaloc(); /* allocate a block of disk space */
EXTERN WORD swap(); /* assembly language byte swapper */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
EXTERN UWORD close_fi(); /* close file function */
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
EXTERN UWORD ro_err(); /* read-only file error handler */
/* External variable definitions */
EXTERN UWORD ro_dsk; /* read-only disk vector */
/**********************************************************/
/* 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]) );
}
setblk(fcbp, index, wrdfcb, block)
/* put block number into fcb */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words */
REG UWORD block; /* block number */
{
fcbp->s2 &= 0x7f; /* set file write flag */
if (wrdfcb)
fcbp->dskmap.big[index] = swap(block);
else fcbp->dskmap.small[index] = (UBYTE)block;
}
/***************************
* disk read/write routine *
***************************/
UWORD do_io(block, rcrd, parm)
UWORD block; /* block number */
UBYTE rcrd; /* record number */
REG WORD parm; /* write parameter */
{
REG LONG lsec;
REG struct dpb *dparmp;
BSETUP
dparmp = GBL.parmp; /* init dpb pointer */
lsec = ((LONG)block << (dparmp->bsh)) +
(LONG)(rcrd & (dparmp->blm));
return( rdwrt(lsec, GBL.dmaadr, parm) );
}
/*******************************************
* routine for crossing extent boundaries *
*******************************************/
WORD new_ext(fcbp, reading, ran)
/* If sequential I/O, open the next extent */
/* If random I/O, compute new extent from random record field */
REG struct fcb *fcbp; /* pointer to fcb */
BOOLEAN reading; /* read/write flag */
WORD ran; /* random I/O flag */
{
REG UBYTE mod; /* module number */
REG UBYTE ext; /* extent number */
REG UBYTE t_mod; /* temp mod number */
REG UBYTE t_ext; /* temp extent */
BSETUP
if (ran)
{
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
ext = ( ((fcbp->ran1) & 0x0f) << 1);
if ((fcbp->ran2) & 0x80) ext |= 1;
/* the calculation of ext was coded this way because of a */
/* compiler bug from Alcyon */
}
else
{
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 one */
if ( close_fi(fcbp) >= 255 ) return(3);
/* can't close old extent */
t_mod = fcbp->s2;
t_ext = fcbp->extent;
fcbp->s2 = mod;
fcbp->extent = ext;
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open extent */
{
if (reading)
{ /* reading unwritten extent */
fcbp->s2 = t_mod;
fcbp->extent = t_ext;
return(4);
}
if ( dirscan(create, fcbp, 8) >= 255 )
return(5); /* can't create new 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 */
}
/************************
* bdosrw entry point *
************************/
UWORD bdosrw(fcbp, reading, random)
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
REG BOOLEAN reading; /* boolean to tell whether to read or write */
WORD random; /* 0 = sequential, 1 = random (normal), */
/* 2 = random with zero fill */
{
REG UWORD block; /* block number from fcb */
REG WORD index; /* index into disk map of fcb */
REG BYTE *old_dma; /* temp holding spot for dmaadr */
REG WORD parm; /* parameter to do-io */
REG WORD bigfile; /* file system is in word mode */
REG UWORD rtn; /* return parameter */
REG UBYTE rc; /* temp storage for rcdcnt */
BSETUP
bigfile = ((GBL.parmp)->dsm) & ~0xff;
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) )
ro_err(fcbp,((GBL.dpbp)->dpbp)->drm);
/* check for read-only file */
if (random)
{
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
/* open new extent if necessary, return if error */
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
}
else /* sequential */
if (fcbp->cur_rec == 128)
{ /* time to try next extent */
if ( new_ext(fcbp, reading, FALSE) )
return(1); /* if can't open new extent, error */
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
}
/* record is now in active fcb */
rc = fcbp->rcdcnt;
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
{
if (reading) return(1); /* reading unwritten data */
fcbp->s2 &= 0x7f; /* set file write flag */
rc = fcbp->cur_rec + 1;
}
index = blkindx(fcbp); /* get index into fcb disk map */
block = blknum(fcbp, index, bigfile);
if (block) parm = (reading ? 0 : 1);
else /* if allocated block, parm is just read or write */
{ /* unallocated block */
if (reading) return(1); /* reading unwritten data */
/* Writing to new block */
/* The parm passed to getaloc is the previously allocated block */
/* or 0, if the previous block is not allocated */
block = getaloc(blknum(fcbp, (index ? (index - 1) : 0), bigfile));
if (block == ~0) return(2); /* out of space */
setblk(fcbp, index, bigfile, block);
parm = 3;
if (random == 2)
{ /* Write random with zero fill */
old_dma = GBL.dmaadr;
GBL.dmaadr = GBL.dirbufp; /* Do DMA from dir_buf */
index = SECLEN;
do GBL.dmaadr[--index] = 0;
while (index); /* zero the dma buffer */
for (index = 0; index <= ((GBL.parmp)->blm); index++)
{
do_io(block, (UBYTE)index, parm);
/* write zeros to the block */
parm = 1; /* next write is not to new block */
}
GBL.dmaadr = old_dma; /* restore dma address */
}
}
rtn = do_io(block, fcbp->cur_rec, parm);
if ( rtn == 0 )
{
fcbp->rcdcnt = rc;
if ( ! random ) fcbp->cur_rec += 1;
}
return(rtn);
}

View File

@@ -0,0 +1,46 @@
/********************************************************
* *
* 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 */
EXTERN BYTE *bios6(); /* for get memory segment table */
#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() bios6(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,332 @@
/********************************************************
* *
* CP/M-68K BDOS Character I/O Routines *
* *
* This module does BDOS functions 1 thru 11 *
* *
* It contains the following functions which *
* are called from the BDOS main routine: *
* constat(); *
* conin(); *
* tabout(); *
* rawconio(); *
* prt_line(); *
* readline(); *
* *
* Copyright (c) 1982 Digital Research, Inc. *
* *
********************************************************/
#include "bdosinc.h"
#include "bdosdef.h"
#include "biosdef.h"
#define ctrlc 0x03
#define ctrle 0x05
#define ctrlp 0x10
#define ctrlq 0x11
#define ctrlr 0x12
#define ctrls 0x13
#define ctrlu 0x15
#define ctrlx 0x18
#define cr 0x0d
#define lf 0x0a
#define tab 0x09
#define rub 0x7f
#define bs 0x08
#define space 0x20
EXTERN warmboot(); /* External function definition */
/******************/
/* console status */
/******************/
BOOLEAN constat()
{
BSETUP
return( GBL.kbchar ? TRUE : bconstat() );
}
/********************/
/* check for ctrl/s */
/* used internally */
/********************/
conbrk()
{
REG UBYTE ch;
REG BOOLEAN stop;
BSETUP
stop = FALSE;
if ( bconstat() ) do
{
if ( (ch = bconin()) == ctrlc ) warmboot(1);
if ( ch == ctrls ) stop = TRUE;
else if (ch == ctrlq) stop = FALSE;
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
else GBL.kbchar = ch;
} while (stop);
}
/******************/
/* console output */
/* used internally*/
/******************/
conout(ch)
REG UBYTE ch;
{
BSETUP
conbrk(); /* check for control-s break */
bconout(ch); /* output character to console */
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
if (ch >= ' ') GBL.column++; /* keep track of screen column */
else if (ch == cr) GBL.column = 0;
else if (ch == bs) GBL.column--;
}
/*************************************/
/* console output with tab expansion */
/*************************************/
tabout(ch)
REG UBYTE ch; /* character to output to console */
{
BSETUP
if (ch == tab) do
conout(' ');
while (GBL.column & 7);
else conout(ch);
}
/*******************************/
/* console output with tab and */
/* control character expansion */
/*******************************/
cookdout(ch)
REG UBYTE ch; /* character to output to console */
{
if (ch == tab) tabout(ch); /* if tab, expand it */
else
{
if ( (UWORD)ch < (UWORD)' ' )
{
conout( '^' );
ch |= 0x40;
}
conout(ch); /* output the character */
}
}
/*****************/
/* console input */
/*****************/
UBYTE getch() /* Get char from buffer or bios */
/* For internal use only */
{
REG UBYTE temp;
BSETUP
temp = GBL.kbchar; /* get buffered char */
GBL.kbchar = 0; /* clear it */
return( temp ? temp : bconin() ); /* if non-zero, return it */
/* else get char from bios */
}
UBYTE conin() /* BDOS console input function */
{
REG UBYTE ch;
BSETUP
conout( ch = getch() );
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
return(ch);
}
/******************
* raw console i/o *
******************/
UBYTE rawconio(parm) /* BDOS raw console I/O function */
REG UWORD parm;
{
BSETUP
if (parm == 0xff) return(getch());
else if (parm == 0xfe) return(constat());
else bconout(parm & 0xff);
}
/****************************************************/
/* print line up to delimiter($) with tab expansion */
/****************************************************/
prt_line(p)
REG UBYTE *p;
{
BSETUP
while( *p != GBL.delim ) tabout( *p++ );
}
/**********************************************/
/* read line with editing and bounds checking */
/**********************************************/
/* Two subroutines first */
newline(startcol)
REG UWORD startcol;
{
BSETUP
conout(cr); /* go to new line */
conout(lf);
while(startcol)
{
conout(' ');
startcol -= 1; /* start output at starting column */
}
}
backsp(bufp, col)
/* backspace one character position */
REG struct conbuf *bufp; /* pointer to console buffer */
REG WORD col; /* starting console column */
{
REG UBYTE ch; /* current character */
REG WORD i;
REG UBYTE *p; /* character pointer */
BSETUP
if (bufp->retlen) --(bufp->retlen);
/* if buffer non-empty, decrease it by 1 */
i = UBWORD(bufp->retlen); /* get new character count */
p = &(bufp->cbuf[0]); /* point to character buffer */
while (i--) /* calculate column position */
{ /* across entire char buffer */
ch = *p++; /* get next char */
if ( ch == tab )
{
col += 8;
col &= ~7; /* for tab, go to multiple of 8 */
}
else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
/* control chars put out 2 printable chars */
else col += 1;
}
while (GBL.column > col)
{
conout(bs); /* backspace until we get to proper column */
conout(' ');
conout(bs);
}
}
readline(p) /* BDOS function 10 */
REG struct conbuf *p;
{
REG UBYTE ch;
REG UWORD i;
REG UWORD j;
REG UBYTE *q;
UWORD stcol;
BSETUP
stcol = GBL.column; /* set up starting column */
if (GBL.chainp != NULL) /* chain to program code */
{
i = UBWORD(*(GBL.chainp++));
j = UBWORD(p->maxlen);
if (j < i) i = j; /* don't overflow console buffer! */
p->retlen = (UBYTE)i;
q = p->cbuf;
while (i)
{
cookdout( *q++ = *(GBL.chainp++) );
i -= 1;
}
GBL.chainp = NULL;
return;
}
p->retlen = 0; /* start out with empty buffer */
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
{ /* main loop for read console buffer */
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
{
cookdout(ctrlc);
warmboot(1);
}
else if ( (ch == cr) || (ch == lf) )
{ /* if cr or lf, exit */
conout(cr);
break;
}
else if (ch == bs) backsp(p, stcol); /* backspace */
else if (ch == rub) /* delete character */
{
if (GBL.echodel)
{
if (p->retlen)
{
i = UBWORD(--(p->retlen));
conout( p->cbuf[i] );
}
}
else backsp(p, stcol);
}
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
/* control-p */
else if (ch == ctrlx) /* control-x */
do backsp(p,stcol); while (p->retlen);
else if (ch == ctrle) newline(stcol); /* control-e */
else if (ch == ctrlu) /* control-u */
{
conout('#');
newline(stcol);
p->retlen = 0;
}
else if (ch == ctrlr) /* control-r */
{
conout('#');
newline(stcol);
for (i=0; i < UBWORD(p->retlen); i++)
cookdout( p->cbuf[i] );
}
else /* normal character */
cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
}
}

View File

@@ -0,0 +1,41 @@
The following is a list of the modules that form the BDOS for the
C language version of CP/M-68K:
SOURCE FILES
bdosif.s - assembly language interface, trap handler,
BIOS caller, function 62 (set supervisor)
conbdos.c - BDOS functions 1 thru 11 (console functions)
bdosmisc.c - BDOS initialization, warmboot, error handler, set exception,
(used for miscellaneous BDOS routines)
dskutil.c - bit map handlers, directory read & write, dirscan
(miscellaneous disk handling utilities)
fileio.c - all file handling calls except read & write
includes open, close, delete, rename, etc.
bdosrw.c - sequential and random read & write
bdosmain.c - the BDOS case statement, global variable declarations
iosys.c - packet I/O to BIOS interface
pgmld.s - program load (function 59)
exceptn.s - exception handler
INCLUDE FILES
bdosinc.h - standard i/o stuff, universal declarations
bdosdef.h - BDOS data structure declarations
biosdef.h - procedure declarations to interface to BIOS
pktio.h - definition of data structure for packet I/O

View File

@@ -0,0 +1,15 @@
$ set noon
$ diff BDOSMAIN.C drb1:[cpm68k.beta2.bdos]BDOSMAIN.C
$ diff BDOSMISC.C drb1:[cpm68k.beta2.bdos]BDOSMISC.C
$ diff BDOSRW.C drb1:[cpm68k.beta2.bdos]BDOSRW.C
$ diff CONBDOS.C drb1:[cpm68k.beta2.bdos]CONBDOS.C
$ diff DSKUTIL.C drb1:[cpm68k.beta2.bdos]DSKUTIL.C
$ diff FILEIO.C drb1:[cpm68k.beta2.bdos]FILEIO.C
$ diff IOSYS.C drb1:[cpm68k.beta2.bdos]IOSYS.C
$ diff BDOSIF.S drb1:[cpm68k.beta2.bdos]BDOSIF.S
$ diff EXCEPTN.S drb1:[cpm68k.beta2.bdos]EXCEPTN.S
$ diff PGMLD.S drb1:[cpm68k.beta2.bdos]PGMLD.S
$ diff BDOSDEF.H drb1:[cpm68k.beta2.bdos]BDOSDEF.H
$ diff BDOSINC.H drb1:[cpm68k.beta2.bdos]BDOSINC.H
$ diff BIOSDEF.H drb1:[cpm68k.beta2.bdos]BIOSDEF.H
$ diff PKTIO.H drb1:[cpm68k.beta2.bdos]PKTIO.H

View File

@@ -0,0 +1,297 @@
/****************************************************************
* *
* CP/M-68K 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 *
* setaloc() - set bit in allocation vector *
* clraloc() - clear bit in allocation vector *
* getaloc() - get free allocation block *
* dchksum() - directory checksum calculator *
* dir_rd() - read directory sector *
* dir_wr() - write directory sector *
* rdwrt() - read/write disk sector *
* *
* *
* Configured for 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 functions and variables */
EXTERN UWORD do_phio(); /* external physical disk I/O routine */
EXTERN UWORD error(); /* external error routine */
EXTERN UWORD log_dsk; /* logged-on disk vector */
EXTERN UWORD ro_dsk; /* read-only disk vector */
EXTERN UWORD crit_dsk; /* critical disk vector */
/**********************
* read/write routine *
**********************/
UWORD rdwrt(secnum, dma, parm)
/* General disk sector read/write 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 */
REG WORD parm; /* 0 for read, write parm + 1 for write */
{
struct iopb rwpkt;
BSETUP
rwpkt.devnum = GBL.curdsk; /* disk to read/write */
if (parm)
{
rwpkt.iofcn = (BYTE)write; /* if parm non-zero, we're doing a write */
rwpkt.ioflags = (BYTE)(parm-1); /* pass write parm */
if ( ro_dsk & (1 << (rwpkt.devnum)) ) error(4);
/* don't write on read-only disk */
}
else
{
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.devtype = disk;
rwpkt.xferlen = 1;
*/
rwpkt.infop = GBL.dphp; /* pass ptr to dph */
while ( do_phio(&rwpkt) )
if ( error( parm ? 1 : 0 ) ) break;
return(0);
}
/***************************
* directory read routine *
***************************/
UWORD dir_rd(secnum)
WORD secnum;
{
BSETUP
return( rdwrt((LONG)secnum, GBL.dirbufp, 0) );
}
/****************************
* directory write routine *
****************************/
UWORD dir_wr(secnum)
REG WORD secnum;
{
REG UWORD rtn;
BSETUP
rtn = rdwrt( (LONG)secnum, GBL.dirbufp, 2);
if ( secnum < (GBL.parmp)->cks )
*((GBL.dphp)->csv + secnum) = dchksum();
return(rtn);
}
/*******************************
* directory checksum routine *
*******************************/
UBYTE dchksum()
/* Compute checksum over one directory sector */
/* Note that this implementation is dependant on the representation */
/* of a LONG and is therefore not very portable. But it's fast */
{
REG LONG *p; /* local temp variables */
REG LONG lsum;
REG WORD i;
BSETUP
p = GBL.dirbufp; /* point to directory buffer */
lsum = 0;
i = SECLEN / (sizeof lsum);
do
{
lsum += *p++; /* add next 4 bytes of directory */
i -= 1;
} while (i);
lsum += (lsum >> 16);
lsum += (lsum >> 8);
return( (UBYTE)(lsum & 0xff) );
}
/************************
* dirscan entry point *
************************/
UWORD dirscan(funcp, fcbp, parms)
BOOLEAN (*funcp)(); /* funcp is a pointer to a Boolean function */
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
REG UWORD parms; /* parms is 16 bit set of bit parameters */
/* Parms & 1 = 0 to start at beginning of dir, 1 to continue from last */
/* Parms & 2 = 0 to stop when *funcp is true, 1 to go until end */
/* Parms & 4 = 0 to check the dir checksum, 1 to store new checksum */
/* Parms & 8 = 0 to stop at hiwater, 1 to go until end of directory */
#define continue 1
#define full 2
#define initckv 4
#define pasthw 8
{
REG UWORD i; /* loop counter */
REG struct dpb *dparmp; /* pointer to disk parm block */
REG UWORD dirsec; /* sector number we're working on */
REG UWORD rtn; /* return value */
REG UBYTE *p; /* scratch pointer */
REG UWORD bitvec; /* disk nmbr represented as a vector */
BSETUP
dparmp = GBL.parmp; /* init ptr to dpb */
rtn = 255; /* assume it doesn't work */
i = ( (parms & continue) ? GBL.srchpos + 1 : 0 );
while ( (parms & pasthw) || (i <= ((GBL.dphp)->hiwater + 1)) )
{ /* main directory scanning loop */
if ( i > dparmp->drm ) break;
if ( ! (i & 3) )
{ /* inside loop happens when we need to
read another directory sector */
retry: dirsec = i >> 2;
dir_rd(dirsec); /* read the directory sector */
if ( dirsec < (dparmp->cks) ) /* checksumming on this sector? */
{
p = ((GBL.dphp)->csv) + dirsec;
/* point to checksum vector byte */
if (parms & initckv) *p = dchksum();
else if (*p != dchksum())
{ /* checksum error! */
(GBL.dphp)->hiwater = dparmp->drm; /* reset hi water */
bitvec = 1 << (GBL.curdsk);
if (crit_dsk & bitvec) /* if disk in critical mode */
ro_dsk |= bitvec; /* then set it to r/o */
else
{
log_dsk &= ~bitvec; /* else log it off */
seldsk(GBL.curdsk); /* and re-select it */
goto retry; /* and re-do current op */
}
}
}
}
GBL.srchpos = i;
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 */
{
if (parms & full) rtn = 0; /* found a match, but keep going */
else return(i & 3); /* return directory code */
}
i += 1;
}
return(rtn);
}
/****************************************
* Routines to manage allocation vector *
* setaloc() *
* clraloc() *
* getaloc() *
****************************************/
setaloc(bitnum)
/* Set bit in allocation vector */
REG UWORD bitnum;
{
BSETUP
if (bitnum >= 0 && bitnum <= (GBL.parmp)->dsm)
*((GBL.dphp)->alv + (bitnum>>3)) |= 0x80 >> (bitnum & 7);
}
clraloc(bitnum)
/* Clear bit in allocation vector */
REG UWORD bitnum;
{
BSETUP
if (bitnum > 0 && bitnum <= (GBL.parmp)->dsm)
*((GBL.dphp)->alv + (bitnum>>3)) &= ~(0x80 >> (bitnum & 7));
}
UWORD chkaloc(i)
/* Check bit i in allocation vector */
/* Return non-zero if block free, else return zero */
REG UWORD i;
{
BSETUP
return( ~(*( (GBL.dphp)->alv + (i >> 3) )) & (0x80 >> (i&7)) );
}
UWORD getaloc(leftblk)
/* Get a free block in the file system and set the bit in allocation vector */
/* It is passed the block number of the last block allocated to the file */
/* It tries to allocate the block closest to the block that was passed */
REG UWORD leftblk;
{
REG UWORD blk; /* block number to allocate */
REG UWORD rtblk; /* high block number to try */
REG UWORD diskmax; /* # bits in alv - 1 */
BSETUP
LOCK /* need to lock the file system while messing
with the allocation vector */
diskmax = (GBL.parmp)->dsm;
/* get disk max field from dpb */
rtblk = leftblk;
blk = ~0; /* -1 returned if no free block found */
while (leftblk || rtblk < diskmax)
{
if (leftblk)
if (chkaloc(--leftblk))
{
blk = leftblk;
break;
}
if (rtblk < diskmax)
if (chkaloc(++rtblk))
{
blk = rtblk;
break;
}
}
if (blk != ~0) setaloc(blk);
UNLOCK
return(blk);
}

View File

@@ -0,0 +1,291 @@
*************************************************
* *
* CP/M-68k Basic Disk Operating System *
* Exception Handling Module *
* *
* Version 0.0 -- July 21, 1982 *
* Version 0.1 -- July 25, 1982 *
* Version 0.2 -- October 6, 1982 *
* Version 0.3 -- December 21, 1982 *
* *
*************************************************
.globl _initexc
.globl _tpa_lp
.globl _tpa_hp
bgetseg = 18
bsetexc = 22
buserr = 2
spurious = 24
trap0 = 32
trap2 = 34
trap3 = 35
endvec = 48
_initexc:
* Initialize Exception Vector Handlers
* It has 1 passed parameter: the address of the exception vector array
move #bsetexc,d0
moveq #2,d1
move.l #exchndl,d2
init1:
movem.l d0-d2,-(sp)
trap #3 * BIOS call to set exception vector
movem.l (sp)+,d0-d2
init2: addq #1,d1
add.l #4,d2
cmpi #spurious,d1
bne init3
move #trap0,d1
init3: cmpi #trap2,d1
beq init2 * don't init trap 2 or trap 3
cmpi #trap3,d1
beq init2
cmpi #endvec,d1
blt init1
* initialize the exception vector array
moveq #bgetseg,d0
trap #3 * get the original TPA limits
movea.l d0,a0
tst.w (a0)+
move.l (a0)+,d1 * d1 = original low TPA limit
move.l d1,d2
add.l (a0),d2 * d2 = original high TPA limit
move.l _tpa_lp,d3 * d3 = new low TPA limit
move.l _tpa_hp,d4 * d4 = new high TPA limit
move #17,d0
movea.l 4(sp),a0
move.l a0,evec_adr * save exception vector address
init4:
cmp.l (a0),d1
bhi do_init * if old exception outside orig TPA, clear it
cmp.l (a0),d2
bls do_init
* current exception array entry is in original TPA
cmp.l (a0),d3
bhi dontinit * if old exception in old TPA but outside new
cmp.l (a0),d4 * TPA, don't clear it
bls dontinit
do_init:
clr.l (a0)
dontinit:
tst.l (a0)+
dbf d0,init4
rts
exchndl:
bsr.w except
excrtn0:
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
bsr.w except
except:
clr.w -(sp)
movem.l a0/d0,-(sp) * 10 words now on stack in following order:
* _______________________________
* |____________D0.L_______________|
* |____________A0.L_______________|
* |____0000______|________________
* |_______Handler Return__________|
* If bus error, extra 2 longs are here
* ______________
* |__Status Reg__|________________
* |_____Exception Return__________|
move.l 10(sp),d0 * get return address from above array
sub.l #excrtn0,d0 * d0 now has 4 * (encoded excptn nmbr), where
* encoded excptn nmbr is in [0..21,22..37]
* representing [2..23,32..47]
cmpi #36,d0 * if d0/4 is in [0..9,22..29] then
ble chkredir * the exception may be redirected
cmpi #88,d0
blt dfltexc
cmpi #116,d0
bgt dfltexc
* in range of redirected exceptions
subi #48,d0 * subtract 4*12 to normalize [0..9,22..29]
* into [0..9,10..17]
chkredir:
movea.l evec_adr,a0
adda d0,a0 * index into exception vector array
tst.l (a0) * if 00000000, then not redirected
bne usrexc
* not redirected, do default handler
cmpi #40,d0
blt dfltexc
addi #48,d0 * add 4*12 that was sub'd above
dfltexc:
adda #14,sp * throw away 7 words that we added to stack
asr #2,d0 * divide d0 by 4
* now d0 is in [0..21,22..37]
* to represent [2..23,32..47]
cmpi #2,d0 * bus or address error?
bge nobusexc
movem.l (sp)+,a0-a1 * if yes, throw away 4 words from stack
nobusexc:
tst.w (sp)+ * throw away stacked SR
addi #2,d0
cmpi #23,d0 * get back real excptn nmbr in [2..23,32..47]
ble lowexc
addi #8,d0
lowexc: move d0,-(sp) * save excptn nmbr
lea excmsg1,a0
bsr print * print default exception message
move (sp)+,d0
bsr prtbyte
lea excmsg2, a0
bsr print
move.l (sp)+,d0
bsr prtlong
lea excmsg3, a0
bsr print
clr.l d0
trap #2 * warm boot
rte
usrexc:
* Call user exception handler
* make sure exception information is on his stack
move.l (a0),10(sp) * put user handler address on our stack
move.l usp,a0 * user stack pointer to a0
cmpi #8,d0 * address or bus error?
blt addrexc * if yes, skip
btst #13,14(sp) * exception occured in user state?
bne supstat1 * if no, go to supervisor handler
move.l 16(sp),-(a0) * put exception return on user stack
move.w 14(sp),-(a0) * put SR on user stack
move.l a0,usp * update user stack pointer
movem.l (sp)+,a0/d0 * restore regs
move.l 2(sp),8(sp) * move address of user handler to excptn rtn
addq #6,sp * clear junk from stack
andi #$7fff,(sp) * clear trace bit
rte * go to user handler
addrexc:
btst #13,22(sp) * exception occured in user state?
bne supstat2 * if no, go to supervisor handler
move.l 24(sp),-(a0) * put exception return on user stack
move.w 22(sp),-(a0) * put SR on user stack
move.l 18(sp),-(a0) * put extra 2 longs on user stack
move.l 14(sp),-(a0)
move.l a0,usp * update user stack pointer
movem.l (sp)+,a0/d0 * restore regs
move.l 2(sp),16(sp) * move address of user handler to excptn rtn
adda #14,sp * clear junk from stack
andi #$7fff,(sp) * clear trace bit
rte * go to user handler
supstat1:
move.w 14(sp),8(sp) * move SR to our exception return
bra supstat3
supstat2:
move.w 22(sp),8(sp)
supstat3:
movem.l (sp)+,a0/d0
rte
*
* Subroutines
*
print:
clr.l d1
move.b (a0)+, d1
beq prtdone
move #2, d0
trap #2
bra print
prtdone:
rts
prtlong:
* Print d0.l in hex format
move d0,-(sp)
swap d0
bsr prtword
move (sp)+,d0
prtword:
* Print d0.w in hex format
move d0,-(sp)
lsr #8,d0
bsr prtbyte
move (sp)+,d0
prtbyte:
* Print d0.b in hex format
move d0,-(sp)
lsr #4,d0
bsr prtnib
move (sp)+,d0
prtnib:
andi #$f,d0
cmpi #10,d0
blt lt10
addi.b #'A'-'9'-1,d0
lt10:
addi.b #'0',d0
move d0,d1
move #2,d0
trap #2
rts
.data
excmsg1:
.dc.b 13,10,10,'Exception $',0
excmsg2:
.dc.b ' at user address $',0
excmsg3:
.dc.b '. Aborted.',0
.bss
evec_adr:
.ds.l 1
.end

View 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 */
}

View File

@@ -0,0 +1,78 @@
/****************************************************************
* *
* 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 "bdosinc.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 */
{
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
was last used, to avoid disk selects */
REG struct dph *hdrp; /* pointer to disk parameter header */
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG UWORD rtn; /* return parameter */
UWORD iosect; /* sector number returned from divide rtn */
LOCK /* lock the disk system while doing physical i/o */
rtn = 0;
switch (iop->iofcn)
{
case sel_info:
last_dsk = iop->devnum;
iop->infop = bseldsk(last_dsk, iop->ioflags);
break;
case read:
case write:
if (last_dsk != iop->devnum)
bseldsk((last_dsk = iop->devnum), 0);
/* guaranteed disk is logged on, because temp_sel in
BDOSMAIN does it */
hdrp = iop->infop;
dparmp = hdrp->dpbp;
bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
+ dparmp->trk_off );
bsetsec( bsectrn( iosect, hdrp->xlt ) );
bsetdma(iop->xferadr);
if ((iop->iofcn) == read) rtn = bread();
else rtn = bwrite(iop->ioflags);
break;
case flush:
rtn = bflush();
}
UNLOCK
return(rtn);
}

View File

@@ -0,0 +1,78 @@
/****************************************************************
* *
* 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 */
{
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
was last used, to avoid disk selects */
REG struct dph *hdrp; /* pointer to disk parameter header */
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG UWORD rtn; /* return parameter */
UWORD iosect; /* sector number returned from divide rtn */
LOCK /* lock the disk system while doing physical i/o */
rtn = 0;
switch (iop->iofcn)
{
case sel_info:
last_dsk = iop->devnum;
iop->infop = bseldsk(last_dsk, iop->ioflags);
break;
case read:
case write:
if (last_dsk != iop->devnum)
bseldsk((last_dsk = iop->devnum), 0);
/* guaranteed disk is logged on, because temp_sel in
BDOSMAIN does it */
hdrp = iop->infop;
dparmp = hdrp->dpbp;
bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
+ dparmp->trk_off );
bsetsec( bsectrn( iosect, hdrp->xlt ) );
bsetdma(iop->xferadr);
if ((iop->iofcn) == read) rtn = bread();
else rtn = bwrite(iop->ioflags);
break;
case flush:
rtn = bflush();
}
UNLOCK
return(rtn);
}

View File

@@ -0,0 +1,72 @@
/****************************************************************
* *
* 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 "bdosinc.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 */
REG UWORD rtn; /* return parameter */
UWORD iosect; /* sector number returned from divide rtn */
LOCK /* lock the disk system while doing physical i/o */
rtn = 0;
switch (iop->iofcn)
{
case sel_info:
iop->infop = bseldsk(iop->devnum, iop->ioflags);
break;
case read:
case write:
bseldsk(iop->devnum, 0);
hdrp = iop->infop;
dparmp = hdrp->dpbp;
bsettrk( udiv( iop->devadr, dparmp->spt, &iosect )
+ dparmp->trk_off );
bsetsec( bsectrn( iosect, hdrp->xlt ) );
bsetdma(iop->xferadr);
if ((iop->iofcn) == read) rtn = bread();
else rtn = bwrite(iop->ioflags);
break;
case flush:
rtn = bflush();
}
UNLOCK
return(rtn);
}

View File

@@ -0,0 +1,42 @@
$ num
BDOSDEF.H
BDOSDEF.lst
$ num
BDOSIF.S
BDOSIF.lis
$ num
BDOSINC.H
BDOSINC.lst
$ num
BDOSMAIN.C
BDOSMAIN.lis
$ num
BDOSMISC.C
BDOSMISC.lis
$ num
BDOSRW.C
BDOSRW.lis
$ num
BIOSDEF.H
BIOSDEF.lst
$ num
CONBDOS.C
CONBDOS.lis
$ num
DSKUTIL.C
DSKUTIL.lis
$ num
EXCEPTN.S
EXCEPTN.lis
$ num
FILEIO.C
FILEIO.lis
$ num
IOSYS.C
IOSYS.lis
$ num
PGMLD.S
PGMLD.lis
$ num
PKTIO.H
PKTIO.lst

View File

@@ -0,0 +1,537 @@
*********************************
* *
* Function 59 -- Program Load *
* Assembly language version *
* *
* June 8, 1982 *
* *
*********************************
.globl _pgmld * this routine is public
secsize = 128 * CP/M sector size
* d0 always contains the return parameter from pgmld
* d1 is the return register from local subroutines
* a0 contains the pointer to the Load Parm Block passed to pgmld
* Return parameters in d0 are:
* 00 - function successful
* 01 - insufficient memory or bad header in file
* 02 - read error on file
* 03 - bad relocation information in file
* Entry point for Program Load routine
_pgmld:
movem.l d1-d7/a0-a6, -(sp) * save everything, just to be safe
move.l 60(sp),a0 * get pointer to LPB
clr.l d0 * start with return parm cleared
bsr gethdr * get header
tst d0
bne lddone * if unsuccessful, return
bsr setaddr * set up load addresses
tst d0
bne lddone * if unsuccessful, return
bsr rdtxt * read code and data text segments into mem
tst d0
bne lddone * if unsuccessful, return
move.l tstart,d7
cmp.l cseg,d7
beq noreloc
bsr reloc * do relocation if necessary
noreloc:
tst d0
bne lddone
bsr setrtn * set up return parameters
lddone:
move.l 64(sp), d1
bsr setdma * restore dma address
movem.l (sp)+,d1-d7/a0-a6
rts
* Subroutines
readseq:
* CP/M read sequential function
move.l d0,-(sp) * save return parm
move.l FCBPtr(a0),d1
moveq #20,d0 * read seq function
trap #2 * call bdos
move.l d0,d1 * return parm in d1
move.l (sp)+,d0
rts
setdma:
* CP/M set dma function
move.l d0,-(sp) * save return parm
moveq #26,d0 * set dma function
trap #2 * call bdos
move.l (sp)+,d0 * restore d0
rts
gethdr:
* Get header into buffer in data segment
move.l LoAdr(a0),d1
bsr setdma
bsr readseq
tst d1 * read ok?
bne badhdr * if no, return bad
moveq #18,d7
movea.l LoAdr(a0),a5
movea.l #hdr,a6
geth1: move.w (a5)+,(a6)+ * move header into hdr
dbf d7,geth1
rts
badhdr: moveq #2,d0
rts
conflict:
* input parms: d2, d3 = 4 * segment nmbr
* if segment d2/4 overlaps segment d3/4, then return 1 in d1
* else return 0 in d1
* uses d7, a2, a3
clr.l d1 * assume it will work
movea.l #cseg,a2 * a2 points to start of segment addresses
movea.l #csize,a3 * a3 points to start of segment lengths
move.l 0(a2,d2),d7 * get 1st seg start
cmp.l 0(a2,d3),d7 * is 1st seg above 2nd seg?
bge conf1
add.l 0(a3,d2),d7 * yes, find top of 1st seg
cmp.l 0(a2,d3),d7 * above start of 2nd seg?
bgt confbd * if yes, we have a conflict
rts * else, return good
conf1:
move.l 0(a2,d3),d7
add.l 0(a3,d3),d7 * find top of 2nd seg
cmp.l 0(a2,d2),d7 * above start of 1st seg?
ble confgd * if no, we're ok
confbd: moveq.l #1,d1
confgd: rts
trymemtp:
* entry: d2 is a segment nmbr [0..4]
* try to fit it at top of memory
* uses d3, d6, d7, a5, a6
* returns 0 in d1 if ok
move.l d2,d6 * d6 is loop counter for chksegs
subq #1,d6
lsl #2,d2 * multiply d2 by 4
move.l HiAdr(a0),d7 * top of mem to d7
chksegs:
* entry: d2 = 4 * (segment nmbr to try)
* d6 = (d2/4) - 1 (loop counter)
* d7 = address below which to try it
* check for conflicts with segments [0..d6] and low memory boundary
* return 0 in d1 if no conflicts, else d1 = 1
* uses d3, a5, a6
movea.l #cseg,a5
movea.l #csize,a6
sub.l 0(a6,d2),d7 * subtract size of segment to try
bclr #0,d7 * make it even address
move.l d7,0(a5,d2) * insert address in segment table
cmp.l LoAdr(a0),d7 * check for conflict with low memory
blt confbd
clr.l d3 * check for conflicts with 0..d6
chk1:
bsr conflict
addq.l #4,d3
tst.l d1 * conflict with this seg?
dbne d6,chk1 * if no, try next
rts
fndseg:
* entry: d2 is a segment nmbr [0..4]
* try to fit segment d2 directly below segments 0..(d2-1)
* uses d3-d7, a5, a6
move.l d2,d5 * d5 is loop counter to find fit
subq.l #1,d5
move.l d5,temp
lsl.l #2,d2 * multiply segment by 4
clr.l d4 * d4 is segment to try to fit below
fnd1:
move.l temp,d6 * d6 is loop counter for chksegs
movea.l #cseg,a5
move.l 0(a5,d4),d7 * segment address to d7
bsr chksegs * check for conflicts
addq.l #4,d4
tst.l d1
dbeq d5,fnd1 * if conflict, try next
rts
setaddr:
* Set up load addresses for cseg, dseg, bss, basepg, and stack
move.w magic,d6
andi.w #$fffe,d6
cmpi.w #$601a,d6
bne badadr * if magic nmbr <> 601a or 601b, skip
move.l bpsize,symsize
move.l #256,d7
move.l d7,bpsize * base page is 256 bytes
lea stksize,a2
cmp (a2),d7
blt set0 * if stack size < 256, set to 256
move.l d7,(a2)
set0: cmpi.w #$601b,magic
beq seta
tst.w rlbflg
beq set1
seta: move.l tstart,cseg * if not relocatable or hdr = $601b,
bra set2 * cseg starts at tstart
set1: btst #0,Flags(a0)
bne sldhi
* relocatable, load low
move.l LoAdr(a0),d7
add.l #$101,d7 * leave room for base page
bclr #0,d7
move.l d7,cseg * cseg is bottom of mem + $100 (even boundary)
bra set2
sldhi:
* relocatable, load high
move.l HiAdr(a0),d7
sub.l csize,d7
sub.l dsize,d7
sub.l bsize,d7
subq.l #4,d7
bclr #0,d7 * put cseg at next even address below
move.l d7,cseg * high memory - (sum of sizes)
set2:
* Cseg has been set up. Now do dseg, bseg
cmpi.w #$601b,magic
bne set3
* if magic # = 601b, take addr from hdr
move.l dstart,dseg
move.l bstart,bseg
bra set4
set3:
* if short header, dseg and bseg follow cseg
move.l cseg,d7
add.l csize,d7
addq.l #1,d7
bclr #0,d7
move.l d7,dseg
add.l dsize,d7
addq.l #1,d7
bclr #0,d7
move.l d7,bseg
set4:
* cseg, dseg, bseg set up
* now find a place for the base page and stack
moveq.l #3,d2
bsr fndseg * try to fit base page below cseg, dseg, bseg
tst.l d1
beq set5 * if found, skip
moveq.l #3,d2
bsr trymemtp * else, try top of memory
tst.l d1
bne badadr * if fail, exit
set5: moveq.l #4,d2
bsr trymemtp * try to fit stack at top of memory
tst.l d1
beq set6 * if ok, skip
moveq.l #4,d2
bsr fndseg * else, try to fit below other segs
tst.l d1
bne badadr
set6:
* now check all segments for conflicts with low and high memory boundaries
movea.l #cseg,a5
movea.l #csize,a6
clr.l d2
moveq #4,d3 * loop counter
set7: move.l 0(a5,d2),d7 * get segment base
cmp.l LoAdr(a0),d7 * above bottom of memory?
blt badadr
add.l 0(a6,d2),d7 * find top of segment
cmp.l HiAdr(a0),d7 * below top of memory?
bgt badadr
addq.l #4,d2 * point to next segment
dbf d3,set7
rts
badadr: moveq.l #1,d0
rts
movebuf:
* move (d3) bytes from the base page buffer to (a2)
* uses d6
movea.l basepg,a1
move.l #secsize,d6
sub.w bufbyts,d6 * address to move from =
adda.w d6,a1 * (basepg) + secsize - (bufbyts)
sub.w d3,bufbyts * update # bytes buffered
bra moveb2
moveb1: move.b (a1)+,(a2)+ * do the move
moveb2: dbf d3,moveb1
rts
rdtxt:
* Read code and data text into memory
* during this routine, a2 is always the load address,
* d2 is number of bytes left to load
moveq #63,d7
movea.l LoAdr(a0),a5
movea.l basepg,a6
rdtxt1: move.w (a5)+,(a6)+ * move header sector to base page
dbf d7,rdtxt1
move.w #secsize-28,d7
cmpi.w #$601a,magic * short header?
beq rdtxt2
subq.w #8,d7
rdtxt2: move.w d7,bufbyts * indicate # bytes of text in buffer
move.w #2,loop * do for code, data segments
move.l cseg,a2 * start at cseg
move.l csize,d2 * for csize bytes
rdtxt3:
clr.l d3
move.w bufbyts,d3
cmp.l d2,d3 * # bytes in buffer >= # bytes to load?
blt rdtxt4
move.l d2,d3
bsr movebuf * if yes, move # bytes to load
bra finrd
rdtxt4:
sub.l d3,d2 * if no, update # bytes to load
bsr movebuf * move remainder of buffer
move.l #secsize,d3 * d3 = secsize fo following loop
rdtxt5:
cmp.l d3,d2 * have at least one more full sector?
blt rdtxt6
move.l a2,d1
bsr setdma * if yes, set up dma address
bsr readseq * read next sector
tst.w d1
bne rdbad * if no good, exit
sub.l d3,d2 * decrement # bytes to load
adda.l #secsize,a2 * increment dma address
bra rdtxt5
rdtxt6:
tst.l d2 * any more bytes to read?
beq finrd
move.l basepg,d1
bsr setdma
bsr readseq * if yes, read into base page
tst.w d1
bne rdbad
move.w d3,bufbyts * indicate that we've buffered a sector
move.l d2,d3
bsr movebuf * move remainder of segment
finrd:
move.l dseg,a2 * set up to load data segment
move.l dsize,d2
sub.w #1,loop
bne rdtxt3
move.l bseg,a2 * clear the bss segment
move.l bsize,d2
beq rdtxt8
rdtxt7: clr.b (a2)+
subq.l #1,d2
bne rdtxt7
rdtxt8: rts
rdbad: moveq.l #2,d0
rts
relocword:
* relocate word at (a2) based on reloc bits at (a3)
* lsb of d2 indicates whether previous word was 1st half of long-word
move.w (a3)+,d7 * get relocation info
andi.w #7,d7 * strip off symbol table bits
lsl #1,d7 * multiply by 2
jmp 2(pc,d7)
bra relabs
bra reldata
bra relcode
bra relbss
bra relbad
bra rellong
bra relbad
bra relop
relbad: move.l (sp)+,d0 * pop return address
moveq #3,d0 * return bad relocation to main routine
rts
relabs:
relop: bclr #0,d2 * reset long word flag
tst.w (a2)+ * point to next word of segment
rts
rellong:
bset #0,d2 * set long word flag
tst.w (a2)+ * point to next word of segment
rts
reldata:
relbss:
relcode:
bclr #0,d2 * long word flag set?
bne relc1 * if yes, skip
move.w (a2),d6
add.w d5,d6
move.w d6,(a2)+
rts
relc1: tst.w -(a2) * point to first word of long
move.l (a2),d6
add.l d5,d6
move.l d6,(a2)+ * note that a2 points past long word
rts
reloc:
* Modify address references of code and data segments based on relocation bits
* During this routine,
* a2 points to text file to relocate
* a3 points to relocation word in basepg
* lsb of d2 is long word flag (set on reloc type 5, reset on next word)
* d3 is # words in relocation buffer
* d4 is nmbr of words left to relocate
* d5 is relocation offset
move.l basepg,d1
bsr setdma * we will always read into base page
* skip past the symbol table
move.l symsize,d7
divu #secsize,d7 * calculate how many sectors to skip
* note that max # symbols is 8k, which is 896 sectors of 128 bytes
move.w d7,d6 * d6 is nmbr sectors to skip
swap d7 * d7 is nmbr bytes to skip
move.w bufbyts,d3
sub.w d7,d3 * subtract bytes to skip from buffer
bge skip1
addi #secsize,d3 *if amt in buffer < # bytes to skip,
addq #1,d6 * read in 1 extra sector
skip1: move.l basepg,a3
adda #secsize,a3
suba.w d3,a3 * set up a3 to point to buffer
lsr #1,d3 * d3 is nmbr words in buffer
bra skip3
skip2:
bsr readseq * read next symbol table sector
tst.w d1
bne rdbad
skip3: dbf d6,skip2
* we got past symbol table
* a3, d3 are set up
move.l cseg,d5
move.l d5,a2 * relocate cseg first
sub.l tstart,d5 * d5 contains the relocation offset
move.l csize,d4 * nmbr of bytes to relocate
move.w #2,loop * we're going to relocate 2 segments
reloc1:
* relocate one segment
clr.l d2 * clear long word flag
lsr.l #1,d4 * make d4 indicate # words
bra reloc4
reloc2:
subq.w #1,d3
bpl reloc3
bsr readseq * if no more words in buffer, refill it
tst.w d1
bne rdbad
move.l basepg,a3
move.w #(secsize/2)-1,d3
reloc3:
bsr relocword * relocate one word
subq.l #1,d4
reloc4:
tst.l d4 * any more to relocate in this segment?
bne reloc2 * if yes, do it
move.l dseg,a2 * else, set up for dseg
move.l dsize,d4
sub.w #1,loop
bne reloc1
rts
setrtn:
* Set up the return parameters in Ld Parm Blk and Base Page
move.l basepg,BasPage(a0)
move.l stk,d7
add.l stksize,d7
bclr #0,d7
move.l d7,Stack(a0)
move.l basepg,a1
move.l LoAdr(a0),(a1)+
move.l HiAdr(a0),(a1)+
move.l cseg,(a1)+
move.l csize,(a1)+
move.l dseg,(a1)+
move.l dsize,(a1)+
move.l bseg,(a1)+
move.l bsize,(a1)
* find size of free memory after bss segment
move.l HiAdr(a0),d7 * d7 contains next segment above bss
move.l -4(a1),d6
add.l (a1)+,d6 * d6 points to start of free mem after bss
movea.l #cseg,a6 * a6 points to segment to try
moveq #4,d5 * try for all segments
clr.l bseg * but force bss not to appear
setb1: cmp.l (a6),d6 * segment above bss?
bhi setb2
cmp.l (a6),d7 * segment is above bss. Is it below previous?
bls setb2
move.l (a6),d7
setb2: tst.l (a6)+ * point to next segment
dbf d5,setb1
sub.l d6,d7 * diff between bss top and next segment abv
move.l d7,(a1)+
* now put disk number that we loaded from into base page
movea.l FCBPtr(a0),a2
move.b (a2),d0 * get disk select byte
bne setb3 * if not auto-select, skip
move #25,d0
trap #2 * get default disk
addq #1,d0 * we want it in range of 1..16
setb3: move.b d0,(a1)+ * move disk number into base page
clr.l d0 * function OK
rts
.bss
* offsets from start of parameter block
FCBPtr = 0
LoAdr = 4
HiAdr = 8
BasPage = 12 * return parameters
Stack = 16
Flags = 21
hdr:
* load file header is read into here
magic: .ds.w 1
csize: .ds.l 1
dsize: .ds.l 1
bsize: .ds.l 1
bpsize: .ds.l 1 * symb tbl size is swapped with base page size
stksize: .ds.l 1
tstart: .ds.l 1
rlbflg: .ds.w 1
dstart: .ds.l 1
bstart: .ds.l 1
cseg: .ds.l 1
dseg: .ds.l 1
bseg: .ds.l 1
basepg: .ds.l 1
stk: .ds.l 1
symsize: .ds.l 1
temp: .ds.l 1
loop: .ds.w 1
bufbyts: .ds.w 1
.end

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,16 @@
$ set noon
$ vsend BDOSDEF.H
$ vsend BDOSIF.S
$ vsend BDOSINC.H
$ vsend BDOSMAIN.C
$ vsend BDOSMISC.C
$ vsend BDOSRW.C
$ vsend BIOSDEF.H
$ vsend CONBDOS.C
$ vsend CPMC.DOC
$ vsend DSKUTIL.C
$ vsend EXCEPTN.S
$ vsend FILEIO.C
$ vsend IOSYS.C
$ vsend PGMLD.S
$ vsend PKTIO.H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
$ set nover
$ set noon
$ set def c:[cpm68k.source.bios]
$ copy normbios.h biostype.h
$ num
bios.c
bios.num
$ cc68 bios
$ as68 -u -l -p biosa.s >biosa.lis
$ lo68 -r -t5000 -o bios.68k biosa.o bios.o
$ pr/nofeed bios.num,bios.lis,biosa.lis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
$ set nover
$ set noon
$ set def [bill.cpm68k.bios]
$ num
bios.c
bios.num
$ cc68 :== @cc68.com
$ as68 :== $bin:as68.exe
$ ld68 :== $bin:lo68.exe
$ cc68 bios
$ as68 -u -l -p biosa.s >biosa.lis
$ as68 -u -l -p ldbiosa.s >ldbiosa.lis
$ ld68 -r -t5000 -o bios.68k biosa.o bios.o
$ s68 - bios.68k >[bill.cpm68k.object]bios.sr
$ pr/nofeed/copies=7 bios.num,biosa.lis,ldbiosa.lis

View File

@@ -0,0 +1,50 @@
.text
.globl _init
.globl _biosinit
.globl _flush
.globl _wboot
.globl _cbios
.globl _dskia
.globl _dskic
.globl _setimask
.globl _ccp
*
*
_init: lea entry,a0
move.l a0,$8C
lea _dskia,a0
move.l a0,$3fc
move #$2000,sr
jsr _biosinit
clr.l d0
rts
*
_wboot: clr.l d0
jmp _ccp
*
entry: move.l d2,-(a7)
move.l d1,-(a7)
move.w d0,-(a7)
jsr _cbios
add #10,a7
rte
*
_dskia: link a6,#0
movem.l d0-d7/a0-a5,-(a7)
jsr _dskic
movem.l (a7)+,d0-d7/a0-a5
unlk a6
rte
*
_setimask: move sr,d0
lsr #8,d0
and.l #7,d0
move sr,d1
ror.w #8,d1
and.w #$fff8,d1
add.w 4(a7),d1
ror.w #8,d1
move d1,sr
rts
*
.end

View File

@@ -0,0 +1,3 @@
#define LOADER 0
#define CTLTYPE 0
#define MEMDSK 4

View File

@@ -0,0 +1,23 @@
/************************************************/
/* */
/* Portable type definitions for use */
/* with the C BIOS according to */
/* CP/M-68K (tm) standard usage. */
/* */
/************************************************/
#define LONG long
#define ULONG unsigned long
#define WORD short int
#define UWORD unsigned short
#define BYTE char
#define UBYTE unsigned char
#define VOID
#define REG register
#define LOCAL auto
#define MLOCAL static
#define GLOBAL extern
#define EXTERN extern
/************************************************/

View File

@@ -0,0 +1,12 @@
$ set nover
$ set noon
$ c68 :== $bin:c68.exe
$ c068 :== $bin:c068.exe
$ c168 :== $bin:c168.exe
$ as68 :== $bin:as68.exe
$ lo68 :== $bin:lo68.exe
$ c68 'p1'.c 'p1'.i
$ c068 'p1'.i 'p1'.ic 'p1'.st
$ c168 'p1'.ic 'p1'.s -LD
$ as68 -l -u -p 'p1'.s >'p1'.lis
$ delete 'p1'.s;*,'p1'.ic;*,'p1'.i;*,'p1'.st;*

View File

@@ -0,0 +1,12 @@
$ set nover
$ set noon
$ c68 :== $bin:c68.exe
$ c068 :== $bin:c068.exe
$ c168 :== $bin:c168.exe
$ as68 :== $bin:as68.exe
$ lo68 :== $bin:lo68.exe
$ c68 'p1'.c 'p1'.i
$ c068 'p1'.i 'p1'.ic 'p1'.st
$ c168 'p1'.ic 'p1'.s -LD
$ as68 -l -u -p 'p1'.s >'p1'.lis
$ delete 'p1'.s;*,'p1'.ic;*,'p1'.i;*,'p1'.st;*

View File

@@ -0,0 +1,641 @@
/*=======================================================================*/
/*/---------------------------------------------------------------------\*/
/*| |*/
/*| CP/M-68K(tm) BIOS for the EXORMACS |*/
/*| |*/
/*| Copyright 1982, Digital Research. |*/
/*| |*/
/*\---------------------------------------------------------------------/*/
/*=======================================================================*/
char copyright[] = "Copyright 1982, Digital Research";
struct memb { char byte; };
struct memw { int word; };
struct meml { long lword;};
/************************************************************************/
/* I/O Device Definitions */
/************************************************************************/
/************************************************************************/
/* Define the two ACIA ports on the Debug board */
/************************************************************************/
#define PORT1 0xFFEE011
#define PORT2 0xFFEE015
#define PORTCTRL 0
#define PORTSTAT 0
#define PORTRDR 2
#define PORTTDR 2
#define PORTRSET 3
#define PORTINIT 0x11
#define PORTRDRF 1
#define PORTTDRE 2
/************************************************************************/
/* Define Disk I/O Addresses and Related Constants */
/************************************************************************/
#define DSKIPC 0xFF0000 /* IPC Base Address */
#define DSKINTV 0x3FC /* Address of Disk Interrupt Vector */
#define INTTOIPC 0xD /* offsets */
#define RSTTOIPC 0xF
#define MSGTOIPC 0x101
#define ACKFMIPC 0x103
#define PKTTOIPC 0x105
#define MSGFMIPC 0x181
#define ACKTOIPC 0x183
#define PKTFMIPC 0x185
#define STX 0x02
#define ETX 0x03
#define ACK 0x06
#define NAK 0x15
/************************************************************************/
/* BIOS Table Definitions */
/************************************************************************/
struct dpb
{
int spt;
char bsh;
char blm;
char exm;
char dpbjunk;
int dsm;
int drm;
char al0;
char al1;
int cks;
int off;
};
struct dph
{
char *xltp;
int dphscr[3];
char *dirbufp;
struct dpb *dpbp;
char *csvp;
char *alvp;
};
/************************************************************************/
/* Directory Buffer for use by the BDOS */
/************************************************************************/
char dirbuf[128];
/************************************************************************/
/* CSV's */
/************************************************************************/
char csv0[16];
char csv1[16];
char csv2[16];
/************************************************************************/
/* ALV's */
/************************************************************************/
char alv0[32]; /* (dsm0 / 8) + 1 */
char alv1[32]; /* (dsm1 / 8) + 1 */
char alv2[2002]; /* (dsm2 / 8) + 1 */
/************************************************************************/
/* Disk Parameter Blocks */
/************************************************************************/
/* The following dpb definitions express the intent of the writer, */
/* unfortunately, due to a compiler bug, these lines cannot be used. */
/* Therefore, the obscure code following them has been inserted. */
/************* spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off
struct dpb dpb0={ 26, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb1={ 26, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb2={ 26, 3, 7, 0, 0, 16008, 63, 0xC0, 0, 16, 2};
********** end of readable definitions *************/
/* The Alcyon C compiler assumes all structures are arrays of int, so */
/* in the following definitions, adjacent pairs of chars have been */
/* combined into int constants --- what a kludge! **********************/
struct dpb dpb0 = { 26, 1799, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb1 = { 26, 1039, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb2 = { 26, 1799, 0, 16008, 63, -16384, 16, 2 };
/*************** End of kludge *****************/
/************************************************************************/
/* Sector Translate Table */
/************************************************************************/
char xlt[26] = { 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15, 21,
2, 8, 14, 20, 26, 6, 12, 18, 24, 4, 10, 16, 22 };
/************************************************************************/
/* Disk Parameter Headers */
/* */
/* Four disks are defined : dsk a: diskno=0, dev name=#fd04 */
/* dsk b: diskno=1, dev name=#fd05 */
/* dsk c: diskno=2, dev name=#hd00 */
/* dsk d: diskno=3, dev name=#hd01 */
/************************************************************************/
struct dph dphtab[4] =
{ {&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv0, &alv0}, /*dsk a*/
{&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv1, &alv1}, /*dsk b*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk c*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk d*/
};
/************************************************************************/
/* Memory Region Table */
/************************************************************************/
struct mrt { int count;
long tpalow;
long tpalen;
}
memtab = { 1, 0x400L, 0xFC00 };
/************************************************************************/
/* IOBYTE */
/************************************************************************/
int iobyte;
/************************************************************************/
/* Currently Selected Disk Stuff */
/************************************************************************/
int settrk, setsec, setdsk;
char *setdma;
char trkbuf[26 * 128];
int tbvalid = 0;
int tbdirty = 0;
int tbtrk;
int tbdsk;
/************************************************************************/
/* Disk I/O Packets for the UDC and other Disk I/O Variables */
/************************************************************************/
struct hmpkst {
char a1;
char a2;
char a3;
char dskno;
char com1;
char com2;
char a6;
char a7;
}
hmpack = { 512, 1792, 0, 768 }; /* kludge init by words */
struct rwpkst {
char stxchr;
char pktid;
char pktsize;
char dskno;
char chcmd;
char devcmd;
int numblks;
int blksize;
long iobf;
int cksum;
long lsect;
char etxchr;
char rwpad;
};
struct rwpkst rwpack = { 512, 5376, 4097, 13, 256, 0, 0, 0, 0, 0, 768 };
char cnvdsk[4] = { 4, 5, 0, 1 }; /* convert from CP/M dsk # to Exormacs */
char flag2; /* used by the disk interrupt handler */
char flag3; /* ditto */
#define MAXDSK 3
/************************************************************************/
/* Generic Serial Port I/O Procedures */
/************************************************************************/
portinit(port)
char *port;
{
*(port + PORTCTRL) = PORTRSET;
*(port + PORTCTRL) = PORTINIT;
}
portstat(port)
char *port;
{
return ( *(port + PORTSTAT) & PORTRDRF) == PORTRDRF;
}
char portin(port)
char *port;
{
while (portstat(port) == 0) ;
return *(port + PORTRDR);
}
portout(port, ch)
char *port;
char ch;
{
while ( (*(port + PORTSTAT) & PORTTDRE) != PORTTDRE) ;
*(port + PORTTDR) = ch;
}
/************************************************************************/
/* Error procedure for BIOS */
/************************************************************************/
bioserr(errmsg)
char *errmsg;
{
printstr("\n\rBIOS ERROR -- ");
printstr(errmsg);
printstr(".\n\r");
while(1);
}
printstr(s) /* used by bioserr */
register char *s;
{
while (*s) {portout(PORT1,*s); s += 1; };
}
printnum(n)
register long n;
{
register int i;
register char c, j;
i = 32;
do {
i -= 4;
j = (n>>i) & 0x0F;
if ( j < 10 ) c = '0' + j;
else c = 'A' + j - 10;
portout(PORT2, c);
} while (i);
portout(PORT2, ' ');
}
printrace(s)
register char *s;
{
while (*s) {portout(PORT2, *s); s += 1;}
}
/************************************************************************/
/* Disk I/O Procedures */
/************************************************************************/
extern dskia();
dskic()
{
/* Disk Interrupt Handler -- C Language Portion */
if ( ! (DSKIPC+MSGFMIPC)->byte )
{
if ( (DSKIPC+ACKTOIPC)->byte != ACK )
{
(DSKIPC+ACKTOIPC)->byte = 0;
}
else
{
(DSKIPC+ACKTOIPC)->byte = 0;
flag2 = 0;
}
}
else
{
if ( (DSKIPC+PKTFMIPC)->byte == 2 )
{
(DSKIPC+ACKFMIPC)->byte = ACK;
(DSKIPC+MSGFMIPC)->byte = 0;
(DSKIPC+INTTOIPC)->byte = 0;
if ( ((DSKIPC+PKTFMIPC+8 )->byte == 0xFF) &&
((DSKIPC+PKTFMIPC+10)->byte == 0x80) )
{
tbtrk = 0xDFFFFFL;
}
flag3 = 0;
}
}
} /* end of dskic */
sendpkt(pktadr, pktsize)
register char *pktadr;
register int pktsize;
{
int i;
register char *iopackp;
flag2 = 0xFF;
flag3 = 0xFF;
DSKINTV->lword = &dskia;
i = pktsize;
iopackp = (DSKIPC + PKTTOIPC);
do { *iopackp = *pktadr++; iopackp += 2; i -= 1;} while (i);
(DSKIPC+MSGTOIPC)->byte = 0x80;
(DSKIPC+ACKTOIPC)->byte = 0;
(DSKIPC+INTTOIPC)->byte = 0;
while (flag2 == 0xFF);
while (flag3 == 0xFF);
}
#define wrongtk ((! tbvalid) || (tbtrk != settrk) || (tbdsk != setdsk))
#define gettrk if (wrongtk) filltb()
flush()
{
if ( tbvalid ) /* write out the contents of the track buffer */
{
rwpack.dskno = cnvdsk[tbdsk];
rwpack.iobf = &trkbuf;
rwpack.lsect = tbtrk * 13;
rwpack.chcmd = 0x20;
(DSKIPC + ACKFMIPC)->byte = ACK;
if ( (DSKIPC + MSGTOIPC)->byte ) bioserr("ERR2");
sendpkt(&rwpack, 21);
}
tbdirty = 0;
return(0);
}
filltb()
{
if ( tbvalid && tbdirty ) flush();
rwpack.dskno = cnvdsk[setdsk];
rwpack.iobf = &trkbuf;
rwpack.lsect = settrk * 13;
rwpack.chcmd = 0x10;
(DSKIPC + ACKFMIPC)->byte = ACK;
if ( (DSKIPC + MSGTOIPC)->byte ) bioserr("ERR2");
sendpkt(&rwpack, 21);
tbvalid = 1;
tbdirty = 0;
tbtrk = settrk;
tbdsk = setdsk;
}
read()
{
register char *p;
register char *q;
register int i;
gettrk;
p = &trkbuf[128 * (setsec-1)];
q = setdma;
i = 128;
do {*q++ = *p++; i -= 1;} while (i);
return(0);
}
write(mode)
char mode;
{
register char *p;
register char *q;
register int i;
gettrk;
p = &trkbuf[128 * (setsec-1)];
q = setdma;
i = 128;
do {*p++ = *q++; i -= 1;} while (i);
tbdirty = 1;
if ( mode == 1 ) flush();
return(0);
}
char sectran(s, xp)
int s;
char *xp;
{
return xp[s];
}
setxvect()
{
/* dummy */
}
long seldsk(dsk, logged)
register char dsk;
char logged;
{
register struct dph *dphp;
register char check;
if (dsk > MAXDSK) return(0L);
setdsk = dsk;
dphp = &dphtab[dsk];
if ( ! logged )
{
hmpack.dskno = cnvdsk[setdsk];
hmpack.com1 = 0x30;
hmpack.com2 = 0x02;
(DSKIPC+ACKFMIPC)->byte = 6;
if ( (DSKIPC+MSGTOIPC)->byte ) bioserr("ERR 6");
else sendpkt(&hmpack, 7);
check = (DSKIPC+PKTFMIPC+0x18)->byte;
switch ( check )
{
case 3: dphp->dpbp = &dpb0;
break;
case 7: dphp->dpbp = &dpb1;
break;
default: bioserr("ERR 7");
break;
}
}
return(dphp);
}
/************************************************************************/
/* BIOS PROPER */
/************************************************************************/
biosinit()
{
portinit(PORT1);
portinit(PORT2);
}
long bios(d0, d1, d2)
int d0;
long d1, d2;
{
if ( d0 > 7) {
printrace("\n\rBIOS( ");
printnum((long)d0);
printnum(d1);
printnum(d2);
printrace(")\n\r");
}
switch(d0)
{
case 0: init(); /* INIT */
break;
case 1: wboot(); /* WBOOT */
break;
case 2: return(portstat(PORT1)); /* CONST */
break;
case 3: return(portin(PORT1)); /* CONIN */
break;
case 4: portout(PORT1, (char)d1); /* CONOUT */
break;
case 5: ; /* LIST */
case 6: portout(PORT2, (char)d1); /* PUNCH */
break;
case 7: return(portin(PORT2)); /* READER */
break;
case 8: settrk = 0; /* HOME */
break;
case 9: return(seldsk((char)d1, (char)d2)); /* SELDSK */
break;
case 10: settrk = (int)d1; /* SETTRK */
break;
case 11: setsec = (int)d1; /* SETSEC */
break;
case 12: setdma = d1; /* SETDMA */
break;
case 13: return(read()); /* READ */
break;
case 14: return(write((char)d1)); /* WRITE */
break;
case 15: return(portstat(PORT2)); /* LISTST */
break;
case 16: return(sectran((int)d1, d2)); /* SECTRAN */
break;
case 17: return(&memtab); /* GMRTA */
break;
case 19: return(iobyte); /* GETIOB */
break;
case 20: iobyte = (int)d1; /* SETIOB */
break;
case 21: return(flush()); /* FLUSH */
break;
case 22: return(setxvect((int)d1,d2)); /* SETXVECT */
break;
} /* end switch */
} /* end bios procedure */
/* End of C Bios */

View File

@@ -0,0 +1,101 @@
conv: proc options(main);
dcl (inname,outname) char(50) varying;
dcl (infile,outfile) file;
dcl bytes char(2);
dcl wigit char(512);
dcl digit char;
dcl bdigit(128) bit(8);
dcl (j,i,bnum) bin ;
Dcl bytesb(2) char(1) based (bp1) ;
Dcl bp1 ptr ;
dcl (eof,fof) bit(1);
dcl (temp,temp2) bit(8);
on endfile(infile) eof = '1'b;
on undefinedfile(infile) begin;
put skip list('File not found');
stop;
end;
bp1 = addr(bytes) ;
put skip edit('Source Filename: ')(a(23)); get edit(inname)(a(50));
put skip edit('Destination Filename: ')(a(23)); get edit(outname)(a(50));
open file(infile) input environment(block_io) sequential title(inname);
open file(outfile) output stream linesize(80) title(outname);
eof = '0'b; fof = '0'b;
read file(infile) into (wigit);
do while( ^fof);
fof = eof;
do bnum = 1 to 512;
temp = unspec(substr(wigit,bnum,1));
do i = 1 to 8 ; substr(temp2,i,1) = substr(temp,9-i,1); end;
bytes = byte_to_hex(temp2);
put file(outfile) edit((bytesb(i) do i = 1 to 2)) (2(a));
end;
if ^eof then read file(infile) into (wigit);
end;
close file(infile);
close file(outfile);
/* utility routines for conversions */
bit_to_hex:
proc(xb) returns(char(1));
dcl
xb bit(4),
xi fixed bin(7),
hex(16) bit(4) static initial
('0000','0001','0010','0011',
'0100','0101','0110','0111',
'1000','1001','1010','1011',
'1100','1101','1110','1111'),
list char(16) static initial
('0123456789ABCDEF');
do xi = 1 to 16 while(hex(xi) ^= xb);
end;
return(substr(list,xi,1));
end bit_to_hex;
hex_to_bit:
proc(xc) returns(bit(4));
dcl
xc char(1),
xi fixed bin(7),
hex(16) bit(4) static initial
('0000','0001','0010','0011',
'0100','0101','0110','0111',
'1000','1001','1010','1011',
'1100','1101','1110','1111'),
list char(16) static initial
('0123456789ABCDEF');
xi = index(list,xc);
if xi = 0 then
do;
put skip list('INVALID HEX CHARACTER:');
stop;
end;
else
return(hex(xi));
end hex_to_bit;
byte_to_hex:
proc(xb) returns(char(2));
dcl
xb bit(8);
return(bit_to_hex(substr(xb,1,4))||bit_to_hex(substr(xb,5,4)));
end byte_to_hex;
hex_to_byte:
proc(xc) returns(bit(8));
dcl
xc char(2);
return(hex_to_bit(substr(xc,1,1))||hex_to_bit(substr(xc,2,1)));
end hex_to_byte;
end;

View File

@@ -0,0 +1,20 @@
$ set noon
$ copy c:[cpm68k.release.bdos]*.c,*.s,*.h,*.com,*.doc [.cbdos]
$ pur [.cbdos]
$ copy c:[cpm68k.release.boot]*.c,*.s,*.h,*.com [.boot]
$ pur [.boot]
$ copy c:[cpm68k.release.ccp]*.c,*.s,*.h,*.com [.ccp]
$ pur [.ccp]
$ copy c:[cpm68k.release.ddt]*.c,*.s,*.h,*.com [.ddt]
$ pur [.ddt]
$ copy b:[cpm68k.release.bios]*.c,*.s,*.h,*.com [.bios]
$ pur [.bios]
$ copy c:[cpm68k.release.pipedstat]*.* [.utils]
$ copy c:[cpm68k.release.tools]*.* [.utils]
$ copy c:[cpm68k.release.serial]*.* [.utils]
$ pur [.utils]
$ copy c:[cpm68k.release.clib]*.* [.clib]
$ pur [.clib]
$ copy c:[cpm68k.release.relnotes]*.* [.doc]
$ copy c:[cpm68k.release.docs]*.* [.doc]
$ pur [.doc]

View File

@@ -0,0 +1,15 @@
.text
.globl _init
.globl _ccp
*
* Init Routine -- User fills in jump address
*
_init: jmp 0
*
* This jump to the CCP may be used by the user to achieve a warmboot
*
jmp _ccp
*
*
.end

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,360 @@
*****************************************************************
* *
* CP/M-68K BIOS *
* Basic Input/Output Subsystem *
* For ERG 68000 with Tarbell floppy disk controller *
* *
*****************************************************************
.globl _init * bios initialization entry point
.globl _ccp * ccp entry point
_init: move.l #traphndl,$8c * set up trap #3 handler
clr.l d0 * log on disk A, user 0
rts
traphndl:
cmpi #nfuncs,d0
bcc trapng
lsl #2,d0 * multiply bios function by 4
movea.l 6(pc,d0),a0 * get handler address
jsr (a0) * call handler
trapng:
rte
biosbase:
.dc.l _init
.dc.l wboot
.dc.l constat
.dc.l conin
.dc.l conout
.dc.l lstout
.dc.l pun
.dc.l rdr
.dc.l home
.dc.l seldsk
.dc.l settrk
.dc.l setsec
.dc.l setdma
.dc.l read
.dc.l write
.dc.l listst
.dc.l sectran
.dc.l setdma
.dc.l getseg
.dc.l getiob
.dc.l setiob
.dc.l flush
.dc.l setexc
nfuncs=(*-biosbase)/4
wboot: jmp _ccp
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
cmpi.b #1,d0
beq break
rts
break:
trap $f
.dc.w 0 * return to MACSBUG
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
lstout: rts
pun: rts
rdr: rts
listst: move.b #$ff,d0
rts
*
* 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 given by register d1.b
moveq #0,d0
cmp.b #maxdsk,d1 * valid drive number?
bpl selrtn * if no, return 0 in d0
move.b d1,seldrv * else, save drive number
lsl.b #4,d1
move.b d1,selcode * select code is 00 for drv 0, $10 for drv 1
move.b seldrv,d0
mulu #dphlen,d0
add.l #dph0,d0 * point d0 at correct dph
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
write:
* Write one sector to requested disk, track, sector from dma address
* Retry if necessary, return in d0 00 if ok, else non-zero
move.b #10,errcnt * set up retry counter
wretry:
bsr setup
ori #$a8,d3 * OR write command with head load bit
move.b d3,dcmd * output it to FDC
wloop: btst #7,dwait
beq wdone * if end of read, exit
move.b (a0)+,ddata * else, move next byte of data
bra wloop
wdone:
bsr rstatus * get FDC status
bne werror
clr.l d0
rts
werror: bsr errchk * go to error handler
subq.b #1,errcnt
bne wretry
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
flush:
clr.l d0 * return successful
rts
getseg:
move.l #memrgn,d0 * return address of mem region table
rts
getiob:
rts
setiob:
rts
setexc:
andi.l #$ff,d1 * do only for exceptions 0 - 255
cmpi #47,d1
beq noset * this BIOS doesn't set Trap 15
cmpi #9,d1 * or Trace
beq noset
lsl #2,d1 * multiply exception nmbr by 4
movea.l d1,a0
move.l (a0),d0 * return old vector value
move.l d2,(a0) * insert new vector
noset: 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 $800 * starts at 800 hex
.dc.l $17800 * goes until 18000 hex
* 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 ckv0 * ptr to check vector
.dc.l alv0 * ptr to allocation vector
dph1: .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 ckv1 * ptr to check vector
.dc.l alv1 * 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
ckv0: .ds.b 16 * check vector
ckv1: .ds.b 16
alv0: .ds.b 32 * allocation vector
alv1: .ds.b 32
.end

View File

@@ -0,0 +1,2 @@
#define LOADER 0
#define CTLTYPE 1

View File

@@ -0,0 +1,2 @@
#define LOADER 1
#define CTLTYPE 1

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
$ set nover
$ set noon
$ set def [bill.cpm68k.bios]
$ num
hdbios.c
hdbios.num
$ cc68 :== @cc68.com
$ as68 :== $bin:as68.exe
$ ld68 :== $bin:lo68.exe
$ cc68 hdbios
$ as68 -u -l -p biosa.s >biosa.lis
$ pr/nofeed hdbios.num,hdbios.lis,biosa.lis

View File

@@ -0,0 +1,13 @@
$ set nover
$ set noon
$ set def [bill.cpm68k.bios]
$ num
hdbios.c
hdbios.num
$ cc68 :== @cc68.com
$ as68 :== $bin:as68.exe
$ ld68 :== $bin:lo68.exe
$ cc68 hdbios
$ as68 -u -l -p biosa.s >biosa.lis
$ ld68 -t76400 -o hdbiosys.sys biosa.o hdbios.o
$ pr/nofeed hdbios.num,hdbios.lis,biosa.lis

View File

@@ -0,0 +1,12 @@
$ set nover
$ set noon
$ set def [bill.cpm68k.bios]
$ num
hdbios.c
hdbios.num
$ cc68 :== @cc68.com
$ as68 :== $bin:as68.exe
$ ld68 :== $bin:lo68.exe
$ cc68 hdbios
$ as68 -u -l -p ldbiosa.s >ldbiosa.lis
$ pr/nofeed hdbios.num,hdbios.lis,ldbiosa.lis

View File

@@ -0,0 +1,41 @@
.text
.globl _bios
.globl _biosinit
.globl _cbios
.globl _dskia
.globl _dskic
.globl _setimask
*
*
*
*
_bios: link a6,#0
move.l d2,-(a7)
move.l d1,-(a7)
move.w d0,-(a7)
move #$2000,sr
lea _dskia,a0
move.l a0,$3fc
jsr _cbios
unlk a6
rts
*
_dskia: link a6,#0
movem.l d0-d7/a0-a5,-(a7)
jsr _dskic
movem.l (a7)+,d0-d7/a0-a5
unlk a6
rte
*
_setimask: move sr,d0
lsr #8,d0
and.l #7,d0
move sr,d1
ror.w #8,d1
and.w #$fff8,d1
add.w 4(a7),d1
ror.w #8,d1
move d1,sr
rts
*
.end

View File

@@ -0,0 +1,2 @@
#define LOADER 1
#define CTLTYPE 0

View File

@@ -0,0 +1,3 @@
#define LOADER 0
#define CTLTYPE 0
#define MEMDSK 4

View File

@@ -0,0 +1 @@
$pr/nofeed bios.num,bios.lis,biosa.lis

View File

@@ -0,0 +1,706 @@
/*=======================================================================*/
/*/---------------------------------------------------------------------\*/
/*| |*/
/*| CP/M-68K(tm) BIOS for the EXORMACS |*/
/*| |*/
/*| Copyright 1982, Digital Research. |*/
/*| |*/
/*\---------------------------------------------------------------------/*/
/*=======================================================================*/
#define DEBUG 0
char copyright[] = "Copyright 1982, Digital Research";
struct memb { char byte; };
struct memw { int word; };
struct meml { long lword;};
/************************************************************************/
/* I/O Device Definitions */
/************************************************************************/
/************************************************************************/
/* Define the two ACIA ports on the DEBUG board */
/************************************************************************/
#define PORT1 0xFFEE011
#define PORT2 0xFFEE015
#define PORTCTRL 0
#define PORTSTAT 0
#define PORTRDR 2
#define PORTTDR 2
#define PORTRSET 3
#define PORTINIT 0x11
#define PORTRDRF 1
#define PORTTDRE 2
/************************************************************************/
/* Define Disk I/O Addresses and Related Constants */
/************************************************************************/
#define DSKIPC 0xFF0000 /* IPC Base Address */
#define DSKINTV 0x3FC /* Address of Disk Interrupt Vector */
#define INTTOIPC 0xD /* offsets */
#define RSTTOIPC 0xF
#define MSGTOIPC 0x101
#define ACKTOIPC 0x103
#define PKTTOIPC 0x105
#define MSGFMIPC 0x181
#define ACKFMIPC 0x183
#define PKTFMIPC 0x185
#define DSKREAD 0x10
#define DSKWRITE 0x20
#define STX 0x02
#define ETX 0x03
#define ACK 0x06
#define NAK 0x15
/************************************************************************/
/* BIOS Table Definitions */
/************************************************************************/
struct dpb
{
int spt;
char bsh;
char blm;
char exm;
char dpbjunk;
int dsm;
int drm;
char al0;
char al1;
int cks;
int off;
};
struct dph
{
char *xltp;
int dphscr[3];
char *dirbufp;
struct dpb *dpbp;
char *csvp;
char *alvp;
};
/************************************************************************/
/* Directory Buffer for use by the BDOS */
/************************************************************************/
char dirbuf[128];
/************************************************************************/
/* CSV's */
/************************************************************************/
char csv0[16];
char csv1[16];
char csv2[16];
/************************************************************************/
/* ALV's */
/************************************************************************/
char alv0[32]; /* (dsm0 / 8) + 1 */
char alv1[32]; /* (dsm1 / 8) + 1 */
char alv2[2002]; /* (dsm2 / 8) + 1 */
/************************************************************************/
/* Disk Parameter Blocks */
/************************************************************************/
/* The following dpb definitions express the intent of the writer, */
/* unfortunately, due to a compiler bug, these lines cannot be used. */
/* Therefore, the obscure code following them has been inserted. */
/************* spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off
struct dpb dpb0={ 26, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb1={ 26, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb2={ 26, 3, 7, 0, 0, 16008, 63, 0xC0, 0, 16, 2};
********** end of readable definitions *************/
/* The Alcyon C compiler assumes all structures are arrays of int, so */
/* in the following definitions, adjacent pairs of chars have been */
/* combined into int constants --- what a kludge! **********************/
struct dpb dpb0 = { 26, 775, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb1 = { 26, 1039, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb2 = { 26, 775, 0, 16008, 63, -16384, 16, 2 };
/*************** End of kludge *****************/
/************************************************************************/
/* Sector Translate Table */
/************************************************************************/
char xlt[26] = { 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15, 21,
2, 8, 14, 20, 26, 6, 12, 18, 24, 4, 10, 16, 22 };
/************************************************************************/
/* Disk Parameter Headers */
/* */
/* Four disks are defined : dsk a: diskno=0, dev name=#fd04 */
/* dsk b: diskno=1, dev name=#fd05 */
/* dsk c: diskno=2, dev name=#hd00 */
/* dsk d: diskno=3, dev name=#hd01 */
/************************************************************************/
struct dph dphtab[4] =
{ {&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv0, &alv0}, /*dsk a*/
{&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv1, &alv1}, /*dsk b*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk c*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk d*/
};
/************************************************************************/
/* Memory Region Table */
/************************************************************************/
struct mrt { int count;
long tpalow;
long tpalen;
}
memtab = { 1, 0x0000,0x400, 0x0001,0x7c00 };/* kludge init by int */
/************************************************************************/
/* IOchar */
/************************************************************************/
int iobyte;
/************************************************************************/
/* Currently Selected Disk Stuff */
/************************************************************************/
int settrk, setsec, setdsk;
char *setdma;
char trkbuf[26 * 128];
int tbvalid = 0;
int tbdirty = 0;
int tbtrk;
int tbdsk;
/************************************************************************/
/* Disk I/O Packets for the UDC and other Disk I/O Variables */
/************************************************************************/
struct hmpkst {
char a1;
char a2;
char a3;
char dskno;
char com1;
char com2;
char a6;
char a7;
}
hmpack = { 512, 1792, 0, 768 }; /* kludge init by words */
struct rwpkst {
char stxchr;
char pktid;
char pktsize;
char dskno;
char chcmd;
char devcmd;
int numblks;
int blksize;
long iobf;
int cksum;
long lsect;
char etxchr;
char rwpad;
};
struct rwpkst rwpack = { 512, 5376, 4097, 13, 256, 0, 0, 0, 0, 0, 768 };
char cnvdsk[4] = { 4, 5, 0, 1 }; /* convert from CP/M dsk # to Exormacs */
#define MAXDSK 3
#define DSKIDLE 0
#define MSGSENT 1
#define NAKRCVD 2
#define ACKRCVD 3
#define IODONE 4
int dskstate = DSKIDLE;
/************************************************************************/
/* Generic Serial Port I/O Procedures */
/************************************************************************/
portinit(port)
register char *port;
{
*(port + PORTCTRL) = PORTRSET;
*(port + PORTCTRL) = PORTINIT;
}
portstat(port)
register char *port;
{
return ( *(port + PORTSTAT) & PORTRDRF) == PORTRDRF;
}
char portin(port)
register char *port;
{
while (portstat(port) == 0) ;
return *(port + PORTRDR);
}
portout(port, ch)
register char *port;
register char ch;
{
while ( (*(port + PORTSTAT) & PORTTDRE) != PORTTDRE) ;
*(port + PORTTDR) = ch;
}
/************************************************************************/
/* Error procedure for BIOS */
/************************************************************************/
bioserr(errmsg)
register char *errmsg;
{
printstr("\n\rBIOS ERROR -- ");
printstr(errmsg);
printstr(".\n\r");
while(1);
}
printstr(s) /* used by bioserr */
register char *s;
{
while (*s) {portout(PORT1,*s); s += 1; };
}
#if DEBUG
printds(ds)
int ds;
{
switch(ds){
case DSKIDLE: printstr("DSKIDLE");
break;
case MSGSENT: printstr("MSGSENT");
break;
case NAKRCVD: printstr("NAKRCVD");
break;
case ACKRCVD: printstr("ACKRCVD");
break;
case IODONE: printstr("IODONE");
break;
default: printstr("Invalid");
break;
}
}
#endif
/************************************************************************/
/* Disk I/O Procedures */
/************************************************************************/
extern dskia();
extern setimask();
dskic()
{
/* Disk Interrupt Handler -- C Language Portion */
#if DEBUG
printstr("\n\rDisk Interrupt ");
printds(dskstate);
printstr("->");
#endif
switch ( dskstate )
{
case DSKIDLE: ;
case IODONE: ;
case NAKRCVD: {
if ( ((DSKIPC+ACKFMIPC)->byte == ACK) ||
((DSKIPC+ACKFMIPC)->byte == NAK) )
{
(DSKIPC+ACKFMIPC)->byte = 0;
}
if ( (DSKIPC+MSGFMIPC)->byte == 0x80 )
{
(DSKIPC+ACKTOIPC)->byte = ACK;
(DSKIPC+MSGFMIPC)->byte = 0;
(DSKIPC+INTTOIPC)->byte = 0;
}
}
break;
case MSGSENT: {
if ( (DSKIPC+ACKFMIPC)->byte == ACK )
{
(DSKIPC+ACKFMIPC)->byte = 0;
dskstate = ACKRCVD;
}
else if ( (DSKIPC+ACKFMIPC)->byte == NAK )
{
(DSKIPC+ACKFMIPC)->byte = 0;
dskstate = NAKRCVD;
}
else bioserr("Expected ACK or NAK");
if ( (DSKIPC+MSGFMIPC)->byte == 0x80 )
{ dskstate = IODONE; }
}
break;
case ACKRCVD: {
if ( (DSKIPC+MSGFMIPC)->byte != 0x80 )
{ bioserr("Expected status packet from IPC");}
dskstate = IODONE;
(DSKIPC+MSGFMIPC)->byte = 0;
(DSKIPC+ACKTOIPC)->byte = ACK;
(DSKIPC+INTTOIPC)->byte = 0;
}
break;
}
#if DEBUG
printds(dskstate);
printstr("\n\r");
#endif
} /* end of dskic */
sendpkt(pktadr, pktsize)
register char *pktadr;
register int pktsize;
{
register char *iopackp;
register int imsave;
while ( (DSKIPC+MSGTOIPC)->byte ); /* wait til ready */
if ( (DSKIPC+ACKFMIPC)->byte == NAK ) bioserr("NAK from IPC");
(DSKIPC+ACKFMIPC)->byte = 0;
(DSKIPC+MSGFMIPC)->byte = 0;
iopackp = (DSKIPC+PKTTOIPC);
do {*iopackp = *pktadr++; iopackp += 2; pktsize -= 1;} while(pktsize);
(DSKIPC+MSGTOIPC)->byte = 0x80;
imsave = setimask(7);
dskstate = MSGSENT;
(DSKIPC+INTTOIPC)->byte = 0;
setimask(imsave);
}
dskxfer(dsk, trk, bufp, cmd)
register int dsk, trk, cmd;
register char *bufp;
{
/* build packet */
rwpack.dskno = cnvdsk[dsk];
rwpack.iobf = bufp;
rwpack.lsect = trk * 13;
rwpack.chcmd = cmd;
sendpkt(&rwpack, 21);
while (dskstate == MSGSENT); /* wait */
if (dskstate == NAKRCVD) bioserr("NAK from IPC");
while (dskstate == ACKRCVD); /* wait */
}
#define wrongtk ((! tbvalid) || (tbtrk != settrk) || (tbdsk != setdsk))
#define gettrk if (wrongtk) filltb()
flush()
{
if ( tbvalid ) dskxfer(tbdsk, tbtrk, &trkbuf, DSKWRITE);
tbdirty = 0;
return(0);
}
filltb()
{
if ( tbvalid && tbdirty ) flush();
dskxfer(setdsk, settrk, &trkbuf, DSKREAD);
tbvalid = 1;
tbdirty = 0;
tbtrk = settrk;
tbdsk = setdsk;
}
read()
{
register char *p;
register char *q;
register int i;
gettrk;
p = &trkbuf[128 * (setsec-1)];
q = setdma;
i = 128;
do {*q++ = *p++; i -= 1;} while (i);
return(0);
}
write(mode)
char mode;
{
register char *p;
register char *q;
register int i;
gettrk;
p = &trkbuf[128 * (setsec-1)];
q = setdma;
i = 128;
do {*p++ = *q++; i -= 1;} while (i);
tbdirty = 1;
if ( mode == 1 ) flush();
return(0);
}
char sectran(s, xp)
int s;
char *xp;
{
return xp[s];
}
long setxvect(vnum, vval)
int vnum;
long vval;
{
register long oldval;
register char *vloc;
vloc = ( (long)vnum ) << 2;
oldval = vloc->lword;
vloc->lword = vval;
return(oldval);
}
long seldsk(dsk, logged)
register char dsk;
char logged;
{
register struct dph *dphp;
register char check;
if (dsk > MAXDSK) return(0L);
setdsk = dsk;
dphp = &dphtab[dsk];
if ( ! logged )
{
hmpack.dskno = cnvdsk[setdsk];
hmpack.com1 = 0x30;
hmpack.com2 = 0x02;
(DSKIPC+ACKFMIPC)->byte = 6;
if ( (DSKIPC+MSGTOIPC)->byte ) bioserr("ERR 6");
else sendpkt(&hmpack, 7);
while ( dskstate == MSGSENT ); /* wait */
if (dskstate == NAKRCVD) bioserr("NAK from IPC");
while ( dskstate == ACKRCVD ); /* wait */
check = (DSKIPC+PKTFMIPC+0x18)->byte;
switch ( check )
{
case 3: dphp->dpbp = &dpb0;
break;
case 7: dphp->dpbp = &dpb1;
break;
default: bioserr("ERR 7");
break;
}
}
return(dphp);
}
/************************************************************************/
/* BIOS PROPER */
/************************************************************************/
biosinit()
{
portinit(PORT1);
portinit(PORT2);
}
long bios(d0, d1, d2)
int d0;
long d1, d2;
{
#if DEBUG
if ( d0 > 7) {
printrace("\n\rBIOS( ");
printnum((long)d0);
printnum(d1);
printnum(d2);
printrace(")\n\r");
}
#endif
switch(d0)
{
case 0: init(); /* INIT */
break;
case 1: wboot(); /* WBOOT */
break;
case 2: return(portstat(PORT1)); /* CONST */
break;
case 3: return(portin(PORT1)); /* CONIN */
break;
case 4: portout(PORT1, (char)d1); /* CONOUT */
break;
case 5: ; /* LIST */
case 6: portout(PORT2, (char)d1); /* PUNCH */
break;
case 7: return(portin(PORT2)); /* READER */
break;
case 8: settrk = 0; /* HOME */
break;
case 9: return(seldsk((char)d1, (char)d2)); /* SELDSK */
break;
case 10: settrk = (int)d1; /* SETTRK */
break;
case 11: setsec = (int)d1; /* SETSEC */
break;
case 12: setdma = d1; /* SETDMA */
break;
case 13: return(read()); /* READ */
break;
case 14: return(write((char)d1)); /* WRITE */
break;
case 15: return(portstat(PORT2)); /* LISTST */
break;
case 16: return(sectran((int)d1, d2)); /* SECTRAN */
break;
case 18: return(&memtab); /* GMRTA */
break;
case 19: return(iobyte); /* GETIOB */
break;
case 20: iobyte = (int)d1; /* SETIOB */
break;
case 21: return(flush()); /* FLUSH */
break;
case 22: return(setxvect((int)d1,d2)); /* SETXVECT */
break;
} /* end switch */
} /* end bios procedure */
/* End of C Bios */

View File

@@ -0,0 +1,13 @@
$ set nover
$ set noon
$ set def [bill.cpm68k.bios]
$ num
relbios.c
relbios.num
$ cc68 :== @cc68.com
$ as68 :== $bin:as68.exe
$ ld68 :== $bin:lo68.exe
$ cc68 relbios
$ as68 -u -l -p relbiosa.s >relbiosa.lis
$ ld68 -r -t1e000 -o relbios.68k relbiosa.o relbios.o
$ s68 relbios.68k >[bill.cpm68k.object]relbios.sr

View File

@@ -0,0 +1,887 @@
.globl _copyrigh
.data
_copyrigh:
.dc.b 67,111,112,121,114,105,103,104,116,32,49,57,56,50,44,32,68,105,103,105,116,97,108,32,82,101,115,101,97,114,99,104,0
.even
.globl _dirbuf
.comm _dirbuf,128
.globl _csv0
.comm _csv0,16
.globl _csv1
.comm _csv1,16
.globl _csv2
.comm _csv2,16
.globl _alv0
.comm _alv0,32
.globl _alv1
.comm _alv1,32
.globl _alv2
.comm _alv2,2002
.globl _dpb0
.data
_dpb0:
.dc.w 26
.dc.w 775
.dc.w 0
.dc.w 242
.dc.w 63
.dc.w -16384
.dc.w 16
.dc.w 2
.globl _dpb1
.data
_dpb1:
.dc.w 26
.dc.w 1039
.dc.w 0
.dc.w 242
.dc.w 63
.dc.w -16384
.dc.w 16
.dc.w 2
.globl _dpb2
.data
_dpb2:
.dc.w 26
.dc.w 775
.dc.w 0
.dc.w 16008
.dc.w 63
.dc.w -16384
.dc.w 16
.dc.w 2
.globl _xlt
.data
_xlt:
.dc.b 1
.dc.b 7
.dc.b 13
.dc.b 19
.dc.b 25
.dc.b 5
.dc.b 11
.dc.b 17
.dc.b 23
.dc.b 3
.dc.b 9
.dc.b 15
.dc.b 21
.dc.b 2
.dc.b 8
.dc.b 14
.dc.b 20
.dc.b 26
.dc.b 6
.dc.b 12
.dc.b 18
.dc.b 24
.dc.b 4
.dc.b 10
.dc.b 16
.dc.b 22
.globl _dphtab
.data
_dphtab:
.dc.l _xlt
.dc.w 0
.dc.w 0
.dc.w 0
.dc.l _dirbuf
.dc.l _dpb0
.dc.l _csv0
.dc.l _alv0
.dc.l _xlt
.dc.w 0
.dc.w 0
.dc.w 0
.dc.l _dirbuf
.dc.l _dpb0
.dc.l _csv1
.dc.l _alv1
.dc.w 0,0
.dc.w 0
.dc.w 0
.dc.w 0
.dc.l _dirbuf
.dc.l _dpb2
.dc.l _csv2
.dc.l _alv2
.dc.w 0,0
.dc.w 0
.dc.w 0
.dc.w 0
.dc.l _dirbuf
.dc.l _dpb2
.dc.l _csv2
.dc.l _alv2
.globl _memtab
.data
_memtab:
.dc.w 1
.dc.w 0
.dc.w 1024
.dc.w 1
.dc.w 31744
.globl _iobyte
.comm _iobyte,2
.globl _settrk
.comm _settrk,2
.globl _setsec
.comm _setsec,2
.globl _setdsk
.comm _setdsk,2
.globl _setdma
.comm _setdma,4
.globl _trkbuf
.comm _trkbuf,3328
.globl _tbvalid
.data
_tbvalid:
.dc.w 0
.globl _tbdirty
.data
_tbdirty:
.dc.w 0
.globl _tbtrk
.comm _tbtrk,2
.globl _tbdsk
.comm _tbdsk,2
.globl _hmpack
.data
_hmpack:
.dc.w 512
.dc.w 1792
.dc.w 0
.dc.w 768
.globl _rwpack
.data
_rwpack:
.dc.w 512
.dc.w 5376
.dc.w 4097
.dc.w 13
.dc.w 256
.dc.w 0
.dc.w 0
.dc.w 0
.dc.w 0
.dc.w 0
.dc.w 768
.globl _cnvdsk
.data
_cnvdsk:
.dc.b 4
.dc.b 5
.dc.b 0
.dc.b 1
.globl _dskstate
.data
_dskstate:
.dc.w 0
.globl _portinit
.text
_portinit:
~~portinit:
~port=R13
link R14,#0
movem.l R7-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.b #3,(R13)
move.b #17,(R13)
L2:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _portstat
.text
_portstat:
~~portstat:
~port=R13
link R14,#0
movem.l R7-R7/R13-R13,-(sp)
move.l 8(R14),R13
btst #0,(R13)
bne L10000
clr R0
bra L10001
L10000:move #1,R0
L10001:bra L3
L3:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _portin
.text
_portin:
~~portin:
~port=R13
link R14,#0
movem.l R7-R7/R13-R13,-(sp)
move.l 8(R14),R13
L6:
move.l R13,(sp)
jsr _portstat
tst R0
bne L5
bra L6
L5:
move.b 2(R13),R0
ext.w R0
bra L4
L4:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _portout
.text
_portout:
~~portout:
~ch=R7
~port=R13
link R14,#0
movem.l R6-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.b 13(R14),R7
L9:
btst #1,(R13)
bne L8
bra L9
L8:
move.b R7,2(R13)
L7:tst.l (sp)+
movem.l (sp)+,R7-R7/R13-R13
unlk R14
rts
.globl _bioserr
.text
_bioserr:
~~bioserr:
~errmsg=R13
link R14,#0
movem.l R7-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.l #L11,(sp)
jsr _printstr
move.l R13,(sp)
jsr _printstr
move.l #L12,(sp)
jsr _printstr
L14:
bra L14
L13:L10:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _printstr
.text
_printstr:
~~printstr:
~s=R13
link R14,#0
movem.l R7-R7/R13-R13,-(sp)
move.l 8(R14),R13
L17:
tst.b (R13)
beq L16
move.b (R13),R0
ext.w R0
move R0,(sp)
move.l #$ffee011,-(sp)
jsr _portout
add #4,sp
add.l #1,R13
bra L17
L16:L15:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _dskia
.globl _setimask
.globl _dskic
.text
_dskic:
~~dskic:
link R14,#-4
move _dskstate,R0
bra L20
L21:L22:L23:
cmp.b #6,$ff0183
beq L10002
cmp.b #21,$ff0183
bne L24
L10002:clr.b $ff0183
L24:
cmp.b #128,$ff0181
bne L25
move.b #6,$ff0103
clr.b $ff0181
clr.b $ff000d
L25:bra L19
L26:
cmp.b #6,$ff0183
bne L27
clr.b $ff0183
move #3,_dskstate
bra L28
L27:
cmp.b #21,$ff0183
bne L29
clr.b $ff0183
move #2,_dskstate
bra L30
L29:
move.l #L31,(sp)
jsr _bioserr
L30:L28:
cmp.b #128,$ff0181
bne L32
move #4,_dskstate
L32:bra L19
L33:
cmp.b #128,$ff0181
beq L34
move.l #L35,(sp)
jsr _bioserr
L34:
move #4,_dskstate
clr.b $ff0181
move.b #6,$ff0103
clr.b $ff000d
bra L19
bra L19
L20:cmp #4,R0
bhi L19
asl #2,R0
move R0,R8
add.l #L36,R8
move.l (R8),R8
jmp (R8)
.data
L36:.dc.l L21
.dc.l L26
.dc.l L23
.dc.l L33
.dc.l L22
.text
L19:L18:unlk R14
rts
.globl _sendpkt
.text
_sendpkt:
~~sendpkt:
~imsave=R6
~pktadr=R13
~iopackp=R12
~pktsize=R7
link R14,#0
movem.l R5-R7/R12-R13,-(sp)
move.l 8(R14),R13
move 12(R14),R7
L39:
tst.b $ff0101
beq L38
bra L39
L38:
cmp.b #21,$ff0183
bne L40
move.l #L41,(sp)
jsr _bioserr
L40:
clr.b $ff0183
clr.b $ff0181
move.l #$ff0105,R12
L44:
move.b (R13)+,(R12)
add.l #2,R12
sub #1,R7
L43:
tst R7
bne L44
L42:
move.b #128,$ff0101
move #7,(sp)
jsr _setimask
move R0,R6
move #1,_dskstate
clr.b $ff000d
move R6,(sp)
jsr _setimask
L37:tst.l (sp)+
movem.l (sp)+,R6-R7/R12-R13
unlk R14
rts
.globl _dskxfer
.text
_dskxfer:
~~dskxfer:
~cmd=R5
~dsk=R7
~trk=R6
~bufp=R13
link R14,#0
movem.l R4-R7/R13-R13,-(sp)
move 8(R14),R7
move 10(R14),R6
move.l 12(R14),R13
move 16(R14),R5
move R7,R0
ext.l R0
add.l #_cnvdsk,R0
move.l R0,R8
move.b (R8),3+_rwpack
move.l R13,10+_rwpack
move R6,R0
muls #13,R0
move.l R0,16+_rwpack
move.b R5,4+_rwpack
move #21,(sp)
move.l #_rwpack,-(sp)
jsr _sendpkt
add #4,sp
L47:
cmp #1,_dskstate
bne L46
bra L47
L46:
cmp #2,_dskstate
bne L48
move.l #L49,(sp)
jsr _bioserr
L48:L51:
cmp #3,_dskstate
bne L50
bra L51
L50:L45:tst.l (sp)+
movem.l (sp)+,R5-R7/R13-R13
unlk R14
rts
.globl _flush
.text
_flush:
~~flush:
link R14,#-4
tst _tbvalid
beq L53
move #32,(sp)
move.l #_trkbuf,-(sp)
move _tbtrk,-(sp)
move _tbdsk,-(sp)
jsr _dskxfer
add #8,sp
L53:
clr _tbdirty
clr R0
bra L52
L52:unlk R14
rts
.globl _filltb
.text
_filltb:
~~filltb:
link R14,#-4
tst _tbvalid
beq L55
tst _tbdirty
beq L55
jsr _flush
L55:
move #16,(sp)
move.l #_trkbuf,-(sp)
move _settrk,-(sp)
move _setdsk,-(sp)
jsr _dskxfer
add #8,sp
move #1,_tbvalid
clr _tbdirty
move _settrk,_tbtrk
move _setdsk,_tbdsk
L54:unlk R14
rts
.globl _read
.text
_read:
~~read:
~i=R7
~p=R13
~q=R12
link R14,#0
movem.l R6-R7/R12-R13,-(sp)
tst _tbvalid
beq L10003
move _tbtrk,R0
cmp _settrk,R0
bne L10003
move _tbdsk,R0
cmp _setdsk,R0
beq L57
L10003:jsr _filltb
L57:
move _setsec,R0
sub #1,R0
asl #7,R0
ext.l R0
move.l R0,R13
add.l #_trkbuf,R13
move.l _setdma,R12
move #128,R7
L60:
move.b (R13)+,(R12)+
sub #1,R7
L59:
tst R7
bne L60
L58:
clr R0
bra L56
L56:tst.l (sp)+
movem.l (sp)+,R7-R7/R12-R13
unlk R14
rts
.globl _write
.text
_write:
~~write:
~i=R7
~p=R13
~q=R12
~mode=9
link R14,#0
movem.l R6-R7/R12-R13,-(sp)
tst _tbvalid
beq L10004
move _tbtrk,R0
cmp _settrk,R0
bne L10004
move _tbdsk,R0
cmp _setdsk,R0
beq L62
L10004:jsr _filltb
L62:
move _setsec,R0
sub #1,R0
asl #7,R0
ext.l R0
move.l R0,R13
add.l #_trkbuf,R13
move.l _setdma,R12
move #128,R7
L65:
move.b (R12)+,(R13)+
sub #1,R7
L64:
tst R7
bne L65
L63:
move #1,_tbdirty
cmp.b #1,9(R14)
bne L66
jsr _flush
L66:
clr R0
bra L61
L61:tst.l (sp)+
movem.l (sp)+,R7-R7/R12-R13
unlk R14
rts
.globl _sectran
.text
_sectran:
~~sectran:
~s=8
~xp=10
link R14,#-4
move 8(R14),R8
move.l 10(R14),R9
move.b 0(R8,R9.l),R0
ext.w R0
bra L67
L67:unlk R14
rts
.globl _setxvect
.text
_setxvect:
~~setxvect:
~oldval=R7
~vloc=R13
~vval=10
~vnum=8
link R14,#0
movem.l R6-R7/R13-R13,-(sp)
move 8(R14),R0
ext.l R0
asl.l #2,R0
move.l R0,R13
move.l (R13),R7
move.l 10(R14),(R13)
move.l R7,R0
bra L68
L68:tst.l (sp)+
movem.l (sp)+,R7-R7/R13-R13
unlk R14
rts
.globl _seldsk
.text
_seldsk:
~~seldsk:
~logged=11
~dsk=R7
~dphp=R13
~check=R6
link R14,#0
movem.l R5-R7/R13-R13,-(sp)
move.b 9(R14),R7
cmp.b #3,R7
ble L70
move.l #$0,R0
bra L69
L70:
move.b R7,R0
ext.w R0
move R0,_setdsk
move.b R7,R0
ext.w R0
muls #26,R0
move.l R0,R13
add.l #_dphtab,R13
tst.b 11(R14)
bne L71
move.l #_cnvdsk,R0
move _setdsk,R1
ext.l R1
add.l R1,R0
move.l R0,R8
move.b (R8),3+_hmpack
move.b #48,4+_hmpack
move.b #2,5+_hmpack
move.b #6,$ff0183
tst.b $ff0101
beq L72
move.l #L73,(sp)
jsr _bioserr
bra L74
L72:
move #7,(sp)
move.l #_hmpack,-(sp)
jsr _sendpkt
add #4,sp
L74:L76:
cmp #1,_dskstate
bne L75
bra L76
L75:
cmp #2,_dskstate
bne L77
move.l #L78,(sp)
jsr _bioserr
L77:L80:
cmp #3,_dskstate
bne L79
bra L80
L79:
move.b $ff019d,R6
move.b R6,R0
ext.w R0
bra L82
L83:
move.l #_dpb0,14(R13)
bra L81
L84:
move.l #_dpb1,14(R13)
bra L81
L85:
move.l #L86,(sp)
jsr _bioserr
bra L81
bra L81
L82:cmp #3,R0
beq L83
cmp #7,R0
beq L84
bra L85
L81:L71:
move.l R13,R0
bra L69
L69:tst.l (sp)+
movem.l (sp)+,R6-R7/R13-R13
unlk R14
rts
.globl _biosinit
.text
_biosinit:
~~biosinit:
link R14,#-4
move.l #$ffee011,(sp)
jsr _portinit
move.l #$ffee015,(sp)
jsr _portinit
L87:unlk R14
rts
.globl _bios
.text
_bios:
~~bios:
~d0=8
~d1=10
~d2=14
link R14,#-4
move 8(R14),R0
bra L90
L91:
jsr _init
bra L89
L92:
jsr _wboot
bra L89
L93:
move.l #$ffee011,(sp)
jsr _portstat
ext.l R0
bra L88
bra L89
L94:
move.l #$ffee011,(sp)
jsr _portin
ext.l R0
bra L88
bra L89
L95:
move.l 10(R14),R0
move R0,(sp)
move.l #$ffee011,-(sp)
jsr _portout
add #4,sp
bra L89
L96:L97:
move.l 10(R14),R0
move R0,(sp)
move.l #$ffee015,-(sp)
jsr _portout
add #4,sp
bra L89
L98:
move.l #$ffee015,(sp)
jsr _portin
ext.l R0
bra L88
bra L89
L99:
clr _settrk
bra L89
L100:
move.l 14(R14),R0
move R0,(sp)
move.l 10(R14),R0
move R0,-(sp)
jsr _seldsk
add #2,sp
bra L88
bra L89
L101:
move.l 10(R14),R0
move R0,_settrk
bra L89
L102:
move.l 10(R14),R0
move R0,_setsec
bra L89
L103:
move.l 10(R14),_setdma
bra L89
L104:
jsr _read
ext.l R0
bra L88
bra L89
L105:
move.l 10(R14),R0
move R0,(sp)
jsr _write
ext.l R0
bra L88
bra L89
L106:
move.l #$ffee015,(sp)
jsr _portstat
ext.l R0
bra L88
bra L89
L107:
move.l 14(R14),(sp)
move.l 10(R14),R0
move R0,-(sp)
jsr _sectran
add #2,sp
ext.l R0
bra L88
bra L89
L108:
move.l #_memtab,R0
bra L88
bra L89
L109:
move _iobyte,R0
ext.l R0
bra L88
bra L89
L110:
move.l 10(R14),R0
move R0,_iobyte
bra L89
L111:
jsr _flush
ext.l R0
bra L88
bra L89
L112:
move.l 14(R14),(sp)
move.l 10(R14),R0
move R0,-(sp)
jsr _setxvect
add #2,sp
bra L88
bra L89
bra L89
L90:cmp #22,R0
bhi L89
asl #2,R0
move R0,R8
add.l #L113,R8
move.l (R8),R8
jmp (R8)
.data
L113:.dc.l L91
.dc.l L92
.dc.l L93
.dc.l L94
.dc.l L95
.dc.l L96
.dc.l L97
.dc.l L98
.dc.l L99
.dc.l L100
.dc.l L101
.dc.l L102
.dc.l L103
.dc.l L104
.dc.l L105
.dc.l L106
.dc.l L107
.dc.l L89
.dc.l L108
.dc.l L109
.dc.l L110
.dc.l L111
.dc.l L112
.text
L89:L88:unlk R14
rts
.data
L11:.dc.b 10,13,66,73,79,83,32,69,82,82,79,82,32,45,45,32,0
L12:.dc.b 46,10,13,0
L31:.dc.b 69,120,112,101,99,116,101,100,32,65,67,75,32,111,114,32,78,65,75,0
L35:.dc.b 69,120,112,101,99,116,101,100,32,115,116,97,116,117,115,32,112,97,99,107,101,116,32,102,114,111,109,32,73,80,67,0
L41:.dc.b 78,65,75,32,102,114,111,109,32,73,80,67,0
L49:.dc.b 78,65,75,32,102,114,111,109,32,73,80,67,0
L73:.dc.b 69,82,82,32,54,0
L78:.dc.b 78,65,75,32,102,114,111,109,32,73,80,67,0
L86:.dc.b 69,82,82,32,55,0

View File

@@ -0,0 +1,49 @@
.text
.globl _init
.globl _wboot
.globl _bios
.globl _dskia
.globl _dskic
.globl _setimask
*
ccp = $18000 ccp entry point
rtp = $1dc00 rtp entry point
*
_init: lea entry,a0
move.l a0,$8C
lea _dskia,a0
move.l a0,$3fc
clr.l d0
move.l #rtp,$84 setup rtp trap
move #$2000,sr
jmp ccp
*
_wboot: clr.l d0
jmp ccp
*
entry: move.l d2,-(a7)
move.l d1,-(a7)
move.w d0,-(a7)
jsr _bios
add #10,a7
rte
*
_dskia: link a6,#0
movem.l d0-d7/a0-a5,-(a7)
jsr _dskic
movem.l (a7)+,d0-d7/a0-a5
unlk a6
rte
*
_setimask: move sr,d0
lsr #8,d0
and.l #7,d0
move sr,d1
ror.w #8,d1
and.w #$fff8,d1
add.w 4(a7),d1
ror.w #8,d1
move d1,sr
rts
*
.end

View File

@@ -0,0 +1,850 @@
/*=======================================================================*/
/*/---------------------------------------------------------------------\*/
/*| |*/
/*| CP/M-68K(tm) BIOS for the EXORMACS |*/
/*| |*/
/*| Copyright 1982, Digital Research. |*/
/*| |*/
/*\---------------------------------------------------------------------/*/
/*=======================================================================*/
#define DEBUG 0
#define TRACEPORT 0xffee015
#include "[bill.cpm68k.csupport]stdtypes.h"
char copyright[] = "Copyright 1982, Digital Research";
struct memb { BYTE byte; };
struct memw { WORD word; };
struct meml { LONG lword;};
/************************************************************************/
/* I/O Device Definitions */
/************************************************************************/
/************************************************************************/
/* Define the two ACIA ports on the DEBUG board */
/************************************************************************/
#define PORT1 0xFFEE011
#define PORT2 0xFFEE015
#define PORTCTRL 0
#define PORTSTAT 0
#define PORTRDR 2
#define PORTTDR 2
#define PORTRSET 3
#define PORTINIT 0x11
#define PORTRDRF 1
#define PORTTDRE 2
/************************************************************************/
/* Define Disk I/O Addresses and Related Constants */
/************************************************************************/
#define DSKIPC 0xFF0000 /* IPC Base Address */
#define DSKINTV 0x3FC /* Address of Disk Interrupt Vector */
#define INTTOIPC 0xD /* offsets */
#define RSTTOIPC 0xF
#define MSGTOIPC 0x101
#define ACKTOIPC 0x103
#define PKTTOIPC 0x105
#define MSGFMIPC 0x181
#define ACKFMIPC 0x183
#define PKTFMIPC 0x185
#define DSKREAD 0x10
#define DSKWRITE 0x20
#define STX 0x02
#define ETX 0x03
#define ACK 0x06
#define NAK 0x15
/************************************************************************/
/* BIOS Table Definitions */
/************************************************************************/
struct dpb
{
WORD spt;
BYTE bsh;
BYTE blm;
BYTE exm;
BYTE dpbjunk;
WORD dsm;
WORD drm;
BYTE al0;
BYTE al1;
WORD cks;
WORD off;
};
struct dph
{
BYTE *xltp;
WORD dphscr[3];
BYTE *dirbufp;
struct dpb *dpbp;
BYTE *csvp;
BYTE *alvp;
};
/************************************************************************/
/* Directory Buffer for use by the BDOS */
/************************************************************************/
BYTE dirbuf[128];
/************************************************************************/
/* CSV's */
/************************************************************************/
BYTE csv0[16];
BYTE csv1[16];
BYTE csv2[16];
/************************************************************************/
/* ALV's */
/************************************************************************/
BYTE alv0[32]; /* (dsm0 / 8) + 1 */
BYTE alv1[32]; /* (dsm1 / 8) + 1 */
BYTE alv2[2002]; /* (dsm2 / 8) + 1 */
/************************************************************************/
/* Disk Parameter Blocks */
/************************************************************************/
/* The following dpb definitions express the intent of the writer, */
/* unfortunately, due to a compiler bug, these lines cannot be used. */
/* Therefore, the obscure code following them has been inserted. */
/************* spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off
struct dpb dpb0={ 26, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb1={ 26, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2};
struct dpb dpb2={ 26, 3, 7, 0, 0, 16008, 63, 0xC0, 0, 16, 2};
********** end of readable definitions *************/
/* The Alcyon C compiler assumes all structures are arrays of int, so */
/* in the following definitions, adjacent pairs of chars have been */
/* combined into int constants --- what a kludge! **********************/
struct dpb dpb0 = { 26, 775, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb1 = { 26, 1039, 0, 242, 63, -16384, 16, 2 };
struct dpb dpb2 = { 26, 775, 0, 16008, 63, -16384, 16, 2 };
/*************** End of kludge *****************/
/************************************************************************/
/* Sector Translate Table */
/************************************************************************/
BYTE xlt[26] = { 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15, 21,
2, 8, 14, 20, 26, 6, 12, 18, 24, 4, 10, 16, 22 };
/************************************************************************/
/* Disk Parameter Headers */
/* */
/* Four disks are defined : dsk a: diskno=0, dev name=#fd04 */
/* dsk b: diskno=1, dev name=#fd05 */
/* dsk c: diskno=2, dev name=#hd00 */
/* dsk d: diskno=3, dev name=#hd01 */
/************************************************************************/
struct dph dphtab[4] =
{ {&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv0, &alv0}, /*dsk a*/
{&xlt, 0, 0, 0, &dirbuf, &dpb0, &csv1, &alv1}, /*dsk b*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk c*/
{ 0L, 0, 0, 0, &dirbuf, &dpb2, &csv2, &alv2}, /*dsk d*/
};
/************************************************************************/
/* Memory Region Table */
/************************************************************************/
struct mrt { WORD count;
LONG tpalow;
LONG tpalen;
}
memtab = { 1, 0x0002,0x0000, 0x0003,0xfff0 };/* kludge init by int */
/************************************************************************/
/* IOBYTE */
/************************************************************************/
WORD iobyte;
/************************************************************************/
/* Currently Selected Disk Stuff */
/************************************************************************/
WORD settrk, setsec, setdsk;
BYTE *setdma;
/************************************************************************/
/* Track Buffering Definitions and Variables */
/************************************************************************/
#define NUMTB 10 /* must be at least 3 for some algorithms */
struct tbstr {
struct tbstr *nextbuf;
BYTE buf[26*128];
WORD dsk;
WORD trk;
BYTE valid;
BYTE dirty;
};
struct tbstr *firstbuf;
struct tbstr *lastbuf;
struct tbstr tbuf[NUMTB];
/************************************************************************/
/* Disk I/O Packets for the UDC and other Disk I/O Variables */
/************************************************************************/
struct hmpkst {
BYTE a1;
BYTE a2;
BYTE a3;
BYTE dskno;
BYTE com1;
BYTE com2;
BYTE a6;
BYTE a7;
}
hmpack = { 512, 1792, 0, 768 }; /* kludge init by words */
struct rwpkst {
BYTE stxchr;
BYTE pktid;
BYTE pktsize;
BYTE dskno;
BYTE chcmd;
BYTE devcmd;
WORD numblks;
WORD blksize;
LONG iobf;
WORD cksum;
LONG lsect;
BYTE etxchr;
BYTE rwpad;
};
struct rwpkst rwpack = { 512, 5376, 4097, 13, 256, 0, 0, 0, 0, 0, 768 };
BYTE cnvdsk[4] = { 4, 5, 0, 1 }; /* convert from CP/M dsk # to Exormacs */
#define MAXDSK 3
#define DSKIDLE 0
#define MSGSENT 1
#define NAKRCVD 2
#define ACKRCVD 3
#define IODONE 4
#define DSKERROR 5
WORD dskstate = DSKIDLE;
/************************************************************************/
/* Generic Serial Port I/O Procedures */
/************************************************************************/
portinit(port)
REG BYTE *port;
{
*(port + PORTCTRL) = PORTRSET;
*(port + PORTCTRL) = PORTINIT;
}
portstat(port)
REG BYTE *port;
{
return ( *(port + PORTSTAT) & PORTRDRF) == PORTRDRF;
}
BYTE portin(port)
REG BYTE *port;
{
while (portstat(port) == 0) ;
return *(port + PORTRDR);
}
portout(port, ch)
REG BYTE *port;
REG BYTE ch;
{
while ( (*(port + PORTSTAT) & PORTTDRE) != PORTTDRE) ;
*(port + PORTTDR) = ch;
}
/************************************************************************/
/* Error procedure for BIOS */
/************************************************************************/
bioserr(errmsg)
REG BYTE *errmsg;
{
printstr("\n\rBIOS ERROR -- ");
printstr(errmsg);
printstr(".\n\r");
}
printstr(s) /* used by bioserr */
REG BYTE *s;
{
while (*s) {portout(PORT1,*s); s += 1; };
}
#if DEBUG
printrace(s)
REG BYTE *s;
{
while (*s) {portout(TRACEPORT, *s); s += 1;}
}
printnum(n)
REG LONG n;
{
REG WORD i;
REG BYTE d;
i = 32;
while (i)
{
i -= 4;
d = (n >> i) & 0x0fL;
if ( d <= '9' ) d = d + '0';
else d = d - 10 + 'a';
portout(TRACEPORT, d);
}
portout(TRACEPORT, ' ');
}
printds(ds)
WORD ds;
{
switch(ds){
case DSKIDLE: printrace("DSKIDLE");
break;
case MSGSENT: printrace("MSGSENT");
break;
case NAKRCVD: printrace("NAKRCVD");
break;
case ACKRCVD: printrace("ACKRCVD");
break;
case IODONE: printrace("IODONE");
break;
case DSKERROR: printrace("DSKERROR");
break;
default: printrace("Invalid");
break;
}
}
#endif
/************************************************************************/
/* Disk I/O Procedures */
/************************************************************************/
EXTERN dskia();
EXTERN setimask();
dskic()
{
/* Disk Interrupt Handler -- C Language Portion */
#if DEBUG
printrace("\n\rDisk Interrupt ");
printds(dskstate);
printrace("->");
#endif
switch ( dskstate )
{
case DSKIDLE: ;
case IODONE: ;
case DSKERROR:;
case NAKRCVD: {
if ( ((DSKIPC+ACKFMIPC)->byte == ACK) ||
((DSKIPC+ACKFMIPC)->byte == NAK) )
{
(DSKIPC+ACKFMIPC)->byte = 0;
}
if ( (DSKIPC+MSGFMIPC)->byte == 0x80 )
{
(DSKIPC+ACKTOIPC)->byte = ACK;
(DSKIPC+MSGFMIPC)->byte = 0;
(DSKIPC+INTTOIPC)->byte = 0;
}
}
break;
case MSGSENT: {
if ( (DSKIPC+ACKFMIPC)->byte == ACK )
{
(DSKIPC+ACKFMIPC)->byte = 0;
dskstate = ACKRCVD;
}
else if ( (DSKIPC+ACKFMIPC)->byte == NAK )
{
(DSKIPC+ACKFMIPC)->byte = 0;
dskstate = NAKRCVD;
}
else
{
bioserr("Expected ACK or NAK");
dskstate = DSKERROR;
return;
}
if ( (DSKIPC+MSGFMIPC)->byte == 0x80 )
{ dskstate = IODONE; }
}
break;
case ACKRCVD: {
if ( (DSKIPC+MSGFMIPC)->byte != 0x80 )
{ bioserr("Expected status packet from IPC");}
else dskstate = IODONE;
(DSKIPC+MSGFMIPC)->byte = 0;
(DSKIPC+ACKTOIPC)->byte = ACK;
(DSKIPC+INTTOIPC)->byte = 0;
}
break;
}
#if DEBUG
printds(dskstate);
printrace("\n\r");
#endif
} /* end of dskic */
sendpkt(pktadr, pktsize)
REG BYTE *pktadr;
REG WORD pktsize;
{
REG BYTE *iopackp;
REG WORD imsave;
while ( (DSKIPC+MSGTOIPC)->byte ); /* wait til ready */
if ( (DSKIPC+ACKFMIPC)->byte == NAK ) bioserr("NAK from IPC");
(DSKIPC+ACKFMIPC)->byte = 0;
(DSKIPC+MSGFMIPC)->byte = 0;
iopackp = (DSKIPC+PKTTOIPC);
do {*iopackp = *pktadr++; iopackp += 2; pktsize -= 1;} while(pktsize);
(DSKIPC+MSGTOIPC)->byte = 0x80;
imsave = setimask(7);
dskstate = MSGSENT;
(DSKIPC+INTTOIPC)->byte = 0;
setimask(imsave);
}
dskxfer(dsk, trk, bufp, cmd)
REG WORD dsk, trk, cmd;
REG BYTE *bufp;
{
/* build packet */
rwpack.dskno = cnvdsk[dsk];
rwpack.iobf = bufp;
rwpack.lsect = trk * 13;
rwpack.chcmd = cmd;
sendpkt(&rwpack, 21);
while (dskstate == MSGSENT); /* wait */
if (dskstate == NAKRCVD) bioserr("NAK from IPC");
while (dskstate == ACKRCVD); /* wait */
}
flush1(tbp)
REG struct tbstr *tbp;
{
if ( tbp->valid && tbp->dirty )
dskxfer(tbp->dsk, tbp->trk, tbp->buf, DSKWRITE);
tbp->dirty = 0;
return(0);
}
flush()
{
REG struct tbstr *tbp;
tbp = firstbuf;
while (tbp)
{
flush1(tbp);
tbp = tbp->nextbuf;
}
}
fill(tbp)
REG struct tbstr *tbp;
{
if ( tbp->valid && tbp->dirty ) flush1(tbp);
dskxfer(setdsk, settrk, tbp->buf, DSKREAD);
tbp->valid = 1;
tbp->dirty = 0;
tbp->trk = settrk;
tbp->dsk = setdsk;
}
struct tbstr *gettrk()
{
REG struct tbstr *tbp;
REG struct tbstr *ltbp;
REG struct tbstr *mtbp;
tbp = firstbuf;
ltbp = 0;
mtbp = 0;
while (tbp)
{
if ( (tbp->valid) && (tbp->dsk == setdsk)
&& (tbp->trk == settrk) )
{
if (ltbp)
{
ltbp->nextbuf = tbp->nextbuf;
tbp->nextbuf = firstbuf;
firstbuf = tbp;
}
return tbp;
}
else
{
mtbp = ltbp;
ltbp = tbp;
tbp = tbp->nextbuf;
}
}
if (mtbp) mtbp->nextbuf = 0; /* detach lru buffer */
if ( (! firstbuf->valid) ||
(firstbuf->trk > dphtab[firstbuf->dsk].dpbp->off) ) /* dir trk? */
{
ltbp->nextbuf = firstbuf;
firstbuf = ltbp;
}
else
{
ltbp->nextbuf = firstbuf->nextbuf;
firstbuf->nextbuf = ltbp;
}
flush1(ltbp);
fill(ltbp);
return ltbp;
}
read()
{
REG BYTE *p;
REG BYTE *q;
REG WORD i;
REG struct tbstr *tbp;
tbp = gettrk();
p = (tbp->buf) + ((setsec-1) << 7); /* multiply by shifting */
q = setdma;
i = 128;
do {*q++ = *p++; i -= 1;} while (i);
return(0);
}
write(mode)
BYTE mode;
{
REG BYTE *p;
REG BYTE *q;
REG WORD i;
REG struct tbstr *tbp;
tbp = gettrk();
p = (tbp->buf) + ((setsec-1) << 7); /* multiply by shifting */
q = setdma;
i = 128;
if ( (mode != 1) || (tbp->dirty) ) /* normal case */
{
do {*p++ = *q++; i -= 1;} while (i);
tbp->dirty = 1;
}
else /* for dir write, only mark dirty if changed. */
{
do
{
if (*p != *q) tbp->dirty=1;
*p++ = *q++;
i -= 1;
}
while (i);
}
if ( mode == 1 ) flush();
return(0);
}
BYTE sectran(s, xp)
WORD s;
BYTE *xp;
{
return xp[s];
}
LONG setxvect(vnum, vval)
WORD vnum;
LONG vval;
{
REG LONG oldval;
REG BYTE *vloc;
vloc = ( (long)vnum ) << 2;
oldval = vloc->lword;
vloc->lword = vval;
return(oldval);
}
LONG seldsk(dsk, logged)
REG BYTE dsk;
BYTE logged;
{
REG struct dph *dphp;
REG BYTE check;
if (dsk > MAXDSK) return(0L);
setdsk = dsk;
dphp = &dphtab[dsk];
if ( ! logged )
{
hmpack.dskno = cnvdsk[setdsk];
hmpack.com1 = 0x30;
hmpack.com2 = 0x02;
(DSKIPC+ACKFMIPC)->byte = 6;
if ( (DSKIPC+MSGTOIPC)->byte ) {bioserr("ERR 6"); return 0L;}
else sendpkt(&hmpack, 7);
while ( dskstate == MSGSENT ); /* wait */
if (dskstate == NAKRCVD) {bioserr("NAK from IPC"); return 0L;}
while ( dskstate == ACKRCVD ); /* wait */
check = (DSKIPC+PKTFMIPC+0x18)->byte;
switch ( check )
{
case 3: dphp->dpbp = &dpb0;
break;
case 7: dphp->dpbp = &dpb1;
break;
default: {bioserr("ERR 7"); return 0L;}
break;
}
}
return(dphp);
}
/************************************************************************/
/* BIOS PROPER */
/************************************************************************/
biosinit()
{
REG WORD i;
portinit(PORT1);
portinit(PORT2);
for ( i = 0; i < NUMTB; ++i )
{
tbuf[i].valid = 0;
tbuf[i].dirty = 0;
if ( (i+1) < NUMTB ) tbuf[i].nextbuf = &tbuf[i+1];
else tbuf[i].nextbuf = 0;
}
firstbuf = &tbuf[0];
lastbuf = &tbuf[NUMTB-1];
}
LONG bios(d0, d1, d2)
WORD d0;
LONG d1, d2;
{
#if DEBUG
if ( d0 > 7) {
printrace("\n\rBIOS( ");
printnum((long)d0);
printnum(d1);
printnum(d2);
printrace(")\n\r");
}
#endif
switch(d0)
{
case 0: init(); /* INIT */
break;
case 1: wboot(); /* WBOOT */
break;
case 2: return(portstat(PORT1)); /* CONST */
break;
case 3: return(portin(PORT1)); /* CONIN */
break;
case 4: portout(PORT1, (char)d1); /* CONOUT */
break;
case 5: ; /* LIST */
case 6: portout(PORT2, (char)d1); /* PUNCH */
break;
case 7: return(portin(PORT2)); /* READER */
break;
case 8: settrk = 0; /* HOME */
break;
case 9: return(seldsk((char)d1, (char)d2)); /* SELDSK */
break;
case 10: settrk = (int)d1; /* SETTRK */
break;
case 11: setsec = (int)d1; /* SETSEC */
break;
case 12: setdma = d1; /* SETDMA */
break;
case 13: return(read()); /* READ */
break;
case 14: return(write((char)d1)); /* WRITE */
break;
case 15: return(portstat(PORT2)); /* LISTST */
break;
case 16: return(sectran((int)d1, d2)); /* SECTRAN */
break;
case 18: return(&memtab); /* GMRTA */
break;
case 19: return(iobyte); /* GETIOB */
break;
case 20: iobyte = (int)d1; /* SETIOB */
break;
case 21: return(flush()); /* FLUSH */
break;
case 22: return(setxvect((int)d1,d2)); /* SETXVECT */
break;
} /* end switch */
} /* end bios procedure */
/* End of C Bios */

View File

@@ -0,0 +1,23 @@
/************************************************/
/* */
/* Definitions for use with C programs */
/* according to CP/M-68K (tm) standard */
/* coding practices */
/* */
/************************************************/
#define LONG long
#define ULONG unsigned long
#define WORD short int
#define UWORD unsigned short
#define BYTE char
#define UBYTE unsigned char
#define VOID
#define REG register
#define LOCAL auto
#define MLOCAL static
#define GLOBAL extern
#define EXTERN extern
/************************************************/

View File

@@ -0,0 +1 @@
$ as68 -p -L 'p1'.s >'p1'.lis

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,97 @@
.globl _bios1
.globl _bios2
.globl _bios3
.globl _bios4
.globl _bios5
.globl _copyrt
.data
_copyrt:
.dc.l L1
.globl _serial
.data
_serial:
.dc.l L2
.globl _seldisk
.globl _openfile
.globl _dirscan
.globl _seqread
.globl _gbls
.comm _gbls,16
.globl __bdos
.text
__bdos:
~~_bdos:
~infop=R13
~info=R6
~func=R7
link R14,#0
movem.l R5-R7/R13-R13,-(sp)
move 8(R14),R7
move 10(R14),R6
move.l 12(R14),R13
move R7,R0
bra L5
L6:
move.b R6,R0
ext.w R0
move R0,(sp)
move #4,-(sp)
jsr _bios2
add #2,sp
bra L4
L7:
move R6,(sp)
jsr _seldisk
bra L3
L8:
clr.b (R13)
clr.b 12(R13)
clr.b 14(R13)
move.l R13,(sp)
move.l #_openfile,-(sp)
jsr _dirscan
add #4,sp
bra L3
L9:
clr.b (R13)
move.l R13,(sp)
jsr _seqread
bra L3
L10:
move.l R13,12+_gbls
bra L4
L11:
move #65535,R0
bra L3
bra L4
L5:ext.l R0
move.l #L12,R8
move #5,R1
L13:cmp.l (R8)+,R0
dbeq R1,L13
move.l 20(R8),R8
jmp (R8)
.data
L12:.dc.l 2
.dc.l 14
.dc.l 15
.dc.l 20
.dc.l 26
.dc.l 0
.dc.l L6
.dc.l L7
.dc.l L8
.dc.l L9
.dc.l L10
.dc.l L11
.text
L4:
clr R0
bra L3
L3:tst.l (sp)+
movem.l (sp)+,R6-R7/R13-R13
unlk R14
rts
.data
L1:.dc.b 67,80,47,77,45,54,56,75,40,116,109,41,44,32,86,101,114,115,105,111,110,32,49,46,49,44,32,67,111,112,121,114,105,103,104,116,32,40,99,41,32,49,57,56,51,44,32,68,105,103,105,116,97,108,32,82,101,115,101,97,114,99,104,0
L2:.dc.b 88,88,88,88,45,48,48,48,48,45,54,53,52,51,50,49,0

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,311 @@
.globl _rdsec
.globl _swap
.globl _dirscan
.globl _openfile
.globl _blkindx
.text
_blkindx:
~~blkindx:
~i=R7
~blkshf=R6
~dparmp=R12
~fcbp=R13
link R14,#0
movem.l R5-R7/R12-R13,-(sp)
move.l 8(R14),R13
move.l 8+_gbls,R12
move.b 2(R12),R6
ext.w R6
move.b 12(R13),R0
ext.w R0
move.b 4(R12),R1
ext.w R1
and R1,R0
move #7,R1
sub R6,R1
asl R1,R0
move R0,R7
move R7,R0
move.b 32(R13),R1
ext.w R1
and #255,R1
move R6,R2
asr R2,R1
add R1,R0
bra L1
L1:tst.l (sp)+
movem.l (sp)+,R6-R7/R12-R13
unlk R14
rts
.globl _blknum
.text
_blknum:
~~blknum:
~index=R7
~wrdfcb=14
~fcbp=R13
link R14,#0
movem.l R6-R7/R13-R13,-(sp)
move.l 8(R14),R13
move 12(R14),R7
tst 14(R14)
beq L3
move R7,R8
add.l R8,R8
move 16(R13,R8.l),(sp)
jsr _swap
bra L2
bra L4
L3:
move.b 16(R13,R7),R0
ext.w R0
and #255,R0
bra L2
L4:L2:tst.l (sp)+
movem.l (sp)+,R7-R7/R13-R13
unlk R14
rts
.globl _do_io
.text
_do_io:
~~do_io:
~block=8
~dparmp=R13
~lsec=-4
~rcrd=11
link R14,#-4
movem.l R7-R7/R13-R13,-(sp)
move.l 8+_gbls,R13
clr.l R0
move 8(R14),R0
move.b 2(R13),R1
ext.w R1
ext.l R1
asl.l R1,R0
move.b 3(R13),R1
ext.w R1
move.b 11(R14),R2
ext.w R2
and R2,R1
ext.l R1
add.l R1,R0
move.l R0,-4(R14)
move.l 12+_gbls,(sp)
move.l -4(R14),-(sp)
jsr _rdsec
add #4,sp
bra L5
L5:tst.l (sp)+
movem.l (sp)+,R13-R13
unlk R14
rts
.globl _new_ext
.text
_new_ext:
~~new_ext:
~mod=R7
~ext=R6
~fcbp=R13
link R14,#0
movem.l R5-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.b 14(R13),R7
and.b #63,R7
move.b 12(R13),R6
add.b #1,R6
cmp.b #32,R6
blt L7
clr.b R6
add.b #1,R7
L7:
cmp.b #64,R7
blt L8
move #6,R0
bra L6
L8:
move.b R7,R0
ext.w R0
move.b 14(R13),R1
ext.w R1
and #63,R1
cmp R1,R0
bne L9
move.b R6,R0
ext.w R0
move.b 12(R13),R1
ext.w R1
eor R1,R0
move.l 8+_gbls,R9
move.b 4(R9),R1
ext.w R1
not.b R1
and R1,R0
and #31,R0
bne L10
move.b R6,12(R13)
clr R0
bra L6
L10:L9:
move.b R7,14(R13)
move.b R6,12(R13)
move.l R13,(sp)
move.l #_openfile,-(sp)
jsr _dirscan
add #4,sp
cmp #255,R0
blo L11
move #4,R0
bra L6
L11:
clr R0
bra L6
L6:tst.l (sp)+
movem.l (sp)+,R6-R7/R13-R13
unlk R14
rts
.globl _calcext
.text
_calcext:
~~calcext:
~i=R7
~p=R12
~fcbp=R13
link R14,#0
movem.l R6-R7/R12-R13,-(sp)
move.l 8(R14),R13
move #15,R7
lea 32(R13),R12
L15:
tst.b -(R12)
bne L13
sub #1,R7
L14:
tst R7
bne L15
L13:
move.l 8+_gbls,R8
cmp #255,6(R8)
bls L16
lsr R7
L16:
clr.l R0
move #7,R0
move.l 8+_gbls,R9
move.b 2(R9),R1
ext.w R1
sub R1,R0
lsr R0,R7
move R7,R0
move.l 8+_gbls,R9
move.b 4(R9),R1
ext.w R1
not.b R1
move.b 12(R13),R2
ext.w R2
and R2,R1
and #31,R1
or R1,R0
bra L12
L12:tst.l (sp)+
movem.l (sp)+,R7-R7/R12-R13
unlk R14
rts
.globl _get_rc
.text
_get_rc:
~~get_rc:
~ext=R7
~fcbp=R13
link R14,#0
movem.l R6-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.l R13,(sp)
jsr _calcext
move R0,R7
move.b 12(R13),R0
ext.w R0
cmp R0,R7
bne L18
move.b 15(R13),R0
ext.w R0
and #255,R0
bra L17
bra L19
L18:
move.b 12(R13),R0
ext.w R0
cmp R0,R7
bls L20
move #128,R0
bra L17
bra L21
L20:
clr R0
bra L17
L21:L19:L17:tst.l (sp)+
movem.l (sp)+,R7-R7/R13-R13
unlk R14
rts
.globl _seqread
.text
_seqread:
~~seqread:
~block=R7
~index=R6
~bigfile=R4
~fcbp=R13
~parm=R5
link R14,#0
movem.l R3-R7/R13-R13,-(sp)
move.l 8(R14),R13
move.l 8+_gbls,R8
move 6(R8),R4
and #-256,R4
cmp.b #128,32(R13)
bne L23
move.l R13,(sp)
jsr _new_ext
tst R0
beq L24
move #1,R0
bra L22
L24:
clr.b 32(R13)
L23:
move.l R13,(sp)
jsr _get_rc
move.b 32(R13),R1
ext.w R1
and #255,R1
cmp R1,R0
bhi L25
move #1,R0
bra L22
L25:
move.l R13,(sp)
jsr _blkindx
move R0,R6
move R4,(sp)
move R6,-(sp)
move.l R13,-(sp)
jsr _blknum
add #6,sp
move R0,R7
tst R7
bne L26
move #1,R0
bra L22
L26:
move.b 32(R13),R0
ext.w R0
move R0,(sp)
move R7,-(sp)
jsr _do_io
add #2,sp
add.b #1,32(R13)
bra L22
L22:tst.l (sp)+
movem.l (sp)+,R4-R7/R13-R13
unlk R14
rts
.data

Some files were not shown because too many files have changed in this diff Show More