mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 10:24:19 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,958 @@
|
||||
/*=======================================================================*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*| |*/
|
||||
/*| P-CP/M(tm) BIOS for the OLIVETTI M20 (Z8000) |*/
|
||||
/*| |*/
|
||||
/*| Copyright 1982, Zilog Incorporated. |*/
|
||||
/*| |*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*=======================================================================*/
|
||||
|
||||
/* #define DEBUG 1 */
|
||||
|
||||
char copyright[] = "Copyright 1982, Zilog Incorporated";
|
||||
|
||||
|
||||
/* HISTORY
|
||||
**
|
||||
** 820803 S. Savitzky (Zilog) -- derived from 68000 EXORMACS bios
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* I/O Device Definitions */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define Interrupt Controller constants */
|
||||
/************************************************************************/
|
||||
|
||||
/* The interrupt controller is an Intel 8259 left-shifted one bit */
|
||||
/* to allow for the word-alligned interrupt vectors of the Z8000. */
|
||||
|
||||
/* === I am going to assume that this is set up in the PROM === */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define the two USART ports */
|
||||
/************************************************************************/
|
||||
|
||||
/* The USARTs are Intel 8251's */
|
||||
|
||||
#define KBD 0xA1 /* Keyboard USART base */
|
||||
#define RS232 0xC1 /* RS-232 terminal */
|
||||
|
||||
#define SERDATA 0 /* data port offset */
|
||||
#define SERCTRL 2 /* control port offset */
|
||||
#define SERSTAT 2 /* status port offset */
|
||||
|
||||
#define SERINIT 0x37 /* init (3 times) */
|
||||
#define SERRES 0x40 /* reset */
|
||||
#define SERMODE 0xEE /* mode (2 stop, even parity */
|
||||
/* parity disable, 8 bits */
|
||||
/* divide by 16 */
|
||||
/* DUBIOUS. 15?? */
|
||||
#define SERCMD 0x37 /* cmd (no hunt, no reset, */
|
||||
/* RTS=0, error reset, */
|
||||
/* no break, rcv enable, */
|
||||
/* DTR=0, xmt enable */
|
||||
|
||||
#define SERRRDY 0x02 /* RCV ready bit mask */
|
||||
#define SERXRDY 0x01 /* XMT ready bit mask */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define the counter/timer ports */
|
||||
/************************************************************************/
|
||||
|
||||
/* The counter-timer is an Intel 8253 */
|
||||
|
||||
#define CT_232 0x121 /* counter/timer 0 -- RS232 baud rate */
|
||||
#define CT_KBD 0x123 /* counter/timer 1 -- kbd baud rate */
|
||||
#define CT_RTC 0x125 /* counter/timer 2 -- NVI (rt clock) */
|
||||
#define CT_CTRL 0x127 /* counter/timer control port */
|
||||
|
||||
#define CT0CTL 0x36 /* c/t 0 control byte */
|
||||
#define CT1CTL 0x76 /* c/t 1 control byte */
|
||||
#define CT2CTL 0xB4 /* c/t 2 control byte */
|
||||
|
||||
/* control byte is followed by LSB, then MSB of count to data register */
|
||||
/* baud rate table follows: */
|
||||
|
||||
int baudRates[10] = {
|
||||
1538, /* 50 */
|
||||
699, /* 110 */
|
||||
256, /* 300 */
|
||||
128, /* 600 */
|
||||
64, /* 1200 */
|
||||
32, /* 2400 */
|
||||
16, /* 4800 */
|
||||
8, /* 9600 */
|
||||
4, /* 19200 */
|
||||
2 /* 38400 */
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define Parallel Port constants */
|
||||
/************************************************************************/
|
||||
|
||||
/* The parallel (printer) port is an Intel 8255 */
|
||||
|
||||
#define PAR_A 0x81 /* port A data */
|
||||
#define PAR_B 0x83 /* port B data */
|
||||
#define PAR_C 0x85 /* port C data */
|
||||
#define PARCTRL 0x87 /* control port */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* PROM AND HARDWARE INTERFACE */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* Define PROM I/O Addresses and Related Constants */
|
||||
/************************************************************************/
|
||||
|
||||
extern int disk_io(); /* (char drive, cmd -- disk I/O */
|
||||
/* int blk_count, */
|
||||
/* int blk_num, */
|
||||
/* char *dest) -> int error? */
|
||||
|
||||
extern crt_put(); /* (char character) -- put byte to CRT */
|
||||
|
||||
extern cold_boot(); /* boot operating system */
|
||||
|
||||
#define DSKREAD 0 /* disk read command */
|
||||
#define DSKWRITE 1 /* disk write command */
|
||||
#define DSKFMT 2 /* disk format command */
|
||||
#define DSKVFY 3 /* disk verify command */
|
||||
#define DSKINIT 4 /* disk init. command */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Define external I/O routines and addresses */
|
||||
/************************************************************************/
|
||||
|
||||
extern output(); /* (port, data: int) -- output */
|
||||
extern int input(); /* (port: int) -- input */
|
||||
|
||||
/************************************************************************/
|
||||
/* Define external memory management routines */
|
||||
/************************************************************************/
|
||||
|
||||
extern mem_cpy(); /* (src, dest, len: long)-- copy data */
|
||||
extern long map_adr(); /* paddr = (laddr: long; space: int) */
|
||||
|
||||
#define CDATA 0 /* caller data space */
|
||||
#define CCODE 1 /* caller code space */
|
||||
#define SDATA 2 /* system data space */
|
||||
#define SCODE 3 /* system code space */
|
||||
#define NDATA 4 /* normal data space */
|
||||
#define NCODE 5 /* normal code space */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Memory Region Table */
|
||||
/************************************************************************/
|
||||
|
||||
struct mrt { int count;
|
||||
struct {long tpalow;
|
||||
long tpalen;
|
||||
} regions[4];
|
||||
}
|
||||
memtab = {4,
|
||||
0x0A000000L, 0x10000L, /* merged I and D */
|
||||
0x08000000L, 0x10000L, /* separated I */
|
||||
0x08000000L, 0x10000L, /* and D */
|
||||
0x0B000000L, 0x10000L /* accessing I as D */
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* Set Exception Vector entry */
|
||||
/************************************************************************/
|
||||
|
||||
extern long trapvec[]; /* trap vector */
|
||||
|
||||
long setxvect(vnum, vval)
|
||||
int vnum;
|
||||
long vval;
|
||||
{
|
||||
register long oldval;
|
||||
|
||||
oldval = trapvec[vnum];
|
||||
trapvec[vnum] = vval;
|
||||
|
||||
return(oldval);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* CHARACTER I/O */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
/************************************************************************/
|
||||
/* Generic Serial Port I/O Procedures */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
/* define as extern the dirty flag, which is actually defined later */
|
||||
/* on in this file. Used to flush the buffer at an opportune moment. */
|
||||
|
||||
extern int tbdirty;
|
||||
|
||||
serinit(port)
|
||||
int port;
|
||||
{
|
||||
output(port+SERCTRL, SERINIT);
|
||||
output(port+SERCTRL, SERINIT);
|
||||
output(port+SERCTRL, SERINIT);
|
||||
|
||||
output(port+SERCTRL, SERRES);
|
||||
output(port+SERCTRL, SERMODE);
|
||||
output(port+SERCTRL, SERCMD);
|
||||
|
||||
/* === worry about baud rate. assume the PROM sets it up. === */
|
||||
}
|
||||
|
||||
int serirdy(port)
|
||||
int port;
|
||||
{
|
||||
return(((input(port+SERSTAT) & SERRRDY) == SERRRDY) ? 0xFF : 0);
|
||||
}
|
||||
|
||||
|
||||
char serin(port)
|
||||
int port;
|
||||
{
|
||||
while (serirdy(port) == 0) ;
|
||||
return input(port+SERDATA);
|
||||
}
|
||||
|
||||
|
||||
int serordy(port)
|
||||
int port;
|
||||
{
|
||||
return(((input(port+SERSTAT) & SERXRDY) == SERXRDY) ? 0xFF : 0);
|
||||
}
|
||||
|
||||
|
||||
serout(port, ch)
|
||||
int port;
|
||||
char ch;
|
||||
{
|
||||
while ( (input(port + SERSTAT) & SERXRDY) != SERXRDY) ;
|
||||
output(port+SERDATA, ch);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Olivetti keyboard translation table. */
|
||||
/************************************************************************/
|
||||
|
||||
char kbtran[256] = {
|
||||
|
||||
/* Raw key codes for main keypad:
|
||||
|
||||
RE \ A B C D E F G H I J K L M N
|
||||
O P Q R S T U V W X Y Z 0 1 2 3
|
||||
4 5 6 7 8 9 - ^ @ [ ; : ] , . /
|
||||
*/
|
||||
|
||||
/* main keyboard UNSHIFTED. */
|
||||
|
||||
0xDD,'\\', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '-', '^', '@', '[', ';', ':', ']', ',', '.', '/',
|
||||
|
||||
/* main keyboard SHIFTED */
|
||||
|
||||
0xDE, '|', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '!', '"', '#',
|
||||
'$', '%', '&','\'', '(', ')', '=', '~', '`', '{', '+', '*', '}', '<', '>', '?',
|
||||
|
||||
/* main keyboard CONTROL -- CTL B and C differ from Olivetti. */
|
||||
|
||||
0xA0,0x7F,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
|
||||
0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0xE0,0xE1,0xE2,0xE3,
|
||||
0xE4,0xE5,0xD6,0xE7,0xE8,0xE9,0xEA,0xEB,0x00,0xFB,0x1E,0x1F,0x1D,0xFE,0xFF,0xA4,
|
||||
|
||||
/* main keyboard COMMAND */
|
||||
|
||||
0xDF,0xF8,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,
|
||||
0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xEC,0xED,0xEE,0xEF,
|
||||
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0x13,0x1C,0xFC,0xFD,0x9F,0xF9,0xFA,0xA5,
|
||||
|
||||
/* other keys
|
||||
|
||||
SP CR S1 S2
|
||||
KEYPAD . 0 00 1
|
||||
2 3 4 5
|
||||
6 7 8 9
|
||||
+ - * /
|
||||
*/
|
||||
|
||||
/* other keys UNSHIFTED -- CR differs from Olivetti */
|
||||
|
||||
' ','\r',0x7f,0x08,
|
||||
'.', '0',0xA6, '1',
|
||||
'2', '3', '4', '5',
|
||||
'6', '7', '8', '9',
|
||||
'+', '-', '*', '/',
|
||||
|
||||
/* other keys SHIFTED -- CR differs from Olivetti */
|
||||
|
||||
' ','\r',0xA8,0xA9,
|
||||
'.', '0',0xA6,0x1C,
|
||||
0x9A,0x1D,0x9B,0x9C,
|
||||
0x9D,0x1E,0x9E,0x1F,
|
||||
0x2B,0x2D,0x2A,0x2F,
|
||||
|
||||
/* other keys CONTROL */
|
||||
|
||||
' ','\r',0xA8,0xA9,
|
||||
0xB0,0xB1,0xB2,0xB3,
|
||||
0xB4,0xB5,0xB6,0x1B,
|
||||
0xB8,0xB9,0xBA,0xBB,
|
||||
0xBC,0xBD,0xBE,0xBF,
|
||||
|
||||
|
||||
/* special -- substitute \r for Olivetti's 0xAF. */
|
||||
|
||||
'\r','\r','\r','\r'
|
||||
};
|
||||
|
||||
/************************************************************************/
|
||||
/* specific I/O procedures for use with iobyte */
|
||||
/************************************************************************/
|
||||
|
||||
/* CRT status, read, write routines */
|
||||
|
||||
int crtrs()
|
||||
{
|
||||
return( serirdy(KBD));
|
||||
}
|
||||
|
||||
char crtrd()
|
||||
{
|
||||
return( kbtran[serin(KBD) & 0xff]);
|
||||
}
|
||||
|
||||
int crtws()
|
||||
{
|
||||
return(0xFF);
|
||||
}
|
||||
|
||||
#define crtwr crt_put /* output routine in PROM */
|
||||
|
||||
|
||||
/* TTY status, read, write routines */
|
||||
|
||||
int ttyrs()
|
||||
{
|
||||
return(serirdy(RS232));
|
||||
}
|
||||
|
||||
char ttyrd()
|
||||
{
|
||||
return(serin(RS232));
|
||||
}
|
||||
|
||||
int ttyws()
|
||||
{
|
||||
return(serordy(RS232));
|
||||
}
|
||||
|
||||
ttywr(ch)
|
||||
char ch;
|
||||
{
|
||||
serout(RS232, ch);
|
||||
}
|
||||
|
||||
/* LPT status, output routines */
|
||||
|
||||
int lptws()
|
||||
{
|
||||
}
|
||||
|
||||
lptwr(ch) /* ARGSUSED */
|
||||
char ch;
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* generic device names, batch, and null devices */
|
||||
/************************************************************************/
|
||||
|
||||
/* the device names are the offset of the proper field in iobyte */
|
||||
|
||||
#define CON 0
|
||||
#define READER 2
|
||||
#define PUNCH 4
|
||||
#define LIST 6
|
||||
|
||||
|
||||
/* BATCH status, read, write routines */
|
||||
|
||||
int batrs()
|
||||
{
|
||||
int genstat();
|
||||
|
||||
return genstat(READER);
|
||||
}
|
||||
|
||||
char batrd()
|
||||
{
|
||||
int genread();
|
||||
|
||||
return genread(READER);
|
||||
}
|
||||
|
||||
batwr(ch)
|
||||
char ch;
|
||||
{
|
||||
genwrite(LIST, ch);
|
||||
}
|
||||
|
||||
|
||||
/* NULL status, read, write routines */
|
||||
|
||||
int nulst()
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
char nulrd()
|
||||
{
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
nulwr(ch) /* ARGSUSED */
|
||||
char ch;
|
||||
{
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* Generic I/O routines using iobyte */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** IObyte itself.
|
||||
*/
|
||||
|
||||
char iobyte;
|
||||
|
||||
/*
|
||||
** A dummy aligner for the linker bug.
|
||||
*/
|
||||
|
||||
char alignxx;
|
||||
|
||||
|
||||
/*
|
||||
** Device operation tables. DEVINDEX is the index into the
|
||||
** table appropriate to a device (row) and its iobyte index (column)
|
||||
**
|
||||
** nonexistent devices are mapped into NUL.
|
||||
*/
|
||||
|
||||
#define DEVINDEX (((iobyte>>dev) & 3) + (dev * 2) )
|
||||
|
||||
|
||||
int (*sttbl[16])() = {
|
||||
ttyrs, crtrs, batrs, nulst, /* con */
|
||||
ttyrs, nulst, nulst, nulst, /* reader */
|
||||
ttyws, nulst, nulst, nulst, /* punch */
|
||||
ttyws, crtws, lptws, nulst /* list */
|
||||
};
|
||||
|
||||
char (*rdtbl[16])() = {
|
||||
ttyrd, crtrd, batrd, nulrd,
|
||||
ttyrd, nulrd, nulrd, nulrd,
|
||||
nulrd, nulrd, nulrd, nulrd,
|
||||
nulrd, nulrd, nulrd, nulrd
|
||||
};
|
||||
|
||||
int (*wrtbl[16])() = {
|
||||
ttywr, crtwr, batwr, nulwr,
|
||||
nulwr, nulwr, nulwr, nulwr,
|
||||
ttywr, nulwr, nulwr, nulwr,
|
||||
ttywr, crtwr, lptwr, nulwr
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** the generic service routines themselves
|
||||
*/
|
||||
|
||||
int genstat(dev)
|
||||
int dev;
|
||||
{
|
||||
return( (*sttbl[DEVINDEX])() );
|
||||
}
|
||||
|
||||
int genread(dev)
|
||||
int dev;
|
||||
{
|
||||
return( (*rdtbl[DEVINDEX])() );
|
||||
}
|
||||
|
||||
genwrite(dev, ch)
|
||||
int dev;
|
||||
char ch;
|
||||
{
|
||||
(*wrtbl[DEVINDEX])(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) {crtwr(*s); s += 1; };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* DISK I/O */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* BIOS Table Definitions */
|
||||
/************************************************************************/
|
||||
|
||||
struct dpb
|
||||
{
|
||||
int spt; /* sectors per track */
|
||||
char bsh; /* block shift = log2(blocksize/128) */
|
||||
char blm; /* block mask = 2**bsh - 1 */
|
||||
char exm; /* extent mask */
|
||||
char dpbjunk; /* dummy field to allign words */
|
||||
int dsm; /* size of disk less offset, in blocks */
|
||||
int drm; /* size of directory - 1 */
|
||||
char al0; /* reservation bits for directory */
|
||||
char al1; /* ... */
|
||||
int cks; /* size of checksum vector = (drm+1)/4 */
|
||||
int off; /* track offset for OS boot */
|
||||
char psh; /* log2(sectorsize/128) */
|
||||
char psm; /* physical size mask = 2**psh - 1 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct dph
|
||||
{
|
||||
char *xltp; /* -> sector translation table */
|
||||
int dphscr[3]; /* scratchpad for BDOS */
|
||||
char *dirbufp; /* -> directory buffer (128 bytes) */
|
||||
struct dpb *dpbp; /* -> disk parameter block */
|
||||
char *csvp; /* -> software check vector (cks bytes) */
|
||||
char *alvp; /* -> alloc vector ((dsm/8)+1 bytes) */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk Parameter Blocks */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
** CP/M assumes that disks are made of 128-byte logical sectors.
|
||||
**
|
||||
** The Olivetti uses 256-byte sectors on its disks. This BIOS buffers
|
||||
** a track at a time, so sector address translation is not needed.
|
||||
**
|
||||
** Sample tables are included for several different disk sizes.
|
||||
*/
|
||||
|
||||
/* === Olivetti has 3 floppy formats & a hard disk === */
|
||||
|
||||
#define SECSZ 128 /* CP/M logical sector size */
|
||||
#define TRKSZ 32 /* track size for floppies, 1/2 track sz for hd */
|
||||
#define PSECSZ 256 /* Olivetti physical sector size */
|
||||
#define PTRKSZ 16 /* physical track size */
|
||||
#define MAXDSK 3 /* max. number of disks */
|
||||
|
||||
|
||||
/***** spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off, psh, psm */
|
||||
|
||||
struct dpb dpb0= /* --- 1 side, 16*256 sector, 35 track. 140kb --- */
|
||||
{ 32, 4, 15, 1, 0, 50, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb1= /* --- 2 side, 16*256 sector, 35 track. 280kb --- */
|
||||
{ 32, 4, 15, 1, 0, 120, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb2= /* --- 2 side, 16*256 sector, 80 track. 640kb --- */
|
||||
{ 32, 4, 15, 0, 0, 300, 63, 0xC0, 0, 16, 10};
|
||||
struct dpb dpb3= /* --- 6 side, 32*256 sector, 180 trk. 8640kb --- */
|
||||
{ 64, 4, 15, 0, 0, 4296, 63, 0xC0, 0, 16, 10};
|
||||
|
||||
/* bls = 2K dsm = (disk size - 8 reserved tracks) / bls */
|
||||
|
||||
#ifdef SECT26
|
||||
|
||||
/* === The Olivetti does not have 26-sector disks, but many people do.
|
||||
** The following parameter blocks are provided for their use.
|
||||
*/
|
||||
|
||||
struct dpb dpbS= /* --- 1 side, 26*128 sector, 72 trk --- */
|
||||
{ 26, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2};
|
||||
struct dpb dpbD= /* --- 1 side, 26*256 sector, 72 trk --- */
|
||||
{ 52, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2};
|
||||
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* BDOS Scratchpad Areas */
|
||||
/************************************************************************/
|
||||
|
||||
char dirbuf[SECSZ];
|
||||
|
||||
|
||||
char csv0[16];
|
||||
char csv1[16];
|
||||
char csv2[16];
|
||||
|
||||
|
||||
|
||||
char alv0[32]; /* (dsm0 / 8) + 1 */
|
||||
char alv1[32]; /* (dsm1 / 8) + 1 */
|
||||
char alv2[2002]; /* (dsm2 / 8) + 1 */
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Sector Translate Table */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifdef SECT26
|
||||
|
||||
/* === The Olivetti does not have 26-sector disks, but many people do.
|
||||
** The following translate table is provided for their use.
|
||||
*/
|
||||
|
||||
char xlt26[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 };
|
||||
|
||||
#endif
|
||||
|
||||
char xlt16[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,
|
||||
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk Parameter Headers */
|
||||
/* */
|
||||
/* Three disks are defined: dsk a: diskno=0, drive 0 */
|
||||
/* dsk b: diskno=1, drive 1 */
|
||||
/* dsk c: diskno=2, drive 10 */
|
||||
/************************************************************************/
|
||||
|
||||
struct dph dphtab[3] =
|
||||
{ {xlt16, {0, 0, 0}, dirbuf, &dpb1, csv0, alv0}, /*dsk a*/
|
||||
{xlt16, {0, 0, 0}, dirbuf, &dpb1, csv1, alv1}, /*dsk b*/
|
||||
{(char *) 0L, {0, 0, 0}, dirbuf, &dpb2, csv2, alv2}, /*dsk c*/
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Currently Selected Disk Stuff */
|
||||
/************************************************************************/
|
||||
|
||||
int settrk, setsec, setdsk; /* track, sector, disk # */
|
||||
long setdma; /* dma address with segment info: long */
|
||||
|
||||
|
||||
char trkbuf[TRKSZ * SECSZ]; /* track buffer */
|
||||
int tbvalid = 0; /* track buffer valid */
|
||||
int tbdirty = 0; /* track buffer dirty */
|
||||
int tbtrk; /* track buffer track # */
|
||||
int tbdsk; /* track buffer disk # */
|
||||
int dskerr; /* disk error */
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* Disk I/O Procedures */
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
dskxfer(dsk, trk, bufp, cmd) /* transfer a disk track */
|
||||
register int dsk, trk, cmd;
|
||||
register char *bufp;
|
||||
{
|
||||
if (dsk==3) dsk = 10; /* convert hard disk drive # */
|
||||
dskerr=0; /* assume no error */
|
||||
/* do transfer */
|
||||
if (0 != disk_io(dsk, cmd, PTRKSZ, trk*PTRKSZ, map_adr((long)bufp,0)))
|
||||
dskerr=1;
|
||||
}
|
||||
|
||||
|
||||
#define wrongtk ((! tbvalid) || (tbtrk != settrk) || (tbdsk != setdsk))
|
||||
#define gettrk if (wrongtk) filltb()
|
||||
|
||||
|
||||
flush()
|
||||
{
|
||||
|
||||
if ( tbdirty && tbvalid ) dskxfer(tbdsk, tbtrk, trkbuf, DSKWRITE);
|
||||
|
||||
tbdirty = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
filltb()
|
||||
{
|
||||
|
||||
if ( tbvalid && tbdirty ) flush();
|
||||
|
||||
dskxfer(setdsk, settrk, trkbuf, DSKREAD);
|
||||
|
||||
tbvalid = 1;
|
||||
tbdirty = 0;
|
||||
tbtrk = settrk;
|
||||
tbdsk = setdsk;
|
||||
|
||||
}
|
||||
|
||||
|
||||
dskread()
|
||||
{
|
||||
register char *p;
|
||||
|
||||
gettrk;
|
||||
p = &trkbuf[SECSZ * (setsec-1)];
|
||||
|
||||
/* transfer between memory spaces. setdma is physical address */
|
||||
|
||||
mem_cpy(map_adr((long)p, CDATA), setdma, (long)SECSZ);
|
||||
|
||||
return(dskerr);
|
||||
}
|
||||
|
||||
|
||||
dskwrite(mode)
|
||||
char mode;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
gettrk;
|
||||
p = &trkbuf[SECSZ * (setsec-1)];
|
||||
|
||||
/* transfer between memory spaces. setdma is physical address */
|
||||
|
||||
mem_cpy(setdma, map_adr((long) p, CDATA), (long)SECSZ);
|
||||
tbdirty = 1;
|
||||
if ( mode == 1 ) flush();
|
||||
return(dskerr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char sectran(s, xp)
|
||||
int s;
|
||||
char *xp;
|
||||
{
|
||||
if (xp != 0) return xp[s]; else return s;
|
||||
}
|
||||
|
||||
|
||||
struct dph *seldisk(dsk, logged)
|
||||
register char dsk;
|
||||
char logged;
|
||||
{
|
||||
register struct dph *dphp;
|
||||
|
||||
if (dsk > MAXDSK) return(0L);
|
||||
setdsk = dsk;
|
||||
dphp = &dphtab[dsk];
|
||||
if ( ! logged )
|
||||
{
|
||||
|
||||
/* === disk not logged in. select density, etc. === */
|
||||
|
||||
}
|
||||
return(dphp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* BIOS PROPER */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
biosinit()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printstr("\r\nP-CP/M: Olivetti M20 BIOS.");
|
||||
#endif
|
||||
/* serinit(KBD);*/ /* DON'T init keyboard serial port */
|
||||
serinit(RS232); /* init rs232 serial port */
|
||||
|
||||
tbvalid = 0; /* init disk flags */
|
||||
tbdirty = 0;
|
||||
|
||||
iobyte = 0x41; /* con, list = CRT; rdr, punch = TTY */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
long _bios(d0, d1, d2)
|
||||
int d0;
|
||||
long d1, d2;
|
||||
{
|
||||
|
||||
switch(d0)
|
||||
{
|
||||
case 0: /* INIT */
|
||||
biosinit();
|
||||
break;
|
||||
|
||||
case 1: /* WBOOT */
|
||||
wboot();
|
||||
break;
|
||||
|
||||
case 2: /* CONST */
|
||||
return(genstat(CON));
|
||||
break;
|
||||
|
||||
case 3: /* CONIN */
|
||||
return(genread(CON));
|
||||
break;
|
||||
|
||||
case 4: /* CONOUT */
|
||||
genwrite(CON, (char)d1);
|
||||
break;
|
||||
|
||||
case 5: /* LIST */
|
||||
genwrite(LIST, (char)d1);
|
||||
break;
|
||||
|
||||
case 6: /* PUNCH */
|
||||
genwrite(PUNCH, (char)d1);
|
||||
break;
|
||||
|
||||
case 7: /* READER */
|
||||
return(genread(READER));
|
||||
break;
|
||||
|
||||
case 8: /* HOME */
|
||||
settrk = 0;
|
||||
break;
|
||||
|
||||
case 9: /* SELDSK */
|
||||
return((long)seldisk((char)d1, (char)d2));
|
||||
break;
|
||||
|
||||
case 10: /* SETTRK */
|
||||
settrk = (int)d1;
|
||||
break;
|
||||
|
||||
case 11: /* SETSEC */
|
||||
setsec = (int)d1;
|
||||
break;
|
||||
|
||||
case 12: /* SETDMA */
|
||||
setdma = d1;
|
||||
break;
|
||||
|
||||
case 13: /* READ */
|
||||
return(dskread());
|
||||
break;
|
||||
|
||||
case 14: /* WRITE */
|
||||
return(dskwrite((char)d1));
|
||||
break;
|
||||
|
||||
case 15: /* LISTST */
|
||||
return(genstat(LIST));
|
||||
break;
|
||||
|
||||
case 16: /* SECTRAN */
|
||||
return(sectran((int)d1, (char*)d2));
|
||||
break;
|
||||
|
||||
case 18: /* GMRTA */
|
||||
return((long)&memtab);
|
||||
break;
|
||||
|
||||
case 19: /* GETIOB */
|
||||
return((long)iobyte);
|
||||
break;
|
||||
|
||||
case 20: /* SETIOB */
|
||||
iobyte = (char)d1;
|
||||
break;
|
||||
|
||||
case 21: /* FLUSH */
|
||||
flush();
|
||||
return((long)dskerr);
|
||||
break;
|
||||
|
||||
case 22: /* SETXVECT */
|
||||
return(setxvect((int)d1, d2));
|
||||
break;
|
||||
|
||||
|
||||
|
||||
} /* end switch */
|
||||
|
||||
return(0);
|
||||
|
||||
|
||||
} /* end bios procedure */
|
||||
|
||||
|
||||
|
||||
/* End of C Bios */
|
||||
@@ -0,0 +1,390 @@
|
||||
;********** wboot.s -- Olivetti bootstrap writer*****
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- adapt for nonseg.
|
||||
;* 820930 S. Savitzky (Zilog) -- created
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT
|
||||
;*
|
||||
;* This module contains both the bootstrap
|
||||
;* writer, and the code that receives control
|
||||
;* after being booted.
|
||||
;*
|
||||
;* The main function of the latter is to make
|
||||
;* sure that the system, whose entry point is
|
||||
;* called "bios", is passed a valid stack
|
||||
;* and PSA pointer.
|
||||
;*
|
||||
;* Although this code runs segmented, it must
|
||||
;* be linked with non-segmented code, so it
|
||||
;* looks rather odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bootstrap Writer for P-CP/M on the Olivetti M20.
|
||||
;*
|
||||
;* This program puts out a bootstrap file in the
|
||||
;* Olivetti's peculiar format, which has a lot of
|
||||
;* Olivetti's file system in it.
|
||||
;*
|
||||
;* Track 0 is unused except for sector 0, since
|
||||
;* it is single density and thus has smaller
|
||||
;* sectors.
|
||||
;*
|
||||
;* A total of 10 tracks are reserved from CP/M,
|
||||
;* leaving 9 tracks for the system proper.
|
||||
;*
|
||||
;* The first sector on track 1 is the PCOS file
|
||||
;* descriptor block; the second is the boot file
|
||||
;* header and the start of the system code.
|
||||
;*
|
||||
;* This leaves something under 28K for the
|
||||
;* system (BIOS+BDOS+CCP). It is assumed that
|
||||
;* the system starts at its lowest address,
|
||||
;* and that data follows immediately after code.
|
||||
;*
|
||||
;* For now, we assume that the system starts at
|
||||
;* <<11>>0000 (hex)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios
|
||||
.global _wboot
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
SYSTEM .equ 0B000000h ; system address
|
||||
SYSSTK .equ SYSTEM+0BFFEh ; system stack top
|
||||
rtc_ext .equ 02000022h ; real-time clock
|
||||
; ext. call addr
|
||||
|
||||
BPT .equ 16 ; #blocks in a track
|
||||
BPS .equ 256 ; #bytes in a sector
|
||||
NBLKS .equ 9*16 ; #blocks in boot
|
||||
HDRSIZE .equ 24 ; #bytes in header
|
||||
FILSIZE .equ 256*(NBLKS-1) ; file data size
|
||||
SYSSIZE .equ FILSIZE-HDRSIZE ; total system size
|
||||
S1SIZE .equ BPS-HDRSIZE ; data in sector 1
|
||||
|
||||
SEG4 .equ 04000000h
|
||||
SEG2 .equ 02000000h
|
||||
|
||||
SYSPSA .equ SEG2+100h ; system PSA
|
||||
BOOTPSA .equ SEG4+100h ; PSA in PROM for boot
|
||||
|
||||
sscall .macro ;short segmented call
|
||||
.word 05f00h
|
||||
.word ?1
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Entry Points and post-boot Initialization
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* transfer vector
|
||||
|
||||
jr wboot
|
||||
jr wrboot
|
||||
jr entry
|
||||
|
||||
;* post-boot init.
|
||||
|
||||
entry: ;SEGMENTED
|
||||
|
||||
DI VI,NVI
|
||||
|
||||
ldl rr14, #SYSSTK ; init stack pointer
|
||||
|
||||
ldl rr2, #SYSPSA ; copy PROM's PSA
|
||||
ldctl r4, psapseg
|
||||
ldctl r5, psapoff
|
||||
ld r0, #570/2
|
||||
ldir @r2, @r4, r0
|
||||
|
||||
ldl rr2, #SYSPSA ; shift PSA pointer
|
||||
ldctl psapseg, r2
|
||||
ldctl psapoff, r3
|
||||
|
||||
ld r2,#142h ;CROCK-- turn off
|
||||
ld r3,#1feh ; usart interrupts
|
||||
out @r2,r3
|
||||
|
||||
ldar r2, $ ; go
|
||||
ld r3,#bios
|
||||
jp @r2
|
||||
|
||||
|
||||
wboot: ldar r2, $
|
||||
ld r3,#_wboot
|
||||
jp @r2
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bootstrap Writer
|
||||
;* Although written as if non-segmented,
|
||||
;* this code actually has to run segmented.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
wrboot:
|
||||
|
||||
;* Init
|
||||
|
||||
ldl rr2,#BOOTPSA ; psa
|
||||
ldctl psapseg, r2
|
||||
ldctl psapoff, r3
|
||||
|
||||
ldl rr14,#SYSSTK ; stack ptr
|
||||
ldl rr2,#rtc_ext ; disable real-time
|
||||
ld @r2,#0ffffh ; clock ext call
|
||||
|
||||
EI VI,NVI ; interrupts
|
||||
|
||||
ld r2,#0202h ; type 2 drives & disks
|
||||
ldl rr4,#SEG2+0030h ; (kludge for Olivetti)
|
||||
ld @r4,r2
|
||||
inc r5,#2
|
||||
ld @r4,r2
|
||||
|
||||
sscall 047Ah ; screen init
|
||||
sscall 046Eh ; clock init
|
||||
sscall 0462h ; disk init
|
||||
|
||||
ldar r12, msg2 ; "writing ..."
|
||||
sscall 0486h ; put message
|
||||
|
||||
;* Write track 0 sector 0
|
||||
|
||||
ld r8,#1
|
||||
ld r9,#0
|
||||
ldar r10,T0S0
|
||||
calr Write
|
||||
|
||||
;* copy data into first sector
|
||||
|
||||
ldl rr2,#SYSTEM
|
||||
ldar r4,s1data
|
||||
ld r0, #S1SIZE/2
|
||||
ldir @r4,@r2,r0
|
||||
|
||||
;* write FDB and first data sector
|
||||
|
||||
ld r8,#2
|
||||
ld r9,#BPT
|
||||
ldar r10,T1S0
|
||||
calr Write
|
||||
|
||||
;* write rest of system.
|
||||
|
||||
ld r8,#NBLKS-2
|
||||
ld r9,#BPT+2
|
||||
ldl rr10,#SYSTEM+S1SIZE
|
||||
calr Write
|
||||
|
||||
;* hang up.
|
||||
|
||||
ldar r12, msg1 ; "done ..."
|
||||
sscall 0486h ; put message
|
||||
|
||||
hang:
|
||||
jr hang
|
||||
|
||||
|
||||
;*------------- W R I T E D I S K ------------------
|
||||
|
||||
Write: ; write sectors to disk.
|
||||
; r8 = block count
|
||||
; r9 = block number
|
||||
; rr10= data address
|
||||
|
||||
; add parameters for PROM routine
|
||||
|
||||
ldb rh7,#0 ; rh7 = drive #
|
||||
ldb rl7,#1 ; rl7 = command
|
||||
|
||||
sscall 0468h ; do it
|
||||
ret
|
||||
|
||||
|
||||
;*--------------- messages -----------------------
|
||||
;* Note: must be in same program section as code
|
||||
|
||||
msg1: .byte " Done "
|
||||
msg2: .byte "Writing Bootstrap..."
|
||||
.byte 0 0
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 0 Sector 0
|
||||
;*
|
||||
;* This sector contains the pointer to the
|
||||
;* bootstrap file's FDB.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T0S0:
|
||||
|
||||
.byte 0 ; major version
|
||||
.byte 0 ; minor version
|
||||
.word 40 ; #tracks/surface ?? 35 ??
|
||||
.byte 2 ; #surfaces
|
||||
.byte 16 ; #sectors/track
|
||||
.word 256 ; #bytes/sector
|
||||
.word 40 ; ??? track # of control blk
|
||||
.word 38h ; ??? vdb size
|
||||
.word 136 ; ??? block bitmap size
|
||||
.byte 30 ; ??? directory bitmap size
|
||||
.byte 0 ; ??? track count direction ???
|
||||
.byte 0 ; number of uses (if 0, no boot)
|
||||
.byte 0 ; copy protection (OFF)
|
||||
.byte 0 ; boot block read protect (OFF)
|
||||
.byte 0 ; boot block write protect (OFF)
|
||||
.word 0 ; soft error count
|
||||
.word 0 ; hard error count
|
||||
.word 0 ; lowest useable track side 0 ?1?
|
||||
.word 39 ; highest
|
||||
.word 0 ; side 1
|
||||
.word 39 ;
|
||||
.word 0 ; side 2
|
||||
.word 0 ;
|
||||
.word 0 ; side 3
|
||||
.word 0 ;
|
||||
.long BPT ; BOOT FILE FDB BLOCK NUMBER
|
||||
.byte "PCOS" ; system name??
|
||||
.long 2 ; ??? directory start addr
|
||||
.long 0 ; ??? drive data ???
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.long 0
|
||||
.word 1 ; disk valid (VALID)
|
||||
.byte 0 ; drive number required ???
|
||||
.byte 0 ; disk open
|
||||
.byte 0 ; format major version #
|
||||
.byte 0 ; minor
|
||||
.byte 2 ; disk type = 320Kb
|
||||
.byte 0 ; 27 bytes of nothing
|
||||
.byte 0 ; 26
|
||||
.byte 0 ; 25
|
||||
.byte 0 ; 24
|
||||
.byte 0 ; 23
|
||||
.byte 0 ; 22
|
||||
.byte 0 ; 21
|
||||
.byte 0 ; 20
|
||||
.byte 0 ; 19
|
||||
.byte 0 ; 18
|
||||
.byte 0 ; 17
|
||||
.byte 0 ; 16
|
||||
.byte 0 ; 15
|
||||
.byte 0 ; 14
|
||||
.byte 0 ; 13
|
||||
.byte 0 ; 12
|
||||
.byte 0 ; 11
|
||||
.byte 0 ; 10
|
||||
.byte 0 ; 9
|
||||
.byte 0 ; 8
|
||||
.byte 0 ; 7
|
||||
.byte 0 ; 6
|
||||
.byte 0 ; 5
|
||||
.byte 0 ; 4
|
||||
.byte 0 ; 3
|
||||
.byte 0 ; 2
|
||||
.byte 0 ; 1
|
||||
.block 22 ; forgotten, aparently
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 1 Sector 0
|
||||
;*
|
||||
;* This sector is the FDB for the bootstrap
|
||||
;* file. It has a single extent.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T1S0:
|
||||
.long FILSIZE ; file length in bytes
|
||||
.word 1 ; #extents
|
||||
.byte 0 ; 14 password (14 bytes)
|
||||
.byte 0 ; 13
|
||||
.byte 0 ; 12
|
||||
.byte 0 ; 11
|
||||
.byte 0 ; 10
|
||||
.byte 0 ; 9
|
||||
.byte 0 ; 8
|
||||
.byte 0 ; 7
|
||||
.byte 0 ; 6
|
||||
.byte 0 ; 5
|
||||
.byte 0 ; 4
|
||||
.byte 0 ; 3
|
||||
.byte 0 ; 2
|
||||
.byte 0 ; 1
|
||||
.word 0 ; ??? verify location ???
|
||||
.byte 0 ; write protect
|
||||
.byte 0 ; future
|
||||
.long BPT+1 ; STARTING BLOCK OF EXTENT
|
||||
.word NBLKS-1 ; NUMBER OF BLOCKS IN EXTENT
|
||||
.block 222 ; other extents
|
||||
.long 0 ; next fdb
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Track 1 Sector 1
|
||||
;*
|
||||
;* This sector is the header for the bootstrap
|
||||
;* file, followed by the first S1SIZE bytes of
|
||||
;* data, which are copied in.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
T1S1:
|
||||
|
||||
.word 0101h ; magic number
|
||||
.byte "PCPM" ; identifier
|
||||
.byte "x01."
|
||||
.byte "01"
|
||||
|
||||
.long SYSTEM+6 ; starting addr.
|
||||
.word 1 ; #code blocks
|
||||
|
||||
.long SYSTEM ; load address
|
||||
.word SYSSIZE/2 ; #words
|
||||
|
||||
s1data .block S1SIZE ; data area
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
;************ biosdefs.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
nr14 .equ cr13+2 ;WORD normal r14
|
||||
nr15 .equ nr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scseg .equ scfcw+2 ;WORD caller PC SEG
|
||||
scpc .equ scseg+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _flush ;Flush buffers
|
||||
|
||||
.global ccp ;Command Processor
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _wboot ; warm boot
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;* Control is transferred to the CCP.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* segmented mode
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; enter in segmented mode.
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
calr kludge ; get PC segment on stack
|
||||
kludge: popl rr4, @r14
|
||||
|
||||
; get PSAP into rr2.
|
||||
|
||||
ldctl r2, PSAPSEG
|
||||
ldctl r3, PSAPOFF
|
||||
|
||||
; go non-segmented. save PSAP, system segment,
|
||||
; system stack pointer (in system segment, please)
|
||||
|
||||
NONSEG
|
||||
|
||||
ldl _psap, rr2
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ldl _sysstk, rr14
|
||||
|
||||
; set up system stack so that a return will warm boot
|
||||
|
||||
push @r15,#_wboot
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp ccp
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Warm Boot
|
||||
;*
|
||||
;* flush buffers and initialize Bios
|
||||
;* then transfer to CCP
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
_wboot:
|
||||
call _flush
|
||||
call _biosinit
|
||||
ldl rr14,_sysstk
|
||||
jp ccp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
;************ biosio.z8k **************************
|
||||
;*
|
||||
;* I/O routines for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE The Olivetti PROM routines are segmented.
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _disk_io
|
||||
.global _crt_put
|
||||
.global _cold_boot
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Prom Subroutine Access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_disk_io: ;err=disk_io(drv, cmd, count, blk, addr)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ldb rh7,14+ARG1+1(r15) ;get args
|
||||
ldb rl7,14+ARG2+1(r15)
|
||||
ld r8, 14+ARG3(r15)
|
||||
ld r9, 14+ARG4(r15)
|
||||
ldl rr10,14+ARG5(r15)
|
||||
|
||||
;rh7 = drive #
|
||||
;rl7 = command
|
||||
;r8 = block count
|
||||
;r9 = block number
|
||||
;rr10 = segmented address
|
||||
|
||||
SEG
|
||||
scall 84000068h
|
||||
NONSEG
|
||||
;r8 = block count not transferred
|
||||
;rh7 = #retries
|
||||
;rl7 = final error code (RETURNED)
|
||||
;rh6 = error retried
|
||||
|
||||
and r7,#0FFh ;value returned in r7
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
_crt_put: ;crt_put(char)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ld r1,14+ARG1(r15) ;get arg in r1
|
||||
|
||||
SEG ; SEG clobbers r0
|
||||
ld r0,r1 ;rl0 = char
|
||||
scall 84000080h
|
||||
NONSEG
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
|
||||
_cold_boot:
|
||||
|
||||
SEG
|
||||
scall 8400008Ch
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
;************ biosmem.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
.global memsc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
ldirb @r4,@r6,r3
|
||||
ldl rr6,rr4 ; rr6 = dest + length
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
NONSEG
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
ld r4,scseg+4(r15)
|
||||
ld r2,scfcw+4(r15)
|
||||
calr map_1
|
||||
ldl cr6+4(r15),rr6 ; return rr6
|
||||
SEG
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* Most of the system dependencies are in map_prog,
|
||||
;* which maps a program segment into a data segment
|
||||
;* for access as data.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#15 ; segmented caller?
|
||||
ret nz ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
ret ; already mapped
|
||||
|
||||
call_prog:
|
||||
bit r2,#15 ; segmented caller?
|
||||
jr nz map_prog ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
ld r6, _sysseg
|
||||
ret
|
||||
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
ret eq
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
jr eq map_prog
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ;map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
testb rh5 ; data access?
|
||||
ret nz ; no: done
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; olivetti: segment 8 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as segment 10's data.
|
||||
|
||||
cpb rh6,#8
|
||||
ret ne
|
||||
ldb rh6,#10
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 4 ;system stack pointer
|
||||
_psap: .block 4 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,370 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;* 830305 D. Sallume (Zilog) -- added FPE trap
|
||||
;* code.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
.global _tbvalid ;disk track buff valid
|
||||
.global _tbdirty ;disk track buff is dirty
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap, fp_epu
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* M-20 ROM scratchpad RAM addresses
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
rtc_ext: .equ 82000022h ;Place to put address
|
||||
; of list of functions
|
||||
; for each clock tick
|
||||
motor_on: .equ 82000020h ;Disk motor timeout
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to segmented, with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: LONG
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack,
|
||||
;* IN SEGMENTED MODE. This allows the trap
|
||||
;* handler to be in another segment (with some
|
||||
;* care). This is useful mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ;system call trap server
|
||||
|
||||
push @r14,@r14
|
||||
|
||||
|
||||
_trap:
|
||||
|
||||
sub r15,#30 ; push caller state
|
||||
ldm @r14,r0,#14
|
||||
NONSEG ; go nonsegmented
|
||||
ldctl r1,NSP
|
||||
ld nr14(r15),r14
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
; else call seg @rr0
|
||||
pushl @r15,rr0 ; (done via kludge)
|
||||
SEG
|
||||
popl rr0,@r14
|
||||
calr trap_1
|
||||
jr _trap_ret
|
||||
|
||||
trap_1: ; jp @rr0
|
||||
pushl @r14,rr0
|
||||
ret
|
||||
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
NONSEG
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ld r14,nr14(r15)
|
||||
ldctl NSP,r1
|
||||
SEG ; go segmented for the iret.
|
||||
ldm r0,@r14,#14
|
||||
add r15,#32
|
||||
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r14,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r14,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r14,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r14,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
biossc: ;call bios
|
||||
NONSEG
|
||||
; r3 = operation code
|
||||
; rr4= P1
|
||||
; rr6= P2
|
||||
|
||||
ld r0,scfcw+4(r15) ; if caller nonseg, normal
|
||||
and r0,#0C000h
|
||||
jr nz seg_ok
|
||||
|
||||
ld r4,scseg+4(r15) ; then add seg to P1, P2
|
||||
ld r6,r4
|
||||
seg_ok:
|
||||
; set up C stack frame
|
||||
;===
|
||||
pushl @r15,rr6
|
||||
pushl @r15,rr4
|
||||
push @r15,r3
|
||||
|
||||
; call C program
|
||||
call __bios
|
||||
|
||||
; clean stack & return
|
||||
add r15,#10
|
||||
ldl cr6+4(r15),rr6 ; with long in rr6
|
||||
|
||||
SEG
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
SEG
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#4 ;discard return addr
|
||||
ldl rr4,rr14 ;move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r4,@r6,r2
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _motor_c -- check if disk motor still running.
|
||||
;* Entered each clock tick. Invalidates
|
||||
;* track buffer when motor stops
|
||||
;* (Note: runs segmented)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_motor_c:
|
||||
ldl rr4,#motor_on ;Motor running?
|
||||
test @r4
|
||||
ret nz ;Yes: do nothing
|
||||
ldar r4,$
|
||||
ld r5,#_tbdirty ; Is track buff dirty?
|
||||
test @r4 ; Yes...
|
||||
ret nz ; ...return without invalidating
|
||||
ld r5,#_tbvalid
|
||||
clr @r4 ;No: mark track buffer
|
||||
ret ; invalid
|
||||
|
||||
; Table of functions run each real time clock tick
|
||||
|
||||
_ticktab:
|
||||
.long -1 ;Will contain _motor_c
|
||||
.word 0ffffh ;Terminator
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 8 ; size of a program status entry
|
||||
; --- segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
lda r3,biossc
|
||||
ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
lda r3,fp_epu
|
||||
ldl _trapvec+EPUTRAP*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; rr0 PSA entry: FCW (ints ENABLED)
|
||||
; rr2 PSA entry: PC
|
||||
; rr4 -> PSA slot
|
||||
|
||||
ldl rr4,_psap
|
||||
SEG
|
||||
ldl rr0,#0000D800h
|
||||
|
||||
add r5,#ps ; EPU trap
|
||||
ldar r2,epu_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ldar r2,pi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ldar r2,sc_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ldar r2,seg_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ldar r2,nmi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
; Set up Real-Time Clock external call loc
|
||||
|
||||
ldar r2,_motor_c
|
||||
ldar r4,_ticktab
|
||||
ldl @r4,rr2
|
||||
ldl rr2,#rtc_ext
|
||||
ldl @r2,rr4
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,131 @@
|
||||
;*************************************************
|
||||
;** Change history --
|
||||
;** 30mar81: Broken off from general interface.
|
||||
;** 30mar81: Set up for Zilog ZLAB 8000
|
||||
;** 09may81: Tell cpu when state is free.
|
||||
;** 19jan82: Allow segmented users.
|
||||
;** 21jan82: Took out references to freecpu and needcpu
|
||||
;** 15feb82: Dummy out need/free cpu.
|
||||
;** 13may82: Comment out references to setfp and resfp
|
||||
;*************************************************
|
||||
|
||||
.title "sysdep MODULE"
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;*************************************************
|
||||
;** SAVED CPU STATE --
|
||||
;** is specified by the following "constants."
|
||||
;** Offset stapcsg must point to the word preceding
|
||||
;** the saved PC offset, EVEN FOR NONSEGMENTED
|
||||
;** OPERATION.
|
||||
;*************************************************
|
||||
__data .sect
|
||||
.GLOBAL stareg,staevnt,stafcw,stapcsg
|
||||
stareg .WORD 4 ;offset of r0
|
||||
staevnt .WORD 36 ;saved 1st word
|
||||
stafcw .WORD 38 ;saved fcw
|
||||
stapcsg .WORD 40 ;seg word of PC
|
||||
|
||||
;*************************************************
|
||||
;** ADDRESSES --
|
||||
;** as input parameters to the routines below are
|
||||
;** delivered in register pairs (i.e. as though
|
||||
;** segmented). The high-order word of such an
|
||||
;** address is undefined when the process running
|
||||
;** in that address space runs in nonsegmented
|
||||
;** mode.
|
||||
;*************************************************
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET NEXT INSTRUCTION WORD --
|
||||
;** Input:
|
||||
;** rr6 = saved PC -- seg # must be fixed for
|
||||
;** nonseg users
|
||||
;** Output:
|
||||
;** r3 = next instruction word
|
||||
;*************************************************
|
||||
__data .sect
|
||||
gttxt: .WORD 0
|
||||
__text .sect
|
||||
.GLOBAL gettext
|
||||
gettext: ; PROCEDURE ENTRY
|
||||
; ld r5,#2 ; it is system data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP source
|
||||
|
||||
pushl @r15,rr6
|
||||
ld r7,#gttxt ; address of temp
|
||||
ld r5,#0 ; it is caller Instruction
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
ldl rr2,#2 ; byte count to move
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ld r3,gttxt ; load return values
|
||||
ldb rl2,#0
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET MEMORY BYTES --
|
||||
;** Segmented emulator input --
|
||||
;** rr6 - src address (trapee space)
|
||||
;** rr4 - dst address (emulator space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL getmem
|
||||
getmem:
|
||||
push @r15,r3
|
||||
; pushl @r15,rr4
|
||||
; ld r5,#4 ; it is user data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP source
|
||||
;
|
||||
; popl rr4,@r15
|
||||
pushl @r15,rr6 ; save source
|
||||
ldl rr6,rr4 ; position dest
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; requrired parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** PUT MEMORY BYTES --
|
||||
;** Emulator input --
|
||||
;** rr6 - src address (emulator space)
|
||||
;** rr4 - dst address (trapee space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL putmem
|
||||
putmem: ; PROCEDURE ENTRY
|
||||
push @r15,r3
|
||||
pushl @r15,rr4
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP source
|
||||
|
||||
popl rr4,@r15
|
||||
; pushl @r15,rr6 ; save source
|
||||
; ldl rr6,rr4 ; position destination
|
||||
; ld r5,#2 ; it is system data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP destination
|
||||
;
|
||||
; ldl rr4,rr6
|
||||
; popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; required parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
@@ -0,0 +1,155 @@
|
||||
;************ syscall.z8s **************************
|
||||
;*
|
||||
;* System Call interface for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 820927 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The following system call interface routines
|
||||
;* are designed to be called from non-segmented
|
||||
;* C programs.
|
||||
;*
|
||||
;* Addresses are passed as LONGs.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
.global _xfer
|
||||
.global _mem_cpy
|
||||
.global _map_adr
|
||||
.global _bios
|
||||
.global _bdos
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch Routine
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_xfer:
|
||||
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,#-2
|
||||
subl rr2,rr2
|
||||
sc #XFER_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1)
|
||||
;* sets user segment # from addr.
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* transfer to context block at addr
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 return segmented instruction address,
|
||||
;* not data access address
|
||||
;*
|
||||
;* FFFF set user-space segment from address
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_mem_cpy: ;copy memory C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,ARG3(r15)
|
||||
ldl rr2,ARG5(r15)
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
_map_adr: ;map address C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ld r5, ARG3(r15)
|
||||
subl rr2,rr2 ; 0 length says map
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* long _bios(code, p1, p2)
|
||||
;* long _bdos(code, p1)
|
||||
;* int code;
|
||||
;* long p1, p2;
|
||||
;*
|
||||
;* BIOS, BDOS access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_bios:
|
||||
ld r3,ARG1(r15)
|
||||
ldl rr4,ARG2(r15)
|
||||
ldl rr6,ARG4(r15)
|
||||
sc #BIOS_SC
|
||||
ret
|
||||
|
||||
_bdos:
|
||||
ld r5,ARG1(r15)
|
||||
ldl rr6,ARG2(r15)
|
||||
sc #BDOS_SC
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* 07/20/82 Added new types WORD and BYTE (DMH) */
|
||||
/* 10/15/82 Added some new defines (DMH) */
|
||||
/* 11/13/82 This is the version for Unidot comp- */
|
||||
/* iler which doesn't support unsigned. */
|
||||
|
||||
/* the pseudo storage classes */
|
||||
|
||||
#define AFAST register
|
||||
#define FAST register
|
||||
#define GLOBAL extern
|
||||
#define IMPORT extern
|
||||
#define INTERN static
|
||||
#define LOCAL static
|
||||
|
||||
/* the pseudo types */
|
||||
|
||||
typedef char TEXT, TINY;
|
||||
typedef double DOUBLE;
|
||||
typedef int ARGINT, BOOL, VOID;
|
||||
typedef long LONG;
|
||||
typedef short BITS, COUNT, FILE;
|
||||
typedef /* unsigned */ BYTES, WORD;
|
||||
typedef /* unsigned */ char BYTE, UTINY;
|
||||
typedef /* unsigned */ long ULONG;
|
||||
typedef /* unsigned */ short UCOUNT;
|
||||
|
||||
/* system parameters */
|
||||
|
||||
#define STDIN 0
|
||||
#define STDOUT 1
|
||||
#define STDERR 2
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NULL 0
|
||||
#define FOREVER for (;;)
|
||||
#define BUFSIZE 512
|
||||
#define BWRITE -1
|
||||
#define READ 0
|
||||
#define WRITE 1
|
||||
#define UPDATE 2
|
||||
#define EOF -1
|
||||
#define BYTMASK 0377
|
||||
|
||||
/* macros */
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||||
#define gtc(pf) (0 < (pf)->_nleft ? (--(pf)->_nleft, *(pf)->_pnext++ & BYTMASK) \
|
||||
: getc(pf))
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define iswhite(c) ((c) <= ' ' || 0177 <= (c)) /* ASCII ONLY */
|
||||
#define max(x, y) (((x) < (y)) ? (y) : (x))
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define ptc(pf, c) if ((pf)->_nleft < 512) (pf)->_buf[(pf)->_nleft++] = (c); \
|
||||
else putc(pf, (c))
|
||||
#define tolower(c) (isupper(c) ? ((c) + ('a' - 'A')) : (c))
|
||||
#define toupper(c) (islower(c) ? ((c) - ('a' - 'A')) : (c))
|
||||
|
||||
/* the file IO structure */
|
||||
|
||||
typedef struct fio
|
||||
{
|
||||
FILE _fd;
|
||||
COUNT _nleft;
|
||||
COUNT _fmode;
|
||||
TEXT *_pnext;
|
||||
TEXT _buf[BUFSIZE];
|
||||
} FIO;
|
||||
Reference in New Issue
Block a user