mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-12-10 07:13:02 +00:00
Upload
Digital Research
This commit is contained in:
14
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/ar.h
Normal file
14
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/ar.h
Normal 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];
|
||||
};
|
||||
752
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/ar68.c
Normal file
752
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/ar68.c
Normal 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();
|
||||
}
|
||||
@@ -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*/
|
||||
101
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/cpm.h
Normal file
101
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/cpm.h
Normal 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 */
|
||||
/****************************/
|
||||
135
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/dump.c
Normal file
135
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/dump.c
Normal 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 */
|
||||
} /****************************/
|
||||
|
||||
238
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/grep.c
Normal file
238
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/grep.c
Normal 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 */
|
||||
} /* */
|
||||
} /****************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
struct iobuf{
|
||||
int fildes;
|
||||
int nunused;
|
||||
char *xfree;
|
||||
char buff[512];
|
||||
};
|
||||
111
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/libfix.c
Normal file
111
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/libfix.c
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
1603
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/lo68.c
Normal file
1603
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/lo68.c
Normal file
File diff suppressed because it is too large
Load Diff
198
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/lo68.h
Normal file
198
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/lo68.h
Normal 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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -0,0 +1 @@
|
||||
$clink ar68,lib:klutz/lib ar68
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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*/
|
||||
@@ -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
|
||||
@@ -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
|
||||
104
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/make.sub
Normal file
104
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/make.sub
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
114
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/nm68.c
Normal file
114
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/nm68.c
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
132
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/nm68.new
Normal file
132
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/nm68.new
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
192
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/prtobj.c
Normal file
192
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/prtobj.c
Normal 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*/
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
$ clink as680,as681,as682,as683,as684,as685,as68inits,lib:klutz/lib as68/debug
|
||||
@@ -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
|
||||
434
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/reloc.c
Normal file
434
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/reloc.c
Normal 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 */
|
||||
} /****************************/
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
103
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/size68.c
Normal file
103
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/asmlink/size68.c
Normal 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);
|
||||
}
|
||||
@@ -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)
|
||||
@@ -0,0 +1,6 @@
|
||||
main()
|
||||
{
|
||||
long i;
|
||||
for(i = -1L; i < 0; i--)
|
||||
printf("i = %8lx\n",i);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
174
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosdef.h
Normal file
174
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosdef.h
Normal 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 */
|
||||
};
|
||||
|
||||
154
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosif.s
Normal file
154
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosif.s
Normal 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
|
||||
@@ -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 *********************************/
|
||||
304
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosmain.c
Normal file
304
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosmain.c
Normal 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;
|
||||
}
|
||||
307
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosmisc.c
Normal file
307
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosmisc.c
Normal 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;
|
||||
}
|
||||
}
|
||||
314
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosrw.c
Normal file
314
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/bdosrw.c
Normal 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);
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
332
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/conbdos.c
Normal file
332
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/conbdos.c
Normal 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 );
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
297
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/dskutil.c
Normal file
297
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/dskutil.c
Normal 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);
|
||||
}
|
||||
291
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/exceptn.s
Normal file
291
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/exceptn.s
Normal 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
|
||||
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/fileio.c
Normal file
659
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/fileio.c
Normal file
@@ -0,0 +1,659 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-68K BDOS File I/O Module *
|
||||
* *
|
||||
* This module contains all file handling BDOS functions *
|
||||
* except for read and write for CP/M-68K. Included are: *
|
||||
* *
|
||||
* seldsk() - select disk *
|
||||
* openfile() - open file *
|
||||
* close_fi() - close file *
|
||||
* search() - search for first/next file match *
|
||||
* create() - create file *
|
||||
* delete() - delete file *
|
||||
* rename() - rename file *
|
||||
* set_attr() - set file attributes *
|
||||
* getsize() - get file size *
|
||||
* setran() - set random record field *
|
||||
* free_sp() - get disk free space *
|
||||
* move() - general purpose byte mover *
|
||||
* *
|
||||
* *
|
||||
* Compiled with Alcyon C on the VAX *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "bdosinc.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
/* declare external fucntions */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN UWORD error(); /* disk error routine */
|
||||
EXTERN UWORD ro_err(); /* read-only file error routine */
|
||||
EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
EXTERN clraloc(); /* clear bit in allocation vector */
|
||||
EXTERN setaloc(); /* set bit in allocation vector */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dir_wr(); /* directory write routine */
|
||||
EXTERN tmp_sel(); /* temporary select disk routine */
|
||||
EXTERN UWORD calcext(); /* calc max extent allocated for fcb */
|
||||
EXTERN UWORD udiv(); /* unsigned divide routine */
|
||||
|
||||
|
||||
/* declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of disks in critical state */
|
||||
|
||||
|
||||
/************************************
|
||||
* This function passed to dirscan *
|
||||
* from seldsk (below) *
|
||||
************************************/
|
||||
|
||||
BOOLEAN alloc(fcbp, dirp, dirindx)
|
||||
/* Set up allocation vector for directory entry pointed to by dirp */
|
||||
|
||||
struct fcb *fcbp; /* not used in this function */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory for *dirp */
|
||||
{
|
||||
REG WORD i; /* loop counter */
|
||||
BSETUP
|
||||
|
||||
if ( UBWORD(dirp->entry) < 0x10 ) /* skip MP/M 2.x and CP/M 3.x XFCBs */
|
||||
{
|
||||
(GBL.dphp)->hiwater = dirindx; /* set up high water mark for disk */
|
||||
i = 0;
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
do setaloc( UBWORD(dirp->dskmap.small[i++]) );
|
||||
while (i <= 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
do setaloc(swap(dirp->dskmap.big[i++]));
|
||||
while (i <= 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* seldsk entry point *
|
||||
************************/
|
||||
|
||||
seldsk(dsknum)
|
||||
|
||||
REG UBYTE dsknum; /* disk number to select */
|
||||
|
||||
{
|
||||
struct iopb selpkt;
|
||||
REG WORD i;
|
||||
UWORD j;
|
||||
REG UBYTE logflag;
|
||||
BSETUP
|
||||
|
||||
logflag = ~(log_dsk >> dsknum) & 1;
|
||||
if ((GBL.curdsk != dsknum) || logflag)
|
||||
{ /* if not last used disk or not logged on */
|
||||
selpkt.iofcn = sel_info;
|
||||
GBL.curdsk = (selpkt.devnum = dsknum);
|
||||
if (UBWORD(dsknum) > 15) error(2);
|
||||
selpkt.ioflags = logflag ^ 1;
|
||||
do
|
||||
{
|
||||
do_phio(&selpkt); /* actually do the disk select */
|
||||
if ( (GBL.dphp = selpkt.infop) != NULL ) break;
|
||||
} while ( ! error(3) );
|
||||
|
||||
GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
/* set up GBL copies of dir_buf and dpb ptrs */
|
||||
GBL.parmp = (GBL.dphp)->dpbp;
|
||||
}
|
||||
if (logflag)
|
||||
{ /* if disk not previously logged on, do it now */
|
||||
LOCK /* must lock the file system while messing with alloc vec */
|
||||
i = (GBL.parmp)->dsm;
|
||||
do clraloc(i); while (i--); /* clear the allocation vector */
|
||||
i = udiv( (LONG)(((GBL.parmp)->drm) + 1),
|
||||
4 * (((GBL.parmp)->blm) + 1), &j);
|
||||
/* calculate nmbr of directory blks */
|
||||
if (j) i++; /* round up */
|
||||
do setaloc(--i); while (i); /* alloc directory blocks */
|
||||
dirscan(alloc, NULL, 0x0e); /* do directory scan & alloc blocks */
|
||||
log_dsk |= 1 << dsknum; /* mark disk as logged in */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* General purpose byte mover *
|
||||
*******************************/
|
||||
|
||||
move(p1, p2, i)
|
||||
|
||||
REG BYTE *p1;
|
||||
REG BYTE *p2;
|
||||
REG WORD i;
|
||||
{
|
||||
while (i--)
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* General purpose filename matcher *
|
||||
*************************************/
|
||||
|
||||
BOOLEAN match(p1, p2, chk_ext)
|
||||
|
||||
REG UBYTE *p1;
|
||||
REG UBYTE *p2;
|
||||
BOOLEAN chk_ext;
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
i = 12;
|
||||
do
|
||||
{
|
||||
temp = (*p1 ^ '?');
|
||||
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
return(FALSE);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
if (chk_ext)
|
||||
{
|
||||
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
return(FALSE);
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* openfile entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN openfile(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx;
|
||||
|
||||
{
|
||||
REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
{
|
||||
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
move(dirp, fcbp, sizeof *dirp);
|
||||
/* copy dir entry into user's fcb */
|
||||
fcbp->extent = fcb_ext;
|
||||
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* flush buffers routine */
|
||||
/*************************/
|
||||
|
||||
UWORD flushit()
|
||||
{
|
||||
REG UWORD rtn; /* return code from flush buffers call */
|
||||
struct iopb flushpkt; /* I/O packet for flush buffers call */
|
||||
|
||||
flushpkt.iofcn = flush;
|
||||
while ( rtn = do_phio(&flushpkt) )
|
||||
if ( error(1) ) break;
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* file close routine for dirscan *
|
||||
*********************************/
|
||||
|
||||
BOOLEAN close(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE *fp;
|
||||
REG UBYTE *dp;
|
||||
REG UWORD fcb_ext;
|
||||
REG UWORD dir_ext;
|
||||
BSETUP
|
||||
|
||||
if ( match(fcbp, dirp, TRUE) )
|
||||
{ /* Note that FCB merging is done here as a final
|
||||
confirmation that disks haven't been swapped */
|
||||
LOCK
|
||||
fp = &(fcbp->dskmap.small[0]);
|
||||
dp = &(dirp->dskmap.small[0]);
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{ /* Small disk map merge routine */
|
||||
i = 16;
|
||||
do
|
||||
{
|
||||
if (*dp)
|
||||
{
|
||||
if (*fp)
|
||||
{
|
||||
if (*dp != *fp) goto badmerge;
|
||||
}
|
||||
else *fp = *dp;
|
||||
}
|
||||
else *dp = *fp;
|
||||
fp += 1;
|
||||
dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
else
|
||||
{ /* Large disk map merge routine */
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (*(UWORD *)dp)
|
||||
{
|
||||
if (*(UWORD *)fp)
|
||||
{
|
||||
if (*(UWORD *)dp != *(UWORD *)fp) goto badmerge;
|
||||
}
|
||||
else *(UWORD *)fp = *(UWORD *)dp;
|
||||
}
|
||||
else *(UWORD *)dp = *(UWORD *)fp;
|
||||
(UWORD *)fp += 1;
|
||||
(UWORD *)dp += 1;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
}
|
||||
/* Disk map merging complete */
|
||||
fcb_ext = calcext(fcbp); /* calc max extent for fcb */
|
||||
dir_ext = (UWORD)(dirp->extent) & 0x1f;
|
||||
if ( (fcb_ext > dir_ext) ||
|
||||
((fcb_ext == dir_ext) &&
|
||||
(UBWORD(fcbp->rcdcnt) > UBWORD(dirp->rcdcnt))) )
|
||||
/* if fcb points to larger file than dirp */
|
||||
{
|
||||
dirp->rcdcnt = fcbp->rcdcnt; /* set up rc, ext from fcb */
|
||||
dirp->extent = (BYTE)fcb_ext;
|
||||
}
|
||||
dirp->s1 = fcbp->s1;
|
||||
if ( (dirp->ftype[robit]) & 0x80) ro_err(fcbp,dirindx);
|
||||
/* read-only file error */
|
||||
dirp->ftype[arbit] &= 0x7f; /* clear archive bit */
|
||||
dir_wr(dirindx >> 2);
|
||||
UNLOCK
|
||||
return(TRUE);
|
||||
|
||||
badmerge:
|
||||
UNLOCK
|
||||
ro_dsk |= (1 << GBL.curdsk);
|
||||
return(FALSE);
|
||||
}
|
||||
else return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* close_fi entry point *
|
||||
************************/
|
||||
|
||||
UWORD close_fi(fcbp)
|
||||
|
||||
struct fcb *fcbp; /* pointer to fcb for file to close */
|
||||
{
|
||||
flushit(); /* first, flush the buffers */
|
||||
if ((fcbp->s2) & 0x80) return(0); /* if file write flag not on,
|
||||
don't need to do physical close */
|
||||
return( dirscan(close, fcbp, 0)); /* call dirscan with close function */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* search entry point *
|
||||
************************/
|
||||
|
||||
/* First two functions for dirscan */
|
||||
|
||||
BOOLEAN alltrue(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
BOOLEAN matchit(p1, p2, i)
|
||||
UBYTE *p1;
|
||||
UBYTE *p2;
|
||||
WORD i;
|
||||
{
|
||||
return(match(p1, p2, TRUE));
|
||||
}
|
||||
|
||||
|
||||
/* search entry point */
|
||||
UWORD search(fcbp, dsparm, p)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to search */
|
||||
REG UWORD dsparm; /* parameter to pass through to dirscan */
|
||||
UBYTE *p; /* pointer to pass through to tmp_sel */
|
||||
|
||||
{
|
||||
REG UWORD rtn; /* return value */
|
||||
BSETUP
|
||||
|
||||
if (fcbp->drvcode == '?')
|
||||
{
|
||||
seldsk(GBL.dfltdsk);
|
||||
rtn = dirscan(alltrue, fcbp, dsparm);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_sel(p); /* temporarily select disk */
|
||||
if (fcbp->extent != '?') fcbp->extent = 0;
|
||||
fcbp->s2 = 0;
|
||||
rtn = dirscan(matchit, fcbp, dsparm);
|
||||
}
|
||||
move( GBL.dirbufp, GBL.dmaadr, SECLEN);
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* create entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN create(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to create */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = ((dirp->entry) == 0xe5) )
|
||||
{
|
||||
p = &(fcbp->rcdcnt);
|
||||
i = 17;
|
||||
do
|
||||
{ /* clear fcb rcdcnt and disk map */
|
||||
*p++ = 0;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
move(fcbp, dirp, sizeof *dirp); /* move the fcb to the directory */
|
||||
dir_wr(dirindx >> 2); /* write the directory sector */
|
||||
if ( dirindx > (GBL.dphp)->hiwater )
|
||||
(GBL.dphp)->hiwater = dirindx;
|
||||
crit_dsk |= 1 << (GBL.curdsk);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* delete entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN delete(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG WORD i;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
dirp->entry = 0xe5;
|
||||
LOCK
|
||||
dir_wr(dirindx >> 2);
|
||||
/* Now free up the space in the allocation vector */
|
||||
if ((GBL.parmp)->dsm < 256)
|
||||
{
|
||||
i = 16;
|
||||
do clraloc(UBWORD(dirp->dskmap.small[--i]));
|
||||
while (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 8;
|
||||
do clraloc(swap(dirp->dskmap.big[--i]));
|
||||
while (i);
|
||||
}
|
||||
UNLOCK
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* rename entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN rename(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p; /* general purpose pointers */
|
||||
REG BYTE *q;
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
if ( (dirp->ftype[robit]) & 0x80 ) ro_err(fcbp,dirindx);
|
||||
/* check for read-only file */
|
||||
p = &(fcbp->dskmap.small[1]);
|
||||
q = &(dirp->fname[0]);
|
||||
i = 11;
|
||||
do
|
||||
{
|
||||
*q++ = *p++ & 0x7f;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* set_attr entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN set_attr(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
REG WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
move(&fcbp->fname[0], &dirp->fname[0], 11);
|
||||
dir_wr(dirindx >> 2);
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
* utility routine used by *
|
||||
* setran and getsize *
|
||||
****************************/
|
||||
|
||||
LONG extsize(fcbp)
|
||||
/* Return size of extent pointed to by fcbp */
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
return( ((LONG)(fcbp->extent & 0x1f) << 7)
|
||||
| ((LONG)(fcbp->s2 & 0x3f) << 12) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* setran entry point *
|
||||
************************/
|
||||
|
||||
setran(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to set ran rec */
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG random;
|
||||
|
||||
random = (LONG)UBWORD(fcbp->cur_rec) + extsize(fcbp);
|
||||
/* compute random record field */
|
||||
fcbp->ran0 = random.b2;
|
||||
fcbp->ran1 = random.b1;
|
||||
fcbp->ran2 = random.b0;
|
||||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* fsize is a funtion for dirscan */
|
||||
/* passed from getsize */
|
||||
/**********************************/
|
||||
|
||||
BOOLEAN fsize(fcbp, dirp, dirindx)
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to delete */
|
||||
REG struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx; /* index into directory */
|
||||
|
||||
{
|
||||
REG BOOLEAN rtn;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
LONG temp;
|
||||
|
||||
if ( rtn = match(fcbp, dirp, FALSE) )
|
||||
{
|
||||
temp = (LONG)UBWORD(dirp->rcdcnt) + extsize(dirp);
|
||||
/* compute file size */
|
||||
fcbp->ran0 = temp.b2;
|
||||
fcbp->ran1 = temp.b1;
|
||||
fcbp->ran2 = temp.b0;
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
|
||||
/************************
|
||||
* getsize entry point *
|
||||
************************/
|
||||
|
||||
getsize(fcbp)
|
||||
/* get file size */
|
||||
REG struct fcb *fcbp; /* pointer to fcb to get file size for */
|
||||
|
||||
{
|
||||
LONG maxrcd;
|
||||
LONG temp;
|
||||
REG WORD dsparm;
|
||||
struct
|
||||
{
|
||||
BYTE b3;
|
||||
BYTE b2;
|
||||
BYTE b1;
|
||||
BYTE b0;
|
||||
};
|
||||
|
||||
maxrcd = 0;
|
||||
dsparm = 0;
|
||||
temp = 0;
|
||||
while ( dirscan(fsize, fcbp, dsparm) < 255 )
|
||||
{ /* loop until no more matches */
|
||||
temp.b2 = fcbp->ran0;
|
||||
temp.b1 = fcbp->ran1;
|
||||
temp.b0 = fcbp->ran2;
|
||||
if (temp > maxrcd) maxrcd = temp;
|
||||
dsparm = 1;
|
||||
}
|
||||
fcbp->ran0 = maxrcd.b2;
|
||||
fcbp->ran1 = maxrcd.b1;
|
||||
fcbp->ran2 = maxrcd.b0;
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* free_sp entry point *
|
||||
************************/
|
||||
|
||||
free_sp(dsknum)
|
||||
|
||||
UBYTE dsknum; /* disk number to get free space of */
|
||||
{
|
||||
REG LONG records;
|
||||
REG UWORD *alvec;
|
||||
REG UWORD bitmask;
|
||||
REG UWORD alvword;
|
||||
REG WORD i;
|
||||
BSETUP
|
||||
|
||||
seldsk(dsknum); /* select the disk */
|
||||
records = (LONG)0; /* initialize the variables */
|
||||
alvec = (GBL.dphp)->alv;
|
||||
bitmask = 0;
|
||||
for (i = 0; i <= (GBL.parmp)->dsm; i++) /* for loop to compute */
|
||||
{
|
||||
if ( ! bitmask)
|
||||
{
|
||||
bitmask = 0x8000;
|
||||
alvword = ~(*alvec++);
|
||||
}
|
||||
if ( alvword & bitmask)
|
||||
records += (LONG)( ((GBL.parmp)->blm) + 1 );
|
||||
bitmask >>= 1;
|
||||
}
|
||||
*(LONG *)GBL.dmaadr = records; /* move # records to DMA address */
|
||||
}
|
||||
78
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/iosys.c
Normal file
78
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/iosys.c
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
537
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/pgmld.s
Normal file
537
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/pgmld.s
Normal 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
|
||||
57
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/pktio.h
Normal file
57
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bdos/pktio.h
Normal 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 */
|
||||
|
||||
@@ -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
|
||||
1342
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/bios.c
Normal file
1342
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/bios.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
1945
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/bios.s
Normal file
1945
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/bios.s
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
50
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/biosa.s
Normal file
50
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/biosa.s
Normal 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
|
||||
@@ -0,0 +1,3 @@
|
||||
#define LOADER 0
|
||||
#define CTLTYPE 0
|
||||
#define MEMDSK 4
|
||||
@@ -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
|
||||
|
||||
/************************************************/
|
||||
@@ -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;*
|
||||
@@ -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;*
|
||||
641
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/chbios.c
Normal file
641
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/chbios.c
Normal 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 */
|
||||
101
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/conv.pli
Normal file
101
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/conv.pli
Normal 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;
|
||||
@@ -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]
|
||||
@@ -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
|
||||
|
||||
288
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/eldbios.s
Normal file
288
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/eldbios.s
Normal 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
|
||||
360
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/ergbios.s
Normal file
360
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/ergbios.s
Normal 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
|
||||
@@ -0,0 +1,2 @@
|
||||
#define LOADER 0
|
||||
#define CTLTYPE 1
|
||||
@@ -0,0 +1,2 @@
|
||||
#define LOADER 1
|
||||
#define CTLTYPE 1
|
||||
1124
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/hdbios.c
Normal file
1124
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/hdbios.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
#define LOADER 1
|
||||
#define CTLTYPE 0
|
||||
@@ -0,0 +1,3 @@
|
||||
#define LOADER 0
|
||||
#define CTLTYPE 0
|
||||
#define MEMDSK 4
|
||||
@@ -0,0 +1 @@
|
||||
$pr/nofeed bios.num,bios.lis,biosa.lis
|
||||
706
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/relbios.c
Normal file
706
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/relbios.c
Normal 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 */
|
||||
@@ -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
|
||||
887
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/relbios.s
Normal file
887
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/relbios.s
Normal 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
|
||||
@@ -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
|
||||
850
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/savebios.c
Normal file
850
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/bios/savebios.c
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
/************************************************/
|
||||
@@ -0,0 +1 @@
|
||||
$ as68 -p -L 'p1'.s >'p1'.lis
|
||||
152
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosdef.h
Normal file
152
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosdef.h
Normal 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 */
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
208
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosread.c
Normal file
208
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosread.c
Normal 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)++) );
|
||||
}
|
||||
|
||||
311
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosread.s
Normal file
311
CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v101/boot/bdosread.s
Normal 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
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for CP/M-68K *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios1(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,parm2)
|
||||
/* set exception vector */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user