mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-27 10:24:19 +00:00
Upload
Digital Research
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* B A S E P A G E . H */
|
||||
/* ------------------- */
|
||||
/* */
|
||||
/* This file contains a definition of the CP/M basepage structure, */
|
||||
/* b_page. */
|
||||
/* */
|
||||
/* NOTE: In the portable CP/M environment, it is NOT guaranteed */
|
||||
/* that the location of the base page is known at link-edit time */
|
||||
/* (as it is, for example, in CP/M-80 and CP/M-86.) Instead, a */
|
||||
/* pointer to the current basepage is delivered by the BDOS */
|
||||
/* to each new program which is run. This pointer, _base, is */
|
||||
/* initialized by the C startup function (startup.s) and is */
|
||||
/* available to C programs as an external. */
|
||||
/* */
|
||||
/* This file has been modified to live with the BDOS definitions. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcb fcb2; /* Second basepage FCB */
|
||||
struct fcb fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
@@ -0,0 +1,367 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
|
||||
;****************************************************************
|
||||
;* *
|
||||
;* CP/M-Z8K Basic Disk Operating System interface module *
|
||||
;* For "C" version of CP/M-Z8K *
|
||||
;* *
|
||||
;* Copyright (c) 1982 Digital Research, Inc. *
|
||||
;* *
|
||||
;* Version 0.2 -- September 22, 1982 *
|
||||
;* Z8000 version -- 821014 *
|
||||
;* *
|
||||
;****************************************************************
|
||||
|
||||
; 01/10/83 Modified for use with Z8002 (DMH)
|
||||
; 01/21/83 Fixed TPA caller Pseudo-segment prooblem
|
||||
|
||||
__text: .sect
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Globals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _bios1 ; 6 BIOS entry points from BDOS
|
||||
.global _bios2
|
||||
.global _bios3
|
||||
.global _bios4
|
||||
.global _bios5
|
||||
.global _bios6
|
||||
.global _traphnd ; trap #2 handler
|
||||
.global _swap ; byte swapper
|
||||
.global _udiv ; unsigned divide routine
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals and Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bdos ; BDOS entry point in bdosmain
|
||||
.global _usrseg ; This is user pseudo-segment
|
||||
.global _sysseg ; This is system pseudo_segment
|
||||
|
||||
;* The following were put in so that all BDOS modules were
|
||||
;* referenced, so they could be put in a library
|
||||
|
||||
.global _constat ; references conbdos.o
|
||||
.global _dirscan ; references dskutil.o
|
||||
.global _create ; references fileio.o
|
||||
.global _bdosrw ; references bdosrw.o
|
||||
|
||||
biosf .equ 50
|
||||
setsupf .equ 62
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap Handler
|
||||
;*
|
||||
;* rcode = bdos(command, (long)parameter)
|
||||
;*
|
||||
;* rr6: parameter
|
||||
;* r5: command
|
||||
;* returns
|
||||
;* r7: result
|
||||
;*
|
||||
;* called non-SEGMENTED with caller's registers
|
||||
;* saved on stack, and all but rr0 intact in
|
||||
;* registers.
|
||||
;*
|
||||
;* Calls __bdos(cmd, (word)param, (addr)param)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_traphnd:
|
||||
|
||||
; check for functions handled by assembly
|
||||
; language routines
|
||||
|
||||
cp r5,#setsupf ; set system mode
|
||||
jr eq setsup
|
||||
cp r5,#biosf ; call bios direct
|
||||
jr eq bioscall
|
||||
|
||||
;
|
||||
; if caller was non-segmented (always case for Z8002)
|
||||
; get (pseudo) segment number from _userseg
|
||||
|
||||
ldl rr2,rr6
|
||||
; ld r2,_sysseg ; assume system mode
|
||||
; ld r0,scfcw+co(r15)
|
||||
; bit r0,#14 ; Was user system?
|
||||
; jr nz,callC ; Yes.
|
||||
; ld r2,_usrseg ; user pseudo segment
|
||||
|
||||
;
|
||||
; Call C main routine
|
||||
;
|
||||
|
||||
callC:
|
||||
pushl @r15,rr2 ; xaddr param.
|
||||
push @r15,r7 ; word param
|
||||
push @r15,r5 ; command
|
||||
call __bdos
|
||||
add r15,#8
|
||||
;
|
||||
; Return result in caller's r7.
|
||||
; Restore segmented mode and return
|
||||
;
|
||||
ld cr7+co(r15),r7
|
||||
ret
|
||||
|
||||
;
|
||||
; direct BIOS call function
|
||||
;
|
||||
bioscall:
|
||||
ldm r3,@r7,#5 ;get parameters
|
||||
sc #3 ;call BIOS
|
||||
ret ;done
|
||||
|
||||
callBios:
|
||||
|
||||
;
|
||||
; Set supervisor mode procedure -- VERY DANGEROUS
|
||||
;
|
||||
; Status is set to SYSTEM, SEGMENTED.
|
||||
; Interrupt status will be that at the time
|
||||
; of the call.
|
||||
;
|
||||
setsup:
|
||||
ld r0,scfcw+co(r15)
|
||||
set r0,#14 ;set system
|
||||
ld scfcw+co(r15),r0;in user FCW
|
||||
ret ;return
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* BIOS Interface Routines
|
||||
;*
|
||||
;* Note - there are 6 BIOS entry points from the BDOS,
|
||||
;* labelled BIOS1 - BIOS6, depending on the
|
||||
;* parameters passed.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_bios5:
|
||||
; For BIOS functions sectran and set exception vector
|
||||
; (funct, word, long) offsets 2, 4, 6
|
||||
|
||||
ldl rr6,6(r15) ; get 2nd param (long)
|
||||
jr _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
|
||||
jr _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
|
||||
jr _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
|
||||
|
||||
_bios6:
|
||||
_bios1:
|
||||
; For all BIOS functions that have no parameter
|
||||
; other than function number
|
||||
ld r3,2(r15) ; get function number
|
||||
sc #3 ; do BIOS call
|
||||
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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Miscellaneous Module *
|
||||
* *
|
||||
* This module contains miscellaneous loose ends for *
|
||||
* P-CP/M. Included are: *
|
||||
* *
|
||||
* bdosinit() - BDOS initialization routine *
|
||||
* called from CCP for system init *
|
||||
* warmboot() - BDOS warm boot exit routine *
|
||||
* error() - BDOS error printing routine *
|
||||
* setexc() - BDOS set exception vector *
|
||||
* set_tpa() - BDOS get/set TPA limits *
|
||||
* cpy_bi() - copy byte in *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on the Z8000 *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* BIOS definitions, needed for bios wboot */
|
||||
|
||||
|
||||
/* Declare external functions */
|
||||
EXTERN conout(); /* Console Output function */
|
||||
EXTERN UBYTE conin(); /* Console Input function */
|
||||
EXTERN prt_line(); /* Print String function */
|
||||
EXTERN UWORD _bdos(); /* BDOS main routine */
|
||||
EXTERN UBYTE *traphnd(); /* assembly language trap handler */
|
||||
EXTERN initexc(); /* init the exception handler in */
|
||||
/* exceptn.s */
|
||||
EXTERN UWORD dirscan(); /* Directory scanning routine */
|
||||
EXTERN BOOLEAN set_attr(); /* Set File attributes function */
|
||||
|
||||
/* Declare external variables */
|
||||
EXTERN UWORD log_dsk; /* logged-on disk vector */
|
||||
EXTERN UWORD ro_dsk; /* read-only disk vector */
|
||||
EXTERN UWORD crit_dsk; /* vector of critical disks */
|
||||
EXTERN XADDR tpa_lt; /* TPA lower limit (temporary) */
|
||||
EXTERN XADDR tpa_lp; /* TPA lower limit (permanent) */
|
||||
EXTERN XADDR tpa_ht; /* TPA upper limit (temporary) */
|
||||
EXTERN XADDR tpa_hp; /* TPA upper limit (permanent) */
|
||||
EXTERN BOOLEAN submit; /* external variables from CCP */
|
||||
EXTERN BOOLEAN morecmds;
|
||||
|
||||
|
||||
#define trap2v 34 /* trap 2 vector number */
|
||||
#define ctrlc 3 /* control-c */
|
||||
|
||||
|
||||
/********************************
|
||||
* bdos initialization routine *
|
||||
********************************/
|
||||
|
||||
bdosinit()
|
||||
/* Initialize the File System */
|
||||
{
|
||||
REG struct
|
||||
{
|
||||
WORD nmbr;
|
||||
XADDR low;
|
||||
LONG length;
|
||||
} *segp;
|
||||
BSETUP
|
||||
|
||||
bsetvec(trap2v, map_adr((long)traphnd, 257)); /* set up trap vector */
|
||||
/* (inst. space addr) */
|
||||
GBL.kbchar = 0; /* initialize the "global" variables */
|
||||
GBL.delim = '$';
|
||||
GBL.lstecho = FALSE;
|
||||
GBL.echodel = TRUE;
|
||||
GBL.chainp = XNULL;
|
||||
GBL.user = 0;
|
||||
_bdos(13,0, XNULL); /* reset disk system function */
|
||||
prt_line("
|
||||
\r\nCPM-Z8000 Version 1.3 06/14/83$");
|
||||
prt_line("\r\nCopyright 1982 Digital Research Inc., Zilog Inc.$");
|
||||
segp = bgetseg(); /* get pointer to memory segment table */
|
||||
tpa_lt = tpa_lp = segp->low;
|
||||
tpa_ht = tpa_hp = tpa_lp + segp->length;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* warmboot entry point *
|
||||
************************/
|
||||
|
||||
warmboot(parm)
|
||||
/* Warm Boot the system */
|
||||
WORD parm; /* 1 to reset submit flag */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
log_dsk &= ~ro_dsk; /* log off any disk marked read-only */
|
||||
/* note that this code is specifically for a single-
|
||||
thread system. It won't work in a multi-task sys */
|
||||
ro_dsk = 0;
|
||||
crit_dsk = 0;
|
||||
if (parm)
|
||||
submit = morecmds = FALSE;
|
||||
tpa_lt = tpa_lp;
|
||||
tpa_ht = tpa_hp;
|
||||
initexc( &(GBL.excvec[0]) );
|
||||
bwboot();
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* disk error handlers */
|
||||
/*************************/
|
||||
|
||||
prt_err(p)
|
||||
/* print the error message */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line(p);
|
||||
prt_line(" error on drive $");
|
||||
conout(GBL.curdsk + 'A');
|
||||
}
|
||||
|
||||
|
||||
abrt_err(p)
|
||||
/* print the error message and always abort */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
prt_err(p);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
|
||||
ext_err(p)
|
||||
/* print the error message, and allow for retry, abort, or ignore */
|
||||
|
||||
BYTE *p;
|
||||
{
|
||||
REG UBYTE ch;
|
||||
|
||||
prt_err(p);
|
||||
do
|
||||
{
|
||||
prt_line("\n\rDo you want to: Abort (A), Retry (R),$");
|
||||
prt_line(" or Continue with bad data (C)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': return(1);
|
||||
case 'R': return(0);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
filero(fcbp)
|
||||
/* File R/O error */
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
{
|
||||
REG BYTE *p;
|
||||
REG UWORD i;
|
||||
REG UBYTE ch;
|
||||
|
||||
p = (BYTE *)fcbp;
|
||||
prt_line("file error: $");
|
||||
i = 8;
|
||||
do conout(*++p); while (--i);
|
||||
conout('.');
|
||||
i = 3;
|
||||
do conout(*++p); while (--i);
|
||||
prt_line(" is read-only.$");
|
||||
do
|
||||
{
|
||||
prt_line("\r\nDo you want to: Change it to read/write (C), or Abort (A)? $");
|
||||
ch = conin() & 0x5f;
|
||||
prt_line("\r\n$");
|
||||
|
||||
switch ( ch )
|
||||
{
|
||||
case ctrlc: warmboot(1);
|
||||
case 'A': warmboot(1);
|
||||
case 'C': fcbp->ftype[robit] &= 0x7f;
|
||||
return( dirscan(set_attr, fcbp, 2) );
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* error entry point *
|
||||
************************/
|
||||
|
||||
error(errnum, fcbp) /* VARARGS */
|
||||
/* Print error message, do appropriate response */
|
||||
|
||||
UWORD errnum; /* error number */
|
||||
struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
prt_line("\r\nCP/M Disk $");
|
||||
switch (errnum)
|
||||
{
|
||||
case 0: return( ext_err("read$") );
|
||||
/* break; */
|
||||
|
||||
case 1: return( ext_err("write$") );
|
||||
/* break; */
|
||||
|
||||
case 2: abrt_err("select$");
|
||||
/* break; */
|
||||
|
||||
case 3: return( ext_err("select$") );
|
||||
/* break; */
|
||||
|
||||
case 4: abrt_err("change$");
|
||||
/* break; */
|
||||
|
||||
case 5: return filero(fcbp);
|
||||
/* break; */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* set exception entry point *
|
||||
*****************************/
|
||||
|
||||
setexc(xepbp)
|
||||
/* Set Exception Vector */
|
||||
REG XADDR xepbp;
|
||||
{
|
||||
REG WORD i;
|
||||
REG struct
|
||||
{
|
||||
WORD vecnum;
|
||||
UBYTE *newvec;
|
||||
UBYTE *oldvec;
|
||||
} epb;
|
||||
|
||||
BSETUP
|
||||
|
||||
cpy_in(xepbp, &epb, sizeof epb); /* copy in param block */
|
||||
|
||||
i = epb.vecnum-2;
|
||||
if ( i==32 || i==33) return(-1);
|
||||
if ( (30 <= i) && (i <= 37) ) i -= 20;
|
||||
else if ( (i < 0) || (i > 9) ) return(-1);
|
||||
epb.oldvec = GBL.excvec[i];
|
||||
GBL.excvec[i] = epb.newvec;
|
||||
|
||||
cpy_out(&epb, xepbp, sizeof epb); /* copy out param block */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
* get/set TPA entry point *
|
||||
*****************************/
|
||||
|
||||
set_tpa(xp)
|
||||
/* Get/Set TPA Limits */
|
||||
REG XADDR xp;
|
||||
|
||||
#define set 1
|
||||
#define sticky 2
|
||||
|
||||
{
|
||||
struct
|
||||
{
|
||||
UWORD parms;
|
||||
XADDR low;
|
||||
XADDR high;
|
||||
} p;
|
||||
|
||||
cpy_in(xp, &p, sizeof p); /* copy in param block */
|
||||
|
||||
if (p.parms & set)
|
||||
{
|
||||
tpa_lt = p.low;
|
||||
tpa_ht = p.high;
|
||||
if (p.parms & sticky)
|
||||
{
|
||||
tpa_lp = tpa_lt;
|
||||
tpa_hp = tpa_ht;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p.low = tpa_lt;
|
||||
p.high = tpa_ht;
|
||||
}
|
||||
|
||||
cpy_out(&p, xp, sizeof p); /* copy out param block */
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************
|
||||
**
|
||||
** ubyte = cpy_bi(xaddr)-- copy byte in
|
||||
**
|
||||
*****************************************************/
|
||||
|
||||
UBYTE cpy_bi(addr)
|
||||
XADDR addr;
|
||||
{
|
||||
UBYTE b;
|
||||
|
||||
cpy_in(addr, &b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-Z8K Loader BDOS Disk Read 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: *
|
||||
* *
|
||||
* seqread() - 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 rdsec(); /* disk read/write routine */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN BOOLEAN openfile(); /* open file function passed to dirscan */
|
||||
|
||||
/**********************************************************/
|
||||
/* First, some utility functions used by seqio and ranio */
|
||||
/**********************************************************/
|
||||
|
||||
/******************************
|
||||
* FCB block number routines *
|
||||
******************************/
|
||||
|
||||
WORD blkindx(fcbp)
|
||||
/* return index into fcb disk map */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG WORD i;
|
||||
REG WORD blkshf;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp;
|
||||
blkshf = dparmp->bsh;
|
||||
i = ((fcbp->extent) & dparmp->exm) << (7 - blkshf);
|
||||
return (i + (UBWORD(fcbp->cur_rec) >> blkshf) );
|
||||
}
|
||||
|
||||
|
||||
UWORD blknum(fcbp, index, wrdfcb)
|
||||
/* return block number in fcb indicated by index */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
WORD wrdfcb; /* boolean, fcb disk map of words? */
|
||||
{
|
||||
if (wrdfcb)
|
||||
return( swap(fcbp->dskmap.big[index]) );
|
||||
else return( UBWORD(fcbp->dskmap.small[index]) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*********************
|
||||
* disk read routine *
|
||||
*********************/
|
||||
|
||||
UWORD do_io(block, rcrd)
|
||||
|
||||
UWORD block; /* block number */
|
||||
UBYTE rcrd; /* record number */
|
||||
{
|
||||
REG LONG lsec;
|
||||
REG struct dpb *dparmp;
|
||||
BSETUP
|
||||
|
||||
dparmp = GBL.parmp; /* init dpb pointer */
|
||||
lsec = ((LONG)block << (dparmp->bsh)) +
|
||||
(LONG)(rcrd & (dparmp->blm));
|
||||
return( rdsec(lsec, GBL.dmaadr) );
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* routine for crossing extent boundaries *
|
||||
*******************************************/
|
||||
|
||||
WORD new_ext(fcbp)
|
||||
/* If sequential I/O, open the next extent */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb */
|
||||
{
|
||||
REG UBYTE mod; /* module number */
|
||||
REG UBYTE ext; /* extent number */
|
||||
BSETUP
|
||||
|
||||
mod = (fcbp->s2) & 0x3f;
|
||||
ext = (fcbp->extent) + 1; /* for sequential, incr extent */
|
||||
if (ext >= 32)
|
||||
{
|
||||
ext = 0;
|
||||
mod += 1;
|
||||
}
|
||||
if (mod >= 64) return(6); /* past maximum file size */
|
||||
if ( mod == ((fcbp->s2) & 0x3f) )
|
||||
if ( ! ((ext ^ (fcbp->extent)) & ~((GBL.parmp)->exm) & 0x1f) )
|
||||
{ /* we're in same logical extent */
|
||||
fcbp->extent = ext;
|
||||
return(0);
|
||||
}
|
||||
/* Extent or Module numbers don't match */
|
||||
/* Close the old extent and open a new one */
|
||||
fcbp->s2 = mod;
|
||||
fcbp->extent = ext;
|
||||
if ( dirscan(openfile, fcbp, 0) >= 255 ) /* open new extent */
|
||||
return(4); /* reading unwritten extent */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/************************************
|
||||
* Routine to calculate the maximum *
|
||||
* extent number of an FCB in a *
|
||||
* extent-folded environment *
|
||||
************************************/
|
||||
|
||||
UWORD calcext(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD i;
|
||||
REG BYTE *p;
|
||||
BSETUP
|
||||
|
||||
i = 15;
|
||||
p = &(fcbp->dskmap.small[16]);
|
||||
do
|
||||
{
|
||||
if (*--p) break;
|
||||
i -= 1;
|
||||
} while (i);
|
||||
/* Now i contains the index of the last non-zero block in the FCB */
|
||||
if ((GBL.parmp)->dsm > 255) i >>= 1;
|
||||
i >>= 7 - ((GBL.parmp)->bsh);
|
||||
return ( (fcbp->extent) & ~((GBL.parmp)->exm) & 0x1f | i );
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
* Routine to get the actual *
|
||||
* record count of the currently *
|
||||
* active logical extent of a FCB *
|
||||
*********************************/
|
||||
|
||||
UWORD get_rc(fcbp)
|
||||
|
||||
REG struct fcb *fcbp;
|
||||
|
||||
{
|
||||
REG UWORD ext;
|
||||
|
||||
ext = calcext(fcbp); /* find last active extent in fcb */
|
||||
if (ext == fcbp->extent) return(UBWORD(fcbp->rcdcnt));
|
||||
/* if this is the last active fcb, return fcb's rc */
|
||||
else if (ext > fcbp->extent) return(128);
|
||||
/* if the fcb has more extents past this one, then */
|
||||
/* the current one is logically full */
|
||||
else return (0);
|
||||
/* if we seeked past the last active extent, rc = 0 */
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* bdosrw entry point *
|
||||
************************/
|
||||
|
||||
UWORD seqread(fcbp)
|
||||
|
||||
REG struct fcb *fcbp; /* fcbp is a pointer to a fcb */
|
||||
/* 2 = random with zero fill */
|
||||
{
|
||||
REG UWORD block; /* block number from fcb */
|
||||
REG WORD index; /* index into disk map of fcb */
|
||||
REG UBYTE *buf; /* type compatibility kludge */
|
||||
REG WORD parm; /* parameter to do-io */
|
||||
REG WORD bigfile; /* file system is in word mode */
|
||||
BSETUP
|
||||
|
||||
bigfile = ((GBL.parmp)->dsm) & ~0xff;
|
||||
if (fcbp->cur_rec == 128)
|
||||
{ /* time to try next extent */
|
||||
if ( new_ext(fcbp) )
|
||||
return(1); /* if can't open new extent, error */
|
||||
fcbp->cur_rec = 0; /* opened new extent, zero cur_rec */
|
||||
}
|
||||
|
||||
if ( UBWORD(fcbp->cur_rec) >= get_rc(fcbp) )
|
||||
return(1); /* this is end of file */
|
||||
index = blkindx(fcbp); /* get index into fcb disk map */
|
||||
block = blknum(fcbp, index, bigfile);
|
||||
if ( ! block) return(1);
|
||||
return( do_io(block, (fcbp->cur_rec)++));
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* 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
@@ -0,0 +1,127 @@
|
||||
;********** 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
|
||||
@@ -0,0 +1,80 @@
|
||||
;********** wboot.s -- Olivetti bootstrap writer*****
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- adapt for nonseg.
|
||||
;* 820930 S. Savitzky (Zilog) -- created
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
; 01/12/83 Adapted for the Kontron ECB/16 Z8002 (DMH)
|
||||
; 01/16/83 Added relocation code to relocate the
|
||||
; Z8002 CP/M from 8000h to 0000h (DMH).
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT
|
||||
;*
|
||||
;* This module contains the code that receives
|
||||
;* control after being booted.
|
||||
;*
|
||||
;* The main function is to make sure that the
|
||||
;* system, whose entry point is called "bios",
|
||||
;* is passed a valid stack and PSA pointer.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios
|
||||
.global _wboot
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Constants
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
SYSTEM .equ 00000000h ; system address
|
||||
SYSSTK .equ 08000h-200h ; system stack top, leave room for PSA
|
||||
SYSPSA .equ SYSSTK ; system PSA
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Entry Points and post-boot Initialization
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;* transfer vector
|
||||
|
||||
jr wboot
|
||||
jr entry ; there is no write boot entry
|
||||
jr entry
|
||||
|
||||
;* post-boot init
|
||||
;* (note that this code
|
||||
;* is position indepent).
|
||||
|
||||
entry: DI VI,NVI
|
||||
ld r15, #SYSSTK ; init stack pointer
|
||||
ld r3, #SYSPSA ; initialize PSA
|
||||
ldctl psap, r3
|
||||
ld r7,#0 ; destination of system copy
|
||||
ld r5,#8000h ; source of system copy
|
||||
ld r0,#4000h ; copy 16k words
|
||||
ldir @r7,@r5,r0 ; Zip it!
|
||||
ld r3,#bios
|
||||
jp @r3 ; Actually jumping to low address
|
||||
|
||||
wboot: ld r3,#_wboot
|
||||
jp @r3
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/********************************************************
|
||||
* *
|
||||
* BIOS definitions for P-CP/M *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
* This include file simply defines the BIOS calls *
|
||||
* *
|
||||
* Memory management added 821018 by SS at Zilog *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
EXTERN long bios(); /* main BIOS entry point */
|
||||
EXTERN UBYTE bios1(); /* used for character I/O functions */
|
||||
EXTERN bios2(); /* parm1 is word, no return value */
|
||||
EXTERN bios3(); /* used for set dma only */
|
||||
/* parm1 is a pointer, no return */
|
||||
EXTERN UBYTE *bios4(); /* seldsk only, parm1 and parm2 are */
|
||||
/* words, returns a pointer to dph */
|
||||
EXTERN UWORD bios5(); /* for sectran and set exception */
|
||||
|
||||
|
||||
#define bwboot() bios1(1) /* warm boot */
|
||||
#define bconstat() bios1(2) /* console status */
|
||||
#define bconin() bios1(3) /* console input */
|
||||
#define bconout(parm) bios2(4,parm) /* console output parm */
|
||||
#define blstout(parm) bios2(5,parm) /* list device output */
|
||||
#define bpun(parm) bios2(6,parm) /* punch char output */
|
||||
#define brdr() bios1(7) /* reader input */
|
||||
#define bhome() bios1(8) /* recalibrate drive */
|
||||
#define bseldsk(parm1,parm2) bios4(9,parm1,parm2)
|
||||
/* select disk and return info */
|
||||
#define bsettrk(parm) bios2(10,parm) /* set track on disk */
|
||||
#define bsetsec(parm) bios2(11,parm) /* set sector for disk */
|
||||
#define bsetdma(parm) bios3(12,parm) /* set dma address */
|
||||
#define bread() bios1(13) /* read sector from disk */
|
||||
#define bwrite(parm) bios2(14,parm) /* write sector to disk */
|
||||
#define blistst() bios1(15) /* list device status */
|
||||
#define bsectrn(parm1,parm2) bios5(16,parm1,(XADDR)parm2)
|
||||
/* sector translate */
|
||||
#define bgetseg() bios1(18) /* get memory segment tbl */
|
||||
#define bgetiob() bios1(19) /* get I/O byte */
|
||||
#define bsetiob(parm) bios2(20,parm) /* set I/O byte */
|
||||
#define bflush() bios1(21) /* flush buffers */
|
||||
#define bsetvec(parm1,parm2) bios5(22,parm1,(XADDR)parm2)
|
||||
/* set exception vector */
|
||||
|
||||
|
||||
/************************/
|
||||
/* MEMORY MANAGEMENT */
|
||||
/*----------------------*/
|
||||
EXTERN XADDR map_adr(); /*(laddr, space)->paddr */
|
||||
EXTERN VOID mem_cpy(); /*(src, dst, len) */
|
||||
/*----------------------*/
|
||||
/* copy in, out (s,d,l) */
|
||||
/* */
|
||||
#define cpy_in(s,d,l) mem_cpy((XADDR)s, map_adr((XADDR)d, 0), (long)l)
|
||||
#define cpy_out(s,d,l) mem_cpy(map_adr((XADDR)s, 0), (XADDR)d, (long)l)
|
||||
/* */
|
||||
/************************/
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
;************ biosdefs.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
nr14 .equ cr13+2 ;WORD normal r14
|
||||
nr15 .equ nr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scseg .equ scfcw+2 ;WORD caller PC SEG
|
||||
scpc .equ scseg+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
;************ biosdefs2.z8k **************************
|
||||
;*
|
||||
;* Assembly language definitions for
|
||||
;* P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/11/83 Modified for use with Z8002 (DMH)
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Calls and Trap Indexes
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
XFER_SC .equ 1
|
||||
BIOS_SC .equ 3
|
||||
BDOS_SC .equ 2
|
||||
MEM_SC .equ 1
|
||||
DEBUG_SC .equ 0
|
||||
|
||||
;* the traps use numbers similar to those in the
|
||||
;* 68K version of P-CP/M
|
||||
|
||||
NTRAPS .equ 48 ;total number of traps
|
||||
SC0TRAP .equ 32 ;trap # of system call 0
|
||||
|
||||
;Z8000 traps
|
||||
EPUTRAP .equ 1 ;EPU (floating pt. emulator)
|
||||
SEGTRAP .equ 2 ;segmentation (68K bus err)
|
||||
NMITRAP .equ 0 ;non-maskable int.
|
||||
PITRAP .equ 8 ;priviledge violation
|
||||
;Interrupts, etc.
|
||||
TRACETR .equ 9 ; trace
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* C Stack frame equates
|
||||
;*
|
||||
;* A C stack frame consists of the PC on top,
|
||||
;* followed by the arguments, leftmost argument first.
|
||||
;*
|
||||
;* The caller adjusts the stack on return.
|
||||
;* Returned value is in r7 (int) or rr6 (long)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
co .equ 2 ;call offset, for 8002
|
||||
PCSIZE .equ 2 ;PC size non-segmented
|
||||
INTSIZE .equ 2 ;INT data type size
|
||||
LONGSIZE .equ 4 ;LONG data type size
|
||||
|
||||
ARG1 .equ PCSIZE ;integer arguments
|
||||
ARG2 .equ ARG1+INTSIZE
|
||||
ARG3 .equ ARG2+INTSIZE
|
||||
ARG4 .equ ARG3+INTSIZE
|
||||
ARG5 .equ ARG4+INTSIZE
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Segmented Mode Operations
|
||||
;*
|
||||
;* NOTE: segmented indirect-register operations
|
||||
;* can be done by addressing the low half
|
||||
;* of the register pair.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
SEG .MACRO ; START segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
NONSEG .MACRO ; END segmented mode
|
||||
; r0 destroyed.
|
||||
|
||||
ldctl r0,FCW
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
scall .MACRO ;(segaddr) segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.long ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
sscall .MACRO ;(|segaddr|) short segmented CALL
|
||||
|
||||
.word 05F00h
|
||||
.word ?1
|
||||
|
||||
.ENDM
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call Trap Handler Stack Frame
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
cr0 .equ 0 ;WORD caller r0
|
||||
cr1 .equ cr0+2 ;WORD caller r1
|
||||
cr2 .equ cr1+2 ;WORD caller r2
|
||||
cr3 .equ cr2+2 ;WORD caller r3
|
||||
cr4 .equ cr3+2 ;WORD caller r4
|
||||
cr5 .equ cr4+2 ;WORD caller r5
|
||||
cr6 .equ cr5+2 ;WORD caller r6
|
||||
cr7 .equ cr6+2 ;WORD caller r7
|
||||
cr8 .equ cr7+2 ;WORD caller r8
|
||||
cr9 .equ cr8+2 ;WORD caller r9
|
||||
cr10 .equ cr9+2 ;WORD caller r10
|
||||
cr11 .equ cr10+2 ;WORD caller r11
|
||||
cr12 .equ cr11+2 ;WORD caller r12
|
||||
cr13 .equ cr12+2 ;WORD caller r13
|
||||
cr14 .equ cr13+2 ;WORD caller r14
|
||||
nr15 .equ cr14+2 ;WORD normal r15
|
||||
scinst .equ nr15+2 ;WORD SC instruction
|
||||
scfcw .equ scinst+2 ;WORD caller FCW
|
||||
scpc .equ scfcw+2 ;WORD caller PC OFFSET
|
||||
FRAMESZ .equ scpc+2
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _ldcpm ;Load the system into memory
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Loader Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* segmented mode
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; enter in segmented mode.
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
calr kludge ; get PC segment on stack
|
||||
kludge: popl rr4, @r14
|
||||
|
||||
; get PSAP into rr2.
|
||||
|
||||
ldctl r2, PSAPSEG
|
||||
ldctl r3, PSAPOFF
|
||||
|
||||
; go non-segmented. save PSAP, system segment,
|
||||
; system stack pointer (in system segment, please)
|
||||
|
||||
NONSEG
|
||||
|
||||
ldl _psap, rr2
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ldl _sysstk, rr14
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp _ldcpm
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
;************ biosif.z8k **************************
|
||||
;*
|
||||
;* Assembly language interface for P-CP/M (tm) BIOS
|
||||
;* ----- System-Independent -----
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split into modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for a Z8002 (DMH)
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;* The resulting code looks a little odd.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _biosinit ;C portion init
|
||||
.global _flush ;Flush buffers
|
||||
|
||||
.global ccp ;Command Processor
|
||||
|
||||
.global _trapinit ;trap startup
|
||||
|
||||
.global _psap, _sysseg, _sysstk
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global bios ; initialization
|
||||
.global _wboot ; warm boot
|
||||
.global _input ; input a byte
|
||||
.global _output ; output a byte
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios Initialization and Entry Point
|
||||
;*
|
||||
;* This is where control comes after boot.
|
||||
;* Control is transferred to the CCP.
|
||||
;*
|
||||
;* We get here from bootstrap with:
|
||||
;* valid stack pointer
|
||||
;* valid PSA in RAM
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
bios:
|
||||
|
||||
; Get system (PC) segment into r4
|
||||
|
||||
DI VI,NVI
|
||||
|
||||
; get PSAP into r3.
|
||||
|
||||
ldctl r3, PSAPOFF
|
||||
sub r4,r4 ; this will be _sysseg, for consistency
|
||||
ld _psap, r3
|
||||
ld _sysseg, r4
|
||||
ld r14,_sysseg
|
||||
ld _sysstk, r15
|
||||
|
||||
; set up system stack so that a return will warm boot
|
||||
|
||||
push @r15,#_wboot
|
||||
|
||||
|
||||
; set up traps, then enable interrupts
|
||||
|
||||
call _trapinit
|
||||
EI VI,NVI
|
||||
|
||||
; set up C part of Bios
|
||||
|
||||
call _biosinit
|
||||
|
||||
; Turn control over to command processor
|
||||
|
||||
jp ccp
|
||||
|
||||
;*****************************************************
|
||||
;*
|
||||
;* Warm Boot
|
||||
;*
|
||||
;* flush buffers and initialize Bios
|
||||
;* then transfer to CCP
|
||||
;*
|
||||
;*****************************************************
|
||||
|
||||
_wboot:
|
||||
call _flush
|
||||
call _biosinit
|
||||
ld r15,_sysstk
|
||||
jp ccp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* I/O port operations
|
||||
;*
|
||||
;* int = input(port: int)
|
||||
;* output (port, data: int)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_input:
|
||||
ld r2,ARG1(r15)
|
||||
subl rr6,rr6
|
||||
inb rl7,@r2
|
||||
ldb rl6,rl7
|
||||
ret
|
||||
|
||||
|
||||
_output:
|
||||
ld r2,ARG1(r15)
|
||||
ld r3,ARG2(r15)
|
||||
outb @r2,rl3
|
||||
ret
|
||||
|
||||
|
||||
;*****************************************************
|
||||
;*****************************************************
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
;************ biosio.z8k **************************
|
||||
;*
|
||||
;* I/O routines for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE The Olivetti PROM routines are segmented.
|
||||
;* The C portion of the BIOS is non-segmented.
|
||||
;*
|
||||
;* This assembly-language module is assembled
|
||||
;* non-segmented, and serves as the interface.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
.global _disk_io
|
||||
.global _crt_put
|
||||
.global _cold_boot
|
||||
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Prom Subroutine Access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_disk_io: ;err=disk_io(drv, cmd, count, blk, addr)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ldb rh7,14+ARG1+1(r15) ;get args
|
||||
ldb rl7,14+ARG2+1(r15)
|
||||
ld r8, 14+ARG3(r15)
|
||||
ld r9, 14+ARG4(r15)
|
||||
ldl rr10,14+ARG5(r15)
|
||||
|
||||
;rh7 = drive #
|
||||
;rl7 = command
|
||||
;r8 = block count
|
||||
;r9 = block number
|
||||
;rr10 = segmented address
|
||||
|
||||
SEG
|
||||
scall 84000068h
|
||||
NONSEG
|
||||
;r8 = block count not transferred
|
||||
;rh7 = #retries
|
||||
;rl7 = final error code (RETURNED)
|
||||
;rh6 = error retried
|
||||
|
||||
and r7,#0FFh ;value returned in r7
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
_crt_put: ;crt_put(char)
|
||||
|
||||
dec r15,#14 ;save registers
|
||||
ldm @r15,r8,#7
|
||||
|
||||
ld r1,14+ARG1(r15) ;get arg in r1
|
||||
|
||||
SEG ; SEG clobbers r0
|
||||
ld r0,r1 ;rl0 = char
|
||||
scall 84000080h
|
||||
NONSEG
|
||||
|
||||
ldm r8,@r15,#7 ;restore regs
|
||||
inc r15,#14
|
||||
ret
|
||||
|
||||
|
||||
|
||||
_cold_boot:
|
||||
|
||||
SEG
|
||||
scall 8400008Ch
|
||||
NONSEG
|
||||
ret
|
||||
@@ -0,0 +1,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 */
|
||||
@@ -0,0 +1,234 @@
|
||||
;************ biosmem.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
.global memsc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
ldirb @r4,@r6,r3
|
||||
ldl rr6,rr4 ; rr6 = dest + length
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
NONSEG
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
ld r4,scseg+4(r15)
|
||||
ld r2,scfcw+4(r15)
|
||||
calr map_1
|
||||
ldl cr6+4(r15),rr6 ; return rr6
|
||||
SEG
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* Most of the system dependencies are in map_prog,
|
||||
;* which maps a program segment into a data segment
|
||||
;* for access as data.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#15 ; segmented caller?
|
||||
ret nz ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
ret ; already mapped
|
||||
|
||||
call_prog:
|
||||
bit r2,#15 ; segmented caller?
|
||||
jr nz map_prog ; yes-- use passed seg
|
||||
ld r6,r4 ; no -- use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
ld r6, _sysseg
|
||||
ret
|
||||
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
ret eq
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r0, #-1
|
||||
cp r0, _usrseg
|
||||
jr eq map_prog
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ;map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
testb rh5 ; data access?
|
||||
ret nz ; no: done
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; olivetti: segment 8 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as segment 10's data.
|
||||
|
||||
cpb rh6,#8
|
||||
ret ne
|
||||
ldb rh6,#10
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 4 ;system stack pointer
|
||||
_psap: .block 4 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,303 @@
|
||||
;************ biosmem2.z8k **************************
|
||||
;*
|
||||
;* Memory Management for P-CP/M (tm) BIOS
|
||||
;* for Olivetti M20 (Z8001) system.
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- split modules
|
||||
;* 820913 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for Z8002 (DMH, FMZ)
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* This module copies data from one memory space
|
||||
;* to another. The machine-dependent parts of
|
||||
;* the mapping are well isolated.
|
||||
;*
|
||||
;* Segmented operations are well-isolated, and
|
||||
;* are either the same as their non-segmented
|
||||
;* counterparts, or constructed using macros.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
.global _mem_mov, _map_wdw
|
||||
.global memsc
|
||||
|
||||
.global _blkmov
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global xfersc
|
||||
.global _mem_bcp
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1) -> addr
|
||||
;* sets user seg# from addr
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* control transfer to context at addr.
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* The following does not apply in Z8002 case
|
||||
;*
|
||||
;* x+256 x=1, 3, 5 : segmented I-space addr.
|
||||
;* instead of data access
|
||||
;*
|
||||
;* FFFF: set user segment
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
memsc: ;memory manager system call
|
||||
; CALLED FROM SC
|
||||
; IN SEGMENTED MODE
|
||||
; rr6: source
|
||||
; rr4: dest / space
|
||||
; rr2: length / 0
|
||||
testl rr2
|
||||
jr z mem_map
|
||||
|
||||
|
||||
mem_copy: ; copy data.
|
||||
; rr6: source
|
||||
; rr4: dest
|
||||
; rr2: length
|
||||
push @r15,r3 ; push length as a short!
|
||||
pushl @r15,rr4 ; push dest
|
||||
pushl @r15, rr6 ; push source
|
||||
call _mem_bcp ; call C copy routine
|
||||
ldl rr6,4(r15) ; get dest into rr6
|
||||
add r7,8(r15) ; return dest plus length
|
||||
inc r15,#10 ; restore stack
|
||||
ret
|
||||
|
||||
mem_map: ; map address
|
||||
; rr6: source
|
||||
; r4: caller's seg.
|
||||
; r5: space
|
||||
; r2: caller's FCW
|
||||
|
||||
cp r5,#-2 ; space=-2: xfer
|
||||
jp eq xfersc
|
||||
|
||||
;* ld r4,scseg+co(r15) Not done in Z8002 implementation
|
||||
ld r2,scfcw+co(r15)
|
||||
calr map_1
|
||||
ldl cr6+co(r15),rr6 ; return rr6
|
||||
ret
|
||||
|
||||
map_1: ; dispatch
|
||||
|
||||
cp r5,#0FFFFh
|
||||
jr eq set_usr ; space=-1: user seg
|
||||
|
||||
cpb rl5,#0
|
||||
jr eq call_data
|
||||
cpb rl5,#1
|
||||
jr eq call_prog
|
||||
cpb rl5,#2
|
||||
jr eq sys_data
|
||||
cpb rl5,#3
|
||||
jr eq sys_prog
|
||||
cpb rl5,#4
|
||||
jr eq usr_data
|
||||
cpb rl5,#5
|
||||
jr eq usr_prog
|
||||
|
||||
ret ;default: no mapping
|
||||
|
||||
set_usr: ;-1: set user seg.
|
||||
ld _usrseg,r6
|
||||
ret
|
||||
|
||||
;*
|
||||
;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT ***
|
||||
;*
|
||||
;* rr6= logical address
|
||||
;* r4 = caller's PC segment - but NOT in the Z8002 implementation!
|
||||
;* r2 = caller's FCW
|
||||
;* returns
|
||||
;* rr6= mapped address
|
||||
;*
|
||||
;* This code is much simpler than the corresponding
|
||||
;* Z8001 code. If the caller's FCW indicates that he
|
||||
;* was in Normal mode, then _usrseg is returned.
|
||||
;* Otherwise, pseudo-segment 0 is returned.
|
||||
;*
|
||||
|
||||
call_data:
|
||||
bit r2,#14 ; System caller?
|
||||
jr nz sys_data ; yes-- use system seg
|
||||
ld r6,_usrseg ; no -- use pc segment
|
||||
ret
|
||||
|
||||
call_prog:
|
||||
bit r2,#14 ; System caller?
|
||||
jr nz sys_prog ; yes-- use system seg
|
||||
ld r6,_usrseg ; no 00 use pc segment
|
||||
jr map_prog ; map prog as data
|
||||
|
||||
sys_data:
|
||||
sys_prog:
|
||||
ld r6, _sysseg
|
||||
ret ; assume sys does not
|
||||
; separate code, data
|
||||
|
||||
usr_data:
|
||||
ld r6, _usrseg
|
||||
ret
|
||||
|
||||
usr_prog:
|
||||
ld r6, _usrseg
|
||||
jr map_prog
|
||||
|
||||
|
||||
map_prog: ; map program addr into data
|
||||
; rr6 = address
|
||||
|
||||
and r6,#7F00h ; extract seg bits
|
||||
|
||||
; kontron: pseudo-segment 2 is the only one with
|
||||
; separate I and D spaces, and
|
||||
; the program space is accessed
|
||||
; as pseudo-segment 1, data space as pseudo-segment 2
|
||||
|
||||
cpb rh6,#2
|
||||
ret ne
|
||||
ldb rh6,#1
|
||||
ret
|
||||
|
||||
;*
|
||||
;* The following routine copies a block of data from one part
|
||||
;* of the system address space to another. In practice, part
|
||||
;* of the address space may be windowed, but that is transparent
|
||||
;* here.
|
||||
;*
|
||||
;* The interface is:
|
||||
;* blkmov(source,dest,length)
|
||||
;* short source,dest,length;
|
||||
;*
|
||||
|
||||
_blkmov:
|
||||
ld r5,ARG1(r15) ; r5: source
|
||||
ld r4,ARG2(r15) ; r4: dest
|
||||
ld r2,ARG3(r15) ; r2: length (just a word!)
|
||||
ld r7,r2 ; return value = bytes copied
|
||||
ldirb @r4,@r5,r2 ; copy!
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;* mem_mov -- C callable block move routine
|
||||
;* input stack:
|
||||
;* ret. addr (word)
|
||||
;* source (word)
|
||||
;* destination (word)
|
||||
;* length, bytes (word)
|
||||
|
||||
_mem_mov:
|
||||
ld r5,2(r15) ; pull off source
|
||||
ld r7,4(r15) ; pull off destination
|
||||
ld r0,6(r15) ; pull off length
|
||||
ldirb @r7,@r5,r0 ; block move
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;* map_wdw -- C callable map window routine,
|
||||
; system dependent.
|
||||
;* input stack:
|
||||
;* ret. addr (word)
|
||||
;* window code (word)
|
||||
;* 2 means physical block 2
|
||||
;* 3 means physical block 3
|
||||
;* x means physical block 1
|
||||
;*
|
||||
;* Note: the manual is unclear, but implies that
|
||||
;* history must be kept concerning the window
|
||||
;* mapping, if the window was last block 3.
|
||||
;* That is why I map block one before others.
|
||||
;* See ECB/C16 Hardware description for details.
|
||||
|
||||
_map_wdw:
|
||||
ld r0,2(r15) ; pull off window code
|
||||
out 0c000h,r0 ; map physical block 1
|
||||
cp r0,#2 ; map physical block 2?
|
||||
jr nz,map_wdw_3 ; No, go for physical block 3.
|
||||
out 8001h,r0 ; Funny port address, huh?
|
||||
ret
|
||||
|
||||
map_wdw_3:
|
||||
cp r0,#3 ; map pysical block 3?
|
||||
ret nz ; no, already mapped to 1.
|
||||
|
||||
out 0c001h,r0 ; yes.
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Data
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_sysseg: .block 2 ;system segment
|
||||
_usrseg: .block 2 ;user segment
|
||||
_sysstk: .block 2 ;system stack pointer
|
||||
_psap: .block 2 ;program status area ptr
|
||||
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,370 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;* 830305 D. Sallume (Zilog) -- added FPE trap
|
||||
;* code.
|
||||
;*
|
||||
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
.global _tbvalid ;disk track buff valid
|
||||
.global _tbdirty ;disk track buff is dirty
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* M-20 ROM scratchpad RAM addresses
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
rtc_ext: .equ 82000022h ;Place to put address
|
||||
; of list of functions
|
||||
; for each clock tick
|
||||
motor_on: .equ 82000020h ;Disk motor timeout
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to segmented, with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: LONG
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack,
|
||||
;* IN SEGMENTED MODE. This allows the trap
|
||||
;* handler to be in another segment (with some
|
||||
;* care). This is useful mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ;system call trap server
|
||||
|
||||
push @r14,@r14
|
||||
|
||||
|
||||
_trap:
|
||||
|
||||
sub r15,#30 ; push caller state
|
||||
ldm @r14,r0,#14
|
||||
NONSEG ; go nonsegmented
|
||||
ldctl r1,NSP
|
||||
ld nr14(r15),r14
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
; else call seg @rr0
|
||||
pushl @r15,rr0 ; (done via kludge)
|
||||
SEG
|
||||
popl rr0,@r14
|
||||
calr trap_1
|
||||
jr _trap_ret
|
||||
|
||||
trap_1: ; jp @rr0
|
||||
pushl @r14,rr0
|
||||
ret
|
||||
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
NONSEG
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ld r14,nr14(r15)
|
||||
ldctl NSP,r1
|
||||
SEG ; go segmented for the iret.
|
||||
ldm r0,@r14,#14
|
||||
add r15,#32
|
||||
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r14,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r14,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r14,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r14,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;biossc: ;call bios
|
||||
; NONSEG
|
||||
; ; r3 = operation code
|
||||
; ; rr4= P1
|
||||
; ; rr6= P2
|
||||
;
|
||||
; ld r0,scfcw+4(r15) ; if caller nonseg, normal
|
||||
; and r0,#0C000h
|
||||
; jr nz seg_ok
|
||||
;
|
||||
; ld r4,scseg+4(r15) ; then add seg to P1, P2
|
||||
; ld r6,r4
|
||||
;seg_ok:
|
||||
; ; set up C stack frame
|
||||
;;===
|
||||
; pushl @r15,rr6
|
||||
; pushl @r15,rr4
|
||||
; push @r15,r3
|
||||
;
|
||||
; ; call C program
|
||||
; call _bios
|
||||
;
|
||||
; ; clean stack & return
|
||||
; add r15,#10
|
||||
; ldl cr6+4(r15),rr6 ; with long in rr6
|
||||
;
|
||||
; SEG
|
||||
; ret
|
||||
;
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
SEG
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#4 ;discard return addr
|
||||
ldl rr4,rr14 ;move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r4,@r6,r2
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _motor_c -- check if disk motor still running.
|
||||
;* Entered each clock tick. Invalidates
|
||||
;* track buffer when motor stops
|
||||
;* (Note: runs segmented)
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_motor_c:
|
||||
ldl rr4,#motor_on ;Motor running?
|
||||
test @r4
|
||||
ret nz ;Yes: do nothing
|
||||
ldar r4,$
|
||||
ld r5,#_tbdirty ; Is track buff dirty?
|
||||
test @r4 ; Yes...
|
||||
ret nz ; ...return without invalidating
|
||||
ld r5,#_tbvalid
|
||||
clr @r4 ;No: mark track buffer
|
||||
ret ; invalid
|
||||
|
||||
; Table of functions run each real time clock tick
|
||||
|
||||
_ticktab:
|
||||
.long -1 ;Will contain _motor_c
|
||||
.word 0ffffh ;Terminator
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 8 ; size of a program status entry
|
||||
; --- segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
; lda r3,biossc
|
||||
; ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
; lda r3,fp_epu
|
||||
; ldl _trapvec+EPUTRAP*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; rr0 PSA entry: FCW (ints ENABLED)
|
||||
; rr2 PSA entry: PC
|
||||
; rr4 -> PSA slot
|
||||
|
||||
ldl rr4,_psap
|
||||
SEG
|
||||
ldl rr0,#0000D800h
|
||||
|
||||
add r5,#ps ; EPU trap
|
||||
ldar r2,epu_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ldar r2,pi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ldar r2,sc_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ldar r2,seg_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ldar r2,nmi_trap
|
||||
ldm @r4,r0,#4
|
||||
|
||||
; Set up Real-Time Clock external call loc
|
||||
|
||||
ldar r2,_motor_c
|
||||
ldar r4,_ticktab
|
||||
ldl @r4,rr2
|
||||
ldl rr2,#rtc_ext
|
||||
ldl @r2,rr4
|
||||
NONSEG
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
@@ -0,0 +1,294 @@
|
||||
;************ biostrap.z8k **************************
|
||||
;*
|
||||
;* Trap handlers for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 821013 S. Savitzky (Zilog) -- created
|
||||
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
|
||||
;* specific code to invalidate track buffer
|
||||
;* contents when disk drive motor stops
|
||||
;* (fixes directory-overwrite on disk change)
|
||||
;*
|
||||
|
||||
; 01/12/83 Adapted for Z8002 (DMH)
|
||||
__text: .sect
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* NOTE
|
||||
;* Trap and interrupt handlers are started up
|
||||
;* in segmented mode on the Z8001.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Externals
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global __bios ;C portion of BIOS
|
||||
.global memsc ;memory-management SC
|
||||
|
||||
.global _sysseg, _usrseg, _sysstk, _psap
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Global declarations
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
.global _trapinit
|
||||
.global _trapvec
|
||||
.global _trap
|
||||
|
||||
.global xfersc
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Trap vector table
|
||||
;*
|
||||
;* entries 0..31 are misc. system traps
|
||||
;* entries 32..47 are system calls 0..15
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
_trapvec:
|
||||
.block NTRAPS*4 ; leave trap space same as for Z8001,
|
||||
; for compatibility
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System Call and General Trap Handler And Dispatch
|
||||
;*
|
||||
;* It is assumed that the system runs
|
||||
;* non-segmented on a segmented CPU.
|
||||
;*
|
||||
;* _trap is jumped to with the
|
||||
;* following information on the stack:
|
||||
;*
|
||||
;* trap type: WORD
|
||||
;* reason: WORD
|
||||
;* fcw: WORD
|
||||
;* pc: WORD
|
||||
;*
|
||||
;* The trap handler is called as a subroutine,
|
||||
;* with all registers saved on the stack. This
|
||||
;* allows the trap handler to be in another
|
||||
;* segment (with some care). This is useful
|
||||
;* mainly to the debugger.
|
||||
;*
|
||||
;* All registers except rr0 are also passed
|
||||
;* intact to the handler.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__text: .sect
|
||||
|
||||
sc_trap: ; system call trap server
|
||||
|
||||
push @r15,@r15 ; duplicate type as reason
|
||||
|
||||
|
||||
_trap: ; general trap server
|
||||
|
||||
sub r15,#FRAMESZ-8 ; push caller state
|
||||
ldm @r15,r0,#15
|
||||
ldctl r1,NSP
|
||||
ex r1,nr15(r15)
|
||||
|
||||
; trap# now in r1
|
||||
cpb rh1,#7Fh ; system call?
|
||||
jr ne trap_disp ; no
|
||||
; yes: map it
|
||||
clrb rh1
|
||||
add r1,#SC0TRAP
|
||||
|
||||
;=== need range check ===
|
||||
|
||||
trap_disp: ; dispatch
|
||||
sll r1,#2
|
||||
ldl rr0,_trapvec(r1)
|
||||
testl rr0
|
||||
jr z _trap_ret ; zero -- no action
|
||||
call @r1 ; go execute the trap
|
||||
|
||||
_trap_ret: ;return from trap or interrupt
|
||||
|
||||
ld r1,nr15(r15) ; pop state
|
||||
ldctl NSP,r1
|
||||
ldm r0,@r15,#15
|
||||
add r15,#FRAMESZ-6 ; re-adjust stack
|
||||
iret ; return from interrupt
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Assorted Trap Handlers
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
epu_trap:
|
||||
push @r15,#EPUTRAP
|
||||
jr _trap
|
||||
|
||||
pi_trap:
|
||||
push @r15,#PITRAP
|
||||
jr _trap
|
||||
|
||||
seg_trap:
|
||||
push @r15,#SEGTRAP
|
||||
jr _trap
|
||||
|
||||
nmi_trap:
|
||||
push @r15,#NMITRAP
|
||||
jr _trap
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Bios system call handler
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
biossc: ; call bios
|
||||
; r3 = operation code
|
||||
; rr4= P1
|
||||
; rr6= P2
|
||||
|
||||
; set up C stack frame
|
||||
;===
|
||||
pushl @r15,rr6
|
||||
pushl @r15,rr4
|
||||
push @r15,r3
|
||||
|
||||
; call C program
|
||||
call __bios
|
||||
|
||||
; clean stack & return
|
||||
add r15,#10
|
||||
ldl cr6+co(r15),rr6 ; with long in rr6
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch System Call
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word (trap reason)
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
xfersc: ;enter here from system call
|
||||
|
||||
; build frame on system stack
|
||||
|
||||
; when called from system call, the frame replaces
|
||||
; the caller's context, which will never be resumed.
|
||||
|
||||
inc r15,#co ; discard return addr
|
||||
ld r5,r15 ; move context
|
||||
ld r2,#FRAMESZ/2
|
||||
ldir @r5,@r7,r2
|
||||
dec r5,#2 ;point back to PC
|
||||
ldi @r5,@r7,r2 ;transfer PC
|
||||
jr _trap_ret ;restore context
|
||||
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* _trapinit -- initialize trap system
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
;*
|
||||
;* PSA (Program Status Area) structure
|
||||
;*
|
||||
ps .equ 4 ; size of a program status entry
|
||||
; --- non-segmented ---
|
||||
|
||||
psa_epu .equ 1*ps ; EPU trap offset
|
||||
psa_prv .equ 2*ps ; priviledged instruction trap
|
||||
psa_sc .equ 3*ps ; system call trap
|
||||
psa_seg .equ 4*ps ; segmentation trap
|
||||
psa_nmi .equ 5*ps ; non-maskable interrupt
|
||||
psa_nvi .equ 6*ps ; non-vectored interrupt
|
||||
psa_vi .equ 7*ps ; vectored interrupt
|
||||
psa_vec .equ psa_vi+(ps/2) ; vectors
|
||||
|
||||
|
||||
_trapinit:
|
||||
|
||||
; initialize trap table
|
||||
|
||||
lda r2,_trapvec
|
||||
ld r0,#NTRAPS
|
||||
subl rr4,rr4
|
||||
clrtraps:
|
||||
ldl @r2,rr4
|
||||
inc r2,#4
|
||||
djnz r0,clrtraps
|
||||
|
||||
ld r2,_sysseg
|
||||
lda r3,biossc
|
||||
ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
|
||||
lda r3,memsc
|
||||
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
|
||||
|
||||
|
||||
; initialize some PSA entries.
|
||||
; r0 PSA entry: FCW (ints ENABLED)
|
||||
; r1 PSA entry: PC
|
||||
; r5 -> PSA slot
|
||||
|
||||
ld r5,_psap
|
||||
ld r0,#0D800h
|
||||
|
||||
add r5,#ps ; skip reserved to EPU trap
|
||||
ld r1,#epu_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; Priviledged Inst
|
||||
ld r1,#pi_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; System Call
|
||||
ld r1,#sc_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; segmentation
|
||||
ld r1,#seg_trap
|
||||
ldm @r5,r0,#2
|
||||
|
||||
add r5,#ps ; Non-Maskable Int.
|
||||
ld r1,#nmi_trap
|
||||
ldm @r5,r0,#2
|
||||
ret
|
||||
|
||||
;****************************************************
|
||||
;****************************************************
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,158 @@
|
||||
/*--------------------------------------------------------------*\
|
||||
| ccp_def.c DEFINES v1.0 |
|
||||
| ======= |
|
||||
| |
|
||||
| P-CP/M: A CP/M derived operating system |
|
||||
| |
|
||||
| File contents: |
|
||||
| ------------- |
|
||||
| This file contains all of the #defines |
|
||||
| used by the console command processor. |
|
||||
| |
|
||||
| created by : Tom Saulpaugh Date: 7/13/82 |
|
||||
| ---------- |
|
||||
| last modified: 12/20/82 |
|
||||
| ------------- |
|
||||
| |
|
||||
| (c) COPYRIGHT Digital Research 1982 |
|
||||
| all rights reserved |
|
||||
| |
|
||||
\*--------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| CP/M Transient Commands |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define DIRCMD 0
|
||||
#define TYPECMD 1
|
||||
#define RENCMD 2
|
||||
#define ERACMD 3
|
||||
#define UCMD 4
|
||||
#define CH_DISK 5
|
||||
#define SUBCMD 6
|
||||
#define SUB_FILE 7
|
||||
#define FILE 8
|
||||
#define DIRSCMD 9
|
||||
#define SEARCH 10
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Modes and Flags |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define ON 1
|
||||
#define OFF 0
|
||||
#define MATCH 0
|
||||
#define GOOD 1
|
||||
#define BAD 0
|
||||
#define FILL 1
|
||||
#define NOFILL 0
|
||||
#define VOID /*no return value*/
|
||||
#define NO_FILE 98
|
||||
#define STOP 99
|
||||
#define USER_ZERO 0
|
||||
#define DISK_A 1
|
||||
#define SOURCEDRIVE 88
|
||||
#define DESTDRIVE 99
|
||||
#define BYTE char
|
||||
#define REG register
|
||||
#define WORD short
|
||||
#define UWORD unsigned int
|
||||
#define LONG long
|
||||
#define ULONG unsigned long
|
||||
#define GET_MEM_REG 18
|
||||
#define ZERO 0
|
||||
#define NULL '\0'
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define NO_READ 255
|
||||
#define BLANK ' '
|
||||
#define BACKSLH '\\'
|
||||
#define EXLIMPT '!'
|
||||
#define CMASK 0177
|
||||
#define ONE (long)49
|
||||
#define TAB 9
|
||||
#define Cr 13
|
||||
#define Lf 10
|
||||
#define CR (long)13
|
||||
#define LF (long)10
|
||||
#define EOF 26
|
||||
#define BLANKS (long)32
|
||||
#define PERIOD (long)46
|
||||
#define COLON (long)58
|
||||
#define ARROW (long)62
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| Data Structure Size Constants |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define CMD_LEN 128
|
||||
#define BIG_CMD_LEN 255
|
||||
#define MAX_ARGS 4
|
||||
#define ARG_LEN 26
|
||||
#define NO_OF_DRIVES 16
|
||||
#define NUMDELS 16
|
||||
#define FCB_LEN 36
|
||||
#define DMA_LEN 128
|
||||
#define FILES_PER_LINE 4 /* Zilog */
|
||||
#define SCR_HEIGHT 23
|
||||
#define BIG_WIDTH 80
|
||||
#define SMALL_WIDTH 40
|
||||
|
||||
/*-------------------------------------------*\
|
||||
| BDOS Function Calls |
|
||||
\*-------------------------------------------*/
|
||||
|
||||
#define WARMBOOT 0
|
||||
#define CONIN 1
|
||||
#define CONSOLE_OUTPUT 2
|
||||
#define READER_INPUT 3
|
||||
#define PUNCH_OUTPUT 4
|
||||
#define LIST_OUTPUT 5
|
||||
#define DIR_CONS_I/O 6
|
||||
#define GET_I/O_BYTE 7
|
||||
#define SET_I/O_BYTE 8
|
||||
#define PRINT_STRING 9
|
||||
#define READ_CONS_BUF 10
|
||||
#define GET_CONS_STAT 11
|
||||
#define RET_VERSION_NO 12
|
||||
#define RESET_DISK_SYS 13
|
||||
#define SELECT_DISK 14
|
||||
#define OPEN_FILE 15
|
||||
#define CLOSE_FILE 16
|
||||
#define SEARCH_FIRST 17
|
||||
#define SEARCH_NEXT 18
|
||||
#define DELETE_FILE 19
|
||||
#define READ_SEQ 20
|
||||
#define WRITE_SEQ 21
|
||||
#define MAKE_FILE 22
|
||||
#define RENAME_FILE 23
|
||||
#define RET_LOGIN_VEC 24
|
||||
#define RET_CUR_DISK 25
|
||||
#define SET_DMA_ADDR 26
|
||||
/* #define GET_ADDR(ALLOC) 27 */
|
||||
#define WRITE_PROT_DISK 28
|
||||
#define GET_READ/O_VEC 29
|
||||
#define SET_FILE_ATTRIB 30
|
||||
#define GET_ADDR_D_PARM 31
|
||||
#define GET_USER_NO 32
|
||||
#define READ_RANDOM 33
|
||||
#define WRITE_RANDOM 34
|
||||
#define COMP_FILE-SIZE 35
|
||||
#define SET_RANDOM_REC 36
|
||||
#define RESET_DRIVE 37
|
||||
/* #define WRITE_RAN_ZERO 40 */
|
||||
#define BIOS_CALL 50
|
||||
#define LOAD_PROGRAM 59
|
||||
|
||||
/*----------------------------------------------*\
|
||||
| MACROS |
|
||||
\*----------------------------------------------*/
|
||||
|
||||
#define isalpha(c) (islower(c) || isupper(c))
|
||||
#define islower(c) ('a' <= (c) && (c) <= 'z')
|
||||
#define isupper(c) ('A' <= (c) && (c) <= 'Z')
|
||||
#define tolower(c) (isupper(c) ? ((c)+040):(c))
|
||||
#define toupper(c) (islower(c) ? ((c)-040):(c))
|
||||
#define isdigit(c) ('0' <= (c) && (c) <= '9')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -0,0 +1,322 @@
|
||||
|
||||
/********************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Character I/O Routines *
|
||||
* *
|
||||
* This module does BDOS functions 1 thru 11 *
|
||||
* *
|
||||
* It contains the following functions which *
|
||||
* are called from the BDOS main routine: *
|
||||
* constat(); *
|
||||
* conin(); *
|
||||
* cookdout(); *
|
||||
* rawconio(); *
|
||||
* prt_line(); *
|
||||
* readline(); *
|
||||
* *
|
||||
* Copyright (c) 1982 Digital Research, Inc. *
|
||||
* *
|
||||
********************************************************/
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#include "bdosdef.h"
|
||||
|
||||
#include "biosdef.h"
|
||||
|
||||
|
||||
#define ctrlc 0x03
|
||||
#define ctrle 0x05
|
||||
#define ctrlp 0x10
|
||||
#define ctrlq 0x11
|
||||
#define ctrlr 0x12
|
||||
#define ctrls 0x13
|
||||
#define ctrlu 0x15
|
||||
#define ctrlx 0x18
|
||||
|
||||
#define cr 0x0d
|
||||
#define lf 0x0a
|
||||
#define tab 0x09
|
||||
#define rub 0x7f
|
||||
#define bs 0x08
|
||||
#define space 0x20
|
||||
|
||||
|
||||
EXTERN warmboot(); /* External function definition */
|
||||
EXTERN UBYTE cpy_bi(); /* copy byte in from user space */
|
||||
|
||||
|
||||
/******************/
|
||||
/* console status */
|
||||
/******************/
|
||||
|
||||
BOOLEAN constat()
|
||||
{
|
||||
BSETUP
|
||||
|
||||
return( GBL.kbchar ? TRUE : bconstat() );
|
||||
}
|
||||
|
||||
/********************/
|
||||
/* check for ctrl/s */
|
||||
/* used internally */
|
||||
/********************/
|
||||
conbrk()
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG BOOLEAN stop;
|
||||
BSETUP
|
||||
|
||||
stop = FALSE;
|
||||
if ( bconstat() ) do
|
||||
{
|
||||
if ( (ch = bconin()) == ctrlc ) warmboot(1);
|
||||
if ( ch == ctrls ) stop = TRUE;
|
||||
else if (ch == ctrlq) stop = FALSE;
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
else GBL.kbchar = ch;
|
||||
} while (stop);
|
||||
}
|
||||
|
||||
|
||||
/******************/
|
||||
/* console output */
|
||||
/* used internally*/
|
||||
/******************/
|
||||
|
||||
conout(ch)
|
||||
REG UBYTE ch;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conbrk(); /* check for control-s break */
|
||||
bconout(ch); /* output character to console */
|
||||
if (GBL.lstecho) blstout(ch); /* if ctrl-p on, echo to list dev */
|
||||
if (ch >= ' ') GBL.column++; /* keep track of screen column */
|
||||
else if (ch == cr) GBL.column = 0;
|
||||
else if (ch == bs) GBL.column--;
|
||||
}
|
||||
|
||||
|
||||
/*************************************/
|
||||
/* console output with tab expansion */
|
||||
/*************************************/
|
||||
|
||||
cookdout(ch, ctlout)
|
||||
REG UBYTE ch; /* character to output */
|
||||
BOOLEAN ctlout; /* output ^<char> for control chars? */
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (ch == tab) do /* expand tabs */
|
||||
conout( ' ' );
|
||||
while (GBL.column & 7);
|
||||
|
||||
else
|
||||
{
|
||||
if ( ctlout && (ch < ' ') )
|
||||
{
|
||||
conout( '^' );
|
||||
ch |= 0x40;
|
||||
}
|
||||
conout(ch); /* output the character */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* console input */
|
||||
/*****************/
|
||||
|
||||
UBYTE getch() /* Get char from buffer or bios */
|
||||
/* For internal use only */
|
||||
{
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
temp = GBL.kbchar; /* get buffered char */
|
||||
GBL.kbchar = 0; /* clear it */
|
||||
return( temp ? temp : bconin() ); /* if non-zero, return it */
|
||||
/* else get char from bios */
|
||||
}
|
||||
|
||||
UBYTE conin() /* BDOS console input function */
|
||||
{
|
||||
REG UBYTE ch;
|
||||
BSETUP
|
||||
|
||||
conout( ch = getch() );
|
||||
if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
return(ch);
|
||||
}
|
||||
|
||||
/******************
|
||||
* raw console i/o *
|
||||
******************/
|
||||
|
||||
UBYTE rawconio(parm) /* BDOS raw console I/O function */
|
||||
|
||||
REG UWORD parm;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
if (parm == 0xff) return(getch());
|
||||
else if (parm == 0xfe) return(constat());
|
||||
else return(bconout(parm & 0xff)); /* add return to make lint happy */
|
||||
}
|
||||
|
||||
|
||||
/****************************************************/
|
||||
/* print line up to delimiter($) with tab expansion */
|
||||
/****************************************************/
|
||||
|
||||
prt_line(p)
|
||||
REG UBYTE *p;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
while( *p != GBL.delim ) cookdout( *(p++), FALSE);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************/
|
||||
/* read line with editing and bounds checking */
|
||||
/**********************************************/
|
||||
|
||||
/* Two subroutines first */
|
||||
|
||||
newline(startcol)
|
||||
REG UWORD startcol;
|
||||
{
|
||||
BSETUP
|
||||
|
||||
conout(cr); /* go to new line */
|
||||
conout(lf);
|
||||
while(startcol)
|
||||
{
|
||||
conout(' ');
|
||||
startcol -= 1; /* start output at starting column */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
backsp(p, stcol) /* backspace one character position */
|
||||
REG struct conbuf *p; /* pointer to console buffer */
|
||||
UWORD stcol;
|
||||
{
|
||||
REG WORD i;
|
||||
REG WORD length;
|
||||
REG UBYTE ch;
|
||||
BSETUP
|
||||
|
||||
if (p->retlen) length = UBWORD(--(p->retlen));
|
||||
/* if buffer non-empty, decrease it by 1 */
|
||||
else length = 0;
|
||||
i = stcol;
|
||||
while (length--)
|
||||
{
|
||||
ch = p->cbuf[length]; /* get character from buffer */
|
||||
if ( ch == tab )
|
||||
{
|
||||
i += 8; /* i is our column counter */
|
||||
i &= ~7; /* for tab, go to multiple of 8 */
|
||||
}
|
||||
else if ( ch < ' ' ) i += 2;
|
||||
/* control chars put out 2 printable chars */
|
||||
else i += 1;
|
||||
}
|
||||
while (GBL.column > i)
|
||||
{
|
||||
conout(bs); /* backspace until we get to proper column */
|
||||
conout(' ');
|
||||
conout(bs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
readline(p) /* BDOS function 10 */
|
||||
REG struct conbuf *p;
|
||||
|
||||
{
|
||||
REG UBYTE ch;
|
||||
REG UWORD i;
|
||||
REG UWORD j;
|
||||
REG UBYTE *q;
|
||||
UWORD stcol;
|
||||
|
||||
BSETUP
|
||||
|
||||
stcol = GBL.column; /* set up starting column */
|
||||
if (GBL.chainp != XNULL) /* chain to program code */
|
||||
{
|
||||
i = UBWORD(cpy_bi(GBL.chainp++)); /* cpy in from user space */
|
||||
j = UBWORD(p->maxlen);
|
||||
if (j < i) i = j; /* don't overflow console buffer! */
|
||||
p->retlen = (UBYTE)i;
|
||||
q = p->cbuf;
|
||||
while (i)
|
||||
{
|
||||
cookdout( *q++ = cpy_bi(GBL.chainp++), TRUE);
|
||||
i -= 1;
|
||||
}
|
||||
GBL.chainp = XNULL;
|
||||
return;
|
||||
}
|
||||
|
||||
p->retlen = 0; /* start out with empty buffer */
|
||||
while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
|
||||
{ /* main loop for read console buffer */
|
||||
|
||||
if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
|
||||
{
|
||||
cookdout(ctrlc, TRUE);
|
||||
warmboot(1);
|
||||
}
|
||||
|
||||
else if ( (ch == cr) || (ch == lf) )
|
||||
{ /* if cr or lf, exit */
|
||||
conout(cr);
|
||||
break;
|
||||
}
|
||||
|
||||
else if (ch == bs) backsp(p, stcol); /* backspace */
|
||||
|
||||
else if (ch == rub) /* delete character */
|
||||
{
|
||||
if (GBL.echodel)
|
||||
{
|
||||
if (p->retlen)
|
||||
{
|
||||
i = UBWORD(--(p->retlen));
|
||||
conout( p->cbuf[i] );
|
||||
}
|
||||
}
|
||||
else backsp(p, stcol);
|
||||
}
|
||||
|
||||
else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
|
||||
/* control-p */
|
||||
else if (ch == ctrlx) /* control-x */
|
||||
do backsp(p,stcol); while (p->retlen);
|
||||
|
||||
else if (ch == ctrle) newline(stcol); /* control-e */
|
||||
|
||||
else if (ch == ctrlu) /* control-u */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
p->retlen = 0;
|
||||
}
|
||||
|
||||
else if (ch == ctrlr) /* control-r */
|
||||
{
|
||||
conout('#');
|
||||
newline(stcol);
|
||||
for (i=0; i < UBWORD(p->retlen); i++)
|
||||
cookdout( p->cbuf[i], TRUE);
|
||||
}
|
||||
|
||||
else /* normal character */
|
||||
cookdout( (p->cbuf[UBWORD((p->retlen)++)] = ch), TRUE );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
/*
|
||||
Copyright (C) 1981
|
||||
Digital Research
|
||||
P.O. Box 579
|
||||
Pacific Grove, CA 93950
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* 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 ***********************************/
|
||||
@@ -0,0 +1,39 @@
|
||||
/**************************************************************************
|
||||
* CTYPE.H - macros to classify ASCII-coded integers by table lookup.
|
||||
*
|
||||
*
|
||||
* Note: Integer args are undefined for all int values > 127,
|
||||
* except for macro 'isascii()'.
|
||||
* Assumes:
|
||||
* User will link with standard library functions.
|
||||
* Compiler can handle declarator initializers and
|
||||
* '#defines' with parameters.
|
||||
***************************************************************************/
|
||||
|
||||
/* Define bit patterns for character classes */
|
||||
#define __c 01
|
||||
#define __p 02
|
||||
#define __d 04
|
||||
#define __u 010
|
||||
#define __l 020
|
||||
#define __s 040
|
||||
#define __cs 041
|
||||
#define __ps 042
|
||||
|
||||
#ifndef CTYPE
|
||||
extern char __atab[];
|
||||
#endif
|
||||
|
||||
#define isascii(ch) ((ch) < 0200)
|
||||
#define isalpha(ch) (__atab[ch] & (__u | __l))
|
||||
#define isupper(ch) (__atab[ch] & __u)
|
||||
#define islower(ch) (__atab[ch] & __l)
|
||||
#define isdigit(ch) (__atab[ch] & __d)
|
||||
#define isalnum(ch) (__atab[ch] & (__u | __l | __d))
|
||||
#define isspace(ch) (__atab[ch] & __s)
|
||||
#define ispunct(ch) (__atab[ch] & __p)
|
||||
#define isprint(ch) (__atab[ch] & (__u | __l | __d | __p))
|
||||
#define iscntrl(ch) (__atab[ch] & __c)
|
||||
#define tolower(ch) (isupper(ch) ? (ch)-'A'+'a' : (ch) )
|
||||
#define toupper(ch) (islower(ch) ? (ch)-'a'+'A' : (ch) )
|
||||
#define toascii(ch) ((ch) & 0177)
|
||||
@@ -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);
|
||||
}
|
||||
3447
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/newos/ed.c
Normal file
3447
CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/P-CP M-Z8K SOURCES/newos/ed.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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 ******/
|
||||
@@ -0,0 +1,356 @@
|
||||
;************************************************
|
||||
;* *
|
||||
;* 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) *
|
||||
;* *
|
||||
;************************************************
|
||||
|
||||
|
||||
__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
|
||||
|
||||
BIOS_SC .equ 3 ;Bios system call
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* 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 = BDOS command
|
||||
ldl rr4,#2 ;rr4 = exception #
|
||||
ld r6,_sysseg ;rr6 -> handler
|
||||
lda r7,exchndl ; (segmented)
|
||||
|
||||
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
|
||||
;* in segmented mode, 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
|
||||
|
||||
ldctl r0,FCW ; NONSEGMENTED
|
||||
res r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
popl rr0,@r15 ; get return address
|
||||
; from above array
|
||||
sub r1,#excrtn0 ; r1 now = 4*encoded
|
||||
srl r2,#2 ; exception number
|
||||
|
||||
; 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
|
||||
popl rr0,@r15
|
||||
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 (long) to trap_ret
|
||||
; normal r0..r15
|
||||
; reason, fcw, PC (long)
|
||||
|
||||
ld r1,38(r15) ;34+4 r1 = user FCW
|
||||
bit r1,#14 ;system mode?
|
||||
jr nz sysexc ; yes
|
||||
; no
|
||||
ldl rr2,32(r15) ;28+4 rr2 = user stack
|
||||
bit r1,#15 ;segmented?
|
||||
jr nz segusrx ; yes
|
||||
; no -- get seg
|
||||
ld r2,42(r15) ;38+4
|
||||
segusrx:
|
||||
ldctl r0,FCW ;go segmented
|
||||
set r0,#15
|
||||
ldctl FCW,r0
|
||||
|
||||
sub r3,#44 ;copy frame to usr
|
||||
; (with junk PC)
|
||||
ld r0,#22
|
||||
ldir @r2,@r14,r0
|
||||
|
||||
pushl @r14,rr4 ;go
|
||||
pushl @r14,rr0
|
||||
iret
|
||||
|
||||
sysexc: ;system mode exc.
|
||||
set r1,#15 ; go segmented
|
||||
ldctl FCW,r1
|
||||
jp @r4 ;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
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__data: .sect
|
||||
|
||||
excmsg1:
|
||||
.byte 13,10,10,"Exception $"
|
||||
|
||||
excmsg2:
|
||||
.byte " at user address $"
|
||||
|
||||
excmsg3:
|
||||
.byte ". Aborted.$"
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* bss
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
__bss: .sect
|
||||
|
||||
evec_adr:
|
||||
.block 2
|
||||
|
||||
.end
|
||||
@@ -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
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* CP/M-Z8k Loader BDOS File I/O Module *
|
||||
* *
|
||||
* This module contains all file handling BDOS functions *
|
||||
* except for read and write for CP/M-Z8K. Included are: *
|
||||
* *
|
||||
* seldsk() - select disk *
|
||||
* openfile() - open file *
|
||||
* move() - general purpose byte mover *
|
||||
* *
|
||||
* *
|
||||
* Modified for memory management on Z8000 *
|
||||
* The main change is that search no longer calls tmp_sel *
|
||||
* tmp_sel in bdosmain.c now handles drive number = '?' *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
#include "stdio.h" /* Standard I/O declarations */
|
||||
|
||||
#include "bdosdef.h" /* Type and structure declarations for BDOS */
|
||||
|
||||
#include "biosdef.h" /* and BIOS */
|
||||
|
||||
#include "pktio.h" /* Packet I/O definitions */
|
||||
|
||||
/* declare external fucntions */
|
||||
EXTERN UWORD dirscan(); /* directory scanning routine */
|
||||
EXTERN UWORD do_phio(); /* packet disk i/o handler */
|
||||
EXTERN UWORD swap(); /* assembly language byte swapper */
|
||||
|
||||
/************************
|
||||
* seldsk entry point *
|
||||
************************/
|
||||
|
||||
seldsk(dsknum)
|
||||
|
||||
REG UBYTE dsknum; /* disk number to select */
|
||||
|
||||
{
|
||||
struct iopb selpkt;
|
||||
REG WORD i;
|
||||
UWORD j;
|
||||
BSETUP
|
||||
|
||||
if (UBWORD(dsknum) > 15) return(-1);
|
||||
selpkt.devnum = dsknum;
|
||||
selpkt.iofcn = sel_info;
|
||||
selpkt.ioflags = 0;
|
||||
do_phio(&selpkt); /* actually do the disk select */
|
||||
if( (GBL.dphp = selpkt.infop) == NULL)
|
||||
return(-1);
|
||||
GBL.dirbufp = (GBL.dphp)->dbufp;
|
||||
/* set up GBL copies of dir_buf and dpb ptrs */
|
||||
GBL.parmp = (GBL.dphp)->dpbp;
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
* General purpose byte mover *
|
||||
*******************************/
|
||||
|
||||
move(p1, p2, i)
|
||||
|
||||
REG BYTE *p1;
|
||||
REG BYTE *p2;
|
||||
REG WORD i;
|
||||
{
|
||||
while (i--)
|
||||
*p2++ = *p1++;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* General purpose filename matcher *
|
||||
*************************************/
|
||||
|
||||
BOOLEAN match(p1, p2, chk_ext)
|
||||
|
||||
REG UBYTE *p1;
|
||||
REG UBYTE *p2;
|
||||
BOOLEAN chk_ext;
|
||||
{
|
||||
REG WORD i;
|
||||
REG UBYTE temp;
|
||||
BSETUP
|
||||
|
||||
i = 12;
|
||||
do
|
||||
{
|
||||
temp = (*p1 ^ '?');
|
||||
if ( ((*p1++ ^ *p2++) & 0x7f) && temp )
|
||||
return(FALSE);
|
||||
i -= 1;
|
||||
} while (i);
|
||||
if (chk_ext)
|
||||
{
|
||||
if ( (*p1 != '?') && ((*p1 ^ *p2) & ~((GBL.parmp)->exm)) )
|
||||
return(FALSE);
|
||||
p1 += 2;
|
||||
p2 += 2;
|
||||
if ((*p1 ^ *p2) & 0x3f) return(FALSE);
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
* openfile entry point *
|
||||
************************/
|
||||
|
||||
BOOLEAN openfile(fcbp, dirp, dirindx) /* ARGSUSED */
|
||||
|
||||
REG struct fcb *fcbp; /* pointer to fcb for file to open */
|
||||
struct dirent *dirp; /* pointer to directory entry */
|
||||
WORD dirindx;
|
||||
|
||||
{
|
||||
REG UBYTE fcb_ext; /* extent field from fcb */
|
||||
REG BOOLEAN rtn;
|
||||
BSETUP
|
||||
|
||||
if ( rtn = match(fcbp, dirp, TRUE) )
|
||||
{
|
||||
fcb_ext = fcbp->extent; /* save extent number from user's fcb */
|
||||
move(dirp, fcbp, sizeof *dirp);
|
||||
/* copy dir entry into user's fcb */
|
||||
fcbp->extent = fcb_ext;
|
||||
fcbp->s2 |= 0x80; /* set hi bit of S2 (write flag) */
|
||||
}
|
||||
return(rtn);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -0,0 +1,131 @@
|
||||
;*************************************************
|
||||
;** Change history --
|
||||
;** 30mar81: Broken off from general interface.
|
||||
;** 30mar81: Set up for Zilog ZLAB 8000
|
||||
;** 09may81: Tell cpu when state is free.
|
||||
;** 19jan82: Allow segmented users.
|
||||
;** 21jan82: Took out references to freecpu and needcpu
|
||||
;** 15feb82: Dummy out need/free cpu.
|
||||
;** 13may82: Comment out references to setfp and resfp
|
||||
;*************************************************
|
||||
|
||||
.title "sysdep MODULE"
|
||||
.input "biosdefs2.z8k"
|
||||
|
||||
;*************************************************
|
||||
;** SAVED CPU STATE --
|
||||
;** is specified by the following "constants."
|
||||
;** Offset stapcsg must point to the word preceding
|
||||
;** the saved PC offset, EVEN FOR NONSEGMENTED
|
||||
;** OPERATION.
|
||||
;*************************************************
|
||||
__data .sect
|
||||
.GLOBAL stareg,staevnt,stafcw,stapcsg
|
||||
stareg .WORD 4 ;offset of r0
|
||||
staevnt .WORD 36 ;saved 1st word
|
||||
stafcw .WORD 38 ;saved fcw
|
||||
stapcsg .WORD 40 ;seg word of PC
|
||||
|
||||
;*************************************************
|
||||
;** ADDRESSES --
|
||||
;** as input parameters to the routines below are
|
||||
;** delivered in register pairs (i.e. as though
|
||||
;** segmented). The high-order word of such an
|
||||
;** address is undefined when the process running
|
||||
;** in that address space runs in nonsegmented
|
||||
;** mode.
|
||||
;*************************************************
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET NEXT INSTRUCTION WORD --
|
||||
;** Input:
|
||||
;** rr6 = saved PC -- seg # must be fixed for
|
||||
;** nonseg users
|
||||
;** Output:
|
||||
;** r3 = next instruction word
|
||||
;*************************************************
|
||||
__data .sect
|
||||
gttxt: .WORD 0
|
||||
__text .sect
|
||||
.GLOBAL gettext
|
||||
gettext: ; PROCEDURE ENTRY
|
||||
; ld r5,#2 ; it is system data
|
||||
; ldl rr2,#0 ; required parameter
|
||||
; sc #MEM_SC ; MAP source
|
||||
|
||||
pushl @r15,rr6
|
||||
ld r7,#gttxt ; address of temp
|
||||
ld r5,#0 ; it is caller Instruction
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
ldl rr2,#2 ; byte count to move
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ld r3,gttxt ; load return values
|
||||
ldb rl2,#0
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** GET MEMORY BYTES --
|
||||
;** Segmented emulator input --
|
||||
;** rr6 - src address (trapee space)
|
||||
;** rr4 - dst address (emulator space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL getmem
|
||||
getmem:
|
||||
push @r15,r3
|
||||
pushl @r15,rr4 ; save dest - MEM_SC steps on rr4
|
||||
ld r5,#4 ; it is TPA data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP source
|
||||
|
||||
popl rr4,@r15 ; restore dest
|
||||
pushl @r15,rr6 ; save source
|
||||
ldl rr6,rr4 ; position dest
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6
|
||||
popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; requrired parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
|
||||
.eject
|
||||
;*************************************************
|
||||
;** PUT MEMORY BYTES --
|
||||
;** Emulator input --
|
||||
;** rr6 - src address (emulator space)
|
||||
;** rr4 - dst address (trapee space)
|
||||
;** r3 - byte count
|
||||
;*************************************************
|
||||
.GLOBAL putmem
|
||||
putmem: ; PROCEDURE ENTRY
|
||||
push @r15,r3
|
||||
pushl @r15,rr4 ; save dest - MEM_SC steps on rr4
|
||||
ld r5,#0 ; it is caller data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP source
|
||||
|
||||
popl rr4,@r15
|
||||
pushl @r15,rr6 ; save source
|
||||
ldl rr6,rr4 ; position destination
|
||||
ld r5,#4 ; it is TPA data
|
||||
ldl rr2,#0 ; required parameter
|
||||
sc #MEM_SC ; MAP destination
|
||||
|
||||
ldl rr4,rr6 ; put mapped dest in rr4
|
||||
popl rr6,@r15 ; restore source
|
||||
pop r3,@r15 ; restore byte count
|
||||
ld r2,#0 ; required parameter
|
||||
sc #MEM_SC ; DO TRANSFER
|
||||
|
||||
ret
|
||||
@@ -0,0 +1,212 @@
|
||||
/************************************************************************
|
||||
* *
|
||||
* 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! */
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* P-CP/M BDOS Disk I/O System Module *
|
||||
* *
|
||||
* This module translates from the packet oriented I/O *
|
||||
* passed from the other BDOS modules into BIOS calls. *
|
||||
* *
|
||||
* It includes only one external entry point: *
|
||||
* do_phio() - do physical i/o *
|
||||
* *
|
||||
* *
|
||||
* 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" /* Declarations for BIOS entry points */
|
||||
|
||||
EXTERN udiv(); /* Assembly language unsigned divide routine */
|
||||
/* in bdosif.s. It's used because Alcyon C */
|
||||
/* can't do / or % without an external */
|
||||
|
||||
/************************
|
||||
* do_phio entry point *
|
||||
************************/
|
||||
|
||||
UWORD do_phio(iop)
|
||||
|
||||
REG struct iopb *iop; /* iop is a pointer to a i/o parameter block */
|
||||
|
||||
{
|
||||
MLOCAL UBYTE last_dsk; /* static variable to tell which disk
|
||||
was last used, to avoid disk selects */
|
||||
REG struct dph *hdrp; /* pointer to disk parameter header */
|
||||
REG struct dpb *dparmp; /* pointer to disk parameter block */
|
||||
REG UWORD rtn; /* return parameter */
|
||||
UWORD iosect; /* sector number returned from divide rtn */
|
||||
|
||||
LOCK /* lock the disk system while doing physical i/o */
|
||||
|
||||
rtn = 0;
|
||||
switch (iop->iofcn)
|
||||
{
|
||||
case sel_info:
|
||||
iop->infop = bseldsk(last_dsk, iop->ioflags);
|
||||
break;
|
||||
|
||||
case read:
|
||||
hdrp = iop->infop;
|
||||
dparmp = hdrp->dpbp;
|
||||
|
||||
bsettrk( udiv( iop->devadr, dparmp->spt, (long)&iosect )
|
||||
+ dparmp->trk_off );
|
||||
bsetsec( bsectrn( iosect, hdrp->xlt ) );
|
||||
bsetdma(iop->xferadr);
|
||||
return(bread());
|
||||
}
|
||||
|
||||
UNLOCK
|
||||
return(0);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,75 @@
|
||||
# Makefile for Portable CP/M Peripheral Interchange Program, PIP.
|
||||
#
|
||||
# Change the variables INCLUDE, BIN, UBIN, CC, LD, LIB as necessary for a
|
||||
# particular environment.
|
||||
#
|
||||
# Usage:
|
||||
# make makes executable file PIP for CP/M target
|
||||
# make pipn makes non-split version of above
|
||||
# make pip.o compiles pip.c
|
||||
# make pip.cpm makes file pip.cpm for loading with mkfile
|
||||
# make list sends formatted listing of ALL source
|
||||
# files to print spooler
|
||||
#
|
||||
# Author: D Dunlop, Zilog Inc. 11/19/82
|
||||
|
||||
INCLUDE = /u/Tests/include
|
||||
BIN = /bin
|
||||
UBIN = /usr/bin
|
||||
CC = $(BIN)/zcc -M1 -c
|
||||
LD = $(UBIN)/ld8k -i -w
|
||||
ULIB = /usr/lib
|
||||
LIB = /lib
|
||||
PSOURCE = makefile pip.c portab.h bdos.h\
|
||||
basepage.h setjmp.h
|
||||
ESOURCE = makefile ed.c portab.h bdos.h\
|
||||
basepage.h setjmp.h
|
||||
SSOURCE = makefile stat.c portab.h bdos.h\
|
||||
basepage.h setjmp.h
|
||||
SOURCE = makefile ed.c pip.c stat.c portab.h bdos.h\
|
||||
basepage.h setjmp.h
|
||||
POBJS = pip.o $(ULIB)/libcpm.a $(ULIB)/startup.o
|
||||
EOBJS = ed.o $(ULIB)/libcpm.a $(ULIB)/startup.o
|
||||
SOBJS = stat.o $(ULIB)/libcpm.a $(ULIB)/startup.o
|
||||
|
||||
pip: $(POBJS)
|
||||
$(LD) -o pip $(ULIB)/startup.o pip.o -lcpm
|
||||
|
||||
pip.o: $(PSOURCE)
|
||||
$(CC) pip.c
|
||||
|
||||
pip.cpm: pip
|
||||
$(UBIN)/imager pip
|
||||
|
||||
plist:
|
||||
pr $(PSOURCE) | lpr&
|
||||
|
||||
elist:
|
||||
pr $(ESOURCE) | lpr&
|
||||
|
||||
slist:
|
||||
pr $(SSOURCE) | lpr&
|
||||
|
||||
list:
|
||||
pr $(SOURCE) | lpr&
|
||||
|
||||
pipn: $(POBJS)
|
||||
/bin/ld8k -w -o pipn $(ULIB)/startup.o pip.o -lcpm
|
||||
|
||||
ed: $(EOBJS)
|
||||
$(LD) -o ed $(ULIB)/startup.o ed.o -lcpm
|
||||
|
||||
ed.o: $(ESOURCE)
|
||||
$(CC) ed.c
|
||||
|
||||
ed.cpm: ed
|
||||
$(UBIN)/imager ed
|
||||
|
||||
stat: $(SOBJS)
|
||||
$(LD) -o stat $(ULIB)/startup.o stat.o -lcpm
|
||||
|
||||
stat.o: $(SSOURCE)
|
||||
$(CC) stat.c
|
||||
|
||||
stat.cpm: stat
|
||||
$(UBIN)/imager stat
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
/* This module performs packet normalization and */
|
||||
/* preparation to/from I/O channel. Context dependent */
|
||||
/* data are put in a normal form before transmission */
|
||||
/* over the I/O channel. Conversly, received messages */
|
||||
/* are 'de-normalized' into machine dependent quanti- */
|
||||
/* ties before being returned to the caller. This */
|
||||
/* portion of code should be machine independent, */
|
||||
/* since values such as word-length and long-length */
|
||||
/* are declared as externals. */
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Author: David Heintz *
|
||||
* Module: Normalc.c *
|
||||
* Creation Date: 10/26/82 *
|
||||
* Language: Standard C *
|
||||
* Version: 0.0 *
|
||||
* Last Mod: 01/16/83 *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* STANDARD HEADERS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
#include "unstdsys.h"
|
||||
#include "fioequ.h"
|
||||
#include "chnequ.h"
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* EXTERNAL DECLARATIONS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* I/O Channel Related Externals *
|
||||
* and Globals *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/* Routines defined within this module */
|
||||
|
||||
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();
|
||||
|
||||
|
||||
/* Routines defined outside of this module */
|
||||
|
||||
extern BYTE snd_pkt();
|
||||
extern BYTE rcv_pkt();
|
||||
extern BYTE gb_word();
|
||||
extern BYTE gb_long();
|
||||
extern pb_word();
|
||||
extern pb_long();
|
||||
|
||||
|
||||
/* Machine dependent externals */
|
||||
|
||||
extern WORD bytlen;
|
||||
extern WORD wrdlen;
|
||||
extern WORD lnglen;
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* I/O Channel Data Normalization *
|
||||
* Routines *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* snd_byte(): *
|
||||
* Normalize and transmit *
|
||||
* a byte over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: byte to be transmitted
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE snd_byte(sbyte)
|
||||
|
||||
BYTE sbyte;
|
||||
{
|
||||
return(snd_pkt(byttyp, (BYTE *)&sbyte, bytlen));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* snd_word(): *
|
||||
* Normalize and transmit *
|
||||
* a word over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: word to be transmitted
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE snd_word(sword)
|
||||
|
||||
WORD sword;
|
||||
{
|
||||
WORD i, nword;
|
||||
BYTE *pbyte;
|
||||
pbyte = (BYTE *)&nword;
|
||||
for (i = 0; i < wrdlen; i++)
|
||||
*(pbyte++) = gb_word(&sword, i);
|
||||
return(snd_pkt(wrdtyp, (BYTE *)&nword, wrdlen));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* snd_long(): *
|
||||
* Normalize and transmit *
|
||||
* a long over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: long to be transmitted
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE snd_long(slong)
|
||||
|
||||
LONG slong;
|
||||
{
|
||||
LONG nlong;
|
||||
WORD i;
|
||||
BYTE *pbyte;
|
||||
pbyte = (BYTE *)&nlong;
|
||||
for (i = 0; i < lnglen; i++)
|
||||
*(pbyte++) = gb_long(&slong, i);
|
||||
return(snd_pkt(lngtyp, (BYTE *)&nlong, lnglen));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* snd_data(): *
|
||||
* Normalize and transmit *
|
||||
* data over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: pointer to data to be transmitted
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE snd_data(pbyte, datlen)
|
||||
|
||||
BYTE *pbyte;
|
||||
WORD datlen;
|
||||
{
|
||||
return(snd_pkt(dattyp, pbyte, datlen));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* snd_cmd(): *
|
||||
* Normalize and transmit *
|
||||
* a command over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: command to be transmitted
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE snd_cmd(sd0, sd1, sd2)
|
||||
|
||||
WORD sd0;
|
||||
LONG sd1, sd2;
|
||||
|
||||
{
|
||||
struct {
|
||||
WORD request;
|
||||
LONG param1;
|
||||
LONG param2;
|
||||
} cmd;
|
||||
|
||||
LONG nlong;
|
||||
WORD i;
|
||||
BYTE *pbyte;
|
||||
pbyte = (BYTE *)&cmd;
|
||||
for (i = 0; i < wrdlen; i++)
|
||||
*(pbyte++) = gb_word(&sd0, i);
|
||||
for (i = 0; i < lnglen; i++)
|
||||
*(pbyte++) = gb_long(&sd1, i);
|
||||
for (i = 0; i < lnglen; i++)
|
||||
*(pbyte++) = gb_long(&sd2, i);
|
||||
return(snd_pkt(cmdtyp, (BYTE *)&cmd, sizeof(cmd)));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* rcv_byte(): *
|
||||
* Receive and normalize *
|
||||
* a byte over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/ Inputs: Address of where to put received byte
|
||||
/ Outputs: I/O channel status (BYTE)
|
||||
/ Actions: Place received byte at pbyte
|
||||
*/
|
||||
|
||||
BYTE rcv_byte(pbyte)
|
||||
|
||||
BYTE *pbyte;
|
||||
{
|
||||
return(rcv_pkt(byttyp, pbyte, bytlen));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* rcv_word(): *
|
||||
* Receive and normalize *
|
||||
* a word over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/ Inputs: Address of where to put received word
|
||||
/ Outputs: I/O channel status (BYTE)
|
||||
/ Actions: Place received word at pword
|
||||
*/
|
||||
|
||||
BYTE rcv_word(pword)
|
||||
|
||||
BYTE *pword;
|
||||
|
||||
{
|
||||
BYTE code, *pbyte;
|
||||
WORD i, rword;
|
||||
pbyte = (BYTE *)&rword;
|
||||
code = rcv_pkt(wrdtyp, (BYTE *)&rword, wrdlen);
|
||||
if (code == chsuc)
|
||||
for (i = 0; i < wrdlen; i++)
|
||||
pb_word(*(pbyte++), pword, i);
|
||||
return(code);
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* rcv_long(): *
|
||||
* Receive and normalize *
|
||||
* a long over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/ Inputs: Address of where to put received long
|
||||
/ Outputs: I/O channel status (BYTE)
|
||||
/ Actions: Place received long at plong
|
||||
*/
|
||||
|
||||
BYTE rcv_long(plong)
|
||||
|
||||
BYTE *plong;
|
||||
|
||||
{
|
||||
BYTE code, *pbyte;
|
||||
WORD i;
|
||||
LONG rlong;
|
||||
pbyte = (BYTE *)&rlong;
|
||||
code = rcv_pkt(lngtyp, (BYTE *)&rlong, lnglen);
|
||||
if (code == chsuc)
|
||||
for (i = 0; i < lnglen; i++)
|
||||
pb_long(*(pbyte++), plong, i);
|
||||
return(code);
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* rcv_data(): *
|
||||
* Receive and normalize *
|
||||
* data over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/ Inputs: Address of where to put received data
|
||||
/ Outputs: I/O channel status (BYTE)
|
||||
/ Actions: Place received data at pbyte
|
||||
*/
|
||||
|
||||
BYTE rcv_data(pbyte, datlen)
|
||||
|
||||
BYTE *pbyte;
|
||||
{
|
||||
return(rcv_pkt(dattyp, pbyte, datlen));
|
||||
}
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* rcv_cmd(): *
|
||||
* Receive and Normalize *
|
||||
* a command over I/O channel *
|
||||
* *
|
||||
*****************************************
|
||||
/
|
||||
/ Inputs: addresses of command parameters
|
||||
/ Outputs: I/O channel status (byte)
|
||||
*/
|
||||
|
||||
BYTE rcv_cmd(sd0, sd1, sd2)
|
||||
|
||||
WORD *sd0;
|
||||
LONG *sd1, *sd2;
|
||||
|
||||
{
|
||||
struct {
|
||||
WORD request;
|
||||
LONG param1;
|
||||
LONG param2;
|
||||
} cmd;
|
||||
|
||||
LONG nlong;
|
||||
WORD i;
|
||||
BYTE code, *pbyte;
|
||||
code = rcv_pkt(cmdtyp, (BYTE *)&cmd, sizeof(cmd));
|
||||
if (code == chsuc)
|
||||
{
|
||||
pbyte = (BYTE *)&cmd;
|
||||
for (i = 0; i < wrdlen; i++)
|
||||
pb_word(*(pbyte++), sd0, i);
|
||||
for (i = 0; i < lnglen; i++)
|
||||
pb_long(*(pbyte++), sd1, i);
|
||||
for (i = 0; i < lnglen; i++)
|
||||
pb_long(*(pbyte++), sd2, i);
|
||||
}
|
||||
return(code);
|
||||
}
|
||||
|
||||
/* End of Module */
|
||||
@@ -0,0 +1,432 @@
|
||||
/****************************************************************
|
||||
* *
|
||||
* 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
@@ -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 */
|
||||
|
||||
@@ -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 ********************************/
|
||||
@@ -0,0 +1,216 @@
|
||||
/*=======================================================================*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*| |*/
|
||||
/*| P-CP/M(tm) Bootstrap Writer for the OLIVETTI M20 (Z8000) |*/
|
||||
/*| |*/
|
||||
/*| Copyright 1982, Zilog Incorporated. |*/
|
||||
/*| |*/
|
||||
/*+---------------------------------------------------------------------+*/
|
||||
/*=======================================================================*/
|
||||
|
||||
char copyright[] = "Copyright 1982, Zilog Incorporated";
|
||||
|
||||
|
||||
/* HISTORY
|
||||
**
|
||||
** 830801 F. Zlotnick (Zilog) -- written
|
||||
**
|
||||
*/
|
||||
|
||||
#include "portab.h"
|
||||
#include "cpm.h"
|
||||
#include "bdos.h"
|
||||
#include "stdio.h"
|
||||
#include "xout.h"
|
||||
|
||||
#define CDATA 0 /* Parameter for map_adr() */
|
||||
#define DIRSEC 1 /* Parameter for BIOS Write call */
|
||||
|
||||
#define SETTRK 10 /* BIOS Function 10 = Set Track */
|
||||
#define SETSEC 11 /* BIOS Function 11 = Set Sector */
|
||||
#define BSETDMA 12 /* BIOS Function 12 = Set DMA Addr */
|
||||
#define WSECTOR 14 /* BIOS Function 14 = Write Sector */
|
||||
|
||||
XADDR physdir; /* Segmented address of dirbuf */
|
||||
|
||||
struct dpbs idpb; /* Disk Parameter Block */
|
||||
struct bios_parm ibp; /* BIOS param block for BDOS call 50*/
|
||||
XADDR physibp; /* physical address of ibp structure*/
|
||||
|
||||
extern long map_adr(); /* Function to return physical addr */
|
||||
|
||||
#define BPLS 128 /* Bytes per logical sector */
|
||||
#define BPS 256 /* Bytes per sector */
|
||||
#define BPS0 128 /* Bytes per sector, trk 0 */
|
||||
#define SPT 16 /* sectors per track */
|
||||
#define LSPT 32 /* Logical sectors per track */
|
||||
#define SYSTRKS 2 /* Number of boot tracks */
|
||||
#define SYSSIZE SPT*BPS*SYSTRKS /* Max size of bootstrap */
|
||||
#define STARTRK 1 /* Track number to start on */
|
||||
|
||||
FILE *fin;
|
||||
|
||||
char syscode[SYSSIZE]; /* Hold the entire bootstrap here! */
|
||||
char *system = "CPMLDR.SYS"; /* Name of the prog to boot */
|
||||
|
||||
#ifdef OLIVETTI
|
||||
extern char T0S0[]; /* Track 0 Sector 0 */
|
||||
extern char T1S0[]; /* Track 1 Sector 0 */
|
||||
extern char T1S1[]; /* Track 1 Sector 1 */
|
||||
#define HDRSIZE 24 /* # bytes in track 1 sect 1 header */
|
||||
#endif
|
||||
|
||||
struct x_hdr xh;
|
||||
struct x_sg xs;
|
||||
int dsknum; /* Drive number 0-15 = A-P */
|
||||
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register int i, j, c;
|
||||
register char *p;
|
||||
long fsize;
|
||||
int curdsk; /* Good to remember, & reset*/
|
||||
|
||||
if(argc != 3) usage();
|
||||
system = *++argv;
|
||||
if( (dsknum = **++argv - 'a') < 0 || dsknum > 15) {
|
||||
printf("putboot: Illegal drive code %c\n", *argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
curdsk = _ret_cdisk();
|
||||
_get_dpb(map_adr((long) &idpb, CDATA)); /* Physaddr of idpb */
|
||||
if( (fin = fopenb(system, "r")) == NULL) {
|
||||
printf("putboot: Can't open bootstrap file %s\n", system);
|
||||
exit(1);
|
||||
}
|
||||
fsize = 0L;
|
||||
|
||||
/* read file header */
|
||||
|
||||
p = (char *) &xh;
|
||||
for (i = 0; i < sizeof(xh); i++)
|
||||
*p++ = (char) getc(fin);
|
||||
|
||||
/* read and count segment headers to get file size */
|
||||
for (i = 0; i < xh.x_nseg; i++) {
|
||||
p = (char *) &xs;
|
||||
for( j = 0; j < sizeof(xs); j++)
|
||||
*p++ = (char) getc(fin);
|
||||
if( xs.x_sg_typ != X_SG_BSS && xs.x_sg_typ != X_SG_STK)
|
||||
fsize += xs.x_sg_len;
|
||||
}
|
||||
if (fsize > SYSSIZE) {
|
||||
printf("Bootstrap too big\n");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
printf("Bootstrap file is %ld bytes\n", fsize);
|
||||
p = syscode;
|
||||
#ifdef OLIVETTI
|
||||
for( i = 0; i < BPS; i++) *p++ = T1S0[i];
|
||||
for( i = 0; i < HDRSIZE; i++) *p++ = T1S1[i];
|
||||
#endif
|
||||
while(fsize--) {
|
||||
if( (c = getc(fin)) == EOF) {
|
||||
printf("Unexpected EOF in %s, %ld left\n",system,fsize);
|
||||
exit(1);
|
||||
}
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
/*
|
||||
** At this point, the entire bootstrap program code and data has been loaded
|
||||
** into the array named "syscode", preceded by a bunch of PCOS garbage
|
||||
** which the Olivetti boot PROM expects to find there. Now we use direct
|
||||
** BIOS calls to write the syscode array out to the proper area on disk.
|
||||
** For the Olivetti, this is tracks 1 and 2, since track 0 is special.
|
||||
*/
|
||||
|
||||
putboot(syscode);
|
||||
printf("Bootstrap has been written.\n");
|
||||
_sel_disk(curdsk); /* reselect original disk*/
|
||||
}
|
||||
|
||||
putboot(code)
|
||||
char *code;
|
||||
{
|
||||
register int i; /* Handy index */
|
||||
register int nlsecs; /* # logical sectors in boot*/
|
||||
register char *p; /* ptr to next part of code */
|
||||
|
||||
int track; /* Current track */
|
||||
int sector; /* Current sector */
|
||||
|
||||
physibp = map_adr( (long) &ibp, CDATA );
|
||||
nlsecs = SYSTRKS * LSPT; /* size / log secs per trk */
|
||||
|
||||
/* Pause for the user to insert disk */
|
||||
/* pause(drvname); */
|
||||
|
||||
#ifdef OLIVETTI
|
||||
/* Olivetti Track 0 Sector 0 is special */
|
||||
_sel_disk(dsknum); /* select as current disk */
|
||||
putblk(0, 0, T0S0);
|
||||
#endif
|
||||
p = code;
|
||||
for(i = 0; i < nlsecs; i++) {
|
||||
track = STARTRK + i/LSPT;
|
||||
sector = i%LSPT;
|
||||
putblk(track, sector, p);
|
||||
p += BPLS;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to select a given track for writing on, on the current disk.
|
||||
* Makes use of the BDOS direct BIOS call to issue Bios function 10.
|
||||
*/
|
||||
settrk(n)
|
||||
int n;
|
||||
{
|
||||
ibp.req = SETTRK; /* BIOS request number 10 */
|
||||
ibp.p1 = (long) n; /* parameter = track # */
|
||||
_bios_call( physibp ); /* Pass seg ibp address */
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to put block i of the boot track.
|
||||
*/
|
||||
putblk(trk, sec, addr)
|
||||
int trk, sec;
|
||||
char *addr;
|
||||
{
|
||||
register int n;
|
||||
|
||||
_sel_disk(dsknum); /* select as current disk */
|
||||
settrk(trk);
|
||||
|
||||
n = sec + 1; /* sector number */
|
||||
ibp.req = SETSEC; /* BIOS request number 11 */
|
||||
ibp.p1 = (long) n; /* parameter = sector # */
|
||||
_bios_call( physibp ); /* Pass seg ibp address */
|
||||
|
||||
/* Sector is now set; now set dma address. */
|
||||
|
||||
ibp.req = BSETDMA; /* BIOS Request number 12 */
|
||||
ibp.p1 = map_adr( (long) addr, CDATA);
|
||||
/* param = seg address of I/O buffer */
|
||||
_bios_call( physibp ); /* Call BIOS */
|
||||
|
||||
/* Now can do a write */
|
||||
|
||||
ibp.req = WSECTOR; /* BIOS Request number 14 */
|
||||
ibp.p1 = DIRSEC; /* Complete write immediately */
|
||||
_bios_call( physibp ); /* Do it! */
|
||||
}
|
||||
|
||||
/*
|
||||
* If the user invoked us with the wrong number of args...
|
||||
*/
|
||||
usage()
|
||||
{
|
||||
printf("Usage: putboot <filename> <drivecode>\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -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();
|
||||
@@ -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
@@ -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) */
|
||||
@@ -0,0 +1,128 @@
|
||||
/* CP/M INTERFACE HEADER FILE
|
||||
*/
|
||||
|
||||
/* Modified to include additional CP/M function defi-
|
||||
nitions and DPB structure definition 07/20/82 (DMH)
|
||||
*/
|
||||
/* Modified to include BIOS header 10/13/82 (DMH)
|
||||
*/
|
||||
/* Modified to include size of DPB 10/15/82 (DMH)
|
||||
*/
|
||||
|
||||
#define FCB struct fcb
|
||||
#define FCBLEN sizeof(FCB)
|
||||
struct fcb {
|
||||
TEXT et; /* assumed zero */
|
||||
TEXT fn[8]; /* blank padded */
|
||||
TEXT ft[3]; /* ditto */
|
||||
TINY ex; /* start with zero */
|
||||
TEXT pad[2]; /* assumed zero by CP/M */
|
||||
TINY rcount; /* [0, 128] */
|
||||
TINY dmap[16]; /* eight records per 1024 byte cluster */
|
||||
TINY nr; /* next record to read/write */
|
||||
TINY bleft;
|
||||
TEXT *bnext;
|
||||
LONG lseek;
|
||||
COUNT bufseg;
|
||||
TEXT buf[128];
|
||||
};
|
||||
|
||||
/* CP/M Disk Parameter Block
|
||||
*/
|
||||
|
||||
#define DPB struct dpb
|
||||
#define DPBLEN sizeof(DPB)
|
||||
struct dpb {
|
||||
WORD spt; /* Sectors per track */
|
||||
BYTE bsh; /* Block shift factor */
|
||||
BYTE blm; /* Block mask */
|
||||
BYTE exm; /* Extent mask */
|
||||
WORD dsm; /* Drive capacity */
|
||||
WORD drm; /* Directory capacity */
|
||||
BYTE al0; /* Directory allocation 0 */
|
||||
BYTE al1; /* Directory allocation 1 */
|
||||
WORD cks; /* Check vector size */
|
||||
WORD off; /* Track offset */
|
||||
};
|
||||
|
||||
|
||||
/* CP/M Disk Parameter Header
|
||||
*/
|
||||
|
||||
#define DPH struct dph
|
||||
#define DPHLEN sizeof(DPH)
|
||||
struct dph {
|
||||
BYTE *xltp; /* Translation vector address */
|
||||
WORD dphscr[3]; /* CP/M scratch pad area */
|
||||
BYTE *dirbufp; /* CP/M directory buffer */
|
||||
DPB *dpbp; /* DPB address */
|
||||
BYTE *csvp; /* Check vector address */
|
||||
BYTE *alvp; /* Allocation vector address */
|
||||
};
|
||||
|
||||
|
||||
/* the Whitesmiths control block
|
||||
*/
|
||||
#define WCB struct wcb
|
||||
|
||||
struct wcb {
|
||||
TINY flags, dev;
|
||||
FCB *pf;
|
||||
};
|
||||
|
||||
/* flag values:
|
||||
*/
|
||||
#define WOPEN 1
|
||||
#define WDIRT 2
|
||||
#define WSTD 4
|
||||
#define WCR 010
|
||||
#define WXDIRT 020
|
||||
#define WXOPEN 040
|
||||
|
||||
/* device values:
|
||||
*/
|
||||
#define LST -4
|
||||
#define PUN -3
|
||||
#define RDR -2
|
||||
#define CON -1
|
||||
|
||||
/* intermodule communication
|
||||
*/
|
||||
#define CTRLZ 032
|
||||
#define EOF 1
|
||||
#define FAIL -1
|
||||
#define MCREATE 0
|
||||
#define MOPEN 1
|
||||
#define MREMOVE 2
|
||||
#define MWRITE 4
|
||||
#define SYSBUF 0x80
|
||||
|
||||
/* CP/M innards
|
||||
*/
|
||||
#define CRDCON 1
|
||||
#define CWRCON 2
|
||||
#define CRDRDR 3
|
||||
#define CWRPUN 4
|
||||
#define CWRLST 5
|
||||
#define CGIOST 7
|
||||
#define CSIOST 8
|
||||
#define CPRBUF 9
|
||||
#define CRDBUF 10
|
||||
#define CICRDY 11
|
||||
#define CLFTHD 12
|
||||
#define CINIT 13
|
||||
#define CSDRNO 14
|
||||
#define COPEN 15
|
||||
#define CCLOSE 16
|
||||
#define CSRCH 17
|
||||
#define CSRCHN 18
|
||||
#define CDEL 19
|
||||
#define CREAD 20
|
||||
#define CWRITE 21
|
||||
#define CMAKE 22
|
||||
#define CRENAME 23
|
||||
#define CILOGIN 24
|
||||
#define CGDRNO 25
|
||||
#define CSETAD 26
|
||||
#define CIALLOC 27
|
||||
#define CIPARMS 31
|
||||
@@ -0,0 +1,74 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* C P / M C H E A D E R F I L E
|
||||
* -----------------------------------
|
||||
* Copyright 1982 by Digital Research Inc. All rights reserved.
|
||||
*
|
||||
* This is the standard include file for the CP/M C Run Time Library.
|
||||
*
|
||||
*****************************************************************************/
|
||||
/* */
|
||||
#ifndef BYTE /* If it looks like portab.h not */
|
||||
#include <portab.h> /* included already, include it */
|
||||
#endif /* */
|
||||
/* */
|
||||
/****************************************************************************
|
||||
* Stream I/O File Definitions
|
||||
*****************************************************************************/
|
||||
#define BUFSIZ 512 /* Standard (ascii) buf size */
|
||||
#define MAXFILES 16 /* Max # open files ( < 32 ) */
|
||||
struct _iobuf { /* */
|
||||
WORD _fd; /* file descriptor for low level io */
|
||||
WORD _flag; /* stream info flags */
|
||||
BYTE *_base; /* base of buffer */
|
||||
BYTE *_ptr; /* current r/w pointer */
|
||||
WORD _cnt; /* # chars to be read/have been wrt */
|
||||
}; /* */
|
||||
#ifndef FILE /* conditionally include: */
|
||||
extern struct _iobuf _iob[MAXFILES]; /* an array of this info */
|
||||
#define FILE struct _iobuf /* stream definition */
|
||||
#endif /************************************/
|
||||
/* flag byte definition */
|
||||
#define _IOREAD 0x01 /* readable file */
|
||||
#define _IOWRT 0x02 /* writeable file */
|
||||
#define _IOABUF 0x04 /* alloc'd buffer */
|
||||
#define _IONBUF 0x08 /* no buffer */
|
||||
#define _IOERR 0x10 /* error has occurred */
|
||||
#define _IOEOF 0x20 /* EOF has occurred */
|
||||
#define _IOLBUF 0x40 /* handle as line buffer */
|
||||
#define _IOSTRI 0x80 /* this stream is really a string */
|
||||
#define _IOASCI 0x100 /* this was opened as an ascii file */
|
||||
/************************************/
|
||||
#define stdin (&_iob[0]) /* standard input stream */
|
||||
#define stdout (&_iob[1]) /* " output " */
|
||||
#define stderr (&_iob[2]) /* " error " */
|
||||
/************************************/
|
||||
#define clearerr(p) ((p)->_flag & ~_IOERR) /* clear error flag */
|
||||
#define feof(p) ((p)->_flag & _IOEOF) /* EOF encountered on stream */
|
||||
#define ferror(p) ((p)->_flag & _IOERR) /* error encountered on stream */
|
||||
#define fileno(p) ((p)->_fd) /* get stream's file descriptor */
|
||||
#define getchar() getc(stdin) /* get char from stdin */
|
||||
#define putchar(c) putc(c,stdout) /* put char to stdout */
|
||||
#define putc fputc
|
||||
#define getc fgetc
|
||||
|
||||
FILE *fopen(), *fopena(), *fopenb(), *fdopen();
|
||||
FILE *freopen(), *freopa(), *freopb();
|
||||
LONG ftell(), getl();
|
||||
BYTE *fgets(), *gets();
|
||||
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* M A C R O S */
|
||||
/* ----------- */
|
||||
/* */
|
||||
/* Define some stuff as macros .... */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#define abs(x) ((x) < 0 ? -(x) : (x)) /* Absolute value function */
|
||||
|
||||
#define max(x,y) (((x) > (y)) ? (x) : (y)) /* Max function */
|
||||
#define min(x,y) (((x) < (y)) ? (x) : (y)) /* Min function */
|
||||
|
||||
/*************************** end of stdio.h *********************************/
|
||||
@@ -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
|
||||
@@ -0,0 +1,157 @@
|
||||
;************ syscall2.z8k **************************
|
||||
;*
|
||||
;* System Call interface for P-CP/M (tm) BIOS
|
||||
;*
|
||||
;* 820927 S. Savitzky (Zilog) -- created.
|
||||
;*
|
||||
|
||||
;* 01/17/83 Adapted for Z8002 (DMH)
|
||||
|
||||
__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 "biosdefs2.z8k"
|
||||
|
||||
.global _xfer
|
||||
.global _mem_cpy
|
||||
.global _map_adr
|
||||
.global _bios
|
||||
.global _bdos
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* Context Switch Routine
|
||||
;*
|
||||
;* xfer(context)
|
||||
;* long context;
|
||||
;*
|
||||
;* context is the physical (long) address of:
|
||||
;* r0
|
||||
;* ...
|
||||
;* r13
|
||||
;* r14 (normal r14)
|
||||
;* r15 (normal r15)
|
||||
;* ignored word
|
||||
;* FCW (had better specify normal mode)
|
||||
;* PC segment
|
||||
;* PC offset
|
||||
;*
|
||||
;* The system stack pointer is not affected.
|
||||
;*
|
||||
;* Control never returns to the caller.
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
_xfer:
|
||||
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,#-2
|
||||
subl rr2,rr2
|
||||
sc #XFER_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* System/User Memory Access
|
||||
;*
|
||||
;* _mem_cpy( source, dest, length)
|
||||
;* long source, dest, length;
|
||||
;* _map_adr( addr, space) -> paddr
|
||||
;* long addr; int space;
|
||||
;*
|
||||
;* _map_adr( addr, -1)
|
||||
;* sets user segment # from addr.
|
||||
;*
|
||||
;* _map_adr( addr, -2)
|
||||
;* transfer to context block at addr
|
||||
;*
|
||||
;* system call: mem_cpy
|
||||
;* rr6: source
|
||||
;* rr4: dest
|
||||
;* rr2: length (0 < length <= 64K)
|
||||
;* returns
|
||||
;* registers unchanged
|
||||
;*
|
||||
;* system call: map_adr
|
||||
;* rr6: logical addr
|
||||
;* r5: space code
|
||||
;* r4: ignored
|
||||
;* rr2: 0
|
||||
;* returns
|
||||
;* rr6: physical addr
|
||||
;*
|
||||
;* space codes:
|
||||
;* 0: caller data
|
||||
;* 1: caller program
|
||||
;* 2: system data
|
||||
;* 3: system program
|
||||
;* 4: TPA data
|
||||
;* 5: TPA program
|
||||
;*
|
||||
;* x+256 return segmented instruction address,
|
||||
;* not data access address
|
||||
;*
|
||||
;* FFFF set user-space segment from address
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_mem_cpy: ;copy memory C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ldl rr4,ARG3(r15)
|
||||
ldl rr2,ARG5(r15)
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
_map_adr: ;map address C subroutine
|
||||
|
||||
;===
|
||||
ldl rr6,ARG1(r15)
|
||||
ld r5, ARG3(r15)
|
||||
subl rr2,rr2 ; 0 length says map
|
||||
sc #MEM_SC
|
||||
ret
|
||||
|
||||
|
||||
;****************************************************
|
||||
;*
|
||||
;* long _bios(code, p1, p2)
|
||||
;* long _bdos(code, p1)
|
||||
;* int code;
|
||||
;* long p1, p2;
|
||||
;*
|
||||
;* BIOS, BDOS access
|
||||
;*
|
||||
;****************************************************
|
||||
|
||||
|
||||
_bios:
|
||||
ld r3,ARG1(r15)
|
||||
ldl rr4,ARG2(r15)
|
||||
ldl rr6,ARG4(r15)
|
||||
sc #BIOS_SC
|
||||
ret
|
||||
|
||||
_bdos:
|
||||
ld r5,ARG1(r15)
|
||||
ldl rr6,ARG2(r15)
|
||||
sc #BDOS_SC
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
main()
|
||||
{ float x,y,z;
|
||||
|
||||
x = 1.0;
|
||||
y = 2.0;
|
||||
z = x * y;
|
||||
|
||||
printf ("%0lx\n", *((int *)&z));
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
;****************************************************
|
||||
;*
|
||||
;* 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
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,272 @@
|
||||
/* This module is a collection of all the Z8000 */
|
||||
/* dependent C code for the P-CP/M dual processor */
|
||||
/* BIOS. */
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Author: David Heintz *
|
||||
* Module: Zoom8kc.c *
|
||||
* Creation Date: 10/26/82 *
|
||||
* Language: Standard C *
|
||||
* Version: 1.0 *
|
||||
* Last Mod: 11/26/82 *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* STANDARD HEADERS *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
#include "unstdsys.h"
|
||||
#include "zooequ.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 Zoom side */
|
||||
WORD fioctl = 0x0003; /* only. */
|
||||
|
||||
/*
|
||||
*************************************************
|
||||
* *
|
||||
* Memory Region Table *
|
||||
* *
|
||||
*************************************************
|
||||
*/
|
||||
|
||||
/* The following table describes two memory regions: */
|
||||
/* Region 1 Type: Separated instruction and data space */
|
||||
/* Length: 64k I space, 64k D space, 128k total. */
|
||||
/* Base: <<42>> */
|
||||
/* */
|
||||
/* Region 2 Type: Merged instruction and data space */
|
||||
/* Length: 64k combined space. */
|
||||
/* Base: <<1>> */
|
||||
/* */
|
||||
/* Notes This table is machine dependent (ZOOM board), */
|
||||
/* 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,
|
||||
{{0x42000000L, 0x1ffffL},
|
||||
{0x01000000L, 0x0ffffL}
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
/* ******** This is a kludge table for use with ****** */
|
||||
/* ******** flaky zoom board hardware. ****** */
|
||||
|
||||
struct mrt {
|
||||
int count;
|
||||
struct {long tpalow;
|
||||
long tpalen;
|
||||
} regions[2];
|
||||
} memtab = {2,
|
||||
{{0x42000000L, 0x1ffffL},
|
||||
{0x02000000L, 0x0ffffL}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
*****************************************
|
||||
* *
|
||||
* 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 Modul;
|
||||
A!2,/****************************************************************************/
|
||||
/* */
|
||||
/* B A S E P A G E . H */
|
||||
/* ------------------- */
|
||||
/* */
|
||||
/* This file contains a definition of the CP/M basepage structure, */
|
||||
/* b_page. */
|
||||
/* */
|
||||
/* NOTE: In the portable CP/M environment, it is NOT guaranteed */
|
||||
/* that the location of the base page is known at link-edit time */
|
||||
/* (as it is, for example, in CP/M-80 and CP/M-86.) Instead, a */
|
||||
/* pointer to the current basepage is delivered by the BDOS */
|
||||
/* to each new program which is run. This pointer, _base, is */
|
||||
/* initialized by the C startup function (startup.s) and is */
|
||||
/* available to C programs as an external. */
|
||||
/* */
|
||||
/* This file has been modified to live with the BDOS definitions. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
struct b_page
|
||||
{
|
||||
XADDR ltpa; /* Low TPA address */
|
||||
XADDR htpa; /* High TPA address */
|
||||
XADDR lcode; /* Start address of code seg*/
|
||||
long codelen; /* Code segment length */
|
||||
XADDR ldata; /* Start address of data seg*/
|
||||
long datalen; /* Data segment length */
|
||||
XADDR lbss; /* Start address of bss seg */
|
||||
long bsslen; /* Bss segment length */
|
||||
long freelen; /* Free segment length */
|
||||
char resvd1[20]; /* Reserved area */
|
||||
struct fcb fcb2; /* Second basepage FCB */
|
||||
struct fcb fcb1; /* First basepage FCB */
|
||||
char buff[128]; /* Default DMA buffer, */
|
||||
/* command line tail */
|
||||
};
|
||||
Reference in New Issue
Block a user