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

View File

@@ -0,0 +1,366 @@
/****************************************************************************/
/* */
/* B D O S . H */
/* ----------- */
/* */
/* Copyright (c) 1982, Zilog Incorporated */
/* */
/* Macros defining the direct BDOS calls used by the standard CP/M */
/* utilities (ED, PIP, STAT, SET, SHOW.) Some necessary data */
/* data structures are also defined. */
/* */
/* All macros return a long value, even when the BDOS function they */
/* call does produce a return parameter. */
/* */
/* This header file can be used applications which do not require */
/* to use the C standard I/O library functions. For applications */
/* which require the library, but which wish to make use of the */
/* additional information in this file, cpm.h should be included in */
/* the source ahead of this file. The compiler flags multiple */
/* definition errors if this ordering is not observed. */
/* */
/* portab.h must always be included ahead of this file. */
/* */
/****************************************************************************/
extern long __BDOS(); /* BDOS entry point */
#define XADDR long /* 32-bit address data type */
/****************************************************************************/
/* The following BDOS calls are defined in cpm.h. Define them only if they */
/* are not defined already. */
/****************************************************************************/
#ifndef EXIT /* Find out where we stand */
/* Define if necessary */
#define EXIT 0 /* Exit to BDOS */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#define SETMSC 44 /* Set Multi-Sector Count */
#endif
/****************************************************************************/
/* The following BDOS calls are not defined in cpm.h */
/****************************************************************************/
#define CONIN 1 /* Single char I/P with echo*/
#define READER 3 /* Paper tape input */
#define PUNCH 4 /* Paper tape output */
#define GET_IOB 7 /* Get I/O byte */
#define SET_IOB 8 /* Set I/O byte */
#define PRINT 9 /* Print $-terminated line */
#define CONSTAT 11 /* Check if I/P char waiting*/
#define VERSION 12 /* Return version number */
#define RS_DISK 13 /* Reset disk system */
#define SEL_DISK 14 /* Select disk */
#define SRCH_1ST 17 /* Search 1st filename match*/
#define SRCH_NEXT 18 /* Search next match */
#define S_READ 20 /* Sequential read from file*/
#define S_WRITE 21 /* Sequential write to file */
#define RENAME 23 /* Rename a file */
#define RET_LOGIN 24 /* Return login vector */
#define RET_CDISK 25 /* Return current disk */
#define GET_ALLOC 27 /* Get allocation vector */
#define WR_PROTD 28 /* Write protect disk */
#define GET_RO 29 /* Get read-only vector */
#define SET_ATT 30 /* Set file attributes */
#define GET_DPB 31 /* Get disk parameters */
#define GSET_UCODE 32 /* Get/set user code */
#define SET_RAND 36 /* Set random record */
#define RS_DRIVE 37 /* Reset disk specified drv */
/* 38, 39 not used */
#define B_WRZF 40 /* Write random, zero fill */
/* 41 - 43 not used */
#define RET_ERRORS 45 /* Set error return mode */
#define GET_DFS 46 /* Get free disk space */
#define CHAIN 47 /* Chain to program via CCP */
#define FLUSH 48 /* Flush buffers to disk */
#define GSET_SCB 49 /* Get/set system control bk*/
#define BIOS_CALL 50 /* Direct call to BIOS */
/* 51 - 58 not used */
#define PROG_LOAD 59 /* Program load */
/* 60 unused */
#define SET_EXV 61 /* Set exception vector */
#define SET_SUP 62 /* Set supervisor state */
#define SET_LABEL 100 /* Set directory label */
#define GET_LABEL 101 /* Get directory label */
#define GET_XFCB 102 /* Get extended FCB */
#define SET_XFCB 103 /* Set extended FCB */
#define COND_LST 161 /* Conditionally attach LST:*/
/****************************************************************************/
/* The macros themselves... */
/****************************************************************************/
#define _conin() (__BDOS(CONIN, (long) 0))
#define _conout(a) (__BDOS(CONOUT, (long) (a)))
#define _reader() (__BDOS(READER, (long) 0))
#define _punch(a) (__BDOS(PUNCH, (long) (a)))
#define _lstout(a) (__BDOS(LSTOUT, (long) (a)))
#define _conio(a) (__BDOS(CONIO, (long) (a)))
#define _get_iob() (__BDOS(GET_IOB, (long) 0))
#define _set_iob(a) (__BDOS(SET_IOB, (long) (a)))
#define _print(a) (__BDOS(PRINT, (long) (a)))
#define _conbuf(a) (__BDOS(CONBUF, (long) (a)))
#define _constat() (__BDOS(CONSTAT, (long) 0))
#define _version() (__BDOS(VERSION, (long) 0))
#define _rs_disk(a) (__BDOS(RS_DISK, (long) (a)))
#define _sel_disk(a) (__BDOS(SEL_DISK, (long) (a)))
#define _open(a) (__BDOS(OPEN, (long) (a)))
#define _close(a) (__BDOS(CLOSE, (long) (a)))
#define _srch_1st(a) (__BDOS(SRCH_1ST, (long) (a)))
#define _srch_next() (__BDOS(SRCH_NEXT, (long) 0))
#define _delete(a) (__BDOS(DELETE, (long) (a)))
#define _s_read(a) (__BDOS(S_READ, (long) (a)))
#define _s_write(a) (__BDOS(S_WRITE, (long) (a)))
#define _create(a) (__BDOS(CREATE, (long) (a)))
#define _rename(a) (__BDOS(RENAME, (long) (a)))
#define _ret_login() (__BDOS(RET_LOGIN, (long) 0))
#define _ret_cdisk() (__BDOS(RET_CDISK, (long) 0))
#define _setdma(a) (__BDOS(SETDMA, (long) (a)))
#define _get_alloc() (__BDOS(GET_ALLOC, (long) 0))
#define _wr_protd() (__BDOS(WR_PROTD, (long) 0))
#define _get_ro() (__BDOS(GET_RO, (long) 0))
#define _set_att(a) (__BDOS(SET_ATT, (long) (a)))
/* _get_dpb has parameter in*/
/* some implementations */
/* of CP/M but not others */
/* This macro suitable only */
/* for former */
#define _get_dpb(a) (__BDOS(GET_DPB, (long) (a)))
/* This one handles latter */
#define _get_dpa() (__BDOS(GET_DPB, (long) 0))
#define _gset_ucode(a) (__BDOS(GSET_UCODE, (long) (a)))
#define _b_read(a) (__BDOS(B_READ, (long) (a)))
#define _b_write(a) (__BDOS(B_WRITE, (long) (a)))
#define _filsiz(a) (__BDOS(FILSIZ, (long) (a)))
#define _set_rand(a) (__BDOS(SET_RAND, (long) (a)))
#define _rs_drive(a) (__BDOS(RS_DRIVE, (long) (a)))
#define _b_wrzf(a) (__BDOS(B_WRZF, (long) (a)))
#define _setmsc(a) (__BDOS(SETMSC, (long) (a)))
#define _ret_errors(a) (__BDOS(RET_ERRORS, (long) (a)))
#define _get_dfs(a) (__BDOS(GET_DFS, (long) (a)))
#define _chain() (__BDOS(CHAIN, (long) 0))
#define _flush() (__BDOS(FLUSH, (long) 0))
#define _gset_scb(a) (__BDOS(GSET_SCB, (long) (a)))
#define _bios_call(a) (__BDOS(BIOS_CALL, (long) (a)))
#define _prog_load(a) (__BDOS(PROG_LOAD, (long) (a)))
#define _set_exv(a) (__BDOS(SET_EXV, (long) (a)))
#define _set_sup(a) (__BDOS(SET_SUP, (long) 0))
#define _get_label(a) (__BDOS(GET_LABEL, (long) (a)))
#define _set_label(a) (__BDOS(SET_LABEL, (long) (a)))
#define _get_xfcb(a) (__BDOS(GET_XFCB, (long) (a)))
#define _set_xfcb(a) (__BDOS(SET_XFCB, (long) (a)))
#define _cond_lst() (__BDOS(COND_LST, (long) 0))
/****************************************************************************/
/* BIOS calls, for use in conjunction with BDOS call 50 & struct bios_parms */
/****************************************************************************/
#define _INIT 0 /* Cold start */
#define _WARM 1 /* Warm start */
#define _CONST 2 /* Console status */
#define _CONIN 3 /* Read console character */
#define _CONOUT 4 /* Write console character */
#define _LIST 5 /* Write listing character */
#define _PUNCH 6 /* Write punch character */
#define _READER 7 /* Read tape character */
#define _HOME 8 /* Move to track 0 */
#define _SELDSK 9 /* Select disk drive */
#define _SETTRK 10 /* Set track number */
#define _SETSEC 11 /* Set sector number */
#define _SETDMA 12 /* Set DMA address */
#define _READ 13 /* Read selected sector */
#define _WRITE 14 /* Write selected sector */
#define _LISTST 15 /* Return list status */
#define _GETMRT 16 /* Get memory region table */
/* address */
#define _GETIOB 17 /* Get IOBYTE value */
#define _SETIOB 18 /* Set IOBYTE value */
#define _FLUSH 19 /* Flush buffers */
#define _SETEXC 20 /* Set exception vector */
/****************************************************************************/
/* FCB structure is defined in cpm.h. Define it here only if it is not */
/* defined already. Declare some useful values at the same time. */
/****************************************************************************/
#ifndef SECSIZ /* Not already declared? */
struct fcbtab /* File control block */
{ /* */
BYTE drive; /* Disk drive field */
BYTE fname[8]; /* File name */
BYTE ftype[3]; /* File type */
BYTE extent; /* Current extent number */
BYTE s1,s2; /* "system reserved" */
BYTE reccnt; /* Record counter */
BYTE resvd[16]; /* More "system reserved" */
LONG record; /* Note -- we overlap the */
/* current record field to */
/* make this useful. */
};
#define fcb fcbtab /* A useful synonym */
#define SECSIZ 128 /* size of CP/M sector */
#define _MAXSXFR 1 /* max # sectors xferrable */
#define _MAXSHFT 12 /* shift right BDOS rtn val */
#endif
/****************************************************************************/
/* Data structures not defined in cpm.h */
/****************************************************************************/
struct dpbs /* Disk parameter block */
{
UWORD spt; /* Sectors per track */
BYTE bls; /* Block shift factor */
BYTE bms; /* Block mask */
BYTE exm; /* Extent mark */
/* BYTE filler; *** Pad to align words ***/
UWORD mxa; /* Maximum allocation (blks)*/
UWORD dmx; /* Max directory entries */
UWORD dbl; /* Directory alloc. map */
UWORD cks; /* Directory checksum */
UWORD ofs; /* Track offset from track 0*/
};
struct bios_parm /* BIOS parameters for BDOS */
{ /* call 50 */
UWORD req; /* BIOS request code */
LONG p1; /* First parameter */
LONG p2; /* Second parameter */
};
struct scbs /* System control block */
{
BYTE resvd_1[6]; /* Reserved for system use */
BYTE u_flags[4]; /* Utility flags */
BYTE d_flags[4]; /* Display flags */
BYTE clp_flags[2]; /* Command Line Proc flags */
UWORD p_error; /* Program error return code*/
BYTE resvd_2[8]; /* Reserved for system use */
BYTE con_w; /* Console width */
BYTE con_c; /* Console column */
BYTE con_l; /* Console page length */
BYTE resvd_3[5]; /* Reserved for system use */
UWORD conin_r; /* CONIN redirection flag */
UWORD conout_r; /* CONOUT redirection flag */
UWORD auxin_r; /* AUXIN redirection flag */
UWORD auxout_r; /* AUXOUT redirection flag */
UWORD lstout_r; /* LSTOUT redirection flag */
BYTE resvd_4[2]; /* Reserved for system use */
BOOLEAN ctl_h_a; /* Backspace active */
BOOLEAN rubout_a; /* Rubout active */
BYTE resvd_5[2]; /* Reserved for system use */
UWORD c_xlate; /* Console translate func. */
UWORD con_m; /* Console mode (raw/cooked)*/
UWORD buff_a; /* 128 byte buffer available*/
BYTE o_delim; /* Output delimiter */
BOOLEAN lo_flag; /* List output flag */
BYTE resvd_6[2]; /* Reserved for system use */
UWORD d_m_a; /* Current DMA address */
BYTE disk_no; /* Current disk */
BYTE bdos_info[2]; /* BDOS variable info */
BYTE resvd_7[3]; /* Reserved for system use */
BYTE user_no; /* Current user number */
BYTE resvd_8[6]; /* Reserved for system use */
BYTE bdos_mode; /* BDOS error mode */
BYTE c_chain[4]; /* Current search chain */
BYTE tmp_drv; /* Drive for temporary files*/
BYTE resvd_9[7]; /* Reserved for system use */
BYTE date_s[5]; /* Date stamp */
BYTE error_jmp[3]; /* Error jump */
UWORD cmb_a; /* Common memory base addr */
UWORD bdos_ent; /* BDOS entry point */
};
struct scbpb /* SCB parameter block */
{
BYTE off; /* Index to data in SCB */
BYTE op; /* Operation: 0xff Set byte */
/* 0xfe Set word */
/* else Get word */
UWORD val; /* Byte/word value to be set*/
};
#define SET_BYTE 0xff
#define SET_WORD 0xfe
#define GET 0
/****************************************************************************/
/* HILO must be defined for the Z8000. Undefine it first, in case cpm.h */
/* has already defined it. The tagless structures defining byte ordering */
/* which are declared in cpm.h are not redeclared here (the use of members */
/* of tagless structures to define offsets is an obsolete feature of the C */
/* language.) */
/****************************************************************************/
#undef HILO
#define HILO

