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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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