View File

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

View File

@@ -0,0 +1,119 @@
;****************************************************************
;* *
;* CP/M-Z8K Interface module for the Loader BDOS *
;* For "C" version of CP/M-Z8K *
;* *
;* Copyright (c) 1982 Digital Research, Inc. *
;* *
;* Version 0.2 -- September 22, 1982 *
;* Z8000 version -- 830728 *
;* *
;****************************************************************
__text: .sect
;****************************************************
;*
;* Globals
;*
;****************************************************
.global _bios1 ; 6 BIOS entry points from BDOS
.global _bios2
.global _bios3
.global _bios4
.global _bios5
.global _swap ; byte swapper
.global _udiv ; unsigned divide routine
;****************************************************
;*
;* Externals and Constants
;*
;****************************************************
.global _bios ; The Loader BDOS calls the BIOS direct
;****************************************************
;*
;* BIOS Interface Routines
;*
;* Note - there are 5 BIOS entry points from the BDOS,
;* labelled BIOS1 - BIOS5, depending on the
;* parameters passed.
;*
;****************************************************
_bios5:
; For BIOS functions sectran and set exception vector
; (funct, word, long) offsets 2, 4, 6
ldl rr6,6(r15) ; get 2nd param (long)
jp _bios2 ; join common routine
_bios4:
; For BIOS function seldsk
; (func, word, word) offsets 2, 4, 6
ld r7,6(r15) ; get 2nd param (word)
clr r6 ; extend to ulong
jp _bios2 ; join common routine
_bios3:
; For BIOS function set dma
; (func, long) offsets 2, 4
ldl rr4,4(r15) ; get 1st param (long)
subl rr6,rr6 ; clear second
jp _bios1 ; join common routine
_bios2:
; For all BIOS functions with a word parameter
; (func, word) offsets 2, 4
ld r5,4(r15) ; get 1st param (word)
clr r4 ; extend to ulong
_bios1:
; For all BIOS functions that have no parameter
; other than function number
ld r3,2(r15) ; get function number
sub r15, #10 ; adjust sp...
ldm @r15, r3, #5 ; ... and push args on stack
call _bios ; do BIOS call as a call...
add r15, #10 ; ...and readjust sp
ret ; returns value in rr7
;****************************************************
;*
;* Utility Subroutines
;*
;* swap(word) swap bytes of a word
;*
;* uword udiv((long) dividend,
;* (uword) divisor,
;* (uword *)rem )
;*
;****************************************************
_swap:
ld r7,2(r15)
exb rh7,rl7
ret
_udiv:
ldl rr2,2(r15) ;long dividend
subl rr0,rr0 ; as unsigned quad
ld r5,6(r15) ;word divisor
clr r4 ; as unsigned long
ldl rr6,8(r15) ;->result
divl rq0,rr4
ld @r7,r1 ; store remainder
ld r7,r3 ; return quotient
clr r6
ret

View File

@@ -0,0 +1,173 @@
/****************************************************************
* *
* CP/M-Z8K Loader BDOS Main Routine *
* *
* This is the main routine for the loader BDOS for P-CP/M.*
* It has one entry point, _bdos, which is called from *
* the assembly language trap handler found in bdosif.z8k. *
* The parameters are a function number (integer) and an *
* information parameter, (passed as both an integer and *
* a pointer) *
* The BDOS can potentially return a pointer, long word, *
* or word *
* *
* Memory management for Z8000, etc. added 821018 by SS. *
* One non-obvious change is using tmp_sel to copy in the *
* user's FCB, and copying it out again if changed. *
* Tmp_sel now handles '?' in the drive field, so it need *
* not be called from search (the only place outside of *
* this module where it is called) *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
/* Declare EXTERN functions */
EXTERN seldsk(); /* Select disk */
EXTERN BOOLEAN openfile(); /* Open File */
EXTERN UWORD dirscan(); /* General directory scanning routine */
EXTERN UWORD seqread(); /* Sequential disk read */
/* Declare the "state variables". These are globals for the single-thread
version of the file system, but are put in a structure so they can be
based, with a pointer coming from the calling process */
GLOBAL struct stvars gbls;
struct tempstr
{
UBYTE tempdisk;
BOOLEAN reselect;
struct fcb *fptr;
XADDR fxptr; /* xaddr of caller's FCB */
struct fcb tempfcb; /* added for memory management */
/* because caller's fcb may not */
/* be directly accessible */
};
/****************************************************************
* *
* _bdos MAIN ROUTINE *
* *
* Called with _bdos(func, info, infop) *
* *
* Where: *
* func is the BDOS function number (d0.w) *
* info is the parameter as a word *
* infop is the parameter as a segmented pointer *
* note that info is the word form of infop*
* *
****************************************************************/
UWORD _bdos(func,info,infop)
REG WORD func; /* BDOS function number */
REG UWORD info; /* parameter as word */
REG XADDR infop; /* parameter as (segmented) pointer */
{
REG UWORD rtnval;
LOCAL struct tempstr temp;
BSETUP
temp.reselect = FALSE;
temp.fxptr = infop;
rtnval = 0;
switch (func) /* switch on function number */
{
case 2: bconout((UBYTE)info); /* console output */
break;
case 14: seldsk((UBYTE)info); /* select disk */
GBL.dfltdsk = (UBYTE)info;
break;
case 15: tmp_sel(&temp); /* open file */
temp.fptr->extent = 0;
temp.fptr->s2 = 0;
rtnval = dirscan(openfile, temp.fptr);
break;
case 20: tmp_sel(&temp); /* read sequential */
rtnval = seqread(temp.fptr);
break;
case 26: GBL.dmaadr = infop; /* set dma address */
break;
default: return(-1); /* bad function number */
/* break; */
}; /* end of switch statement */
if (temp.reselect){ /* if reselected disk, restore it now */
temp.fptr->drvcode = temp.tempdisk;
cpy_out(temp.fptr, infop, sizeof *temp.fptr);
}
return(rtnval); /* return the BDOS return value */
} /* end _bdos */
/****************************************************************
* *
* bdos call - replaces system call in real CP/M-Z8K *
* Function is to arrange for parameters to _bdos to be *
* in the right place. *
* *
****************************************************************/
bdos(func, longaddr)
int func;
XADDR longaddr;
{
return(_bdos(func, (int) longaddr, longaddr));
}
/*****************************************************
**
** tmp_sel(temptr) -- temporarily select disk
** pointed to by temptr->fptr.
**
** make local copy of FCB in caller's space.
**
*****************************************************/
tmp_sel(temptr) /* temporarily select disk pointed to by fcb */
/* also copy fcb into temp structure */
REG struct tempstr *temptr;
{
REG struct fcb *fcbp;
REG UBYTE tmp_dsk;
BSETUP
/* get local copy of caller's FCB, */
/* and point temptr->fptr at it */
cpy_in(temptr->fxptr, &temptr->tempfcb, sizeof(struct fcb));
temptr->fptr = &temptr->tempfcb;
/* get local copy of fcb pointer */
fcbp = temptr->fptr;
/* select disk if necessary */
tmp_dsk = fcbp->drvcode;
if (tmp_dsk == '?') { /* -- drive '?' for search */
seldsk( GBL.dfltdsk);
} else { /* -- drive 0 or disk+1 */
temptr->tempdisk = tmp_dsk;
seldsk( tmp_dsk ? tmp_dsk - 1 : GBL.dfltdsk );
fcbp->drvcode = GBL.user;
temptr->reselect = TRUE;
}
}

View File

@@ -0,0 +1,303 @@
/****************************************************************
* *
* P-CP/M BDOS Disk Read/Write Module *
* *
* This module contains functions to perform sequential *
* or random access read or write to the disk for P-CP/M *
* *
* It includes the following external functions: *
* *
* bdosrw() - sequential and random disk I/O *
* *
* *
* Modified for memory management on the Z8000 *
* *
****************************************************************/
#include "stdio.h" /* Standard I/O declarations */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
/* External function definitions */
EXTERN UWORD rdwrt(); /* disk read/write routine */
EXTERN WORD getaloc(); /* allocate a block of disk space */
EXTERN UWORD swap(); /* assembly language byte swapper */
EXTERN UWORD dirscan(); /* directory scanning routine */
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
EXTERN UWORD close_fi(); /* close file function */
EXTERN BOOLEAN create(); /* create file function passed to dirscan */
EXTERN UWORD error(); /* error handler */
/* External variable definitions */
EXTERN UWORD ro_dsk; /* read-only disk vector */
/**********************************************************/
/* First, some utility functions used by seqio and ranio */
/**********************************************************/
/******************************
* FCB block number routines *
******************************/
WORD blkindx(fcbp)
/* return index into fcb disk map */
REG struct fcb *fcbp; /* pointer to fcb */
{
REG struct dpb *dparmp; /* pointer to disk parameter block */
REG WORD i;
REG WORD blkshf;
BSETUP
dparmp = GBL.parmp;
blkshf = dparmp->bsh;
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
}
UWORD blknum(fcbp, index, wrdfcb)
/* return block number in fcb indicated by index */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words? */
{
if (wrdfcb)
return( swap(fcbp->dskmap.big[index]) );
else return( UBWORD(fcbp->dskmap.small[index]) );
}
setblk(fcbp, index, wrdfcb, block)
/* put block number into fcb */
REG struct fcb *fcbp; /* pointer to fcb */
REG WORD index; /* index into disk map of fcb */
WORD wrdfcb; /* boolean, fcb disk map of words? */
REG UWORD block; /* block number */
{
fcbp->s2 &= 0x7f; /* set file write flag */
if (wrdfcb)
fcbp->dskmap.big[index] = swap(block);
else fcbp->dskmap.small[index] = (UBYTE)block;
}
/***************************
* disk read/write routine *
***************************/
UWORD do_io(block, rcrd, parm)
UWORD block; /* block number */
UBYTE rcrd; /* record number */
REG WORD parm; /* write parameter */
{
REG LONG lsec;
REG struct dpb *dparmp;
BSETUP
dparmp = GBL.parmp; /* init dpb pointer */
lsec = ((LONG)block << (dparmp->bsh)) +
(LONG)(rcrd & (dparmp->blm));
return( rdwrt(lsec, GBL.dmaadr, parm) );
}
/*******************************************
* routine for crossing extent boundaries *
*******************************************/
WORD new_ext(fcbp, reading, ran)
/* If sequential I/O, open the next extent */
/* If random I/O, compute new extent from random record field */
REG struct fcb *fcbp; /* pointer to fcb */
BOOLEAN reading; /* read/write flag */
WORD ran; /* random I/O flag */
{
REG UBYTE mod; /* module number */
REG UBYTE ext; /* extent number */
BSETUP
if (ran)
{
mod = ( (fcbp->ran0) << 4) | ( (fcbp->ran1) >> 4);
ext = ( ((fcbp->ran1) & 0x0f) << 1);
if ((fcbp->ran2) & 0x80) ext |= 1;
/* the calculation of ext was coded this way because of a */
/* compiler bug from Alcyon */
}
else
{
mod = (fcbp->s2) & 0x3f;
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
}
if (ext >= 32)
{
ext = 0;
mod += 1;
}
if (mod >= 64) return(6); /* past maximum file size */
if ( mod == ((fcbp->s2) & 0x3f) )
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
{ /* we're in same logical extent */
fcbp->extent = ext;
return(0);
}
/* Extent or Module numbers don't match */
/* Close the old extent and open a new one */
if ( close_fi(fcbp) >= 255 ) return(3);
/* can't close old extent */
fcbp->s2 = mod;
fcbp->extent = ext;
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open new extent */
{
if (reading) return(4); /* reading unwritten extent */
if ( dirscan(create, fcbp, 8) >= 255 )
return(5); /* can't create new extent */
}
return(0);
}
/************************************
* Routine to calculate the maximum *
* extent number of an FCB in a *
* extent-folded environment *
************************************/
UWORD calcext(fcbp)
REG struct fcb *fcbp;
{
REG UWORD i;
REG BYTE *p;
BSETUP
i = 15;
p = &(fcbp->dskmap.small[16]);
do
{
if (*--p) break;
i -= 1;
} while (i);
/* Now i contains the index of the last non-zero block in the FCB */
if ((GBL.parmp)->dsm > 255) i >>= 1;
i >>= 7 - ((GBL.parmp)->bsh);
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
}
/*********************************
* Routine to get the actual *
* record count of the currently *
* active logical extent of a FCB *
*********************************/
UWORD get_rc(fcbp)
REG struct fcb *fcbp;
{
REG UWORD ext;
ext = calcext(fcbp); /* find last active extent in fcb */
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
/* if this is the last active fcb, return fcb's rc */
else if (ext > fcbp->extent) return(128);
/* if the fcb has more extents past this one, then */
/* the current one is logically full */
else return (0);
/* if we seeked past the last active extent, rc = 0 */
}
/************************
* bdosrw entry point *
************************/
UWORD bdosrw(fcbp, reading, random)
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
REG BOOLEAN reading; /* boolean to tell whether to read or write */
WORD random; /* 0 = sequential, 1 = random (normal), */
/* 2 = random with zero fill */
{
REG UWORD block; /* block number from fcb */
REG WORD index; /* index into disk map of fcb */
REG XADDR old_dma; /* temp holding spot for dmaadr */
REG UBYTE *buf; /* type compatibility kludge */
REG WORD parm; /* parameter to do-io */
REG WORD bigfile; /* file system is in word mode */
REG UWORD rtn; /* return parameter */
REG UBYTE rc; /* temp storage for rcdcnt */
BSETUP
bigfile = ((GBL.parmp)->dsm) & ~0xff;
if ( ( ! reading) && (fcbp->ftype[robit] & 0x80) ) error(5,fcbp);
/* check for read-only file */
if (random)
{
if ( rtn = new_ext(fcbp, reading, TRUE) ) return(rtn);
/* open new extent if necessary, return if error */
fcbp->cur_rec = (fcbp->ran2) & 0x7f;
}
else /* sequential */
if (fcbp->cur_rec == 128)
{ /* time to try next extent */
if ( new_ext(fcbp, reading, FALSE) )
return(1); /* if can't open new extent, error */
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
}
/* record is now in active fcb */
rc = fcbp->rcdcnt;
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
{
if (reading) return(1); /* reading unwritten data */
fcbp->s2 &= 0x7f; /* set file write flag */
rc = fcbp->cur_rec + 1;
}
index = blkindx(fcbp); /* get index into fcb disk map */
block = blknum(fcbp, index, bigfile);
if (block) parm = (reading ? 0 : 1);
else /* if allocated block, parm is just read or write */
{ /* unallocated block */
if (reading) return(1); /* reading unwritten data */
/* Writing to new block */
block = getaloc();
if (block == (UWORD *)~0) return(2); /* out of space */
setblk(fcbp, index, bigfile, block);
parm = 3;
if (random == 2)
{ /* Write random with zero fill */
old_dma = GBL.dmaadr;
GBL.dmaadr = map_adr((XADDR)GBL.dirbufp,0);/* Do DMA from dir_buf */
index = SECLEN;
buf = (UBYTE *)GBL.dirbufp; /* fix type incompatibility */
do buf[--index] = 0;
while (index); /* zero the dma buffer */
for (index = 0; index <= ((GBL.parmp)->blm); index++)
{
do_io(block, (UBYTE)index, parm);
/* write zeros to the block */
parm = 1; /* next write is not to new block */
}
GBL.dmaadr = old_dma; /* restore dma address */
}
}
rtn = do_io(block, fcbp->cur_rec, parm);
if ( rtn == 0 )
{
fcbp->rcdcnt = rc;
if ( ! random ) fcbp->cur_rec += 1;
}
return(rtn);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,126 @@
;********** 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.
;*
;****************************************************
;* 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.
;*
;* For now, we assume that the system starts at
;* <<11>>0000 (hex)
;*
;****************************************************
;****************************************************
;*
;* Globals
;*
;****************************************************
.global _startld
;****************************************************
;*
;* Externals
;*
;****************************************************
.global bios
;****************************************************
;*
;* Constants
;*
;****************************************************
BOOTSYS .equ 0A000000h ; system address
BOOTSTK .equ BOOTSYS+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 * Commented out - this has implications for booter
jr entry
;* post-boot init.
entry: ;SEGMENTED
_startld:
DI VI,NVI
ldl rr14, #BOOTSTK ; 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

View File

@@ -0,0 +1,818 @@
/*
***************************************************************************
This is the Master/requestor portion of a Dual processor P-CP/M BIOS. It
should be designed such that only the low level inter-processor transfer
protocols and BIOS primitives should have to be modified to accomplish
porting to different hardware configurations. Error checking and report-
ing is necessary because I/O channel may be unplugged or unreliable.
***************************************************************************
*/
/*
*************************************************
* *
* Author: David Heintz *
* Module: Biosmasc.c *
* Creation Date: 10/20/82 *
* Language: Standard C *
* Version: 1.0 *
* Last Mod: 01/20/83 *
* *
*************************************************
*/
/*
*************************************************
* *
* STANDARD HEADERS *
* *
*************************************************
*/
#include "unstdsys.h"
#include "stdcpm.h"
#include "stdbios.h"
#include "chnequ.h"
/*
*************************************************
* *
* EXTERNAL DECLARATIONS *
* *
*************************************************
*/
/*
extern wboot();
*************************************************
* *
* BIOS Entry Point declaration *
* *
*************************************************
*/
extern LONG _bios();
/*
*************************************************
* *
* Other Globals *
* *
*************************************************
*/
extern biosinit(); /* Initialize system */
extern flush(); /* Flush buffer */
/*
*************************************************
* *
* I/O Channel Related Externals *
* *
*************************************************
*/
extern BYTE rcv_cmd();
extern BYTE rcv_byte();
extern BYTE rcv_word();
extern BYTE rcv_long();
extern BYTE rcv_data();
extern BYTE snd_cmd();
extern BYTE snd_byte();
extern BYTE snd_word();
extern BYTE snd_long();
extern BYTE snd_data();
extern chn_err();
/*
*************************************************
* *
* Machine and Processor Dependent *
* Externals *
* *
*************************************************
*/
extern *memtab;
extern LONG trapvec[];
extern mem_cpy();
extern LONG map_adr();
/*
*************************************************
* *
* LOCAL DEFINITIONS *
* *
*************************************************
*/
static char signon[] = "\n\rKontron Z8000 BIOS v. 1.0 11/23/82\n\r";
/*
*************************************************
* *
* Check Vectors *
* 512 Directory Entries Maximum *
* *
*************************************************
*/
BYTE csvtab[8][128] = {{0}};
/*
*************************************************
* *
* Allocation Vectors *
* 2048 Allocation Blocks Maximum *
* *
*************************************************
*/
BYTE alvtab[8][256] = {{0}};
/*
*************************************************
* *
* Data Parameter Blocks *
* Unitialized *
* *
*************************************************
*/
DPB dpbtab[8] = {0};
/*
*************************************************
* *
* Directory Buffer *
* *
*************************************************
*/
BYTE dirbuf[128] = {0};
/*
*************************************************
* *
* Disk Parameter Headers *
* Maximum of 8 defined *
* *
*************************************************
*/
DPH dphtab[8] =
/*
{ *xltp, dphscr[3], *dirbufp, *dpbp, *csvp, *alvp}
*/
{
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[0], csvtab[0], alvtab[0]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[1], csvtab[1], alvtab[1]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[2], csvtab[2], alvtab[2]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[3], csvtab[3], alvtab[3]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[4], csvtab[4], alvtab[4]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[5], csvtab[5], alvtab[5]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[6], csvtab[6], alvtab[6]},
{(BYTE *) 0L, {0,0,0}, &dirbuf[0], &dpbtab[7], csvtab[7], alvtab[7]},
};
/*
*************************************************
* *
* Time-Honored BIOS Variables *
* *
*************************************************
*/
static LONG dmaadr = 0; /* Caller's data transfer address */
static WORD sector = 0; /* Current sector (Unused) */
static WORD track = 0; /* Current track (Unused) */
static BYTE disk = 0; /* Current drive number (Unused) */
static BYTE IOBYTE = 0; /* Logical to physical mapping (Unused) */
static BYTE retry = 0xff; /* I/O channel retry boolean */
/*
*************************************************
* *
* Sector Buffer *
* *
*************************************************
*/
static BYTE secbuf[seclen] = {0};
/*
*************************************************
* *
* MISCELLANEOUS FUNCTIONS *
* *
*************************************************
*/
/*
/--------------------------------
/ |
/ Print a Message |
/ |
/--------------------------------
/ Inputs: Pointer to message
/ terminated by '\0'
/ Outputs: None
/ Actions: Send message to slave
/ console output.
/
*/
prtmsg(pbyte)
BYTE *pbyte;
{
char c;
while(c = *(pbyte++))
_bios((WORD)coreq, (LONG)c, 0L);
}
/*
/--------------------------------
/ |
/ Illegal Command |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Currently unused
/
*/
ill_cmd()
{
}
/*
/--------------------------------
/ |
/ biosinit(); |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Initialize hardware
/
*/
biosinit()
{
prtmsg(signon);
_bios((WORD)inreq, 0L, 0L); /* Make BIOS request */
}
/*
/--------------------------------
/ |
/ Flush Disk Buffer |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Flush Disk Buffer on Slave
/
*/
flush()
{
_bios((WORD)fbreq, 0L, 0L); /* Ignore return code? */
}
/*
/--------------------------------
/ |
/ snd_rcv(): |
/ send a command and |
/ receive a parameter |
/ |
/--------------------------------
/ Inputs: BIOS parameters d0, d1, d2
/ Outputs: LONG return parameter
/ Actions: Send command through fifo and
/ receive return parameter
/
*/
LONG snd_rcv(d0, d1, d2)
WORD d0;
LONG d1, d2;
{
BYTE code;
LONG temp;
do
{
code = snd_cmd(d0, d1, d2);
if (code == chsuc)
code = rcv_long(&temp);
if (code != chsuc)
{
chn_err(d0, code);
temp = cherr;
}
}
while (retry && (code != chsuc));
return(temp);
}
/*
*************************************************
* *
* P-CP/M BIOS ENTRY POINT *
* *
*************************************************
*/
LONG _bios(d0, d1, d2)
WORD d0;
LONG d1, d2;
{
char zzz = {"kludge "};
switch(d0)
{
/*
/--------------------------------
/ |
/ Function 4: |
/ Console Output |
/ |
/--------------------------------
/ Inputs: (BYTE) d1 contains character
/ to output to slave console
/ Outputs: None
/ Actions: Output character from master
/ to slave console I/O.
*/
case coreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 5: |
/ List Output |
/ |
/--------------------------------
/ Inputs: (BYTE) d1 contains character
/ to output to slave list device.
/ Outpus: None
/ Actions: Output character from master
/ to slave list I/O.
*/
case loreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 6: |
/ Auxilliary Output |
/ |
/--------------------------------
/ Inputs: (BYTE) d1 contains character
/ to output to slave aux. device.
/ Outputs: None
/ Actions: Output character from master
/ to slave auxilliary (punch) I/O.
*/
case aoreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 8: |
/ Home disk |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Perform slave home disk function.
*/
case hdreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 10: |
/ Set Track |
/ |
/--------------------------------
/ Inputs: (WORD) d1 contains track number.
/ Outputs: None
/ Actions: Set track number from master on slave.
*/
case streq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 11: |
/ Set Sector |
/ |
/--------------------------------
/ Inputs: (WORD) d1 contains sector number
/ Outputs: None
/ Actions: Set sector number from master on slave.
*/
case ssreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 20: |
/ Set I/O byte |
/ |
/--------------------------------
/ Inputs: BYTE d1 contains IOBYTE value
/ Outputs: None
/ Actions: Send contents of slave
/ location IOBYTE to master.
*/
case sireq: /* Fall through to next case */
/* All degenerate cases of BIOS functions */
/* end up falling through to here. Request */
/* is forwarded to the slave BIOS and no */
/* parameters are returned to the master. */
{
BYTE code;
code = snd_cmd(d0, d1, d2);
if (code != chsuc)
chn_err(d0, code);
}
break; /* Request completed. */
/*
/--------------------------------
/ |
/ Function 2: |
/ Console Status |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: returns console status.
/ Actions: receive 1-byte slave con-
/ sole status.
*/
case csreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 7: |
/ Auxilliary Input |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Return character from aux device
/ Actions: Input a character from slave
/ auxilliary (reader) I/O to master.
*/
case aireq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 15: |
/ List Status |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Return status of slave list device.
/ Actions: Send 1-byte slave list
/ status to master.
*/
case lsreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 16: |
/ Translate Sector |
/ |
/--------------------------------
/ Inputs: (LONG) d1 is sector translation table address
/ (WORD) d2 is sector number to be translated
/ Outputs: Return translated sector.
/ Actions: Perform slave BIOS sector
/ translation call
*/
case tsreq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 19: |
/ Get I/O byte |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Returns IOBYTE value from slave.
/ Actions: Receive byte from master and
/ store in slave location IOBYTE.
*/
case gireq: /* Fall through to next case */
/*
/--------------------------------
/ |
/ Function 21: |
/ Flush disk buffer |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Send request to slave
/
*/
case fbreq: /* Fall through to next case */
/* All cases which return status or data */
/* end up falling through to here. Request */
/* passed on to the slave BIOS and a long */
/* parameter is returned to the master. */
return(snd_rcv(d0, d1, d2));
/*
/--------------------------------
/ |
/ Function 0: |
/ System Init |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Initialize Master.
/ Just print message, so far.
*/
case inreq:
break;
/*
/--------------------------------
/ |
/ Function 1: |
/ Warm Boot |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Warm boot master.
*/
case wbreq:
wboot();
break;
/*
/--------------------------------
/ |
/ Function 3: |
/ Console Input |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: returns console character.
/ Actions: Input character from
/ slave console to master.
*/
case cireq:
while(!_bios(csreq, 0L, 0L));
return(snd_rcv(d0, d1, d2));
/*
/--------------------------------
/ |
/ Function 9: |
/ Select Disk |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Pointer to DPH for selected drive.
/ Null if illegal drive.
/ Actions: Select drive number from master on slave.
/ Return condition code from slave to master.
/ Pass selected drive's DPB from slave to master,
/ if drive selected.
*/
case sdreq:
{
BYTE code;
LONG temp;
DPH *dphptr;
DPB *dpbptr;
do
{
code = snd_cmd(d0, d1, d2);
if (code == chsuc)
code = rcv_long(&temp);
if (code == chsuc)
if ((DPH *)temp != NULL)
{
dphptr = &dphtab[d1];
dpbptr = dphptr -> dpbp;
if (!((BYTE)d2 & 0x1))
{
code = rcv_long(&temp);
if (code == chsuc)
(dphptr -> xltp) = (BYTE *)temp;
if (code == chsuc)
code = rcv_word(&(dpbptr -> spt));
if (code == chsuc)
code = rcv_byte(&(dpbptr -> bsh));
if (code == chsuc)
code = rcv_byte(&(dpbptr -> blm));
if (code == chsuc)
code = rcv_byte(&(dpbptr -> exm));
if (code == chsuc)
code = rcv_word(&(dpbptr -> dsm));
if (code == chsuc)
code = rcv_word(&(dpbptr -> drm));
if (code == chsuc)
code = rcv_byte(&(dpbptr -> al0));
if (code == chsuc)
code = rcv_byte(&(dpbptr -> al1));
if (code == chsuc)
code = rcv_word(&(dpbptr -> cks));
if (code == chsuc)
code = rcv_word(&(dpbptr -> off));
}
temp = (LONG)dphptr;
}
else temp = (LONG)NULL;
if (code != chsuc)
{
chn_err(sdreq, code);
temp = (LONG)cherr;
}
}
while (retry && (code != chsuc));
return(temp);
}
/*
/--------------------------------
/ |
/ Function 13: |
/ Read Sector |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Read completion status
/ Actions: Receive a 128 byte sector specified by
/ current drive, sector, track from slave
/ and place it at the current DMA add-
/ ress.
*/
case rsreq:
{
BYTE stat, code;
LONG temp;
do
{
code = snd_cmd(d0, d1, d2);
if (code == chsuc)
code = rcv_byte(&stat);
if ((stat == rssuc) && (code == chsuc))
code = rcv_data(&secbuf[0], seclen);
if (code == chsuc)
temp = (LONG)stat;
else
{
chn_err(d0, code);
temp = cherr;
}
}
while (retry && (code != chsuc));
if (temp == rssuc)
mem_cpy(map_adr((LONG)secbuf, 0),(LONG)dmaadr,(LONG)seclen);
return(temp);
}
/*
/--------------------------------
/ |
/ Function 14: |
/ Write Sector |
/ |
/--------------------------------
/ Inputs: Write type.
/ Outputs: Write sector completion status.
/ Actions: Send a 128 byte sector from current DMA
/ address to slave.
/ Receive a 1-byte completion code, in-
/ dicating if write successful or not.
*/
case wsreq:
{
BYTE stat, code;
LONG temp;
do
{
mem_cpy((LONG)dmaadr,map_adr((LONG)secbuf,0),(LONG)seclen);
code = snd_cmd(d0, d1, d2);
if (code == chsuc)
code = snd_data(&secbuf[0], seclen);
if (code == chsuc)
code = rcv_byte(&stat);
if (code == chsuc)
temp = (LONG)stat;
else
{
chn_err(d0, code);
temp = cherr;
}
}
while (retry && (code != chsuc));
return(temp);
}
/*
/--------------------------------
/ |
/ Function 12: |
/ Set DMA Address |
/ |
/--------------------------------
/ Inputs: (LONG) d1 contains DMA address.
/ Outputs: None
/ Actions: Set DMA address from master.
*/
case sareq:
dmaadr = d1;
break;
/*
/--------------------------------
/ |
/ Function 17: |
/ Get Memory Table |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: Return pointer to memory region table
/ Actions: None
*/
case gmreq:
return((long)&memtab);
/*
/--------------------------------
/ |
/ Function 22: |
/ Set Exception Vector |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Currently unused
/
*/
case svreq:
{
LONG oldval;
oldval = trapvec[(int)d1];
trapvec[(int)d1] = d2;
return(oldval);
}
/*
/--------------------------------
/ |
/ Illegal Request |
/ |
/--------------------------------
/ Inputs: None
/ Outputs: None
/ Actions: Currently unused
/
*/
default:
ill_cmd(); /* Illegal command */
break;
} /* End of Switch */
} /* End of BIOS */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,98 @@
;******* ccpif.z8k -- CCP interface *****************
;*
;* 821015 S. Savitzky (Zilog) derived from 68K version
;*
;****************************************************
__text: .sect
;****************************************************
;*
;* EXTERNALS
;*
;****************************************************
.global _bdosinit
.global _main
;****************************************************
;*
;* GLOBALS
;*
;****************************************************
.global ccp ; main entry point
.global _autost
.global _usercmd
.global _submit
.global _morecmds
;****************************************************
;*
;* JUMP VECTOR
;*
;****************************************************
ccp: jr ccpstart ; start ccp with possible
; initial command
jp ccpclear ; clear autostart flag
;****************************************************
;*
;* DATA
;*
;****************************************************
__data: .sect
copy: .byte " COPYRIGHT (C) 1982, Digital Research "
_autost: ; autostart command flag
.byte 0
sysinit: ; set if system initialized
.byte 0
_submit:
.byte 0
_morecmds:
.byte 0
__bss: .sect
_usercmd: ; user command buffer
.block 130
stackp: ; saved stack pointer
.block 2
;****************************************************
;*
;* PROGRAM INTERFACE
;*
;* ccpclear -- clear autostart flag
;* ccpstart -- normal entry from boot
;* jumped to with valid stack ptr.
;* ccploop -- main loop (internal)
;*
;****************************************************
__text: .sect
ccpclear:
clrb _autost ; clear the autostart flag
ccpstart:
ld stackp,r15 ; save stack pointer
tsetb sysinit ; system initialized?
jr mi ccploop ; yes
; no: init flag now set
call _bdosinit ; init bdos
ccploop:
ld r15,stackp ; reset stack pointer
call _main ; call the CCP
jr ccploop ; loop forever

View File

@@ -0,0 +1,344 @@
/* Transfer data through an I/O channel -- in this */
/* particular case the quasi fifo on the Zilog Z8000 */
/* Zoom board. This module should be replacable by */
/* others which utitilize a different I/O channel */
/* (i.e. RS-232), and different protocols. */
/*
*************************************************
* *
* Author: David Heintz *
* Module: Channelc.c *
* Creation Date: 10/26/82 *
* Language: Standard C *
* Version: 0.0 *
* Last Mod: 01/17/83 P.S.W. *
* *
*************************************************
*/
/*
*************************************************
* *
* STANDARD HEADERS *
* *
*************************************************
*/
#include "unstdsys.h"
#include "fioequ.h"
#include "chnequ.h"
/*
*************************************************
* *
* EXTERNAL DECLARATIONS *
* *
*************************************************
*/
/*
*************************************************
* *
* I/O Channel Related Externals *
* and Globals *
* *
*************************************************
*/
/* Routines defined other modules */
extern BYTE input();
extern output();
extern BYTE gb_word();
extern BYTE gb_long();
extern pb_word();
extern pb_long();
/* Varibles defined in other modules */
extern WORD bytlen;
extern WORD wrdlen;
extern WORD lnglen;
/* External port addresses */
extern WORD fiocr1;
extern WORD fioir0;
extern WORD fiomsi;
extern WORD fiomso;
/* Routines defined within this module */
extern BYTE snd_pkt();
extern BYTE rcv_pkt();
extern BYTE snd_sys();
extern chn_err();
/* Static definitions for use within module */
/*
*****************************************
* *
* snd_sys(): *
* Transmit a load buffer *
* over I/O channel *
* *
*****************************************
/
/ Inputs: buffer type, segment, offset, data address, length
/ Outputs: I/O channel status (byte)
/ Assumptions: Data length is always less than FIO size
*/
BYTE snd_sys(buftyp, basseg, basoff, buffer, ldlen)
BYTE buftyp, basseg, *buffer;
WORD basoff, ldlen;
{
BYTE code, fio_put(), fio_gack();
int i;
if (code == chsuc)
{
fio_put(buftyp);
fio_put(basseg);
for (i=(wrdlen-1); i>=0; i--)
fio_put(gb_word(&basoff, i)); /* Send high-order byte first */
for (i=(wrdlen-1); i>=0; i--)
fio_put(gb_word(&ldlen, i)); /* Send high-order byte first */
for (i=0; i<ldlen; i++) /* Send data */
fio_put(buffer[i]);
code = fio_gack(fioack); /* Try for an ack */
}
return(code);
}
/*
****************************************.
* *
* snd_pkt(): *
* Transmit a data packet *
* over I/O channel *
* *
********************"*******************

/
/ Inputs: data type, address, and length
/ Outputs: I/O channel status (byte)
*/
BYTE snd_pkt(pkttyp, pbyte, pktlen)
BYTE pkttyp, *pbyte;
WORD pktlen;
{
BYTE code, fio_put(), fio_gack();
WORD i;
code = chsuc;
if ((code = fio_put(pkttyp)) == chsuc)
{
for (i=1; i <= pktlen; i++)
if ((code = fio_put(*(pbyte++))) != chsuc)
return(code);
code = fio_gack(acktyp);
}
return(code);
}
/*
*****************************************
* *
* rcv_pkt(): *
* Receive a data packet *
* over I/O channel *
* *
*****************************************
/
/ Inputs: data type, address, and length
/ Outputs: I/O channel status (byte)
*/
BYTE rcv_pkt(pkttyp, pbyte, pktlen)
BYTE pkttyp, *pbyte;
WORD pktlen;
{
BYTE code, fio_cat(), fio_get(), fio_pack();
WORD i;
code = chsuc;
if ((code = fio_cat(pkttyp)) == chsuc)
{
for (i=1; i <= pktlen; i++)
if ((code = fio_get(pbyte++)) != chsuc)
return(code);
code = fio_pack(acktyp);
}
else fio_pack(ncktyp);
return(code);
}
/*
*****************************************
* *
* fio_gack(): *
* Wait for a certain byte *
* from the fio. *
* *
*****************************************
/
/ Inputs: Byte to wait for
/ Outputs: Status indicating success/failure
*/
BYTE fio_gack(gbyte)
BYTE gbyte;
{
BYTE code, ack, fio_get();
WORD count;
count = chto2;
while (count--)
{
code = fio_get(&ack);
if ((code == chsuc) && (ack == gbyte))
return(code);
}
return(chena);
}
/*
*****************************************
* *
* fio_pack(): *
* Send either positive or *
* negative acknowledgement. *
* *
*****************************************
/
/ Inputs: chack, or chnck
/ Outputs: Status indicating success/failure
*/
BYTE fio_pack(ack)
BYTE ack;
{
BYTE fio_put();
return(fio_put(ack));
}
/*
*****************************************
* *
* fio_cat(): *
* Conditionally attach to *
* the fifo. *
* *
*****************************************
/
/ Inputs: Byte to wait for
/ Outputs: Status indicating success/failure
*/
BYTE fio_cat(tbyte)
BYTE tbyte;
{
BYTE code, ack, fio_get();
WORD count;
count = chto2;
while (count--)
{
code = fio_get(&ack);
if ((code == chsuc) && (ack == tbyte))
return(code);
}
return(cheut);
}
/*
*****************************************
* *
* fio_get(): *
* Get a byte from *
* the I/O channel. *
* *
*****************************************
/
/ Inputs: Address where byte is to be returned
/ Outputs: Status indicating success/failure
*/
BYTE fio_get(rbyte)
BYTE *rbyte;
{
WORD count;
count = chto1;
while (count--)
{
if ((input(fioir0) & fiordy) == fiordy)
{
*rbyte = input(fiomsi);
return(chsuc);
}
}
return(cheto);
}
/*
*****************************************
* *
* fio_put(): *
* Put a byte into *
* the I/O channel. *
* *
*****************************************
/
/ Inputs: Byte to be written to I/O channel
/ Outputs: Status indicating success/failure
*/
BYTE fio_put(sbyte)
BYTE sbyte;
{
WORD count;
count = chto1;
while (count--)
{
if ((input(fiocr1) & fiobsy) != fiobsy)
{
output(fiomso, sbyte);
return(chsuc);
}
}
return(cheto);
}
/*
*****************************************
* *
* chn_err(): *
* Global I/O channel error *
* handling routine *
* *
*****************************************
/
/ Inputs: Error code
/ Outputs: None
*/
chn_err(d0,ebyte)
int d0;
BYTE ebyte;
{
/* Dummy out for now */
}
/* End of Module */

View File

@@ -0,0 +1,18 @@
/* I/O channel definitions (put in header) */
/* Hopefully hardware independent? */
#define byttyp 0x00
#define wrdtyp 0x01
#define lngtyp 0x02
#define dattyp 0x03
#define cmdtyp 0x04
#define acktyp 0x05
#define ncktyp 0x06
#define chsuc 0x00
#define cheto 0x01
#define chena 0x02
#define cheut 0x03
#define cherr 0xff
#define chto1 0x7fff /* In the 5--15 second range, I think */
#define chto2 0x7fff

View File

@@ -0,0 +1,152 @@
/****************************************************************************/
/* */
/* C P M . H */
/* --------- */
/* Copyright 1982 by Digital Research Inc. All rights reserved. */
/* */
/* This file contains CP/M specific definitions for the CP/M */
/* C Run Time Library. */
/* This file is intended only for inclusion with those functions */
/* dealing directly with the BDOS, as well as any function which */
/* has hardware dependent code (byte storage order, for instance). */
/* */
/* <portab.h> must be included BEFORE this file. */
/* */
/****************************************************************************/
/*
* CP/M FCB definition
*/
struct fcbtab /****************************/
{ /* */
BYTE drive; /* Disk drive field */
BYTE fname[8]; /* File name */
BYTE ftype[3]; /* File type */
BYTE extent; /* Current extent number */
BYTE s1,s2; /* "system reserved" */
BYTE reccnt; /* Record counter */
BYTE resvd[16]; /* More "system reserved" */
LONG record; /* Note -- we overlap the */
/* current record field to */
/* make this useful. */
}; /****************************/
#define SECSIZ 128 /* size of CP/M sector */
#define _MAXSXFR 1 /* max # sectors xferrable */
#define _MAXSHFT 12 /* shift right BDOS rtn val */
/* to obtain nsecs on err */
/****************************/
/****************************************************************************/
/* */
/* Channel Control Block (CCB) */
/* */
/* One CCB is allocated (statically) for each of the 16 possible open */
/* files under C (including STDIN, STDOUT, STDERR). Permanent data */
/* regarding the channel is kept here. */
/* */
/* */
/****************************************************************************/
struct ccb /************************************/
{ /* */
BYTE flags; /* Flags byte */
BYTE chan; /* Channel number being used */
LONG offset; /* File offset word (bytes) */
LONG sector; /* Sector currently in buffer */
LONG hiwater; /* High water mark */
struct fcbtab fcb; /* File FCB (may have TTY info)*/
BYTE buffer[SECSIZ]; /* Read/write buffer */
}; /************************************/
#define MAXCCBS 16 /* Maximum # CC Blocks */
extern struct ccb _fds[MAXCCBS]; /* Declare storage */
#define FD struct ccb /* FD Type definition */
/************************************/
/* Flags word bit definitions */
/************************************/
#define OPENED 0x01 /* Channel is OPEN */
#define ISTTY 0x02 /* Channel open to TTT */
#define ISLPT 0x04 /* Channel open to LPT */
#define ISREAD 0x08 /* Channel open readonly */
#define ISASCII 0x10 /* ASCII file attached */
#define ATEOF 0x20 /* End of file encountered */
#define DIRTY 0x40 /* Buffer needs writing */
#define ISSPTTY 0x80 /* Special tty info */
/************************************/
#define READ 0 /* Read mode parameter for open */
#define WRITE 1 /* Write mode */
/* CCB manipulation macros *************************************/
#define _getccb(i) (&_fds[i]) /* Get CCB addr */
/* Error handling *************************************/
EXTERN WORD errno; /* error place for assigning */
EXTERN WORD __cpmrv; /* the last BDOS return value */
EXTERN WORD _errcpm; /* place to save __cpmrv */
#define RETERR(val,err) {errno=(err);_errcpm=__cpmrv;return(val);}
/************************************/
/****************************************************************************/
/* */
/* B D O S F u n c t i o n D e f i n i t i o n s */
/* ------------------------------------------------- */
/* */
/* Following are BDOS function definitions used by the C runtime */
/* library. */
/* */
/****************************************************************************/
/****************************/
#define EXIT 0 /* Exit to BDOS */
#define CONOUT 2 /* Direct console output */
#define LSTOUT 5 /* Direct list device output*/
#define CONIO 6 /* Direct console I/O */
#define CONBUF 10 /* Read console buffer */
#define OPEN 15 /* OPEN a disk file */
#define CLOSE 16 /* Close a disk file */
#define DELETE 19 /* Delete a disk file */
#define CREATE 22 /* Create a disk file */
#define SETDMA 26 /* Set DMA address */
#define B_READ 33 /* Read Random record */
#define B_WRITE 34 /* Write Random record */
#define FILSIZ 35 /* Compute File Size */
#define SETMSC 44 /* Set Multi-Sector Count */
/****************************/
/****************************************************************************/
/* Other CP/M definitions */
/****************************************************************************/
#define TERM "CON:" /* Console file name */
#define LIST "LST:" /* List device file name */
#define EOFCHAR 0x1a /* End of file character-^Z */
/****************************/
/****************************************************************************/
/* Hardware dependencies */
/****************************************************************************/
#define HILO /* used when bytes stored */
/* Hi,Lo */
/****************************/
#ifdef HILO /* Hi/Lo storage used in */
struct { /* 68K */
BYTE lbhihi; /* Use this for accessing */
BYTE lbhilo; /* ordered bytes in 32 bit*/
BYTE lblohi; /* LONG qtys. */
BYTE lblolo; /* */
}; /* */
struct { /* Use this for accessing */
WORD lwhi; /* ordered words in 32 bit*/
WORD lwlo; /* LONG qtys. */
}; /* */
#else /****************************/
struct { /* Lo/Hi storage use on */
BYTE lblolo; /* PDP-11, VAX, 8086,... */
BYTE lblohi; /* */
BYTE lbhilo; /* */
BYTE lbhihi; /* */
}; /* */
struct { /* */
WORD lwlo; /* */
WORD lwhi; /* */
}; /* */
#endif /****************************/
/*************************** end of cpm.h ***********************************/

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,45 @@
/*
* errno.h - error codes
*/
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
/* math software */
#define EDOM 33
#define ERANGE 34
/* hereafter is available to CP/M specials */
#define ENODSPC 35
/****** end of errno.h ******/

View File

@@ -0,0 +1,352 @@
;************************************************
;* *
;* P-CP/M Basic Disk Operating System *
;* Exception Handling Module *
;* *
;* Version 0.0 -- July 21, 1982 *
;* Version 0.1 -- July 25, 1982 *
;* Version 0.2 -- 821014 (Zilog) *
;* Version 0.3 -- 821222 (Zilog) *
;* *
;************************************************
; 01/11/83 Adapted for Z8002 (DMH)
.input "biosdefs2.z8k"
__text: .sect
;****************************************************
;*
;* Externals
;*
;****************************************************
.global _sysseg
.global _tpa_lp
.global _tpa_hp
;****************************************************
;*
;* Globals and Constants
;*
;****************************************************
.global _initexc
BGETSEG .equ 18 ;Bios call to get mem seg tbl
BSETEXC .equ 22 ;Bios call to set xvec
;****************************************************
;*
;* initexc(vecarray) -- initialize exception vector
;*
;* The BDOS maintains its OWN exception vector.
;* This routine sets up the BIOS exception
;* vectors to point to handlers in this module,
;* that vector again using the BDOS vectors.
;*
;* Only vectors 2-23 and 36-38 are handled by
;* the BDOS, leaving 0-1 and 24-35 for the BIOS
;*
;****************************************************
_initexc:
;* sp -> return addr
;* +2 table addr
ld r3,#BSETEXC ; r3 = BIOS command
ldl rr4,#2 ;rr4 = exception #
ld r6,_sysseg ;rr6 -> handler
lda r7,exchndl ;exception handler offset
dec r15,#10 ;space to save regs
; on stack over SC
initloop:
ldm @r15,r3,#5
sc #BIOS_SC
ldm r3,@r15,#5
inc r5,#1 ;step exception #
inc r7,#2 ;and handler addr.
cp r5,#24 ;done 23 yet?
jr ne init1 ; no
ld r5,#36 ; yes--skip to 36
inc r7,#8 ; we have entries in
; table for 32-36
; but system uses
; them. Skip.
init1: cp r5,#48 ;done all 48?
jr ne initloop ; no--loop
inc r15,#10 ;clean stack
ld r2,2(r15) ;save vector address
ld evec_adr,r2
ld r0,#18 ; 18 long entries
subl rr4,rr4
init2: ;clear vector array
; should check current entry, and keep it if
; between old TPA and current TPA limits.
; The TPA limits are flaky because we have two TPA's,
; for split and merged spaces, not to mention
; segmented programs.
; What we are going to do is clear the lot.
; Programs that want permanent traps can use the
; Bios to set the trap vector.
ldl rr6,@r2 ; rr6 = exception addr
ldl @r2,rr4
init3:
inc r2,#4
djnz r0,init2
ret ;return
;****************************************************
;*
;* Exception Handler Routine
;*
;* An exception handler is called as a subroutine
;* with all registers saved on the stack.
;*
;* Returning (ret) from the handler (in segmented
;* mode) will return to the state-restorer.
;*
;****************************************************
exchndl:
calr except
excrtn0:
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
calr except
except: ; general exception handler
pop r1,@r15 ; get return address
; from above array
sub r1,#excrtn0 ; r1 now = 2 * encoded
sll r1,#2 ; r1 now = 4 * encoded
; r1/4 = [0..21, 22..37] represents exceptions
; [2..23, 32..47].
;
; If r1/4 is in the range [0..9, 22..29] then the
; exception may be redirected by the BDOS.
cp r1,#36
jr le chkredir
cp r1,#88
jr lt dfltexc
cp r1,#116
jr gt dfltexc
; in range of redirected exceptions
sub r1,#48 ; subtract 4*12 to normalize [0..9,22..29]
; into [0..9,10..17]
chkredir:
ld r2,evec_adr ; index into exception
; vector array
ldl rr4,r2(r1) ; rr4 -> handler
testl rr4 ; if non-zero
jr nz usrexc ; go do it
;not redirected,
; do default handler
cp r1,#40
jr lt dfltexc
add r1,#48 ; add 4*12 sub'd above
dfltexc:
srl r1,#2 ; divide r1 by 4
; r1 = [0..21,22..37]
; meaning [2..23,32..47]
add r1,#2 ;get back real except#
cp r1,#23
jr le lowexc
add r2,#12
lowexc:
push @r15,r1 ; save exception #
; print default msg
clr r6
ld r7,#excmsg1
calr print
calr prtdollar
pop r1,@r15
calr prtbyte
clr r6
ld r7,#excmsg2
calr print
calr prtdollar
pop r1,@r15
sub r0,r0
calr prtlong
clr r6
ld r7,#excmsg3
calr print
clr r5 ; warm boot
sc #2
ret
usrexc: ; call user exception handler
; rr4 -> handler
; user exception handler called in with FCW restored
; to that at the time of the exception, with the
; stack containing a copy of the context block.
; On top of the context block will be a GARBAGE
; return address of the appropriate mode.
; Handler must exit with XFER system call.
; stack now contains:
; return address to trap_ret
; normal r0..r15
; reason, fcw, PC
ldl usr_vec,rr4 ; save user exception vector
ld r7,r15 ; map current stack pointer
sub r6,r6 ; dummy segment
ld r5,#2 ; system space code
subl rr2,rr2 ; for map_adr call
sc #MEM_SC ; do map_adr call
ldl rr2,rr6 ; save map_addr results
ld r1,scfcw+co(r15) ; get user fcw
ld r5,#2 ; anticipate system space code
bit r1,#14 ; system mode?
jr nz,sysexc ; yes.
ld r5,#4 ; Normal space code
sysexc: ld r7,nr15+co(r15) ; user stack
sub r7,#FRAMESZ+co ; allocate stack frame on user's stack
sub r6,r6 ; dummy segment, dest. in rr6
pushl @r15,rr2 ; save source on stack
subl rr2,rr2 ; for map_adr call
sc #MEM_SC ; do map_adr call
popl rr4,@r15 ; retrieve source
ldl rr2,#FRAMESZ+co ; length
sc #MEM_SC ; transfer stack frame to user stack
ldl rr4,usr_vec ; restore user exception vector
ld r0,scfcw+co(r15) ; get back user's fcw
push @r15,r5 ; push on user's exception vector.
pushl @r15,rr0 ; push identifier and user's fcw
iret ; go
;****************************************************
;*
;* Subroutines
;*
;****************************************************
print:
ld r5,#9 ;PRINTMSG
sc #2 ;BDOS
ret
prtdollar:
ld r5,#2 ;PRINTCHAR
ldl rr6,#24h ; dollarsign
sc #2
ret
prtlong: ; print rr0 as hex long
push @r15,r1
ex r0,r1
calr prtword
pop r1,@r15
prtword: ; print r1 as hex word
push @r15,r1
ldb rl1,rh1
calr prtbyte
pop r1,@r15
prtbyte: ; Print rl1 as hex byte
push @r15,r1
srl r1,#4
calr prtnib
pop r1,@r15
prtnib:
and r1,#15
cp r1,#10
jr lt,lt10
add r1,#7
lt10:
add r1,#30h
ld r7,r1
ld r5,#2 ;PRINTBYTE
sc #2 ;BDOS
ret
;****************************************************
;*
;* data
;*
;****************************************************
__con: .sect
excmsg1:
.byte 13,10,10,"Exception $"
excmsg2:
.byte " at user address $"
excmsg3:
.byte ". Aborted.$"
;****************************************************
;*
;* bss
;*
;****************************************************
__bss: .sect
evec_adr:
.block 2
usr_vec:
.block 4
.end

View File

@@ -0,0 +1,15 @@
getfile -D basepage.h
getfile -D bdos.h
getfile -D copyrt.lit
getfile -D cpm.h
getfile -D ctype.h
getfile -D ed.c
getfile -D errno.h
getfile -D makefile
getfile -D pip.c
getfile -D portab.h
getfile -D setjmp.h
getfile -D sgtty.h
getfile -D stat.c
getfile -D stdio.h
getfile -D x.out.h

View File

@@ -0,0 +1,18 @@
/* Zoom board fifo definitions */
#define fiobsy 0x20
#define fiordy 0x20
#define fiotst 0xaa
#define fioini 0xfe
#define fiofre 0xfd
#define fioack 0x03
#define fiobeg 0x00
#define fiolen 0x0400 /* No. of bytes in fio */
#define nrmbuf 0x02 /* Not last buffer */
#define lstbuf 0x01 /* Last buffer */
/* System Location */
#define sysseg 0x00 /* System segment */
#define sysoff 0x0000 /* System offset */
#define sysent 0x1002 /* System entry point */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
/************************************************************************
* *
* CP/M-8000 CCP Program Loader (__LOAD) *
* *
* Copyright (c) 1982 Zilog Incorporated *
* *
* This function arranges for the BDOS program loader to be *
* invoked in a suitable environment. Suitable means that it *
* fills in whatever is expected in the LPB, gets the rest back *
* from the BDOS, and then completes the basepage and resets the *
* dma buffer. *
* *
* The loading of segmented programs is not currently supported *
* *
************************************************************************/
#include "stdio.h" /* Standard declarations for BDOS, BIOS */
#include "bdosdef.h" /* BDOS type and structure declarations */
#include "biosdef.h" /* Declarations of BIOS functions */
#include "basepage.h" /* Base page structure */
#define SEP_ID 0x4000 /* Separate I/D flag */
#define SEG 0x2000 /* Segmented load module */
#define NREGIONS 2 /* Number of MRT regions */
/* Return values: indexes into msgs (included here for documentation */
/* purposes - only GOOD is used in this module */
#define GOOD 0 /* good return value */
#define BADHDR 1 /* bad header */
#define NOMEM 2 /* not enough memory */
#define READERR 3 /* read error */
#define WARMBOOT 0 /* Warm reboot BDOS call */
#define PRNTSTR 9 /* Print String BDOS call */
#define SETDMA 26 /* Set DMA Address BDOS call */
#define PGLOAD 59 /* Program Load BDOS call */
#define MYDATA 0 /* Argument for map_adr */
#define TPADATA 4 /* Argument for map_adr */
#define TPAPROG 5 /* Argument for map_adr */
/* Get actual code segment (as opposed */
/* to segment where it can be accessed*/
/* as data) */
#define TRUE_TPAPROG (TPAPROG | 0x100)
#define BGETMRT 18 /* Number of the BIOS call */
extern char cmdfcb[]; /* the FCB for everything */
extern char *tail; /* where the command tail is */
extern UWORD bdos(); /* To do I/O into myself */
extern XADDR bios(); /* To get MRT pointer */
extern VOID fill_fcb(); /* Parse filename into fcb */
extern VOID xfer(); /* Transfer control to user program */
struct lpb {
XADDR fcbaddr; /* Address of fcb of opened file */
XADDR pgldaddr; /* Low address of prog load area */
XADDR pgtop; /* High address of prog load area, +1 */
XADDR bpaddr; /* Address of basepage; return value */
XADDR stackptr; /* Stack ptr of user; return value */
short flags; /* Loader control flags; return value */
} LPB;
struct m_rt { /* The Memory Region Table */
int entries;
struct {
XADDR m_low;
XADDR m_len;
} m_reg[NREGIONS];
};
struct ustack /* User's initial stack (nonsegmented) */
{
short two; /* "Return address" (actually a call to */
/* BDOS warm boot in runtime startup) */
short bpgaddr;/* Input parameter: pointer to basepage */
} stack =
{
0x0002 /* bpgaddr initialized at runtime */
};
struct sstack /* User's initial stack (segmented) */
{
XADDR stwo; /* "Return address" (actually a call to */
/* BDOS warm boot in runtime startup) */
XADDR sbpgadr;/* Input parameter: pointer to basepage */
} sstack;
/* Error messages for bad loads */
static char *msgs[] =
{
"",
"File is not executable$",
"Insufficient memory$",
"Read error on program load$",
"Program Load Error$"
};
struct context /* Startup context for user's program */
{
short regs[16];
short ignore;
short FCW;
XADDR PC;
} context =
{ /* Regs 0-14 cleared, 15 set up below */
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
0, /* Ignore: value is zero */
0x1800 /* FCW: nonsegmented normal, VI, NVI set*/
}; /* PC initialized below */
/********************************/
/* */
/* _ _ L O A D */
/* */
/********************************/
VOID /* Load a program from */
__LOAD() /* info in cmdfcb */
{
register short k;
struct m_rt *mpr;
register XADDR physaddr;
BYTE tlen; /* length of cmd tail */
register char *tp;
mpr = (struct m_rt *) bios(BGETMRT);
/* Set up the Load Parameter Block */
/* Strictly speaking we should look at magic number to find out */
/* which segment(s) the program needs. */
LPB.pgldaddr = mpr->m_reg[0].m_low;
LPB.pgtop = mpr->m_reg[0].m_len;
LPB.fcbaddr = map_adr((XADDR) cmdfcb, MYDATA);
/* Try loading the program. Print message and reboot if load fails */
if ((k = bdos(PGLOAD, map_adr((XADDR) &LPB, MYDATA))) != GOOD)
{
bdos(PRNTSTR, map_adr((XADDR) msgs[min(4, k)], MYDATA));
bdos(WARMBOOT, 0L);
}
/* Move command tail to basepage buffer; reset DMA address to that buffer. */
/* Due to difficulty of adding structure member offset to something */
/* which is not a structure pointer, we use a kludge to get physical */
/* DMA buffer address: buffer is at last thing on basepage and has a */
/* length of one sector. */
/* Compute length of tail, since CCP does not supply it */
for (tlen=0, tp=tail; *tp++ != NULL; tlen++) ;
/* Next expression written in strange way to overcome compiler bug */
physaddr = LPB.bpaddr - (SECLEN - sizeof (struct b_page));
bdos(SETDMA, physaddr);
cpy_out(&tlen, physaddr, 1L); /* tail length */
cpy_out(tail, physaddr+1, (long) SECLEN-1); /* and cmd tail */
/* Fill base page fcb's */
fill_fcb(1, cmdfcb);
physaddr -= sizeof (struct fcb); /* Another kludge */
cpy_out(cmdfcb, physaddr, sizeof (struct fcb));
fill_fcb(2, cmdfcb);
physaddr -= sizeof (struct fcb); /* Yet a third kludge */
cpy_out(cmdfcb, physaddr, sizeof(struct fcb));
/* Now build a user stack which looks like:
* ----------------- ^ ^
* word/long | Base page addr| ^ High address ^
* ----------------- ^ ^
* word/long | 2 | <-- Stack pointer points here
* -----------------
*/
if (LPB.flags & SEG) { /* Segmented */
sstack.sbpgadr = LPB.bpaddr;
sstack.stwo = LPB.pgldaddr + 2;
cpy_out(&sstack, LPB.bpaddr - sizeof sstack, sizeof sstack);
} else { /* Nonsegmented */
stack.bpgaddr = (short) LPB.bpaddr;
cpy_out(&stack, LPB.bpaddr - sizeof stack, sizeof stack);
}
/* Finally, ready to transfer control. Must complete context first. */
if (LPB.flags & SEG) { /* Segmented */
context.regs[14] = (short)(LPB.stackptr >> 16);
context.regs[15] = (short)LPB.stackptr;
context.PC = LPB.pgldaddr;
context.FCW= 0x9800;
} else { /* Nonsegmented!*/
context.regs[15] = (short) LPB.stackptr;
context.PC = map_adr(LPB.pgldaddr, TRUE_TPAPROG);
context.FCW= 0x1800;
}
xfer(map_adr((XADDR) &context, MYDATA)); /* Go for it! */
}

View File

@@ -0,0 +1,228 @@
/* This module is a collection of all the Z8000 */
/* dependent C code for the P-CP/M dual processor */
/* BIOS. */
/*
*************************************************
* *
* Author: David Heintz *
* Module: Kon8kc.c *
* Creation Date: 10/26/82 *
* Language: Standard C *
* Version: 1.0 *
* Last Mod: 12/16/83 *
* *
*************************************************
*/
/* 01/16/83 Adapted for Kontron Z8002 board (DMH) */
/*
*************************************************
* *
* STANDARD HEADERS *
* *
*************************************************
*/
#include "unstdsys.h"
#include "fioequ.h"
#include "chnequ.h"
/*
*************************************************
* *
* EXTERNAL DECLARATIONS *
* *
*************************************************
*/
extern BYTE gb_word();
extern BYTE gb_long();
extern pb_word();
extern pb_long();
extern WORD bytlen;
extern WORD wrdlen;
extern WORD lnglen;
/*
*************************************************
* *
* Byte Ordering Arrays For *
* Word and Long *
* *
*************************************************
*/
static BYTE wrdtab[2] = {1, 0};
static WORD lngtab[4] = {3, 2, 1, 0};
/*
*************************************************
* *
* Machine dependent entities *
* *
*************************************************
*/
WORD bytlen = 1;
WORD wrdlen = 2;
WORD lnglen = 4;
/*
*************************************************
* *
* Port Addresses for Zoom Board *
* *
*************************************************
*/
WORD fiodat = 0x0001; /* Values for Z8002 side */
WORD fioctl = 0x0003; /* only. */
/* Port Addresses for the Zilog 8038 fifo */
WORD fioreg = 0x0051;
WORD fiocr1 = 0x0003;
WORD fioir0 = 0x0005;
WORD fiomso = 0x0017;
WORD fiomsi = 0x0019;
/*
*************************************************
* *
* Memory Region Table *
* *
*************************************************
*/
/* The following table describes two memory regions: */
/* Region 1 Type: Merged instruction and data space */
/* Length: 64k combined space. */
/* Base: Pseudo-segement <<1>> */
/* */
/* Region 2 Type: Split instruction and data space */
/* Length: 64k instruction space, 32, data space */
/* Base: Pseudo-segment <<2>> */
/* */
/* Notes This table is machine dependent */
/* but not processor dependent. */
/* Table does not include system segment. */
/* Table should probably be removed to module of */
/* machine dependent code and data. */
/* ********* This is the real memory region table ******** */
struct mrt {
int count;
struct {long tpalow;
long tpalen;
} regions[2];
} memtab = {2,
{{0x01000000L, 0x10000L},
{0x02000000L, 0x10000L}
}
};
/*
*****************************************
* *
* gb_word(): *
* Retrieve a specified *
* byte from a word *
* *
*****************************************
/
/ Inputs: Address of word
/ Byte number
/ Outputs: Byte corresponding to
/ byte number in word
*/
BYTE gb_word(pbyte, i)
BYTE *pbyte;
WORD i;
{
return(pbyte[wrdtab[i]]);
}
/*
*****************************************
* *
* gb_long(): *
* Retrieve a specified *
* byte from a long *
* *
*****************************************
/
/
/ Inputs: Address of long
/ Byte number
/ Outputs: Byte corresponding to
/ byte number in long
*/
BYTE gb_long(pbyte, i)
BYTE *pbyte;
WORD i;
{
return(pbyte[lngtab[i]]);
}
/*
*****************************************
* *
* pb_word(): *
* Place a specified *
* byte into a word *
* *
*****************************************
/
/
/ Inputs: Byte to be place
/ Address of word
/ Byte number
/ Outputs: None
*/
pb_word(sbyte, pbyte, i)
BYTE sbyte, *pbyte;
WORD i;
{
pbyte[wrdtab[i]] = sbyte;
}
/*
*****************************************
* *
* pb_long(): *
* Place a specified *
* byte into a long *
* *
*****************************************
/
/
/ Inputs: Byte to be place
/ Address of long
/ Byte number
/ Outputs: None
*/
pb_long(sbyte, pbyte, i)
BYTE sbyte, *pbyte;
WORD i;
{
pbyte[lngtab[i]] = sbyte;
}
/* End of Module */

View File

@@ -0,0 +1,99 @@
/*=======================================================================*/
/*+---------------------------------------------------------------------+*/
/*| |*/
/*| P-CP/M(tm) Block Move for the KONTRON BOARD (Z8002) |*/
/*| |*/
/*| Copyright 1982, Zilog Incorporated. |*/
/*| |*/
/*+---------------------------------------------------------------------+*/
/*=======================================================================*/
char copyright[] = "Copyright 1982, Zilog Incorporated";
/* HISTORY
**
** 830111 F. Zlotnick (Zilog)
** 830121 D. Heintz (Me) Fixed bug in s/d window computation
*/
mem_bcp( sseg, source, dseg, dest, length)/* sseg and dseg are pseudo-segment */
unsigned short sseg, source, dseg, dest;/* numbers from mem_copy. */
unsigned short length; /* source and dest are offsets in */
/* the pseudo-segments. length is */
/* the number of bytes to be copied*/
{
register unsigned length1, length2;
register unsigned middle;
short swindow, dwindow;
unsigned short blength;
static char locbuf[256]; /* intermediate buffer */
/* deal recursively with the possibility of crossing the half-segment line */
middle = 0x8000;
if(source < middle && source + length > middle) {
length1 = middle - source; /* first half */
length2 = length - length1; /* second half */
mem_bcp(sseg,source,dseg,dest,length1); /* recurse */
mem_bcp(sseg,middle,dseg,dest+length1,length2);/* recurse */
return;
}
if(dest < middle && dest + length > middle) {
length1 = middle - dest; /* first half */
length2 = length - length1; /* second half */
mem_bcp(sseg,source,dseg,dest,length1); /* recurse */
mem_bcp(sseg,source+length1,dseg,middle,length2);/* recurse */
return;
}
/*
* This part is non-recursive. If you get this far, you're guaranteed
* not to cross a mid-segment boundary on either the source or dest
* blocks.
*/
swindow = ((sseg >> 8) << 1) | ( (source >= middle) ? 1 : 0);
dwindow = ((dseg >> 8) << 1) | ( (dest >= middle) ? 1 : 0);
if ( swindow == dwindow ) { /* Both in same window */
map_wdw(swindow);
if(swindow != 0) { /* If really mapped, then */
source |= 0x8000; /* must be in upper half */
dest |= 0x8000; /* of system address space */
}
blkmov(source,dest,length);
}
else if(swindow != 0 && dwindow != 0) {
source |= 0x8000;
dest |= 0x8000;
while(length > 0) {
blength = (length > 256)? 256: length ;
map_wdw(swindow);
blkmov(source,locbuf,blength); /* Assumes pointers*/
map_wdw(dwindow); /* are short! */
blkmov(locbuf,dest,blength); /* Ditto */
source += blength;
dest += blength;
length -= blength;
}
}
else {
if ( swindow == 0 ) { /* System lower half: no window */
map_wdw(dwindow); /* Put dest block in upper */
dest |= 0x8000; /* half of system space */
}
else if ( dwindow == 0 ) {
map_wdw(swindow); /* Put source block in upper */
source |= 0x8000; /* half of system space */
}
while ( length > 0 ) {
blength = (length > 256)? 256: length ;
blkmov(source,dest,blength);
source += blength;
dest += blength;
length -= blength;
}
}
}

View File

@@ -0,0 +1,431 @@
/****************************************************************
* *
* CP/M-8000 BDOS Program Loader *
* *
* Copyright (c) 1982 Zilog Incorporated *
* *
* This module contains routines for loading the file *
* naked "CPM.SYS" into memory, at the address specified *
* by the first entry in the MRT. If we are properly *
* linked with the Bootstrap BIOS, this is a loader- *
* specific MRT which actually contains the address of *
* system space. *
* *
****************************************************************/
#include "stdio.h" /* Standard declarations for BDOS, BIOS */
#include "bdosdef.h" /* Type and structure declarations for BDOS */
#include "biosdef.h" /* Declarations of BIOS functions */
#include "basepage.h" /* Base page structure */
#include "x.out.h" /* structure of x.out (".Z8[KS] file") */
#define SEP_ID 0x4000 /* Separate I/D flag */
#define PRNTSTR 9 /* Print String BDOS call */
#define SETDMA 26 /* Set DMA Address BDOS call */
#define BGETMRT 18 /* Number of the BIOS call */
#define open(fcbp) _bdos(15, 0, map_adr( (XADDR)fcbp, MYDATA) )
/* BDOS open call */
extern UWORD bdos(); /* To do I/O into myself */
extern XADDR bios(); /* To get MRT pointer */
extern VOID xfer(); /* Transfer control to user program */
#define NPSEG 1 /* Number of physical segs available */
/* for CP/M kernel */
#define NSEG 16 /* Maximum number of x.out segments */
#define SEGLEN 0x10000 /* Length of a Z8000 segment */
#define BPLEN (sizeof (struct b_page))
#define DEFSTACK 0x100 /* Default stack length */
#define NREGIONS 1 /* Number of regions in the Loader MRT */
/* return values */
#define GOOD 0 /* good return value */
#define BADHDR 1 /* bad header */
#define NOMEM 2 /* not enough memory */
#define READERR 3 /* read error */
#define MYDATA 0 /* Argument for map_adr */
#define SYSPROG 3 /* Argument for map_adr */
#define SYSDATA 2 /* Argument for map_adr */
/* Get actual code segment (as opposed */
/* to segment where it can be accessed*/
/* as data) */
#define TRUE_SYSPROG (SYSPROG | 0x100)
struct m_rt { /* The Memory Region Table */
int entries;
struct {
XADDR m_low;
XADDR m_len;
} m_reg[NREGIONS];
};
struct context /* Startup context for user's program */
{
short regs[14];
XADDR segstkptr;
short ignore;
short FCW;
XADDR PC;
};
extern struct context context; /* defined in bios.c */
/* Define the data structures used in ldcpm */
struct fcb cpmfcb =
{ (BYTE)0, /* drive code */
'C','P','M',' ',' ',' ',' ',' ','S','Y','S', /* file name */
0,0,0,0,0,0,0,0,0,0, /* the rest of the fcb */
0,0,0,0,0,0,0,0,0,0,0
};
#define NSPREG 0 /* The MRT region for non-split programs */
#define READ 20 /* Read Sequential BDOS call */
extern UWORD bdos(); /* To do I/O into myself (note this */
/* function does not map 2nd param - */
/* see mbdos macro below) */
XADDR textloc, /* Physical locations of pgm sections. */
dataloc,
bssloc,
stkloc;
XADDR textsiz, /* Sizes of the various sections. */
datasiz,
bsssiz,
stksiz;
UWORD split, /* Tells if split I/D or not */
seg; /* Tells if segmented or not */
char *gp; /* Buffer pointer for char input */
char *mydma; /* Local address of read buffer */
struct x_hdr x_hdr; /* Object File Header structure */
struct x_sg x_sg[NSEG]; /* Segment Header structure */
XADDR segsiz[NPSEG]; /* Segment lengths */
XADDR seglim[NPSEG]; /* Segment length limits */
XADDR segloc[NPSEG]; /* Segment base physical addresses */
short textseg, /* Logical seg # of various segments */
dataseg,
bssseg,
stkseg;
/**************************/
/* Utility Routines */
/**************************/
pstring(p)
/* print string */
REG BYTE *p;
{
while (*p) bconout(*p++);
}
badload(errtype)
/* Load failed. Print message and try again */
REG WORD errtype;
{
REG WORD i;
switch (errtype)
{
case 0: pstring("\r\nBoot error.");
startld();
case 1: pstring("\n\rOpen or Read error on ");
break;
case 2: pstring("\n\rBad file format on ");
}
pstring("CPM.SYS");
startld();
}
/***************************
* ldcpm main routine *
***************************/
/********************************/
/* */
/* l d c p m */
/* */
/********************************/
VOID /* Load a program from */
ldcpm() /* info in cpmfcb */
{
register unsigned k;
register XADDR physaddr;
register char *tp;
if (seldsk(0)) badload(0);
k = open(&cpmfcb);
if( k >= 255 ) badload(1);
k = load(); /* load the CP/M system */
if(k != GOOD) badload(2);
pstring("\r\n\nCP/M-Z8K(tm) Version 1.3 ");
pstring("\n\rCopyright (c) 1983 Zilog Inc, Digital Research, Inc.\r\n\n");
/* Finally, ready to transfer control. Must complete context first. */
xfer(map_adr((XADDR) &context, MYDATA)); /* Go for it! */
}
/********************************/
/* */
/* Start of load function */
/* */
/********************************/
load() /* Load a program from FCB info */
{ register int i,j; /* Temporary counters etc. */
struct m_rt *mrp; /* Pointer to a MRT structure */
char mybuf[SECLEN]; /* Local buffer for file reading*/
mydma = mybuf; /* Initialize addr for local DMA*/
gp = &mybuf[SECLEN]; /* Point beyond end of buffer */
mrp = (struct m_rt *) bios(BGETMRT);/* Get address of memory region */
/* table (note segment # lost)*/
if (readhdr() == EOF) /* Get x.out file header */
return (READERR); /* Read error on header */
if (x_hdr.x_magic == X_NXN_MAGIC) /* Is this acceptable x.out file*/
{ /* CP/M kernel must be nonseg nonsplit*/
split = FALSE;
seg = FALSE;
}
else
return (BADHDR); /* Sorry, can't load it! */
/* Set the user space segment number, from the low address in the */
/* appropriate entry of the MRT. */
/* m_reg[SPREG] is the region used for split I/D programs in the MRT */
/* m_reg[NSPREG] is used for non-split. */
/* NOTE -- the tpa limits passed in the MRT are really system space */
/* limits. It is assumed that the system is non-split. */
for (i = 0; i < x_hdr.x_nseg; i++) { /* For each segment... */
if( readxsg(i) == EOF) /* ...get segment hdr */
return(READERR);
seglim[i] = SEGLEN; /* ...set max length */
segsiz[i] = 0L; /* ...and current size */
}
/* Set section base addresses */
textloc = dataloc = bssloc = stkloc = 0L;
/* Zero section sizes */
textsiz = datasiz = bsssiz = 0L;
stksiz = DEFSTACK;
stkseg = bssseg = dataseg= textseg = 0;
/* assign locations */
segloc[textseg] = mrp->m_reg[NSPREG].m_low;
/* Assign limits */
seglim[textseg] = mrp->m_reg[NSPREG].m_len - stksiz;
/* Assign stack location */
stkloc = segloc[dataseg] + seglim[dataseg] + stksiz;
for (i = 0; i < x_hdr.x_nseg; i++) /* For each segment... */
if( (j = loadseg(i)) != GOOD) /* ...load memory. If */
return (j); /* error return, pass */
/* it back. */
return (GOOD);
}
/* Macro to call BDOS. First parameter is passed unchanged, second */
/* is cast into an XADDR, then mapped to caller data space. */
#define mbdos(func, param) (bdos((func), map_adr((XADDR) (param), MYDATA)))
/* Macro to read the next character from the input file (much faster */
/* than having to make a function call for each byte) */
#define fgetch() ((gp<mydma+SECLEN) ? (int)*gp++&0xff : fillbuff())
/* Routine to fill input buffer when fgetch macro detects it is empty */
int fillbuf() /* Returns first char in buffer */
{ /* or EOF if read fails */
/* Set up address to read into */
mbdos(SETDMA, mydma);
if (mbdos(READ, &cpmfcb) != 0) /* Have BDOS do the read*/
return (EOF);
gp = mydma; /* Initialize buffer pointer */
return ((int)*gp++ & 0xff); /* Return first character */
}
/* Routine to read the file header */
int readhdr()
{
register int n, k;
register char *p;
p = (char *) &x_hdr;
for (n = 0; n < sizeof (struct x_hdr); n++) {
if( (k = fgetch()) == EOF)
return (k);
*p++ = (char) k;
}
return (GOOD);
}
/* Routine to read the header for segment i */
int readxsg(i)
int i;
{
register int n, k;
register char *p;
p = (char *) &x_sg[i];
for(n = 0; n < sizeof (struct x_sg); n++) {
if ( (k = fgetch()) == EOF)
return (READERR);
*p++ = (char) k;
}
return (GOOD);
}
/* Routine to load segment number i */
/* This assumes that the segments occur in load order in the file, and */
/* that all initialized data and, in the case of combined I/D programs, */
/* text segments, precede all bss segments. */
/* In the case of segmented programs, the stack segment must exist, */
/* and all segments are presumed to be of maximum length. */
/* Text, data, bss, and stack lengths are sum of lengths of all such */
/* segments, and so may be bigger than maximum segment length. */
int loadseg(i)
int i;
{
register UWORD l, length; /* Total, incremental length */
register int type; /* Type of segment loaded */
register short lseg; /* logical segment index */
register XADDR phystarg; /* physical target load address */
l = x_sg[i].x_sg_len; /* number of bytes to load */
type = x_sg[i].x_sg_typ; /* Type of segment */
lseg = textseg; /* try putting in text space */
phystarg = segloc[lseg] + segsiz[lseg]; /* physical target addr */
switch (type) /* Now load data, if necessary */
/* save physical address & size */
{
case X_SG_BSS: /* BSS gets cleared by runtime */
/* startup. */
stkloc = (phystarg & 0xffff0000L) + SEGLEN - BPLEN - stksiz;
/* ...in case no stack segment */
if (bssloc == 0L) bssloc = phystarg;
bsssiz += l;
if ((segsiz[lseg] += l) >= seglim[lseg])
return (NOMEM);
return (GOOD); /* Transfer no data */
case X_SG_STK: /* Stack segment: */
if (stkloc == 0L) { /* if segmented, we now */
/* know where to put */
seglim[lseg] -= BPLEN; /* the base page */
stkloc = segloc[lseg] + seglim[lseg];
}
stkseg = lseg;
stksiz += l; /* adjust size and */
seglim[lseg] -= l; /* memory limit */
if (segsiz[lseg] >= seglim[lseg])
return (NOMEM);
return (GOOD); /* Transfer no data */
case X_SG_COD: /* Pure text segment */
case X_SG_MXU: /* Dirty code/data (better not)*/
case X_SG_MXP: /* Clean code/data (be sep I/D)*/
if (textloc == 0L) textloc = phystarg;
textsiz += l;
break;
case X_SG_CON: /* Constant (clean) data */
case X_SG_DAT: /* Dirty data */
stkloc = (phystarg & 0xffff0000L) + SEGLEN - BPLEN - stksiz;
/* ...in case no stack or */
/* bss segments */
if (dataloc == 0L) dataloc = segloc[i];
datasiz += l;
break;
}
/* Check seg overflow */
if ((segsiz[lseg] += l) >= seglim[lseg])
return (NOMEM);
/* load data from file */
/* Following loop is optimized for load speed. It knows*/
/* about three conditions for data transfer: */
/* 1. Data in read buffer: */
/* Transfer data from read buffer to target */
/* 2. Read buffer empty and more than 1 sector of data */
/* remaining to load: */
/* Read data direct to target */
/* 3. Read buffer empty and less than 1 sector of data */
/* remaining to load: */
/* Fill read buffer, then proceed as in 1 above */
while (l) /* Until all loaded */
{ /* Data in disk buffer? */
if (gp < mydma + SECLEN)
{
length = min(l, mydma + SECLEN - gp);
cpy_out(gp, phystarg, length);
gp += length;
}
else if (l < SECLEN) /* Less than 1 sector */
{ /* remains to transfer*/
length = 0;
mbdos(SETDMA, mydma);
fillbuf();
gp = mydma;
}
else /* Read full sector */
{ /* into target space */
length = SECLEN;
bdos(SETDMA, phystarg);
mbdos(READ, &cpmfcb);
}
phystarg += length;
l -= length;
}
return (GOOD);
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,52 @@
/*****************************************************************************
*
* C P / M C R U N T I M E L I B H E A D E R F I L E
* -------------------------------------------------------------
* Copyright 1982 by Digital Research Inc. All rights reserved.
*
* This is an include file for assisting the user to write portable
* programs for C.
*
*****************************************************************************/
#
/* #un!define ALCYON 1 */ /* using Alcyon compiler */
/* ALCYON undefined 9/3/82 by FZ */
/*
* Standard type definitions
*/
/***************************/
#define BYTE char /* Signed byte */
#define BOOLEAN char /* 2 valued (true/false) */
#define WORD short /* Signed word (16 bits) */
#define UWORD unsigned int /* unsigned word */
#define LONG long /* signed long (32 bits) */
#define ULONG unsigned long /* Unsigned long */
#define REG register /* register variable */
#define LOCAL auto /* Local var on 68000 */
#define EXTERN extern /* External variable */
#define MLOCAL static /* Local to module */
#define GLOBAL /**/ /* Global variable */
#define VOID /**/ /* Void function return */
/***************************/
#ifdef ALCYON
#define UBYTE char
#else
#define UBYTE unsigned char /* Unsigned byte */
#endif
/****************************************************************************/
/* Miscellaneous Definitions: */
/****************************************************************************/
#define FAILURE (-1) /* Function failure return val */
#define SUCCESS (0) /* Function success return val */
#define YES 1 /* "TRUE" */
#define NO 0 /* "FALSE" */
#define FOREVER for(;;) /* Infinite loop declaration */
#define NULL 0 /* Null pointer value */
#define EOF (-1) /* EOF Value */
#define TRUE (1) /* Function TRUE value */
#define FALSE (0) /* Function FALSE value */
/*************************** end of portab.h ********************************/

View File

@@ -0,0 +1 @@
These are the sources for a CP/M-8000 version from June 14, 1983. Some sources contain the version string "P-CP/M for the Olivetti M20 (Z8000) v. 1.3". Sources are in C language. Includes BIOS for the Olivetti M20 Z8000.

View File

@@ -0,0 +1,17 @@
/****************************************************************************/
/* */
/* s e t j m p . h */
/* --------------- */
/* */
/* Copyright 1982 by Zilog Inc. All rights reserved */
/* */
/* Definitions for setjmp and longjmp non-local goto library functions.*/
/* jmp_buf is large enough to hold copies of the eight "safe" */
/* registers and a segmented return address. Thus the last word is */
/* not used in non-segmented environments */
/* */
/****************************************************************************/
typedef int jmp_buf[10];
extern int setjmp(), longjmp();

View File

@@ -0,0 +1,14 @@
/* sgtty.h - tty control information */
/* Note reduced contents for CP/M implementation... */
struct sgttyb{
char sg_ispeed; /* ignored */
char sg_ospeed; /* ignored */
char sg_erase; /* ignored */
char sg_kill; /* ignored */
int sg_flags;
};
#define RAW 0000040
#define CRMOD 0000020
#define ECHO 0000010
#define LCASE 0000004
#define CBREAK 0000002

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/*
/--------------------------------
/ BIOS Request Codes |
/--------------------------------
*/
#define inreq 0 /* Initialize */
#define wbreq 1 /* Warm boot */
#define csreq 2 /* Console status */
#define cireq 3 /* Console input */
#define coreq 4 /* Console output */
#define loreq 5 /* List output */
#define aoreq 6 /* Auxilliary output */
#define aireq 7 /* Auxilliary input */
#define hdreq 8 /* Home disk head */
#define sdreq 9 /* Select disk */
#define streq 10 /* Set track */
#define ssreq 11 /* Set sector */
#define sareq 12 /* Set DMA address */
#define rsreq 13 /* Read a sector */
#define wsreq 14 /* Write a sector */
#define lsreq 15 /* List status */
#define tsreq 16 /* Translate Sector */
#define sbreq 17 /* Set DMA base */
#define gmreq 18 /* Get memory table */
#define gireq 19 /* Get IOBYTE */
#define sireq 20 /* Set IOBYTE */
#define fbreq 21 /* Flush disk buffers */
#define svreq 22 /* Set Exception Vector */
/*
/--------------------------------
/ BIOS Status Codes |
/--------------------------------
*/
#define csaye 0xff /* Console character available */
#define csnay 0x00 /* Console character not available */
#define sdsuc 0x00 /* Select disk successful */
#define sderr 0x01 /* Select disk error */
#define sdfrs 0x00 /* First select call since warm boot */
#define rssuc 0x00 /* Read sector successful */
#define rserr 0x01 /* Read sector error, non-recoverable */
#define wssuc 0x00 /* Write sector successful */
#define wserr 0x01 /* Write sector error, non-recoverable */
#define lsaye 0xff /* List device ready */
#define lsnay 0x00 /* List device not ready */
/*
/--------------------------------
/ BIOS Sector Length |
/--------------------------------
*/
#define seclen 0x80 /* Length of CP/M sector (128 bytes) */

View File

@@ -0,0 +1,144 @@
;************ 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 _bdos(code, p1)
;* int code;
;* long p1, p2;
;*
;* BIOS, BDOS access. Not used in the bootstrap!
;*
;****************************************************
;_bdos:
; ld r5,ARG1(r15)
; ldl rr6,ARG2(r15)
; sc #BDOS_SC
; ret

View File

@@ -0,0 +1,183 @@
;****************************************************
;*
;* Globals
;*
;****************************************************
.global _T0S0, _T1S0, _T1S1
;****************************************************
;*
;* Constants
;*
;****************************************************
SYSTEM .equ 0A000000h ; 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 2*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
;****************************************************
;*
;* Track 0 Sector 0
;*
;* This sector contains the pointer to the
;* bootstrap file's FDB.
;*
;****************************************************
__data: .sect
_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 ; starting addr.
.word 1 ; #code blocks
.long SYSTEM ; load address
.word SYSSIZE/2 ; #words
s1data .block S1SIZE ; data area

View File

@@ -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;

View File

@@ -0,0 +1,61 @@
struct x_hdr {
short x_magic; /* magic number */
short x_nseg; /* number of segments in file */
long x_init; /* length of initialized part of file */
long x_reloc; /* length of relocation part of file */
long x_symb; /* length of symbol table part of file */
};
struct x_sg {
char x_sg_no; /* assigned number of segment */
char x_sg_typ; /* type of segment */
unsigned x_sg_len; /* length of segment */
} x_sg[]; /* array of size x_nseg */
#define X_SU_MAGIC 0xEE00 /* segmented, non executable */
#define X_SX_MAGIC 0xEE01 /* segmented, executable */
#define X_NU_MAGIC 0xEE02 /* non-segmented, non executable */
#define X_NXN_MAGIC 0xEE03 /* non-segmented, executable, non-shared */
#define X_NXS_MAGIC 0xEE07 /* non-segmented, executable, shared */
#define X_NXI_MAGIC 0xEE0B /* non-segmented, executable, split ID */
#define X_SG_BSS 1 /* non-initialized data segment */
#define X_SG_STK 2 /* stack segment, no data in file */
#define X_SG_COD 3 /* code segment */
#define X_SG_CON 4 /* constant pool */
#define X_SG_DAT 5 /* initialized data */
#define X_SG_MXU 6 /* mixed code and data, not protectable */
#define X_SG_MXP 7 /* mixed code and data, protectable */
struct x_rel { /* relocation item */
char x_rl_sgn; /* segment containing item to be relocated */
char x_rl_flg; /* relocation type (see below) */
unsigned x_rl_loc; /* location of item to be relocated */
unsigned x_rl_bas; /* number of (external) element in symbol table
or (internal) segment by which to relocate */
};
#define X_RL_OFF 1 /* adjust a 16 bit offset value only */
#define X_RL_SSG 2 /* adjust a short form segment plus offset */
#define X_RL_LSG 3 /* adjust a long form (32 bit) seg plus off */
#define X_RL_XOF 5 /* adjust a 16 bit offset by an external */
#define X_RL_XSSG 6 /* adjust a short seg ref by an external */
#define X_RL_XLSG 7 /* adjust a long seg ref by an external */
#define XNAMELN 8 /* length of a symbol */
struct x_sym {
char x_sy_sg; /* the segment number */
char x_sy_fl; /* the type of entry */
unsigned x_sy_val; /* the value of this entry */
char x_sy_name[XNAMELN]; /* the symbol name, padded with 0's */
};
#define X_SY_LOC 1 /* local symbol (for debug only) */
#define X_SY_UNX 2 /* undefined external entry */
#define X_SY_GLB 3 /* global definition */
#define X_SY_SEG 4 /* segment name */