BIOS C  BIOS C  !BIOS C "#BIOS REL$s.c */ /*This conditionally compiles bios.c leaving unrequired code out of the object*/ /*file. */ /*----------FPE O ^FPEDEP O LBIOSASM8KN LDRBDOS REL1M20 (Z8000) |*/ /*| |*/ /*| Copyright 1984, Digital Research Inc. |*/ /*| |*/ /*+------------------BIOS SUB%BIOSASM 8KN &'BIOSBOOT8KN"()*+,BIOSDEFS8KN-./0------------------------------------------------------------------*/ /* The normal bios compile command for cpm.sys is: zcc -c MAKELDR SUBMKPUTBT SUBPUTBOOT C 2README ---------------------------------------------------+*/ /*======================================================================BIOSIF 8KN1234BIOSIO 8KN567BIOSMEM 8KN#89:;<BIOSTRAP8KN>=>?@ABCD-M1 bios.c */ /* This will provide the full functionallity of the bios in the object file */ /*----------------------SYSCALL 8KNTRK O =*/ /*-------------------------*/ /* Compilation information */ /*-------------------------*/ /*--------------------------CPMLDR RELbEFGHIJKLMNOPQCPMSYS RELRSTUVWXYZ[\]^_`aCPMSYS RELbcdefghijklmnopqCPMSYS RELr#ifdef loader #define LOADER 1 #endif /*=======================================================================*/ /*+------------------------------------------------------------*/ /* By compiling bios.c with the command : zcc -c -M1 -dTRANSFER bios.c --------------------------------------------------*/ /*To compile bios.c for cpmldr.sys the command is: zcc -c -M1 -dLOADER bioCPMSYS SUBsCPMSYS2 RELtuvwxyz{|}~CPMSYS2 RELCPMSYS2 REL--------------------------------------------------------------+*/ /*| |*/ /*| CP/M-8000(tm) BIOS for the OLIVETTI */ /* You are provided with a bios object that allows the two floppy drives to */ /* have two different formats. ThisZlotnick (Zilog) -- Added escape character to keyboard ** map, as ctrl'['. ** ** 831205 K. Greenberg (Zilog) -- Fixed disk of iobyte ** upon each warmboot. Changed seldisk to test for ** overflow of the dphtab (to fix the "dir d:" bug). ** *r is an Intel 8259 left-shifted one bit */ /* to allow for the word-alligned interrupt vectors of the Z8000. */ /* === I am ompile*/ /* code setting the tty port to 1200 baud listening */ /* XOFF on that port. */ /* #define DEBUG *************************************************/ /* */ /* I/O Device Definitions */ /* */ /**** is left purely as an example for the */ /* the benefit of porting to a different format and can be modified. */ /*parameter table for hard ** drive C to point to dpb3, not dpb2 (80 trk floppy). ** ** 831212 K. Greenberg (Zilog) -- Modifi* 830804 F. Zlotnick (Zilog) -- Added conditional compilation for ** loader BIOS, which only needs a few of the BIOS ** fugoing to assume that this is set up in the PROM === */ /*******************************************************************1 */ /* By decommenting this define hard disk debugging */ /* is enabled. This provides drive, block, and */ /* tra********************************************************************/ /*******************************************************----------------------------------------------------------------------------*/ /* By compiling bios.c with the command: zcc -c ed disk parameter tables for ** hard disk to look more like floppies (fewer sectors ** but more tracks). This will fix thenctions. The loader DOES require the definition ** of a context structure, for transfer of control to ** the system prope*****/ /* Define the two USART ports */ /************************************************************************/ ck information to be printed on the console. */ char copyright[] = "Copyright 1984 Digital Research Inc."; /* HISTORY *******************/ /************************************************************************/ /* Define Interrupt Cont-M1 -dsect26 bios.c */ /* 8" floppy disk support is provided by conditional compilation. */ /*-------------------- sector deblocking ** part of the bios to be compatible with both. Also ** switched to 4K allocation blocks and 512 direntr. ** ** 830804 F. Zlotnick (Zilog) -- Changed Disk Parameter Blocks to ** reflect new bootstrap method. ** ** 830809 F. /* The USARTs are Intel 8251's */ #define KBD 0xA1 /* Keyboard USART base */ #define RS232 0xC1 /* RS-232 terminal */ ** 820803 S. Savitzky (Zilog) -- derived from 68000 EXORMACS bios ** ** 830614 F. Zlotnick (Zilog) -- removed initializationroller constants */ /************************************************************************/ /* The interrupt controlle--------------------------------------------------------*/ #define BAUD 0 /* Setting this define to 1 will conditionally cries. */ /************************************************************************/ /*********************** #define SERDATA 0 /* data port offset */ #define SERCTRL 2 /* control port offset */ #define SERSTAT 2 /* status port , /* 4800 */ 8, /* 9600 */ 4, /* 19200 */ 2 /* 38400 */ }; #endif /* End Conditional */ nter/timer control port */ #define CT0CTL 0x36 /* c/t 0 control byte */ #define CT1CTL 0x76 /* c/t 1 control byte */ sses and Related Constants */ /************************************************************************/ /* SEE BIOSIO.8KN */ #define XOFF 0x13 /* Control- S */ /************************************************************************/ /* (fault bit) needs to be high */ /************************************************************************/ /***************offset */ #define SERINIT 0x37 /* init (3 times) */ #define SERRES 0x40 /* reset */ #define SERMODE 0xEE /* mode (2 /************************************************************************/ /* Define Parallel Port constants */ /******** #define CT2CTL 0xB4 /* c/t 2 control byte */ /* control byte is followed by LSB, then MSB of count to data register */ /FOR THESE EXTERNALS */ extern int disk_io(); /* (char drive, cmd -- disk I/O */ /* int blk_count, */ /* int Define the counter/timer ports */ /************************************************************************/ /* The*********************************************************/ /* */ /* PROM AND HARDWARE INTERFACE */ /* */ stop, even parity */ /* parity disable, 8 bits */ /* divide by 16 */ /* DUBIOUS. 15?? */ #define TTYON 0x37****************************************************************/ /* The parallel (printer) port is an Intel 8255 */ #defi* baud rate table follows: */ #ifndef LOADER /* NOT needed by the Loader Bios */ int baudRates[10] = { 1538, /* blk_num, */ /* char *dest) -> int error? */ extern crt_put(); /* (char character) -- put byte to CRT */ extern counter-timer is an Intel 8253 */ #define CT_232 0x121 /* counter/timer 0 -- RS232 baud rate */ #define CT_KBD 0x123 /* c /************************************************************************/ /************************************************* /* cmd (no hunt, no reset, */ /* RTS=0, error reset, */ /* no break, rcv enable, */ /* DTR=0, xmt enable */ #ne PAR_A 0x81 /* port A data */ #define PAR_B 0x83 /* port B data */ #define PAR_C 0x85 /* port C data */ #define PARCT 50 */ 699, /* 110 */ 256, /* 300 */ 128, /* 600 */ 64, /* 1200 */ 32, /* 2400 */ 16cold_boot(); /* boot operating system */ #define DSKREAD 0 /* disk read command */ #define DSKWRITE 1 /* disk write commaounter/timer 1 -- kbd baud rate */ #define CT_RTC 0x125 /* counter/timer 2 -- NVI (rt clock) */ #define CT_CTRL 0x127 /* cou***********************/ /************************************************************************/ /* Define PROM I/O Addredefine SERRRDY 0x02 /* RCV ready bit mask */ #define SERXRDY 0x01 /* XMT ready bit mask */ #define XON 0x11 /* Control- QRL 0x87 /* control port */ #define PARBSY 0x02 /* bit one (busy bit) needs to be low */ #define PARFLT 0x10 /* bit fivend */ #define DSKFMT 2 /* disk format command */ #define DSKVFY 3 /* disk verify command */ #define DSKINIT 4 /* disk initNOT needed for the Loader Bios */ struct mrt { int count; struct {long tpalow; long tpalen; } regions[5];*******************************************************************/ /* System Entry and Stack Pointer */ /***************#endif /* End conditional */ /************************************************************************/ /* Set Exception *****************************************************************/ /* SEE SYSCALL.8KN FOR THESE EXTERNALS */ extern mem_c0C000L, /* system space: merged I and D */ }; struct context /* Startup context for user's program */ { short r. command */ /************************************************************************/ /* Define external I/O routines an } memtab = {5, 0x0A000000L, 0x10000L, /* merged I and D */ 0x08000000L, 0x10000L, /* separated I */ *********************************************************/ #define SYSENTRY 0x0b000006L /* entry point */ #define SYSSTKPTR Vector entry */ /************************************************************************/ extern long trapvec[]; /* py(); /* (src, dest, len: long)-- copy data */ extern long map_adr(); /* paddr = (laddr: long; space: int) */ #define CDATegs[14]; long segstkptr; short ignore; short FCW; long PC; }; struct context context = { /* Regs 0-13 cleard addresses */ /************************************************************************/ /* SEE BIOSIF.8KN FOR THESE EXTE 0x08000000L, 0x10000L, /* and D */ 0x0B000000L, 0x10000L, /* accessing I as D */ 0x09000000L, 0x100000x0b00bffeL /* system's stack pointer start */ /************************************************************************/ /*trap vector */ long setxvect(vnum, vval) int vnum; long vval; { register long oldval; oldval = trapvec[vnum]; trA 0 /* caller data space */ #define CCODE 1 /* caller code space */ #define SDATA 2 /* system data space */ #define SCOed, sp set up below */ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, SYSSTKPTR, /* Loaded system's stack pointer */ 0, /RNALS */ extern output(); /* (port, data: int) -- output */ extern int input(); /* (port: int) -- input */ /********L /* ddt debugger sits here */ }; #endif /* End conditional */ #ifdef LOADER /* NEEDED fr the Loader Bios */ stru Memory Region Table */ /************************************************************************/ #ifndef LOADER /* apvec[vnum] = vval; return(oldval); } /********************************************DE 3 /* system code space */ #define NDATA 4 /* normal data space */ #define NCODE 5 /* normal code space */ /****** Ignore: value is zero */ 0xD800, /* FCW: segmented system, VI, NVI set */ SYSENTRY /* Entry point to system */ }; ****************************************************************/ /* Define external memory management routines */ /*******ct mrt { int count; struct {long tpalow; long tpalen; } regions[1]; } memtab = {1, 0x0B000000L, 0x****************************/ /************************************************************************/ /* */ /* /* Conditional for 1200 baud and XOFF */ while ( ((input(port + SERSTAT) & SERXRDY) != SERXRDY) | ((((input(port + SERDATet for 1200 baud */ #else /* === assume the PROM sets it up. === */ #endif /* End conditional */ } int s***************************************************/ #ifndef LOADER /* NOT needed for the Loader Bios */ char kbtran[256ffer at an opportune moment. */ extern int tbdirty; serinit(port) int port; { output(port+SERCTRL, SERINIT); check for */ {printstr ("\n\rPrinter Timeout.\n\r"); /* printer ready a */ return; /* finite number of */ } CHARACTER I/O */ /* */ /************************************************************************/ /*************A)) & 0x7F) ^ XOFF) == 0)); output(port + SERDATA, ch); #else while ( (input(port + SERSTAT) & SERXRDY) != SERXRDYerirdy(port) int port; { return(((input(port+SERSTAT) & SERRRDY) == SERRRDY) ? 0xFF : 0); } char serin(port) ] = { /* Raw key codes for main keypad: RE \ A B C D E F G H I J K L M N output(port+SERCTRL, SERINIT); output(port+SERCTRL, SERINIT); output(port+SERCTRL, SERRES); output( /* times */ } while (!parordy(PAR_B)); /* if printer ready */ output (port, ch); /* print character */ ***********************************************************/ /***************************************************************) ; output(port+SERDATA, ch); #endif /* End conditional */ } parordy(port) int port; { int status; int port; { while (serirdy(port) == 0) ; return input(port+SERDATA); } int serordy(port) int port; O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 - ^ @ [ port+SERCTRL, SERMODE); output(port+SERCTRL, TTYON); #if BAUD /* Conditional for 1200 baud */ output(CT_CTRL,CT0CTL); output (PARCTRL, 0x0A); /* set strobe low */ output (PARCTRL, 0x0B); /* set strobe high */ } /*************************/ /* Generic Serial Port I/O Procedures */ /***************************************************************** status = (input(port)); return (((status & PARBSY) != PARBSY) && ((status & PARFLT) == PARFLT) ? 0xFF : 0); } parout { return(((input(port+SERSTAT) & SERXRDY) == SERXRDY) ? 0xFF : 0); } serout(port, ch) int port; char ch; { #if BAUD ; : ] , . / */ /* main keyboard UNSHIFTED. */ 0xDD,'\\', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j /* Set baud rate genrator */ output(CT_232,baudRates[4]); /* Modify for different speeds */ output(CT_232,0); /* S********************************************************/ /* Olivetti keyboard translation table. */ /****************************/ /* define as extern the dirty flag, which is actually defined later */ /* on in this file. Used to flush the bu(port, ch) int port; char ch; { register int i, status; i = 0; do { if (--i == 0) /* only ', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', ' 0xB4,0xB5,0xB6,0x1B, 0xB8,0xB9,0xBA,0xBB, 0xBC,0xBD,0xBE,0xBF, /* special -- substitute \r for Olivetti's 0xAF. 4 5 6 7 8 9 + - * / */ /* other keys UNSHIFTED -- CR differs from Olivetti */ 'return (parordy (PAR_B)); } lptwr(ch) /* ARGSUSED */ char ch; { parout (PAR_A, ch); } /*****************************x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0xE0,0xE1,0xE2,0xE3, 0xE4,0xE5,0xD6,0xE7,0xE8,0xE9,0xEA,0xEB,0x00,0x1B,0x1E,0x1F,0x1D,0xtional */ #ifdef LOADER /* Conditional for Loader Bios disable KBD */ #define crtrd nulrd #endif /* End conditional */8', '9', '-', '^', '@', '[', ';', ':', ']', ',', '.', '/', /* main keyboard SHIFTED */ 0xDE, '|', 'A', 'B', 'C', 'D', 'E',*/ '\r','\r','\r','\r' }; #endif /* End conditional */ /******************************************************** ','\r',0x7f,0x08, '.', '0',0xA6, '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '*', '/', /* oth*******************************************/ /* generic device names, batch, and null devices */ /**************************FE,0xFF,0xA4, /* main keyboard COMMAND */ 0xDF,0xF8,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D, int crtws() { return(0xFF); } #define crtwr crt_put /* output routine in PROM */ /* TTY status, read, write rou 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_', '!', '"', '#', ****************/ /* specific I/O procedures for use with iobyte */ /**********************************************er keys SHIFTED -- CR differs from Olivetti */ ' ','\r',0xA8,0xA9, '.', '0',0xA6,0x1C, 0x9A,0x1D,0x9B,0x9C, **********************************************/ /* the device names are the offset of the proper field in iobyte */ #defin 0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xEC,0xED,0xEE,0xEF, 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0x13tines */ int ttyrs() { return(serirdy(RS232)); } char ttyrd() { return(serin(RS232)); } int ttyws() { return '$', '%', '&','\'', '(', ')', '=', '~', '`', '{', '+', '*', '}', '<', '>', '?', /* main keyboard CONTROL -- CTL B and C dif**************************/ /* CRT status, read, write routines */ int crtrs() { return( serirdy(KBD)); } #ifndef L 0x9D,0x1E,0x9E,0x1F, 0x2B,0x2D,0x2A,0x2F, /* other keys CONTROL */ ' ','\r',0xA8,0xA9, 0xB0,0xB1,0xB2,0xB3, e CON 0 #define READER 2 #define PUNCH 4 #define LIST 6 /* BATCH status, read, write routines */ #ifndef LOADER,0x1C,0xFC,0xFD,0x9F,0xF9,0xFA,0xA5, /* other keys SP CR S1 S2 KEYPAD . 0 00 1 2 3 (serordy(RS232)); } ttywr(ch) char ch; { serout(RS232, ch); } /* LPT status, output routines */ int lptws() { fer from Olivetti. */ 0xA0,0x7F,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, 0x0F,0x10,0x11,0x12,0OADER /* NOT needed for the Loader Bios */ char crtrd() { return( kbtran[serin(KBD) & 0xff]); } #endif /* End condi /* NOT needed by the Loader Bios */ int batrs() { int genstat(); return genstat(READER); } char batrd() { int (*sttbl[DEVINDEX])() ); } int genread(dev) int dev; { return( (*rdtbl[DEVINDEX])() ); } genwrite(dev, ch) int dev;lst, nulst, /* reader */ ttyws, nulst, nulst, nulst, /* punch */ ttyws, crtws, lptws, nulst /* list */ }; char (*rd***/ /* */ /* DISK I/O */ /* */ /********************************************************************/ /* Generic I/O routines using iobyte */ /************************************************************************/ }; } #ifdef DEBUG /* Conditional for Disk Debugging Hex output */ puthexd(i) /* put a hex digit to crt */ int i; { genread(); return genread(READER); } batwr(ch) char ch; { genwrite(LIST, ch); } #endif /* End Conditional */ char ch; { (*wrtbl[DEVINDEX])(ch); } /************************************************************************/ tbl[16])() = { ttyrd, crtrd, batrd, nulrd, ttyrd, nulrd, nulrd, nulrd, nulrd, nulrd, nulrd, nulrd, nulrd, nulrd, nulrd, *******/ /************************************************************************/ /*************************************/* ** IObyte itself. */ char iobyte = 0x41;; /* ** Device operation tables. DEVINDEX is the index into the ** table ai &= 0xf; if (i < 10) crtwr(i + '0'); else crtwr(i + 'a' - 10); } puthexv(i) /* put an int in hex */ int i; { #ifdef LOADER /* NEEDED for the Loader Bios */ #define batrd nulrd #define batrs nulst #define batwr nulwr #endif //* Error procedure for BIOS */ /************************************************************************/ bioserr(enulrd }; int (*wrtbl[16])() = { ttywr, crtwr, batwr, nulwr, nulwr, nulwr, nulwr, nulwr, ttywr, nulwr, nulwr, nulwr, ***********************************/ /* BIOS Table Definitions */ /*****************************************************ppropriate to a device (row) and its iobyte index (column) ** ** nonexistent devices are mapped into NUL. */ #define DEVINputhexd(i >> 12); puthexd(i >> 8); puthexd(i >> 4); puthexd(i); } #endif /* End conditional */ /****************** End conditional */ /* NULL status, read, write routines */ int nulst() { return 0xFF; } char nulrd() { return rrmsg) register char *errmsg; { printstr("\n\rBIOS ERROR -- "); printstr(errmsg); printstr(".\n\r")ttywr, crtwr, lptwr, nulwr }; /* ** the generic service routines themselves */ int genstat(dev) int dev; { return(*******************/ struct dpb { int spt; /* sectors per track */ char bsh; /* block shift = log2(blocksize/128) */DEX (((iobyte>>dev) & 3) + (dev * 2) ) int (*sttbl[16])() = { ttyrs, crtrs, batrs, nulst, /* con */ ttyrs, nulst, nu*******************************************************/ /*********************************************************************0xFF; } nulwr(ch) /* ARGSUSED */ char ch; { } /*********************************************************************; while(1); } printstr(s) /* used by bioserr */ register char *s; { while (*s) {crtwr(*s); s += 1; char blm; /* block mask = 2**bsh - 1 */ char exm; /* extent mask */ char dpbjunk; /* dummy field to allign words / #define MAXDSK 3 /* max. number of disks */ #endif /* End conditional */ #ifdef TRANSFER /* Tranfer Conditional needss disks. This BIOS buffers ** a track at a time, so sector address translation is not needed. ** ** Sample tables are includ bls = 2K dsm = (disk size - 3 reserved tracks) / bls */ /* bls = 4K for hard disk (8640 - 24) / 4 */ #ifdef SECT2rectory buffer (128 bytes) */ struct dpb *dpbp; /* -> disk parameter block */ char *csvp; /* -> software check vector (cks16, 3}; struct dpb dpb2= /* --- 2 side, 16*256 sector, 80 track. 640kb --- */ { 32, 4, 15, 0, 0, 314, 63, 0xC0, */ int dsm; /* size of disk less offset, in blocks */ int drm; /* size of directory - 1 */ char al0; /* reservation bi an extra dpb define*/ #define MAXDSK 4 /* Disk 4 is a pseudonym for disk 2, with */ #endif /* an old-style dpb to rescue ed for several different disk sizes. */ /* === Olivetti has 3 floppy formats & a hard disk === */ #define SECSZ 128 /* CP6 /* Conditional for 8" floppy drives */ /* === The Olivetti does not have 26-sector disks, but many people do. ** The bytes) */ char *alvp; /* -> alloc vector ((dsm/8)+1 bytes) */ }; /************************************************ 0, 16, 3}; struct dpb dpb3= /* --- 6 side, 32*256 sector, 180 trk. 8640kb --- */ { 32, 5, 31, 1, 0, 2154, 511,ts for directory */ char al1; /* ... */ int cks; /* size of checksum vector = (drm+1)/4 */ int off; /* track offsetthose files. */ /* End conditional */ /***** spt, bsh, blm, exm, jnk, dsm, drm, al0, al1, cks, off, psh, psm */ s/M logical sector size */ #define TRKSZ 32 /* track size for floppies, 1/2 track sz for hd */ #define PSECSZ 256 /* Olivettfollowing parameter blocks are provided for their use. */ struct dpb dpbS= /* --- 1 side, 26*128 sector, 77 trk --- */ { 2************************/ /* Disk Parameter Blocks */ /****************************************************************** 0xf0, 0, 0, 3}; #ifdef TRANSFER /* Conditional Tranfer dpb defined here */ struct dpb dpb4= /* --- 2 side, 16*256 sect for OS boot */ char psh; /* log2(sectorsize/128) */ char psm; /* physical size mask = 2**psh - 1 */ }; struct truct dpb dpb0= /* --- 1 side, 16*256 sector, 35 track. 140kb --- */ { 32, 4, 15, 1, 0, 64, 63, 0xC0, 0, 16, i physical sector size */ #define PTRKSZ 16 /* physical track size */ #ifndef TRANSFER /* Conditional for Normal bios *6, 3, 7, 0, 0, 242, 63, 0xC0, 0, 16, 2}; struct dpb dpbD= /* --- 1 side, 26*256 sector, 77 trk --- */ { 52, ******/ /* ** CP/M assumes that disks are made of 128-byte logical sectors. ** ** The Olivetti uses 256-byte sectors on itor, 35 track. 280kb --- */ { 32, 4, 15, 1, 0, 120, 63, 0xC0, 0, 16, 10}; #endif /* End conditional */ /* dph { char *xltp; /* -> sector translation table */ int dphscr[3]; /* scratchpad for BDOS */ char *dirbufp; /* -> di3}; struct dpb dpb1= /* --- 2 side, 16*256 sector, 35 track. 280kb --- */ { 32, 4, 15, 1, 0, 134, 63, 0xC0, 0, 4, 15, 0, 0, 242, 63, 0xC0, 0, 16, 2}; #endif /* End conditional */ /******************************************************************************/ #ifndef TRANSFER /* Normal bios dph conditional */ struct dph dphtab[3] = { {xl14, 20, 26, 6, 12, 18, 24, 4, 10, 16, 22 }; #endif /* End conditional */ char xlt16[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0; /* track buffer dirty */ int tbtrk; /* track buffer track # */ int tbdsk; /* track buffer disk # */ int dskerr; /** End conditional */ /************************************************************************/ /* Sector Translate Tab0, 0, 0}, dirbuf, &dpb4, csv3, alv3}, /*dsk d*/ }; #endif /* End conditional */ /***********************************************************************/ /* BDOS Scratchpad Areas */ /*******************************************************t16, {0, 0, 0}, dirbuf, &dpb1, csv0, alv0}, /*dsk a*/ {xlt16, {0, 0, 0}, dirbuf, &dpb1, csv1, alv1}, /*dsk b*/ {xl10,11,12,13,14,15,16, 17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; /***************************************** disk error */ /************************************************************************/ /* Disk I/O Procedures */le */ /************************************************************************/ #ifdef SECT26 /* Conditional for************************************/ /* Currently Selected Disk Stuff */ /****************************************************************/ char dirbuf[SECSZ]; char csv0[16]; char csv1[16]; char csv2[32]; #ifdef TRANSFER /* For Transfer t16, {0, 0, 0}, dirbuf, &dpb3, csv2, alv2}, /*dsk c*/ }; #endif /* End conditional */ #ifdef TRANSFER /* Trnafer con*******************************/ /* Disk Parameter Headers */ /* */ /* Three disks are defined: dsk a: diskno=0, /************************************************************************/ dskxfer(dsk, trk, bufp, cmd) /* transfer a d 8" floppy drives */ /* === The Olivetti does not have 26-sector disks, but many people do. ** The following translate t*************************/ int settrk, setsec, setdsk; /* track, sector, disk # */ long setdma; /* dma address with segmeconditional */ char csv3[16]; #endif /* End conditional */ char alv0[32]; /* (dsm0 / 8) + 1 */ char alv1[32]; /* (dsm1ditional with extra dph */ struct dph dphtab[4] = { {xlt16, {0, 0, 0}, dirbuf, &dpb1, csv0, alv0}, /*dsk a*/ {xlt16, { drive 0 */ /* dsk b: diskno=1, drive 1 */ /* dsk c: diskno=2, drive 10 */ /*******************************isk track */ register int dsk, trk, cmd; register char *bufp; /* This is a handy place to keep notes on Olivetti blocable is provided for their use. */ char xlt26[26] = { 1, 7, 13, 19, 25, 5, 11, 17, 23, 3, 9, 15, 21, 2, 8, nt info: long */ char trkbuf[TRKSZ * SECSZ]; /* track buffer */ int tbvalid = 0; /* track buffer valid */ int tbdirty = / 8) + 1 */ char alv2[2002]; /* (dsm2 / 8) + 1 */ #ifdef TRANSFER /* For Transfer conditional */ char alv3[32]; #endif /0, 0, 0}, dirbuf, &dpb1, csv1, alv1}, /*dsk b*/ {xlt16, {0, 0, 0}, dirbuf, &dpb3, csv2, alv2}, /*dsk c*/ {xlt16, {k numbering. For a floppy, bits 3-0 are sector, bit 4 is side, and high-order bits are track. We define a floppy to have t) || (tbdsk != setdsk)) #define gettrk if (wrongtk) filltb() #ifndef LOADER /* NOT needed for Loader Bios */ flush() {rror */ /* do transfer */ #ifdef DEBUG /* Conditional DEBUG output */ blknum = trk*PTRKSZ; printstr("\nx */ char sectran(s, xp) int s; char *xp; { if (xp != 0) return xp[s]; else return s; } struct dph *seldisk(dsk, l will overflow into the real high-order bit of the sector number. This works because we will always move half a track at a tes. setdma is physical address */ mem_cpy(map_adr((long)p, CDATA), setdma, (long)SECSZ); return(dskerr); } #ifndef wice as many sectors as there are on a track; thus, the sector number overflows to the side bit and all is well. On the hard if ( tbdirty && tbvalid ) dskxfer(tbdsk, tbtrk, trkbuf, DSKWRITE); tbdirty = 0; } #endif /* End conditionafer block "); puthexv(blknum); printstr(" unit "); puthexd(dsk); printstr(" track "); puthexv(trk); if (cmd == DSKREogged) register char dsk; char logged; { register struct dph *dphp; if (dsk > MAXDSK) return(0L); setdsk = dsk; ime. The tracks and surfaces simply take care of themselves, incrementing through the surfaces and effectively minimizing seLOADER /* NOT needed by Loader Bios it doesn't write */ dskwrite(mode) char mode; { register char *p; gettrk; p disk, bits 4-0 are sector (there are 32 per track), and the high-order bits are (track*6)+surface, where surface is in the l */ filltb() { #ifndef LOADER /* NOT needed by Loader Bios */ if ( tbvalid && tbdirty ) flush(); #endif /* EndAD) printstr(" read"); else printstr(" write"); crtwr(10); crtwr(13); #endif /* End conditional */ if (0 != disk dphp = &dphtab[dsk]; if (dphp >= dphtab + (sizeof(dphtab)/sizeof(struct dph)) ) return(0L); if ( ! logged ) { /* ===eks. */ { int blknum; if (dsk==2) dsk = 10; /* convert hard disk drive # */ #ifdef TRANSFER /* Conditional reasign= &trkbuf[SECSZ * (setsec-1)]; /* transfer between memory spaces. setdma is physical address */ mem_cpy(setdma, map_adrrange 0..5. To make the indexing of trkbuf consistent, we define a hard disk to have only 32 logical (16 physical) sectors p conditional */ dskxfer(setdsk, settrk, trkbuf, DSKREAD); tbvalid = 1; tbdirty = 0; tbtrk = settrk; tbdsk = setdsk_io(dsk, cmd, PTRKSZ, trk*PTRKSZ, map_adr((long)bufp,0))) dskerr=1; } #define wrongtk ((! tbvalid) || (tbtrk != settrk disk not logged in. select density, etc. === */ } return(dphp); } /********ment for Transfer */ if(dsk==3) dsk = 1; /* for transfer disks */ #endif /* End conditional */ dskerr=0; /* assume no e((long) p, CDATA), (long)SECSZ); tbdirty = 1; if ( mode == 1 ) flush(); return(dskerr); } #endif /* End conditionaler track, like a floppy. Thus we will transfer only half a track to/from the buffer at a time, and the logical sector number; } dskread() { register char *p; gettrk; p = &trkbuf[SECSZ * (setsec-1)]; /* transfer between memory spac****************************************************************/ /************************************************************r)d1); break; case 6: /* PUNCH */ genwrite(PUNCH, (char)d1); break; case 7: /* READER */ retur long d1, d2; { switch(d0) { case 0: /* INIT */ biosinit(); break; #ifndef LOADER /* Normal Bios uselush(); return((long)dskerr); break; #endif /* End conditional */ case 22: /* SETXVECT */ return(setxvec */ tbvalid = 0; /* init disk flags */ tbdirty = 0; /* Following reset of iobyte on each warm boot has been */ /* WRITE */ return(dskwrite((char)d1)); break; case 15: /* LISTST */ return(genstat(LIST)); break; #************/ /* */ /* BIOS PROPER */ /* */ /************************************************n(genread(READER)); break; case 8: /* HOME */ settrk = 0; break; #endif /* End conditional */ ca */ case 1: /* WBOOT */ wboot(); break; #endif /* End conditional */ case 2: /* CONST */ returnt((int)d1, d2)); break; } /* end switch */ return(0); } /* end bios procedure */ /* End of C Bio/* removed, so that STAT can reassign devices. iobyte */ /* is now initialized on cold boot only. */ /* iobyte = 0x41; */endif /* End conditional */ case 16: /* SECTRAN */ return(sectran((int)d1, (char*)d2)); break; case 18: ************************/ /************************************************************************/ biosinit() { se 9: /* SELDSK */ return((long)seldisk((char)d1, (char)d2)); break; case 10: /* SETTRK */ settrk = (int)(genstat(CON)); break; case 3: /* CONIN */ return(genread(CON)); break; case 4: /* CONOUT */ gs */  /* con, list = CRT; rdr, punch = TTY */ } /* In the LOADER bios, the main routine is called "bios", not "_bios" */ #ifdef /* GMRTA */ return((long)&memtab); break; #ifndef LOADER /* Normal Bios use */ case 19: /* GETIOB */ ret #ifdef DEBUG /* Conditional banner for DEBUG */ printstr("\r\nCP/M-8000: Olivetti M20 BIOS DEBUG"); #endif /* End condid1; break; case 11: /* SETSEC */ setsec = (int)d1; break; case 12: /* SETDMA */ setdma = d1; benwrite(CON, (char)d1); break; #ifndef LOADER /* Normal Bios use */ case 5: /* LIST */ genwrite(LIST, (cha */  LOADER /* Loader Bios conditional */ #define _bios bios #endif /* End conditional */ long _bios(d0, d1, d2) int d0;urn((long)iobyte); break; case 20: /* SETIOB */ iobyte = (char)d1; break; case 21: /* FLUSH */ ftional */ /* serinit(KBD);*/ /* DON'T init keyboard serial port */ serinit(RS232); /* init rs232 serial port reak; case 13: /* READ */ return(dskread()); break; #ifndef LOADER /* Normal Bios use */ case 14: rel biosasm.o bios.o fpedep.o fpe.o pip c:bios.rel[g5]=bios.rel ******************************************** ;* ;* Data ;* ;**************************************************** __bss: .;********************************************* ;Build the assembly modules using conditionals ; __text: .sect ; ;by setting; build a bios with floating point emulation NOTE biosboot.o is loaded 1st zcc -c -M1 bios.c asz8k -o biosasm.o biosasm.8kn asect _sysseg: .block 2 ;system segment _usrseg: .block 2 ;user segment _sysstk: .block 4 ;system stack pointer _psap: .bl the value of the label LOADER false ;(0) the normal Bios code will be generated ;while setting the label to true (1) will sz8k -o fpedep.o fpedep.8kn asz8k -o fpe.o fpe.8kn ld8k -w -o bios.rel -r biosasm.o bios.o fpedep.o fpe.o ar8k qv bios.a biosock 4 ;program status area ptr ;**************************************************** ;* ;* Trap vector table ;* ;* entr ;provide the loader Bios code. ; LOADER .equ 0 ; 1 or 0 which ever ; ; .input "biosdefs.8kn" .input "biosboot.8kn" .rel biosasm.o bios.o fpedep.o fpe.o pip c:bios.rel[g5]=bios.rel ies 0..31 are misc. system traps ;* entries 32..47 are system calls 0..15 ;* ;*********************************************** .input "biosif.8kn" .input "biosio.8kn" .input "biosmem.8kn" .input "biostrap.8kn" .input "syscall.8kn" ;************* _trapvec: .block NTRAPS*4 ;**************************************************** ;******************************oint is ;* called "bios", is passed a valid stack ;* and PSA pointer. ;* ;* Although this code runs segmented, it must ;* g) -- adapt for nonseg. ;* 820930 S. Savitzky (Zilog) -- created ;* 840813 R. Weiser (DRI) -- conditional assembly ;* ;*************************** ;**************************************************** ;* ;* Globals ;* ;**********************per. ;* ;* The first sector on track 1 is the PCOS file ;* descriptor block; the second is the boot file ;* header and the s********************** ; ***** 8/15/84 R.F.W. ***** be linked with non-segmented code, so it ;* looks rather odd. ;* ;**************************************************** ;*********************************************** __text: .sect ;**************************************************** ;* ;****************************** .if LOADER .global _startld ;entry to read system tracks .endif ;*********************tart of the system code. ;* ;* This leaves something under 28K for the ;* system (BIOS+BDOS+CCP). It is assumed that ;* th********************* ; ***** 8/15/84 R.F.W. ***** **************************************************** ;* ;* CP/M - 8000 on the Olivetti M20. ;* ;* Olivetti's peculiar forma* NOTE -- THIS CODE IS HIGHLY SYSTEM-DEPENDENT ;* ;* This module contains both the bootstrap ;* writer, and the code that rec******************************* ;* ;* Externals ;* ;**************************************************** .global bios e system starts at its lowest address, ;* and that data follows immediately after code. ;* ;* For now, we assume that the syst, has a lot of ;* Olivetti's file system in it. ;* ;* Track 0 is unused except for sector 0, since ;* it is single densityeives control ;* after being booted. ;* ;* The main function of the latter is to make ;* sure that the system, whose entry p.if LOADER .else ; no warm boots in loader bios .global _wboot .endif ;***********************************************;******** biosboot.8kn for cpm.sys + cpmldr.sys***** ;* Copyright 1984, Digital Research Inc. ;* ;* 821013 S. Savitzky (Zilotem starts at ;* <<11>>0000 (hex) for normal system ;* <<10>>0000 (hex) for boot system ;* ;****************************** and thus has smaller ;* sectors. ;* ;* A total of 10 tracks are reserved from CP/M, ;* leaving 9 tracks for the system pro***** ;* ;* Constants ;* ;**************************************************** .if LOADER BOOTSYS .equ 0A000000h ;sypts out @r2,r3 ldar r2, $ ; go ld r3,#bios jp @r2 .if LOADER .else ;no warmboot in loader bios wboot:os jr wboot .endif jr entry ;* post-boot init. entry: ;SEGMENTED .if LOADER _startld: .endif DI VI,NVI;************ biosdefs.8kn ************************** ;* ;* Assembly language definitions for ;* CP/M-8000 (tm) BIOS ;* ;* ; data in sector 1 SEG4 .equ 04000000h SEG2 .equ 02000000h SYSPSA .equ SEG2+100h ; system PSA BOOTPSA .equ SEG4+100h ; Pstem address on boot BOOTSTK .equ BOOTSYS+0BFFEh ;system stack top on boot .else SYSTEM .equ 0B000000h ; system address SYS ldar r2, $ ld r3,#_wboot jp @r2 .endif  .if LOADER ldl rr14, #BOOTSTK ;init boot stack pointer .else ldl rr14, #SYSSTK ;init normat stack pointer .endif 821013 S. Savitzky (Zilog) -- created. ;* ;**************************************************** ;* ;* System Calls and TSA in PROM for boot sscall .macro ;short segmented call .word 05f00h .word ?1 .endm STK .equ SYSTEM+0BFFEh ; system stack top .endif ;rtc_ext .equ 02000022h ; real-time clock ; ext. call addr BPT .equldar r2, $ ld r3,#_wboot jp @r2 .endif  ldl rr2, #SYSPSA ; copy PROM's PSA ldctl r4, psapseg ldctl r5, psapoff ld r0, #570/2 ldir @r2, @r4, r0 ldl rr2, #SYrap Indexes ;* ;**************************************************** XFER_SC .equ 1 BIOS_SC .equ 3 BDOS_SC .equ 2 MEM_SC ;**************************************************** ;* ;* Entry Points and post-boot Initialization ;* ;***** 16 ; #blocks in a track BPS .equ 256 ; #bytes in a sector NBLKS .equ 9*16 ; #blocks in boot HDRSIZE .equ 24 ; #bytes inSPSA ; shift PSA pointer ldctl psapseg, r2 ldctl psapoff, r3 ld r2,#142h ;CROCK-- turn off ld r3,#1feh ; usart interru .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 *********************************************** ;* transfer vector .if LOADER .else ; no warm boot in the loader bi header FILSIZE .equ 256*(NBLKS-1) ; file data size SYSSIZE .equ FILSIZE-HDRSIZE ; total system size S1SIZE .equ BPS-HDRSIZE number of traps SC0TRAP .equ 32 ;trap # of system call 0 ;Z8000 traps EPUTRAP .equ 1 ;EPU (floating pt. emulator) SEler Stack Frame ;* ;**************************************************** cr0 .equ 0 ;WORD caller r0 cr1 .equ cr0+2 ;WOR******************* SEG .MACRO ; START segmented mode ; r0 destroyed. ldctl r0,FCW set r0,#15 ldctl FCW,r0 . PCSIZE .equ 2 ;PC size non-segmented INTSIZE .equ 2 ;INT data type size LONGSIZE .equ 4 ;LONG data type size ARG1 .eequ nr15+2 ;WORD SC instruction scfcw .equ scinst+2 ;WORD caller FCW scseg .equ scfcw+2 ;WORD caller PC SEG scpc .equ scsGTRAP .equ 2 ;segmentation (68K bus err) NMITRAP .equ 0 ;non-maskable int. PITRAP .equ 8 ;priviledge violation ;InterruD 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 cr4ENDM NONSEG .MACRO ; END segmented mode ; r0 destroyed. ldctl r0,FCW res r0,#15 ldctl FCW,r0 .ENDM scqu PCSIZE ;integer arguments ARG2 .equ ARG1+INTSIZE ARG3 .equ ARG2+INTSIZE ARG4 .equ ARG3+INTSIZE ARG5 .equ ARG4+INTSIZE eg+2 ;WORD caller PC OFFSET FRAMESZ .equ scpc+2 pts, etc. TRACETR .equ 9 ; trace ;**************************************************** ;* ;* C Stack frame equates ;* +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 .all .MACRO ;(segaddr) segmented CALL .word 05F00h .long ?1 .ENDM sscall .MACRO ;(|segaddr|) short segmented CAL ;**************************************************** ;* ;* Segmented Mode Operations ;* ;* NOTE: segmented indirect-reg+2 ;WORD caller PC OFFSET FRAMESZ .equ scpc+2 ;* A C stack frame consists of the PC on top, ;* followed by the arguments, leftmost argument first. ;* ;* The caller adjustsequ cr8+2 ;WORD caller r9 cr10 .equ cr9+2 ;WORD caller r10 cr11 .equ cr10+2 ;WORD caller r11 cr12 .equ cr11+2 ;WORD cL .word 05F00h .word ?1 .ENDM ;**************************************************** ;* ;* System Call Trap Handgister operations ;* can be done by addressing the low half ;* of the register pair. ;* ;********************************* the stack on return. ;* Returned value is in r7 (int) or rr6 (long) ;* ;****************************************************aller r12 cr13 .equ cr12+2 ;WORD caller r13 nr14 .equ cr13+2 ;WORD normal r14 nr15 .equ nr14+2 ;WORD normal r15 scinst .* ;**************************************************** .global bios ; initialization .if LOADER ; If Loader stub out ;* ;* Externals ;* ;**************************************************** .global _biosinit ;C portion init .if LOa return will warm boot push @r15,#_wboot .endif ; set up traps, then enable interrupts call _trapinit EI VI,NVI ******************************************** ;* ;* NOTE ;* The C portion of the BIOS is non-segmented. ;* ;* This assembly************************************************* bios: ; enter in segmented mode. ; Get system (PC) segment into r4 _wboot .else .global _wboot ; warm boot .endif .global _input ; input a byte .global _output ; output a byte ;**ADER ; If LOADER is True then .global _ldcpm ; Load the system into memory .else ; else its the normal bios .g ; set up C part of Bios call _biosinit ; Turn control over to command processor .if LOADER jp _ldcpm ; do Program l-language module is assembled ;* non-segmented, and serves as the interface. ;* ;* Segmented operations are well-isolated, an DI VI,NVI calr kludge ; get PC segment on stack kludge: popl rr4, @r14 ; get PSAP into rr2. ldctl r2, PSAPSEG ldct;********* biosif.8kn for cpm.sys + cpmldr.sys ******* ;* Copyright 1984, Digital Research Inc. ;* ;* Assembly language inte************************************************** ;* ;* Bios Initialization and Entry Point ;* ;* This is where control comlobal _flush ;Flush buffers .global ccp ;Command Processor .endif ; end conditional .global _trapinit ;trap staoad .else jp ccp ;***************************************************** ;* ;* Warm Boot ;* ;* flush buffers and inid ;* are either the same as their non-segmented ;* counterparts, or constructed using macros. ;* The resulting code looks a ll r3, PSAPOFF ; go non-segmented. save PSAP, system segment, ; system stack pointer (in system segment, please) NONSEG rface for CP/M-8000(tm) BIOS ;* ----- System-Independent ----- ;* ;* 821013 S. Savitzky (Zilog) -- split into modules es after boot. ;* If (the label LOADER is true 1) ;* Control is transferred to -ldcpm ;* else ;* Control is transferred trtup .global _psap, _sysseg, _sysstk ;**************************************************** ;* ;* Global declarations ;tialize Bios ;* then transfer to CCP ;* ;***************************************************** _wboot: call _flush calittle odd. ;* ;**************************************************** ;**************************************************** ldl _psap, rr2 ld _sysseg, r4 ld r14,_sysseg ldl _sysstk, rr14 .if LOADER .else ; set up system stack so that ;* 820913 S. Savitzky (Zilog) -- created. ;* 840811 R. Weiser (DRI) -- conditional assembly ;* __text: .sect ;********o the ccp. ;* ;* We get here from bootstrap with: ;* segmented mode ;* valid stack pointer ;* valid PSA in RAM ;* ;***l _biosinit ldl rr14,_sysstk jp ccp .endif ;**************************************************** ;* ;* I/O port ope************************ ;.input "biosdefs.8kn" ;**************************************************** ;* ;* Global tem. ;* ;* 821013 S. Savitzky (Zilog) -- created. ;* __text: .sect ;***************************************************EG clobbers r0 ld r0,r1 ;rl0 = char scall 84000080h NONSEG ldm r8,@r15,#7 ;restore regs inc r15,#14 ret _c****** ,14+ARG5(r15) ;rh7 = drive # ;rl7 = command ;r8 = block count ;r9 = block number ;rr10 = segmented addrerations ;* ;* int = input(port: int) ;* output (port, data: int) ;* ;**************************************************** declarations ;* ;**************************************************** .global _disk_io .global _crt_put .global _col* ;* ;* NOTE The Olivetti PROM routines are segmented. ;* The C portion of the BIOS is non-segmented. ;* ;* This assembly-lold_boot: SEG scall 8400008Ch NONSEG ret ss SEG scall 84000068h NONSEG ;r8 = block count not transferred ;rh7 = #retries ;rl7 = final error code (RE _input: ld r2,ARG1(r15) subl rr6,rr6 inb rl7,@r2 ldb rl6,rl7 ret _output: ld r2,ARG1(r15) ld r3,ARG2(r15) d_boot ;**************************************************** ;* ;* Prom Subroutine Access ;* ;*****************anguage module is assembled ;* non-segmented, and serves as the interface. ;* ;* Segmented operations are well-isolated, and ld_boot: SEG scall 8400008Ch NONSEG ret TURNED) ;rh6 = error retried and r7,#0FFh ;value returned in r7 ldm r8,@r15,#7 ;restore regs inc r15,#14 ret outb @r2,rl3 ret ;***************************************************** ;********************************************************************************* _disk_io: ;err=disk_io(drv, cmd, count, blk, addr) dec r15,#14 ;save registers ldm ;* are either the same as their non-segmented ;* counterparts, or constructed using macros. ;* ;****************************;************ biosio.z8k ************************** ;* ;* I/O routines for CP/M-8000(tm) BIOS ;* for Olivetti M20 (Z8001) sys _crt_put: ;crt_put(char) dec r15,#14 ;save registers ldm @r15,r8,#7 ld r1,14+ARG1(r15) ;get arg in r1 SEG ; S*******  @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 .global _sysseg, _usrseg, _sysstk, _psap .global memsc ;**************************************************** ;* ;*********************** ;* ;* This module copies data from one memory space ;* to another. The machine-dependent parts of ;************ memsc: ;memory manager system call ; CALLED FROM SC ; IN SEGMENTED MODE ; rr6: source ; r: dest ;* rr2: length (0 < length <= 64K) ;* returns ;* registers unchanged ;* ;* system call: map_adr ;* rr6: logical a* Externals ;* ;**************************************************** .global xfersc ;********************************* the mapping are well isolated. ;* ;* Segmented operations are well-isolated, and ;* are either the same as their non-segmenr4: dest / space ; rr2: length / 0 testl rr2 jr z mem_map mem_copy: ; copy data. ; rr6: source ; rr4: d;******* biosmem.8kn for cpm.sys + cpmldr.sys ******** ;* Copyright 1984, Digital Research Inc. ;* ;* Memory Management for ddr ;* r5: space code ;* r4: ignored ;* rr2: 0 ;* returns ;* rr6: physical addr ;* ;* space codes: ;* 0: caller data ;******************** ;* ;* System/User Memory Access ;* ;* _mem_cpy( source, dest, length) ;* long source, dest, length; ted ;* counterparts, or constructed using macros. ;* ;**************************************************** ;************est ; rr2: length ldirb @r4,@r6,r3 ldl rr6,rr4 ; rr6 = dest + length ret mem_map: ; map address ; rr6: sourCP/M-8000(tm) BIOS ;* for Olivetti M20 (Z8001) system. ;* ;* 821013 S. Savitzky (Zilog) -- split modules ;* 820913 S. Savitz* 1: caller program ;* 2: system data ;* 3: system program ;* 4: TPA data ;* 5: TPA program ;* ;* x+256 x=1, 3, 5 : segmen;* _map_adr( addr, space) -> paddr ;* long addr; int space; ;* ;* _map_adr( addr, -1) -> addr ;* sets user seg# from **************************************** ;* ;* Global declarations ;* ;**************************************************** ce ; r4: caller's seg. ; r5: space ; r2: caller's FCW NONSEG cp r5,#-2 ; space=-2: xfer jp eq xferscky (Zilog) -- created. ;* 840815 R. Weiser (DRI) -- conditional assembly ;* __text: .sect ;*****************************ted I-space addr. ;* instead of data access ;* ;* FFFF: set user segment ;* ;****************************************addr ;* ;* _map_adr( addr, -2) ;* control transfer to context at addr. ;* ;* system call: mem_cpy ;* rr6: source ;* rr4 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 cpb rh6,#8 ret ne ldb rh6,#10 ret s not ; separate code, data usr_data: ld r0, #-1 cp r0, _usrseg ret eq ld r6, _usrseg ret usr_prog: ld r0code to invalidate track buffer ;* contents when disk drive motor stops ;* (fixes directory-overwrite on disk change) ;* f the system dependencies are in map_prog, ;* which maps a program segment into a data segment ;* for access as data. ;* c 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 rlcpb rh6,#8 ret ne ldb rh6,#10 ret , #-1 cp r0, _usrseg jr eq map_prog ld r6, _usrseg jr map_prog map_prog: ;map program addr into data ; rr6 = 830305 D. Sallume (Zilog) -- added FPE trap ;* code. ;* 840815 R. WEISER (DRI) -- conditional assembly ;* __text: all_data: bit r2,#15 ; segmented caller? ret nz ; yes-- use passed seg ld r6,r4 ; no -- use pc segment ret ; alrea5,#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 ;defauaddress testb rh5 ; data access? ret nz ; no: done and r6,#7F00h ; extract seg bits ; olivetti: segment 8 is t.sect ;**************************************************** ;* ;* NOTE ;* Trap and interrupt handlers are started up ;* dy mapped call_prog: bit r2,#15 ; segmented caller? jr nz map_prog ; yes-- use passed seg ld r6,r4 ; no -- use pc seg;********** biostrap.8kn cpm.sys + cpmldr.sys ****** ;* Copyright 1984, Digital Research Inc. ;* ;* Trap handlers for CP/M-8lt: no mapping set_usr: ;-1: set user seg. ld _usrseg,r6 ret ;* ;*** THE FOLLOWING CODE IS SYSTEM-DEPENDENT *** ;*he only one with ; separate I and D spaces, and ; the program space is accessed ; as segment 10's data. in segmented mode. ;* ;**************************************************** ;********************************************ment jr map_prog ; map prog as data sys_data: ld r6, _sysseg ret sys_prog: ld r6, _sysseg ret ; assume sys doe000(tm) BIOS ;* ;* 821013 S. Savitzky (Zilog) -- created ;* 821123 D. Dunlop (Zilog) -- added Olivetti M20- ;* specific ;* rr6= logical address ;* r4 = caller's PC segment ;* r2 = caller's FCW ;* returns ;* rr6= mapped address ;* ;* Most o******** ;* ;* Externals ;* ;**************************************************** .if LOADER .global _bios ; C portioso passed ;* intact to the handler. ;* ;**************************************************** __text: .sect sc_trap: ;sumed that the system runs ;* non-segmented on a segmented CPU. ;* ;* _trap is jumped to segmented, with the ;* following iEPUTRAP jr _trap pi_trap: push @r14,#PITRAP jr _trap seg_trap: push @r14,#SEGTRAP jr _trap nmi_trap: push @****** rtc_ext: .equ 82000022h ;Place to put address ; of list of functions ; for each clock tick motor_on: .equ a kludge) SEG popl rr0,@r14 calr trap_1 jr _trap_ret trap_1: ; jp @rr0 pushl @r14,rr0 ret _trap_ret: ;ren of Loader Bios .else .global __bios ;C portion of Normal Bios .endif .global memsc ;memory-management SC .global _tystem call trap server push @r14,@r14 _trap: sub r15,#30 ; push caller state ldm @r14,r0,#14 NONSEG ; go nonnformation on the stack: ;* ;* trap type: WORD ;* reason: WORD ;* fcw: WORD ;* pc: LONG ;* ;* The trap handlr14,#NMITRAP jr _trap .if LOADER .else ; not used in Loader Bios ;**************************************************82000020h ;Disk motor timeout ;**************************************************** ;* ;* Global declarations ;* ;*******turn from trap or interrupt NONSEG ld r1,nr15(r15) ; pop state ld r14,nr14(r15) ldctl NSP,r1 SEG ; go segmented fobvalid ;disk track buff valid .global _tbdirty ;disk track buff is dirty .global _tbdsk ;current drive code .global _ssegmented ldctl r1,NSP ld nr14(r15),r14 ex r1,nr15(r15) ; trap# now in r1 cpb rh1,#7Fh ; system call? jr ne trer is called as a subroutine, ;* with all registers saved on the stack, ;* IN SEGMENTED MODE. This allows the trap ;* handle** ;* ;* Bios system call handler ;* ;**************************************************** biossc: ;call bios NONSE********************************************* .global _trapinit .global _trapvec .global _trap .global xfersc ;r the iret. ldm r0,@r14,#14 add r15,#32 iret ; return from interrupt ;*****************************************ysseg, _usrseg, _sysstk, _psap, .if LOADER .else ; only the normal Bios .global fp_epu .endif ;*******************ap_disp ; no ; yes: map it clrb rh1 add r1,#SC0TRAP ;=== need range check === trap_disp: ; dispatch sll r1,#2r to be in another segment (with some ;* care). This is useful mainly to the debugger. ;* ;* All registers except rr0 are alG ; r3 = operation code ; rr4= P1 ; rr6= P2 ld r0,scfcw+4(r15) ; if caller nonseg, normal and r0,#0C000h **************************************************** ;* ;* System Call and General Trap Handler And Dispatch ;* ;* It is ass*********** ;* ;* Assorted Trap Handlers ;* ;**************************************************** epu_trap: push @r14,#********************************* ;* ;* M-20 ROM scratchpad RAM addresses ;* ;********************************************** ldl rr0,_trapvec(r1) testl rr0 jr z _trap_ret ; zero -- no action ; else call seg @rr0 pushl @r15,rr0 ; (done vijr 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 @r15nz ; ...return without invalidating ld r5,#_tbvalid clr @r4 ;No: mark track buffer ret ; invalid ; Table of funct***************************** ;* ;* _motor_c -- check if disk motor still running. ;* Entered each clock tick. Invalitrapvec+(MEM_SC+SC0TRAP)*4,rr2 .if LOADER .else ; not used by Loader Bios lda r3,fp_epu ldl _trapvec+EPUTRAP*4,rr2 .efset ;* ;* The system stack pointer is not affected. ;* ;* Control never returns to the caller. ;* ;**********************trap psa_seg .equ 4*ps ; segmentation trap psa_nmi .equ 5*ps ; non-maskable interrupt psa_nvi .equ 6*ps ; non-vectored interr,rr6 pushl @r15,rr4 push @r15,r3 ; call C program call __bios ; clean stack & return add r15,#10 ldl cr6ions run each real time clock tick _ticktab: .long -1 ;Will contain _motor_c .word 0ffffh ;Terminator ;*************dates ;* track buffer when motor stops ;* (Note: runs segmented) ;* ;*****************************************ndif ; initialize some PSA entries. ; rr0 PSA entry: FCW (ints ENABLED) ; rr2 PSA entry: PC ; rr4 -> PSA slot ldl rr4,****************************** xfersc: ;enter here from system call SEG ; build frame on system stack ; when calledupt psa_vi .equ 7*ps ; vectored interrupt psa_vec .equ psa_vi+(ps/2) ; vectors _trapinit: ; initialize trap table +4(r15),rr6 ; with long in rr6 SEG ret .endif ;**************************************************** ;* ;* Context S*************************************** ;* ;* _trapinit -- initialize trap system ;* ;************************************************* _motor_c: ld r5,#_tbdsk ;Which disk is it? cp r5,#2 ; is it the hard disk ret z ldl rr4,#motor_on ;Motor_psap SEG ldl rr0,#0000D800h ; traps here add r5,#ps ; EPU trap ldar r2,epu_trap ldm @r4,r0,#4 add r5,#ps ; P from system call, the frame replaces ; the caller's context, which will never be resumed. inc r15,#4 ;discard return addrlda r2,_trapvec ld r0,#NTRAPS subl rr4,rr4 clrtraps: ldl @r2,rr4 inc r2,#4 djnz r0,clrtraps ld r2,_sysseg .if Lwitch System Call ;* ;* xfer(context) ;* long context; ;* ;* context is the physical (long) address of: ;* r0 ;* ... ;* ************** ;* ;* PSA (Program Status Area) structure ;* ps .equ 8 ; size of a program status entry ; --- segment running? test @r4 ret nz ;Yes: do nothing ldar r4,$ ld r5,#_tbdirty ; Is track buff dirty? test @r4 ; Yes... ret riviledged 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 ldl rr4,rr14 ;move context ld r2,#FRAMESZ/2 ldir @r4,@r6,r2 jr _trap_ret ;restore context ;***********************OADER .else ;not used by Loader Bios lda r3,biossc ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2 .endif lda r3,memsc ldl _r13 ;* r14 (normal r14) ;* r15 (normal r15) ;* ignored word ;* FCW (had better specify normal mode) ;* PC segment ;* PC ofed --- psa_epu .equ 1*ps ; EPU trap offset psa_prv .equ 2*ps ; priviledged instruction trap psa_sc .equ 3*ps ; system call ; segmentation ldar r2,seg_trap ldm @r4,r0,#4 add r5,#ps ; Non-Maskable Int. ldar r2,nmi_trap ldm @r4,r0,#4 ; Q_ @aA_ a1_ 7a!_^ _aq/_ !!g^ _a/_Faa!Ka!KaT   }} }om  T  }} _ _0MRMT^ _a!V^_N _j^ _j` p/ _7` p/` `_hao _aw`X`aRkvfadz@p^ _`p/af` XPaB[eUaS0^ _a _l/_l 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 ta/_p^ _aq/_ !!g^ _aq/_ ``/a_^_a}} aa}}}   {    }} !a@!  D4! D! H%ao T]_ ja /S_|pj!&hQ S_T^ah^Tf^aHa   r| }D}U!A },}=!B!?#4!:(|}$}5}} ]oa]_`|(_l^ _a p/_ ^_aaaa M h_Y _tM NONSEG ret ;**************************************************** ;**************************************************** /_o  a !!W^ _ _l^ _Vt`p/S_ _ v !0D$#av]T}} 4rI4lI4I4ZI4TI4f4B"$}} _ aTaHT@/q7h!8_aaTL]̽!^p/ _3p/_n*v_^af+``aaT}} _h}} a}} _}} }^ _ SS_MRMTaoao^ _MR aKaK_ayvxQ  NONSEG ret ;**************************************************** ;**************************************************** _ _ _^ _!^ _ _^ _ _ұp^ _ _^ _`p/ _"^ _T"TTT Ta" _awwTxT]t^ _ 7aq_ 7aa_ 7a/_ aLh aLXa/ _|v/_ a/_|] !^La`.~$ h__} _}} (a@F}} ^a(a&]}}        o/F/(__a^ _M aA : '^`p _L!^`po``ivh" R!졇 _V^ _`p/ _^ _!^ _ p^ _^ _aw`X`aRkvfadZ@^ _QSS_ ^_a$ vH_Q_voI n ??`  /_`.L ,_$_ :_$ T_$ j_$_^ _ _t _L !h_ _x  _L_ xaaa }.mt^_aa p ?n򡖩 \@ k04 p^ L $ ??ah aH__Ao1  ah_ __ao! _ !h_/_ y` py`p^` py!! _aaavmL /_ Ft!^L /_ V` `vawwvzaK ai ~`g_y s^.~ ޽p _awwax`~`ja UUTR`````/_`.L^ _aa `p{` ``PV@Fkj` pbs^ _aaM _L !h__^!_vtoo _or_ s^MMMq/_ `mPp @GPW p  p `g? p pϽ_a S_n` n S_Z _hlp^ Printer Timeout. BIOS ERROR -- . Boot error. Open or Read error on Bad file!/_ z/_ Ωy!` h p/_ !_`nLLT]T]a ov/_^ _VR,!^FWR]\] hV]UU(VR]RPr^p\wwTt]t wav/_^`~`g _a ah`Po`0`*&hQ_^_a`?n` s顇ww]t]rK]]]]]]]]MMMMa33arT ]0T&R`n ` n`p^_a p!^`p/`̱` _o4aa vhQ_A/ _ format on CPM.SYSCopyright 1984 Digital Research Inc. A. a h_aH_ ^ _aa & ak/_ \t!^/yA a`ff33T0V`]o hV]UU(TP ]PwwDDTrPBrĽp\] hV]FW``n  L`nL@@v^`?``ga`\@`0` #@C`n p`n`n ]6aUUTRVRV] /_8y蔩Kp莽 _ ah_ _ !H_ _!HS _/ _Q _ _p^! _a ~`/ _ ^ _a!^.\@@@n @? ? :?꩐K!!_`p !^`nLLv/_ao T!a avo a aT opڽ _R]\a33T0]hV]wwHVt]tPtrdaK(aChaCY _ tɽpǽ _av  aMqa`~`PeVR`~`` p`g^ _at!^aoi ~`g _! aK ai ~`g_y ^.~ ޽p _ j    ,prtvxz|~&:R`j&>DJRV\"*"*,.02:<>@BJ   *2@HLT^*<\|@Zdnx 8 J \ CPM SYS~`lvp<TTtz  2 6 D R X d`djpl= 2l>HPl\jnrvLNP /(/.4D\V\h\z\\\rr (@JPZ^<<fb\XTPL6|vlfP ~zvrb ~      l ^     l ,^ H P l t x  I$(.28I<BFNZhlp^vz"<HLT^bjn~r &2rN\TZdr\\\bfj9nrx|9lTLg4IZ\^`bdfhjlnprtvxz        8 > D J       ( T Z d Z\^`bdfhjln,0 &,2:>DTZ`hlrvlD (0<@HL\v|~ ~         " & H V Z ` h pl     >DLPblp~psa_sc_copyrig&_memtab0_context_setxvec0_serinit_serirdy_serin_serordy"_seroutV_pcr0_tbdskZ_ticktab SC0TRAPARG3psNMITRAP(FRAMESZBDOS_SCBIOS_SC cr5iz_datasiz_bsssiz_stksiz_split_seg_gp_mydma_x_hdr_segsiz_seglim_sUTRAPSEGTRAPARG4map_prog"scfcwpsa_epu2_motor_cpsa_prv cr6(psa_nmi_sysseg_filltb _dskread|_sectran_seldisk_bioscsvcretswitch1_bios3_udiv_bios5l^ $l06:>NX`llarordy_paroutl_printst_crtrs_crtws_ttyrs_ttyrd._ttyws@_ttywr\_lptwsn_lptwrPITRAPcr13Nset_usrmemsc$scsegNBLKSLOADER_usrseg TRACETRt_outputSYegloc_textseg_dataseg_bssseg_stkseg$_pstringL_badload _load_readhdr_readxsg8_loadsegMEM_SC0psa_nvipusr_datadsys_datausr_prog8psa_vijsys_prog _trapvec scinstSYSPSASEG2_bios2_swap_bios4_bios1_chainp _seldsk&_openfil _dirscan _seqread_gbls ____text__bssmem_mapepu_trapARG2R_tbvalidseg_trap0NTRAPS_nulst_nulrd_nulwrX_iobyteZ_sttblz_rdtbl_wrtbl_genstat_genread_genwritF_bioseSSIZE_mem_cpyPCSIZEnr15 motor_oncr2nmi_trap ARG5cr10entryT_tbdirty_fillbuf"map_1XFER_SCARG1kludgeBPTHDRSIZEjclrtrapsBOOTPSA`_trapiniS1SIZEnr14_trapcr1EPlv2_xlt16"_dphtab_settrk_setsec_setdsk_setdma_trkbuf_tbtrk_dskerr_dskxfern^v/_aLh aLX S _|^v/_a/_|^] v/_v/ S_|^T }} 0! $ X t 0au$H$ (0  h!ӗƍh!`0*Q v__^ _ !h_ " _L!Bo@o>L$$LL_Uv/_a/_JpyGoGoGo7v/_  S_|'/_#T] __^]v/_v/ S_|^v/_ S _|^v/_ S_|^v/_ SڕՍh! Xa&T a*}} ,! {}H! !$  ] _ _ _ _xT]]V]] _^ _MapGo `pakO(> JDd.x}} >: 2ba&a(_o}} a&a(b}} a$&Q_^_^_!^La`.~$ h__^_a$ W_|^v/_aLh aLX aLHaL8 S _|^v/_ S _|^a^`p0!!8_aaTL]̽!,^ __p^p/_^ _p񡗱p/ _^p/GoMMMLLLT]T] _ _^ _a/_ _``A/_^ _a}} oo} }} aa&o&}} T^ah^Tf^aHaaTaHT@/q7hH_Q_GoI n ??`  /_`.L`````/_`.L^!_ vh^] ^`pakEo^a^v/_ S _|^`J``/_ aH_ _^/_p _p/ _^_L^_^_p!0"MMMLL^p/_/_ * _^_a/_ *a/_ _L _ 6___n :_`p!^ _ _L!av.Pq !$w 0ao!D&$#_]`p/_QTB]_`J ^!_ vH_Q_v/__^ n`p^v/_  S_|pv/_  S_|`v/_a/q^p_a >_ /_ ._ /_ V_a/_ f___n /_ za/_ Щy L!!o_L!a/`!_ Щ/_y !/S_ p/_ s`n` n`n`n _ L `n`n t  _ u衽p_ _^6L L  _8^NL a/_(^6LLL}j`py`mP/_8la ]H_Q_`p^ _aa `p{` ``PV@Fkj` pbs^ _aaMp/_`p  ^_8`@@n`p/_8^_La@i@ ~njL!Bo>o@`p^ _p_`p!^ _ _` `gn  _ay/_^ _ _a!^  _ rMM1T  a h_j]! a xa/`_ ZMa`~`j] a/` `蟽 _av  aMqa`~`PeVR`~`` p`g^ _a/_y` py`/_(dLLxvnYL a/_(LJLa/_@L #_8a/_L0L  wav/_^`~`g_aaa ` `gnM U/3_1oGn~^ ___np/_8LLhfn`p^ _a _p^ _p/ _p _a^  _ r _ V  _ r _ V!_T vH__aJ  !!^_ Zot `nM` n a^ _Lq _pp^_L _7 _n  _p^` py!!!_aaavoLf a aT aC/_M `p_ ot#_8a/_ `~`/_Ω`py`hp`n~`/_`p `g^^!_a `aa ah`Po`0`*&j/Q_^!_aM`"vpy`!PYuninf# ~`/_ J^ _a _8 _8 _8^_aaLj`pz ~n   %   !졧wavoaou vEH__p!_T vLLLLLLxvn L~~ a>i>`.~hL^ __`p/ _L ``^`#n L  `p_ t!L `n/_@` `vL!` `gn` PPnn獄L`n`PAKG _LLT]T]a o !!/_tv/_t!n `?n` ``nL L`nL@@v^`?``ga`\@`0` #@C`n   `p    t _8 _8 _8K ^!_aaoL^6_n  L H__gT]T]g ]]T]T] vH__^_/ _`p  i L MLk^ _L _8a`p/_8^ _L `^ _ a h_aJ_R^ _a  a h_J_RyaK8 _ha AF   /_}` po}}```PV`nn ` n f a/_` `gn aEo^ _aaa }.mt^_aa p ?n򡖩 \@ k04 p^ ]콑/ !D_ `n!`n"`n#^!_`p/_L]a ah! !v`j a }P!B3P5W^ _aaa{! /_Ht/_Htꋺ /_^ _wav/_/_`p^_aaa _nf /_vнǩ ~թ.o^ _a  ! z MJ-*FWp^!_aaa ! ap!ziKoY/_ p^`pakEo p p __afw!^ S _ _ p^ _ L $ ??a`mPp @GPW p  p `g? p pϽ_a S_n ` n`mPPJV]aK{Q ogh__^_a p!^`n``/p a p +a aoeaMA`~`/_ wav/_/_ ^! _`par.^ I/_`p^_aaa _n `P_l󡤳I/_`p^ _a`Eq|/_K ;a Ae o_ha.O,_ha o&a aou` @1;oGaEoapGoSS_p^ _aa ??`p/_L/ H_zL ??L L/ X_zQ a H S_l`n ` n` 0!+Eo`p^!_L _tv/_x^_a_oZ`J `n` _aa }hQ_A/ _!HS _/ _Q c`n` J6L`nnp  _`p nv/_ao d _ta avo a ?jm ` JMduF^!_a/_ ` PHd]`n!`n"`n#^!_aa _``/_o /yA a` ^ a av`j㎡ _a aKxa__^_aaa hfn)!  x  _l󡦳i/_a KZoZ`paka _^aMq!  ό j . .   !Ǎt !dgR!/!/  _  _p{ `p/ _{ _p{^!_ !H_Q_vto*aT oL=aax/_to/a`\@@DDaS0(_xM/_  _`pakn/_ `PHd]`n!`n"`n#`p^!_a]콐]`!n`"n`#nTPa AV!B3k.k^ _a aKxaa AV!B300 j #.k^ _aqa AgEo`p^_aaa _n5f /_ 塧y/_aMa! `~`/_o( _or_&^ !^a!^M$M&M$@M& M$M& ! M&M$!!yarTV]T]\ V] T ] T]a33T0lR0,]SQ_ v#(__^] hV]FWR ]\a33T0]hV]wwHVt,]t,Ptlr\a*K((a* p.o     ;; ^ _a !!  !!   ^ _a_! a*K( a(i( ~`g_y ^.~ ޽p _awwvza*K( a(i(wwav~/_+0t33a7^ 齐 L:: LL LAALPP!  LAALgTv_/_& !轡ww]tl]r,K]] ]]]]]] M& MM^*LzovL{_av_ _ _ _^ _aa !^ ! C(ha*C(Yh a(H__A(o()  a*h_ __&a*o(!  x x1  u n[ !!   衧uLX   !! o ~`g_y s^.~ ޽p _awwax`~`ja M$!^a M&wwaff`mPP! L::! _0b ! v/_/t!觽L !螩 L!MMbMM$!!oooaww 3p_1p]6M$a"" 3p_1p]Fa !! _a! L!  }.m u L }.m  !! ^!_ _! _Q _hlp^'޽ _M$tuxM&T Q_a]VaT]r M&hdg !! ^ _a !^ J! ! _a ** ??p^/_/ti 07  pJ}PJM]twwTtVt,L!&^FWR ]\ ] hV]UU(VR,]R,Plr^ _a  !! q!! L oLLL La tLL^ _aTphww]tlaffM$!!9arsT4R ]dlVdV ] /_'y^#K _)/_*y _xA_+$ L11v&nL$$v0nL$$ h_ _h _>jTda]4a$E&aor^! _M& T]] Q_]]T]T]M&M$T_aa  x # u LL??L MALt!`.~ p\wwTtl]tlff33T0V`l]o 򡇍hV ] UU(TPl ]PlwwDDTr,PBlrĽp\jL !H_ _LL;;_+`pLu L;;L !     aa zz pQ !H__!^# _ a*h_ _Q _t!^a*o(i( ~`g _^ _aa LL_+ ~`gj _  !! ? __+^ _a _p.L! ^!asWLq::&5`Y.aAo4LD!`.~ L! 1L  uLQ::`}J _,p^   ^96L^96LZ^96vЍtt _0bxELB !h_ _ 0`  pj _  !h_  !h_ _!^L ^>Lx쩀 `ppj _L??L !H_ q{^4f f L_+L"׍h _M !h_ _yQ[ɡ_0bx 6L3 !Dh_ _ _n< aa zzp`b>v>*>P>d  $;B*BBB*BlBB E,D@DTDZD`DfDDE,EDJ4POPa` U Q R S T U  $ ([ .Y 8: < @: DU P^ T[ ZY dACR AC r z   #"""# $0$$$0$$0$0$0$0$0$0$0$'D'@'@'D'@'@(''(Z(r(r(ZFGN NOOPP*:AFHLUP1X5\I`dUjJpvtinue with bad data (C)$? $ $CP/M Disk file error: $ is read-only.$ Do you want to: Change it to read/write (C), or Abor 9 $*.6<N@ODPHUNUR\<bUf,xYZ02468:<> l p[ vY   :  :  :  : 7  :  j(Z CP/M-8000(tm) Version 1.6 COPYRIGHT (C) 1984, Digital Research  NON-SYSTEM FILE(S) EXIST$K|L34Y34U<2U:<>UJ[RYb3v84U[t (A)? $ $ CP/M Disk $read$write$select$select$change$DIRDIRSTYPERENERAUSERSUBMITFile is not executablep=@>U?U?C @(2BAJ@BDFHJLNPRTVXZ\^`bdfh   [ Y  : ^ ^ 0^ 8 <: @ F: J N: R7 ^ b: l pjEnter Filename: $Enter Old Name: $Enter New Name: $File already exists$No file$No wildcard filenames$Syntax: REN NewfilY34;34[Y$ ,3<BUFUJUNURUXU\U$Insufficient memory$Read error on program load$Program Load Error$ Exception $ at user address $. Aborted.$?TdAlvB@D@NUUUOOjlnprtvxz|~ x  E @ _ [ Y  :  Z e=Oldfile$Confirm(Y/N)? $Enter User No: $.SUB file not found$User # range is [0-15]$Too many arguments: $.,=[];>><h1v|::QRSTU[YONNUNN ,4:Th*Ln2p"BJZbr~BT O$E(@04U8U>UF<XU`3h4nUUAA  [         Y 83 B4 `[ U U 3 4 Y 3 4U<YNnUPP[Yhy[YUprg{[UU3[Y*U23@HURVUf[lYpU[YUUU%%%3%4&& Y&&3&(&.&6&D[&H&L&P&bY&f&n&v&|&&UUU[YU[Y[Y"U(U,U6U:U@UDU#(#8 #L#X #f#v# ##[#Y##3#4####$[$$$ Z R T Q S R $T B3 J4 P[ VY n3 z4 [ Y U [ Y  [ Y @  XOOY 2[>B@LYV[\Ylt[zYU@@UU3&U2UBPHOPO\N`NdUl<rUU[UYUU[YU"UF&[&Y&&&&&&&['Y'"'&'.'2':'>Z "HUR[ZdYhtUU[Y[ YU[Y  $$$$ $&$*$<$J$j3$v[ ^Y fU U k [ Y"[8Uh>=@B@YUU>[DYNh[Y4[Y8F{JUXUdPhPr[xYg{U}  } [ Y ,[LYZU|[YU[YUU |: @|J[RY\NpUUh$'B'F'`'d'r'|'''Z*,.02468'''&[,YU[YU5  &2UZh$$$$$$$$$$$$$$$$$$%%%UUg[ (dtlUU3 UU4BUPUd Dg t{ ~[ Y   { [ Y![! Y!!B[!JY!^!n![!Y!!@"[" yUhUUUUU} U(<|LP@bNfNj[pY[Y['''''''['''((((("(&(4(:(J(N(\(bxUU4LP[XY`UOhUhy[Y% %$3%.%2%8%P3%Z%^%l%p%x%%%%%%%%%%YU[Y5UUUU"U,U6[<Y@P VUh zY",":U"`U"|U"U"3"4"["Y""Z"" "## (j(n(((((((((((((((() )3)45n5z55355555355566636(646<36H6N[6VY11111111112&2,Y202:2B32N2X2\2f[2rY2|= ===0=6=<=B=H=L=V=\==3========,tY,,,,,,,[,Y,,-- [-"-0-6-<-D-X-`-t-9999[999`9:3:: :&:>:D:H:L:T:\:h:p3:|)$)():)B3)N)T)X)\)l)r)z))Y)))))3)))6\6f6n36z666666366666666677 722[2Y222222[2Y222333 333&3.33:>$>(Z>8>>>D>J>^>r>x>~>>>>>------Y.a..`.$.*a.2`.6.>a.Fa.J[.PY.d.n.v3.::3::Y:::3:::::[:;;;;,;8;J;Z;rY))*[*Y***0*43*B*J*R*X*^*d*h*p*x*~****77&767:7B7\7n777777[777777773L3T33`3r3z3333333344$4.4@4Z4d4l34x44>3>>`>>>>?`???4?J?P?T?h?p3?|????......../ [/&Y/V[/\Y/d////[/Y0[00.Y;z;;;;;;;;;;;3;<[< <<*<:<@setsupf_bios4r__bdos>bioscall^dirbcallGYG2GGGG3GGG3GHH 3H,H2H>HPHZ_ext_err _ro_err _error R_cpy_biswitch2R_rdwrt~_getaloc _blkindx _blknum _setblk Z_do_ioDDDDDDEEEE E2E6E<[EDYEHEREZ3EfElErE~dlinL_seldsk8_openfil_close_fv_search_dirscan_bdosrw_createt_delete _rename _set_att!B"B:B>BLBTBdBpB|BBBBBBBBBB_bios1__data__bsslowexcchkredirDprtwordZexchndlzexcept sysexcBIOS_SCsegusrxLprtbyte(init30excrtn0dlt10excmsg1BSETEXCJ3J JJJ"J,J43J<JB[__text_bios6setsuptcallBios_bios3_udiv2_x_sg_mylpb_bdos_x_hdr&^_readhdr&_readxsg'_loadseg*_setbase)_setaddr&_fillbuf_usercmdG*G0G6G:G@GFGJGPGVGZG^GbGfGjGtGzG~`GGGG[_copyrt_serial8_conout_dir_rd|_submit}_morecmd_bdosini *_prt_err V_abrt_er_warning rDFDPDVD\DbDhDtD|3DDDDDD3D_chainp_bios_map_adr_mem_cpy_warmboo_constat`_conin_tabout_rawconi_prt_lin_rea*ccpstartcopy*ccpz_autoststackpsysinitE>_main*ccploop*ccpclear~_cmd_tbl_msg$  0!!8_aaTL]̽!^ __p^p_find_co2_chk_col:_user_cm;l_cmd_fil?_sub_rea?_dollarAJ_commentC6_submit_+_cr_lf+r_copy_cm+_promptO(8XI| > 2 b_oqa$o$TahTfaHaa_msg2_msg3_msg4_msg5_msg6_msg7&_msg8D_msg9T_msg10f_msg11|;cpmsys.rel is the relocateable ccp and bdos for a Z8002 processor. ;make cpm.sys for z8001 systems ld8k -w -o cpm.sys bios.re/_^@ _p񡗱p/ _^@p/ _^@/_p _p/ _^@_^@_Z^@_,p_echo_cm-_check_c.L_get_cmd/X_get_par2_dir_cmd5_type_cm6P_ren_cmd9^_era_cmdG___LOADA_translaD(_exeTaHT@/q7h!avʫPq !$w 0ao!D&$#_msg12_msg13_load_tr_first_s_chain_s_end_of__dirflag_subprom_sub_ind_index_sub_usel cpmsys.rel -lcpm p!0"MMMLL^@p/_n^@v/_vaLh aLX S _|^@v/_va/_|cute_xfer_LPB_stack_sstack_context̳ $ X t 0au$H% (0  _user_cur_dis_subcom_subdma_user_pt_glb_ind_save_su$_subfcb$_cmdfcb_tail_aut cpmsys.rel -lcpm ^@] v/_vv/ S_|^@T ]v/_vv/ S_|^@v/_v S _|^@v/ute_xfer_LPB_stack_sstack_contexth!Ɨ߹h!͗ɍh! ؍X]f!"ba$!!a (f"(Ta${! !orom_dmax_parm_del/"_scan_cm+0_strcmp,_decode/_delim0*_true_ch0b_fill_fc2(_too_man2n_v S_|^@v/_v S_|^@v/_vaLh aLX aLHaL8 S _|^@^ _ _a!^  _ "^  _ " _   _ " _ !_T v_^ _MapGo `pakGoMMMLLLT]T] _ _^ _p`g^ _a/_y` py`p^` py!!!_aaavoLf a aT __^X_a$ WH_Q_GoI n ??`  /_`.L``` U/3_1oGn~^ _aa ah`Po`0`*&j/Q_^!_aMv/_v S _|^@a^X`p^X] ^@`pakEo^@a^Xv/_v S _|^H__aJ  !!^  %   !졧wavoaou vEHa/_ _``A/_^ _a/_ _h^_a/_a/_ _L @_ b__aC/_M `p_ Not^`#n L  `p_ Nt!L `n/_` ```/_`.L^!_ vh_]`p/_QTB]_`J ^!_`"vpy`!PYuninf#n `?n` ``nL L`nL@@v^`?`@`J``/_ aH__^@ n`p^Xv/_v  S_|p__p!_T vH__gT]T]g ]]T]T] _n f_`p!^ _h _hLq^p_a j_ /_ ._ /_vL!` `gn` PPn/_ 8za/_ y L!!o_L!a/` vH_Q_v/_`0*Q v__^ _ !h_`ga`\@`0` #@C`n p/_ s`n` n`n`n _ L v/_v  S_|`v/_va/_Uv/_va/_JpyGoGoGo7v/_v  vH__^_ ]H_Q_`p^ _aa `p{` ``PV@ _a/_ ___n _`p!^ _h _h` `gn  _ay/_!_ /_y !/S_ MM1T  a h_j]! a xa/` " _L!Bo@o>L$$LL] _ _ _ _xT]]V]] `n`n t  _ u衽p蟽 _av  aMqa`~`PeVR`~`` S_|'/_#T] __^XQ_^X_^X_!^XLa`.~$ hFkj` pbs^ _aaM wav/_^`~`g_aaa ` `gnM_ Ma`~`j] a/` `_ ot `nM` n a^ _Lq _pp^_aaa ! ap!ziKoEq|/_K ;a Ae o_a.O,_a o&a aou_@L #_a/_L0L #_a/_ `~`/_~`py`hp`n~` pϽ_a S_Hn ` n S_`n ` n` 0!+Eo`p^!_L_@p/ _p _a ~`/_L J^ _a _ _ _^_a聇av/_/_ ^! _`parc`n` J6L`nnp  _`p nv_L _7 _n  _LLLLLLxvn L~~ a>i>`.~hL` @1;oGaEoapGo``/_o /yA a` ^ a/_~`p `g^z^!_a `n獄L`n`PAKG _LLT]T]a _tv/_x^_aa _H^aMq!  ό j . . aLj`pz ~n    `p    t _ _ _K ^!/_ao d _ta avo a aT oL=aax/_to/a`\@@DDaS0(_xM^ __``p/ _L ``/ _`p  i L MLk^ _L _ av`j㎡ _a aKxaa AV!B3k.k^ _a aKxaa AV! o !!/_tv/_t!^ _ a h_aJ_^ _a  a h  !Ǎt !dgR!/!/   /_}` po}}```PV`nn _aaoL^_n  L _~ _^L L  _^L a/_ة^L/_  _`pakEo^ _aaa }.mt^_aa p ?a`p/_^ _L `p/_L`p  ^_`@@n`p/_^_La@i@ ~B300 j #.k^ _aqa Ag }P!B3P5W^ _aaa{! /_t_J_yaK8 _a AF .o^ _a  ! z MJ-*FWp^!` n f a/_` `gn aY/_ p^`pakEo p p __Tafw!LL}j`py`mP/_la/_ةdLLxvnYL a/_ةLJLa/n򡖩 \@ k04 p^ L $ ??a`mPp @GPW p  p `g? pnjL!Bo>o@`p^ _p__np/_LLhfn`p^ _a _ʱp^ /_tꋺ /_p^ _a p +a aoeaMA`~`/_ w^ S _ _ p^ _ SS_Hp^ _aa ??`p/_/ _zL ??]] ]] ]]]$M* MMMMbMM(!!oooaww 3p_1p]6_a p!^`n``/p _oZ`J `n` _aa }hQ_A a.h_ __%a.o,! _Q _hlp^' _M(tuxM*TP_󡤳I/_`p^ _a`?jm ` JMduF^!_a/_ ` PHd]`n!M(!^a M*wwaff`mJ}PJM]twwTtVt0L!^FWR$]\] L L/ _zQ a H__^_aaa hfn)!  x  M(a"" 3p_1p]Faww]tpaffM(!!9arsT4R$]dpVdV$]/ _!HS _/ _Q _  _p{ `p/ _{ _p{^!_ Q_a]VaT]r M*hdgjTda]4a(E*aor^! _M* T]] Q`n"`n#^!_aa _Hn/_ `PHd]`n!`n"`n#`p^!_ahV ] UU(VR0]R0Ppr^p\wwTtp]tpff33T0V`p]o hV$]$UU _󡦳i/_a KZoZ`pakEo`p^_aaa _Hn5f /_ /_&¡y^#K _)@/_)Q !H__!^# _ a.h_ _Q !H_Q_vto.o, _or_& !^a!^M(M*M(@M* M(M* _]]T]T]M*M(T TV]T]\V ]T] T ]a33T0pR00]]콐]`!n`"n`#nTP]콑/ _ `n!`n"`n#^!_`p/_(TPp ]PpwwDDTr0PBprĽp\] hV]FWR$]\ a33T0] hV]y/_aMa! `~`/_wav/_/_`p^_aaa _H _t!^a.o,i, ~`g _! a.K, a,i, ~`g_y ^.~ ! M*M(!!yargTv_/_&d !轡ww]tp]r0K]SQ_ v#(__^^*LNozLO_az_ _ _ _^]a ah! !v`j a`mPPJV]aK{Q ogh__^wwHVt0]t0Ptpr\a.K,(a.C,ha.C,Yh a,H__A,o,) nf /_vнǩ ~թ.^ I/_`p^_aaa _Hn `p _awwvza.K, a,i, ~`g_y s^.~ ޽p _awwax`~`ja _aa !^ ! !! _a! L!  }.m u LA/_/tA`[0*.iA/_/ڡ._  q?? ^0 _LuLX   !! o  !! ^ _a !^ J~! ! _!؍h_ _^!0_L8 !h_ _ Z_-LZ^7` !(_ t!觽L !螩 L!蔽 _a  !! q!! L oLLL gj _  _ !H_ _y 1; f f _* }.m  !! ^!_ _y _xA_*$ L11v&nL$$v0nL$$ < !hh_ _ <_, !^! _LL::^ _!ALq::MLa ** ??p^/_/ti 07  p_aa  x # u LL??L M_ _-L<==;L==LL== LL< L<==L=LZL==LLa tLL^ _aTphjL !H_ _LL;;_*`pLu L;;L ^3$M#_* !rh_ _ !vh_ _^ _L !h_h_ _h _> _^ _aa LL_+v ~`gj _ AALPP _, !^!!_aML_1؍t^4_2|/_2>t^4 _0`pv}@ !H_ALt!`.~  _p.L! ^!asWLq::&5`Y.aAo`}nmZL<==;uLQ::1L  uLQ::`}J~ _, L !     aa zz p p.o     ;; ^ _a _ _-_1؍t|_2x/_2>tt _0xELB !h_ _ 0`  !! ? __*^ _awwavR/_*t33a7T^ 齐 L:: L _y  !؍(_ _q{^4hf f L_*L"׍h _M4LD!`.~ L! ! _p.A/_/ڡ._ i^   ^8L^8LZ^8v/ _0x _0y^8ȍ^8`JL::L[::nL:: !!  !!   ^ _a!  x x1  u n[ !!   pj _  !h_ _t` PJ %_%L"  !h_ _ L LAALPP!  LAALPP! L::! _0 ! v/_/ !h_ _yQ[ɡqy: _ _  _`~ L[::`nLL" vЍh_ _  !H_ _K!`~!h_ _  LLLL`n $LL _t L 88L KKv/ _*t``KLELAL L L v/ _*t``KL$L L^ _aL  _zaH _ !(_ _LL L  !(h_ _ _-L!^_1؍t!L00L99!`pvx  !L o _?R^? _aa_+vL$$ / _?x `~`gj _ LL n #LL1 !h_ _  !؍H_ _ !h_ _a/_-_M !:h_ _ah _LL^; _ ! SSL UUL BBv/ _*t ``KLLM LML! !h_ __?RML/_ALaa Lzz`p`pn !h_ _H _^ _a衇 ` PWvx  L h _!!!_LLL _o _`   _?RtL  _?RL洡^ _aa W`p!^/_@{I _^7` !h_ _^7` _L !h_ _ _-L_1؍t_2x/h_ _tL!^!_aaaa _?Rt^` 00y 99vpv}oai aSSx ^<M  _0 _0ah _ML Lt!^/_,!^ _2x _2s_4p_6m_9j_:Vt !Ph_ _V`pj _IL2oM _0x _0x  !h_ _!^L ^><Lx쩀 `pp`}nm L L _?Rt(o / _?{a  _?RL`}nm_2>tL:: L _, ^ _0x 6L3 !h_ _ _n< aa *ai QUU#ai ABBai 1MMai !IIai qTTa a oia q  ta q i _L ZZL 88L KK _ _L SSL UUL BBL SS L UUL BBLF !h_ _ _-`~nL L LLL/_;t  j _L??L !H_ _x^=d! xLt`}PKt `~ PVn~ L L ZZ _?RL L L!!L L!!# L L L!! _?Rt LLo zzp`@BDFHJLNPRTVXZa( _ _La h򡗩 !! T j _ =(__ile$No wildcard filenames$Syntax: REN Newfile=Oldfile$Confirm(Y/N)? $Enter User No: $.SUB file not found$User # range`Otptn|tߩLxtvt]FL&L! _B LaL _B aL $ _, n program load$Program Load Error$?8JR\jvJd`8 @`8888XXXX-0000-654321 WARNING -- Do not attempt to change disks$ CP/M-8000(tm) Version 1.1 12/19/84$ Copyright (c) 1984,\^`bdfhjlnprtvxz|~ a#(__ _ $$ !__ _ $$ is [0-15]$Too many arguments: $.,=[];>:=>>&=>>  $;AB8BHABABP DCDD DDD>DXDDC02J`|_+v!L L  _, L  _-Xo/_/LL;; _CL/_.ҡx8!LL L888 88888888888"8.,nACR | AC " * 2 d #P"x""#D ##### Digital Research Inc.$ error on drive $ Do you want to: Abort (A), Retry (R)$, or Continue with bad data (C)$? $ $CPPTZdhp88 !(__g !T ]T] !(__aoT /8Srd(DH _+"a/_+"La/_.o _BLL LaL _B  _, ^!_ #######&&&&&&(`'>'( ("("( ( CP/M-8000(tm) Version 1.6 COPYRIGHT (C) 1984, Digital Research     <@HR\bfp ~         @ F L T  LP| l v z               ,2:Rf &HRX`x)BJRV\dlx|&RV^htx6>Zj$jr       ( 0 J N ^ b l p t |   :Nfnz &/,048@JNVZ^bVfl (0Fbt~>DHV8^dp8|8                FL8DHRZjxx~V86@`z 04>HXhx*8FJP`dx| < H d l z              * 6 < D x $*<D       & 0 4 : > B L P T X \ hZbnz "2T`t  &,2>dltz 8$08BHV\fzLPnr"(@Xj)V)\)f)j)|))))))))))))*****&&&&'''"','0'8'<22 22 2 222333"3* 34 3@3V3h 3p3|3333#####$$&$B$L$R$^$b$f$j$n$r$v$$$$--.. . .&.2.8 .> .F.J .T .Z .b .h ..// //Fn  $ . 4 L j x       !* *(*.*2*6*>*F*N*R*f*j**********  'L'V'Z'`'h'l'z'~'''''''''' 34 4 44(4N 4X 4^4n4x44444444444$$$$$$$$$$$$%% %%% %(%F%P%T/n/ ///////000J0^0j0n0000000!!R!Z!!!!!!"",">"P"X"^"d"r"vRVZ^bfj******+&+.+2+8+V+t+|+'''''( ((((0(:(>(L(P(X(\(l(p(t((4444555 55*54 5<5H5Z 5n5 555 555%X%\%f%r%x%~%%%%%%%%%%%%%%%&0011$1<1@1F1Z1d1h1n1|111111111"~"-"""-"""## #&8#<#J8#T#\#l#t##++++,,,,$,6,< ,B,Z,z,,,,,,,,,(((((((((((())) ))")*)>)D)H55555566 666*686<6B6F6N6V6b6p6t6z6&&&&&&,&0&@&N&h&t&|&&&&&&&&&&1122 22"2,222<2B2N2^2f2r2v222222##########,,,---$-2 -:-X-^-p----------6666666666667 7747H7L7V7\7b7zBZB^BjBnBzBBBBBBBBBBBBBCCC">( >. >4 >> >F >N >b >j>v>>>> > >>>>>??*H HHH.I.I0I .I0I.0I6I>IF.IJIV.IfInIvI|.I.II.:::::; ;";*;0;F;L;\;b;n ;v; ;;;;;;F&F,F2F6F<F@FJFNF\FdFhFlFr F|FF FFFFF7~77777 7777 777 777 88&868>8JC,C4C@CFCLCVCbCfCjCrCzCCCCC CCCCCC?? ?,?2?>?D?J?P?V?^ ?f?r?|??????@~@II.III.II.IIIIIIII-I__textR_bios6ARG2 ;; ;; ; ; <<<<& <, <2<@ >"GGGGGHH  H$.H6HRHZHv HHH HH HHH H99:: : : :,:<:D:P:Z:^:h:p:|::::::DE E EEE"E.E4E@EFEJEPE\EbEEEF FFFF"ARG1cr3cr11LONGSIZEcr8callCL_bios2DEBUG_SCZ_swapcr0 SC0TRAt_tpa_hp_tpa_ht_gbls_uprt_liZ_ureadliv_tmp_selcsvswitch1cret_copyrt_scr2 ARG5cr10lt10excmsg1cr7$scpcINTSIZEBSETEXC_chainp_bios_cur_dis_subcom_subdma_user_pt_glb_ind_save_su$_subfcb$_cmdfcb_tail_autorom_dGTRAPBGETSEGARG4co"scfcw cr6_syssegcr14MEM_SC|_initexc scinst_bdos_x_hdr&_readhdr&d_readxsg&_loadseg)_setbase)@_setaddr%_fillbuf__data_usercmd*ccpstaPARG3NMITRAP&FRAMESZBDOS_SCBIOS_SC cr5_traphndPITRAP>setsupfcr13<_berial_conout_dir_rdP_submitQ_morecmd_bdosini_prt_err _abrt_er_warning "_ext_err _ro_err_map_adr_mem_cpyh_warmboo@_constat_coninL_taboutD_rawconi_prt_lin^_readlin_seldsk_omax_parm~_del._scan_cm*_strcmp,_decode/_delim/_true_ch0_fill_fc1_too_man2_find_coprintprtdollaXFER_SCARG1initloopcr3init1cr11excmsg2LONGSIZEcr8rt copy*ccpN_autoststackpKsysinitD_main*ccploop*ccpclearR_cmd_tblr_msg_mios4 TRACETR"__bdosPCSIZEnr15cr2 ARG5cr10"bioscallcr7$scpc h_error _cpy_biswitch2_rdwrt._getaloc 8_blkindx _blknum _setblk _do_io N_new_ext_calcepenfil_close_f&_search\_dirscan0_bdosrw_create$_delete_rename 0_set_att!T_getsize _setran2>_chk_col:V_user_cm;_cmd_fil?R_sub_rea?_dollar@_commentB_submit_*_cr_lf+"_copy_cm+v_prompt, _echo_LdfltexcDEBUG_SCexchndlcr0exceptsysexc SC0TRAPARG3NMITRAP&FRAMESZBDsg2_msg3_msg4_msg5_msg6_msg7_msg8_msg9(_msg10:_msg11P_msg12R_bios1INTSIZE__con__bss^lowexc6chkredirARG2prtwordusr_vec0NTRAPSprtlonxt_get_rc`_conbrk~_cookdou_getch_newline_backsp"`_do_phio_dchksum_dir_wrp_setaloc_c!_free_spT_flushit#V_pgmld _setexc t_set_tpa_move_log_dsk_ro_dsk_crit_ds_tpa_lp_tpa_lcm-_check_c-_get_cmd/_get_par2_dir_cmd4_type_cm6_ren_cmd9_era_cmdGV___LOADA_translaC_execute_xOS_SCBIOS_SC cr5PITRAPprtbyteinit3cr13excrtn0 TRACETRPCSIZEnr15h_msg13_load_tr_first_s_chain_s_end_of__dirflag_subprom_sub_ind_index_sub_use_usergcr4init2cr12 excmsg3usrexccr9evec_adrprtnibcr1EPUTRAPSElraloc_chkaloc_allocH_match_close_alltrue_matchit _extsize _fsize@_x_sg_mylpbfer_LPB_stack_sstack_contextDLbĔ&wfUDwfUD持 LbĔ&Tdt_0_1`` Ʒ5$fUDOfUD$HhL\l|_1`a6_`aX0 ^&1T 4]1 a   @A! ! !BA-w _xh|5|9!B,J,J,JBBB>RJ,Ԥ֦צ צզԦU5xB)5|5P 5T5HFDB@><:863_a0wT_WH#C = k: v@!A_X  !)2  ""7aq v3'!Aqaq!Aq?877J,JBBB>D: 0, :,J"X5\ 4l4`q0+6)567P!7T7X7\ 314l4`9U1~|z:KFUDHUDUDʵ*W 5|9B$ _5zq4l9@>420.,*(&|X55x55|!03_x _a>0_ B _ _g ___J___ž1J  JJBBB> D  6 f  8 * *z 0]2]U5x𠐠4[4Y4^ 8.8U5-$#Ԕ*___ B_a05|A:9W_A Wg*_$" VNJF:,xvz5|5q0U _a`0_ Bw_!@>@A!@3!@p_j_ق__žGI _򒈔f X R J ~&!5(--7,/*513-5*"4  D@ X  @>Wp_j 0]_0]2]_62]U0Y0[1x פզפԦ'!դ֦trpnljhfdb`^\ZXVTRPNLJ511111!@>W_,P___ BĖjYH  1W50 pdecodedminusinf epu_n $1sqrin Dlvry1Fdiv3 &Flbcd8Flil92cr9round60tempARG2 intu0TFlcb13fFlcb21JFlC65`wpdstFsqrFRemS13 intnext get_cpu *Fneg scinstactlddFresflgFldctl^Fmul24 Dlvry53FcpFremstep`        SEGTRAPremnodARG4 tDlvry11tFlcb23Flcb31under willstuf"scfcwFRemS15ldi0<:86420.,Fsub52Fsqr221pshifD1setup src1Fsubdotrap ~ldd0Fmul1 fpepu197Fwpreg7oFlbcd39,Flbcd55Ns_or_d0NTRAPSsetup31Fsqr22`actint6Fldil FldPFlil71^stafcw8FRemS1XFER_SCfdnan resinfroundupRvsD5actaddFcp2ARG1actldi  x t 0 , (    fpepu567xwpop1 Bdeliveryitsunder reg1Fcpx~nonre3:Fcp33 reg99 cr6*(&$"    ,    z d0 @ 2  |  ^lwpsrcFmul30under2 Dlvry35 jDlvry51 epu_s 8Fabs$round41Fsub578Fdiv10,FlC6nonre10Fcp31adddst0Fsub15Fsub31cr4lFsqr200FlC12FlC20:cmps0XnonrestoNFlcb12VFlcb20@FlC64Lgstep2b over64@addno lmemadrsFadd fpepu556(setup14divn~zv@ Fsub336addsrc0FlC14 FlC22Frf1Fsub1vnowroundfdzun bFlbcd20gstep3 stuffmem\ZXVTRPNLJHFDB@> b ^ Z T N2^FlC70Frf9 Fldbcd,resinv Rldnan|wpdadrsetup12vsetup20 cmpsinfFsqr11 4Flbcd10gstep1fReSrc37 fpepu192\wpcntlwpreg2 Fintcr12 0over643Flcb34FlcboFsqr21 $memerrstaregjshiftdigFlil54:Flil70cr3nFsub14Fsub30FRemS6__text__data"remno LDlvry54Flcb90setup101 jfpepu17lddjnkbFsub10BFRemS2 Ftil(wpreg4 Fint27MEM_SCFlil20>resprec &epuFRemS36PwpcregsNoMoD1foolsrougett J > 0 &  ~|zxvtrpnljhfdbnr14Flil60cr1 epu_xXFRemS4wpmadEPUTRAP lddnoplusinfXwpflgs nfrombinFlC11gstep0$frm_setstaevnt wpreg1 fpepu191cr11 Dlvry13toptab~Flcb25Flcb33 fp_epuFsqr12nr15cmpunorcr2 0getiwordFlC10sqrnoresdstwpreg0rounfpepu10under20FlC16cmpcasePwpfigepuwp remnz .Flbcd9,cmpeqFsub37Fsqr222 dx !P"3dU"3"2aT"3FP"3d"P"3FT"y55Flil51FnoopFcp11cr0dFsub11nearest SC0TRAP Fint21ARG3.makenannFlbcd50INTSIZE $Fld4 fpepu560 XldnostapcsgxFmul25 src99FstpldinowpstateldijnkFdiv2HFsqr26dround11FcpztFlil750d_preLONGd Fint23 ARG5Fsetflgcr10locunder|Flcb24Flcb32Flcb40 8over68"addinfshifD2FlC50Frf5over34 src2getmemnormordireszero Fld2Fmul2unde3d $&(&__text__dataARG20NTRAPScr4cr12cr9gtFlcb22Flcb30ZFlC66bFlC90NMITRAP 4over66(FRAMESZBDOS_SCFRemS30 fpepu566BIOS_SClbcd50INTSIZE $Fld4 fpepu560 XldnostapcsgxFmul25 src99SIZEcr8 dst2Rs_preFlC16Xcpzcaseactmulactld fpepu21DEBUG_SCFRemS70FmulRvsD2intadjusover31FlC15 fpepu1952wpreg5Rdivdz Dlvry33Fdivremvsdiv&scpcFlil21 XfpepFcp1^ReSrc30reminv TRACETRgstep2_2FFlcb11 over636FlC63PCSIZE Flbcd37gstep2a_stafcwXFER_SCARG1staregcr3staevntcr11LONGSIZEcr8DEBUG_SCcr0d11cmp2infwpreg30cmpd0cr13 Dyankmem Dlvry15 Dlvry31cmpdinf DFclrwpsadr HfFsetmodedononedouble&FlC61over61 Flbcd35 fpepu553normdigsoversetup11 ZDlvru12under22mulnoNoMoD2@round31zsqrcaseressrcputmemFrf7over60 FlC60 SC0TRAPARG3NMITRAP(FRAMESZBDOS_SCBIOS_SC cr5PITRAPcr13,getmem$sc********************** ; ***** 8/15/84 R.F.W. ***** sect _sysseg: .block 2 ;system segment _usrseg: .block 2 ;user segment _sysstk: .block 4 ;system stack pointer _psap: .bl/_|] !^La`.~$ h__ _QSS_Z^_a$ the value of the label LOADER false ;(0) the normal Bios code will be generated ;while setting the label to true (1) will seg TRACETRPCSIZEnr15cr2 ARG5cr10cr7&scpcRputmemINTSIZE********************* ; ***** 8/15/84 R.F.W. ***** ock 4 ;program status area ptr ;**************************************************** ;* ;* Trap vector table ;* ;* entrvH_Q_voI n ??`  /_`.L`````/_`.L^ _aa ` ;provide the loader Bios code. ; LOADER .equ 1 ; 1 or 0 which ever ; ; .input "biosdefs.8kn" .input "biosboot.8kn" stapcsgies 0..31 are misc. system traps ;* entries 32..47 are system calls 0..15 ;* ;***********************************************p{` ``PV@Fkj` pbs^ _aaM wav/_^`~`g _a a .input "biosif.8kn" .input "biosio.8kn" .input "biosmem.8kn" .input "biostrap.8kn" .input "syscall.8kn" ;******** x0 FfT^ah^Tf^"aHa _ aTaHT@/q7h!8_stapcsg***** _trapvec: .block NTRAPS*4 ;**************************************************** ;******************************h`Po`0`*&hQ_^_a`?n` ``n  L`nL@@v^`?`******************************************** ;* ;* Data ;* ;**************************************************** __bss: .aaTL]̽!^p/ _3p/_n*v/_JaLh aLXa/ _|v/_Ja;********************************************* ;Build the assembly modules using conditionals ; __text: .sect ; ;by setting`ga`\@`0` #@C`n p`n`n _ tɽpǽ _av  p莽 _ ah_ _ !"H_ _t!^aoi ~`g _! ap^! _a ~`/ _ ^ _a!F^ _n_ _n (_n >_n_^ _  & 2BHNj v   nLLv/_ao T!a avo a aT opڽ _aaa }.mt^_aawHVt]tPtrdaK(aChaCYh aH__Ao1 aMqa`~`PeVR`~`` p`g^ _a/_By` py`p^` py!!K ai ~`g_y ^.~ ޽p _awwvzaK ai ~`g__t _ !"h_ _x  __Tx _ !h__^!_vt:>VZ, 0Fbr p ?n򡖩 \@ k04 p^ L $ ??a`mPp @GPW p  p `g? ah_ __ hao! _ !"h_ _hlp^ Boot error. Open _aaavmL /_t!^L /_` `v!/_Сz/_y!` h p/_y s^.~ ޽p _awwax`~`ja UUTRVR,!R^FWR]\] oo _or_ s^MMMq/_ $ s顇ww]t]rK]]4@`lp  p pϽ_a S_Щn` n S_`n ` n`p^_a p!^ or Read error on Bad file format on CPM.SYShCPM SYSR!_`nLLT]T]a ov/_^ _ a h_aH_f^ _aa hV]UU(VR]RPr^p\wwTt]tff33T0V`]o hV]UU(TP]]]]]]MMMMa33arT ]0T&R]6aUUTRVRV] /_ y蔩KBZt|*t`p/`` _o4aa vhQ_A/ _!HS _/ _Q _ _  0`|  & ak/_t!^/yA a`꩐K!!_`p !^` ]PwwDDTrPBrĽp\] hV]FWR]\a33T0]hV]w" (<HV`fr"JLNaloc_bssloc_stkloc_textsiz_datasiz_bsssiz_stksiz_split_seg_gp_mydma__text_bios3@_udiv_bios5_bios28_swap_bios4"_bios1_bio N1 ^C l  # # 7 6 4  "VXZ\^`bd . * P==  "&4_x_hdr_segsiz_seglim_segloc_textseg_dataseg_bssseg_stksegn_pstring_badload_startlds_chainp_map_adr_mem_cpy<_seldskp_openfil_dirscan_seqread_gblsZ__bdosJ_tmp_sel.) ) - - 4 4 5  * 5 *5 :6 >5 B* F: N. R. `5 f5 v4 z5 '<%D L$RZb2j1rz3/0543*)('_ldcpmT_load _readhdr $_readxsg _loadseg h_fillbuf_bios28_swap_bios4"_bios1_bio_bdoscsvswitch2cretf_rdsec_blkindx_blknumR_do_io_new_extB_calcext_get_rc;;;;;;Build cpmldr.sys;;;;;; asz8k -o lbiosasm.o lbiosasm.8kn zcc -c -M1 -Dloader bios.c ld8k -o ldrbios.rel -r lbiosasm.o bi ' + + . * ( 6 ( , , 4 4 5 2 1 2 1 2 "1 81 @ -,+. 7 8 9 : 7 "6 *. .5 28 :6 >5 B. F* P `3 l t2 | _ldcpmT_load _readhdr $_readxsg _loadseg h_fillbuf_bios28_swap_bios4"_bios1_bio_do_phio_dir_rd_move_matchswitch1@_x_sg_xfer_context"_cpmfcb_textloc_datos.o ;make relocatable version ld8k -o cpmldr.rel -r ldrbios.rel ldrbdos.rel ;make a stripped version thats smaller ld8k -s H  P1 T1 f2 n  z  2 1           2 1 1  3 2 1 1 1 C  ( 4# <2 D1 J1-o cpmldrs.sys cpmldr.rel -lcpm era bootldr.a ar8k qv bootldr.a ldrbios.rel ldrbdos.rel ar8k qv bootldr.a lbiosasm.o bios.o Function 10 = Set Track */ #define SETSEC 11 /* BIOS Function 11 = Set Sector */ #define BSETDMA 12 /* BIOS Functiotm) Ver. 1.1, Copyright 1984, Digital Research Inc."; char *serial = "XXXX-0000-654321"; /* HISTORY ** ** 830801 F. Zlot ;Use the stripped version as its much smaller. pip c:cpmldr.sys[g0]=cpmldrs.sys user 0 putboot cpmldr.sys a: ;;;;;;;;; THE /*=======================================================================*/ /*+------------------------------------------------n 12 = Set DMA Addr */ #define WSECTOR 14 /* BIOS Function 14 = Write Sector */ XADDR physdir; /* Segmented address of;;;;;;;;;;;;;;;;;;;;;; ;Make putboot.z8k ;03/16/84 RFW ;;;;;;;;;;;;;;;;;;;;;; asz8k -o trk.o trk.8kn zcc -c -M1 putboot.nick (Zilog) -- written ** 840524 rfw modified includes */ #include "portab.h" #include "osif.h" /* cpm.h and bdos.h rEND ;;;;;;;;;; ---------------------+*/ /*| |*/ /*| CP/M-Z8K(tm) Bootstrap Writer for the OLIVETTI M20 (Z8000) |*/ /*| | dirbuf */ struct dpbs idpb; /* Disk Parameter Block */ struct bios_parm ibp; /* BIOS param block for BDOS callc ld8k -w -i -o putboot.z8k startup.o opt1.o putboot.o trk.o -lcpm era putboot.o eplaces with */ #include "stdio.h" /* osif.h 03-15-84 rfw */ #include "bdos.h" #include "xout.h" #define CDATA ND ;;;;;;;;;; */ /*| Copyright 1984, Digital Research Inc. |*/ /*| |*/ /*+-------------------------------------------------- 50*/ XADDR physibp; /* physical address of ibp structure*/ extern long map_adr(); /* Function to return physical addr */ ld8k -w -i -o putboot.z8k startup.o opt1.o putboot.o trk.o -lcpm era putboot.o 0 /* Parameter for map_adr() */ #define DIRSEC 1 /* Parameter for BIOS Write call */ #define SETTRK 10 /* BIOS -------------------+*/ /*=======================================================================*/ char *copyrt = "CP/M-Z8K( #define BPLS 128 /* Bytes per logical sector */ #define BPS 256 /* Bytes per sector */ #define BPS0 128 /* Bytes per); 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; } *argv[0]); exit(1); } curdsk = _ret_cdisk(); _get_dpb(map_adr((long) &idpb, CDATA)); /* Physaddr of idpb */ if( (finogical sectors in boot*/ register char *p; /* ptr to next part of code */ int track; /* Current track */ int se1 Sector 0 */ extern char T1S1[]; /* Track 1 Sector 1 */ #define HDRSIZE 24 /* # bytes in track 1 sect 1 header */ #endifrray named "syscode", preceded by a bunch of PCOS garbage ** which the Olivetti boot PROM expects to find there. Now we use d sector, trk 0 */ #define SPT 16 /* sectors per track */ #define LSPT 32 /* Logical sectors per track */ #define SYSTRKS if (fsize > SYSSIZE) { printf("Bootstrap too big\n"); exit(1); } else printf("Bootstrap file is %ld bytes\n", fsi = fopenb(system, "r")) == NULL) { printf("putboot: Can't open bootstrap file %s\n", system); exit(1); } fsize = 0L; ctor; /* Current sector */ physibp = map_adr( (long) &ibp, CDATA ); nlsecs = SYSTRKS * LSPT; /* size / log secs pe struct x_hdr xh; struct x_sg xs; int dsknum; /* Drive number 0-15 = A-P */ main(argc,argv) int argc; char *argv[];irect ** BIOS calls to write the syscode array out to the proper area on disk. ** For the Olivetti, this is tracks 1 and 2, 2 /* Number of boot tracks */ #define SYSSIZE SPT*BPS*SYSTRKS /* Max size of bootstrap */ #define STARTRK 1 /* Track numbze); p = syscode; #ifdef OLIVETTI for( i = 0; i < BPS; i++) *p++ = T1S0[i]; for( i = 0; i < HDRSIZE; i++) *p++ = T1S1[i]; /* read file header */ p = (char *) &xh; for (i = 0; i < sizeof(xh); i++) *p++ = (char) getc(fin); /* read andr trk */ /* Pause for the user to insert disk */ /* pause(drvname); */ #ifdef OLIVETTI /* Olivetti Track 0 Sector { register int i, j, c; register char *p; long fsize; int curdsk; /* Good to remember, & reset*/ if(argc != 3) since track 0 is special. */ putboot(syscode); printf("Bootstrap has been written.\n"); _sel_disk(curdsk); /* reselecer to start on */ FILE *fin; char syscode[SYSSIZE]; /* Hold the entire bootstrap here! */ char *system = "CPMLDR.SYS"; #endif while(fsize--) { if( (c = getc(fin)) == EOF) { printf("Unexpected EOF in %s, %ld left\n",system,fsize); ex count segment headers to get file size */ for (i = 0; i < xh.x_nseg; i++) { p = (char *) &xs; for( j = 0; j < sizeof(xs0 is special */ _sel_disk(dsknum); /* select as current disk */ putblk(0, 0, T0S0); #endif p = code; for(i = 0; i < nlusage(); system = *++argv; if( (dsknum = **++argv - 'a') < 0 || dsknum > 15) { printf("putboot: Illegal drive code %c\n",t original disk*/ } putboot(code) char *code; { register int i; /* Handy index */ register int nlsecs; /* # l/* Name of the prog to boot */ #ifdef OLIVETTI extern char T0S0[]; /* Track 0 Sector 0 */ extern char T1S0[]; /* Track it(1); } *p++ = c; } /* ** At this point, the entire bootstrap program code and data has been loaded ** into the asecs; i++) { track = STARTRK + i/LSPT; sector = i%LSPT; putblk(track, sector, p); p += BPLS; } } /* * Functibp.p1 = DIRSEC; /* Complete write immediately */ _bios_call( physibp ); /* Do it! */ } /* * If the user invoked us witple protocall on the serial port. I have also run in to a problem with the new ZCC compiler the -D option no longer works so ; n = sec + 1; /* sector number */ ibp.req = SETSEC; /* BIOS request number 11 */ ibp.p1 = (long) n; /* parameter = 12/19/84 The present release of CP/M-8000 you have just recieved is slightly restructured. the bios assembly modules have bon to select a given track for writing on, on the current disk. * Makes use of the BDOS direct BIOS call to issue Bios functioh the wrong number of args... */ usage() { printf("Usage: putboot \n"); exit(1); } now the loader define must be set to 1 at the beginning of bios.c in order to produce a LOADER BIOS. COPY.Z8K is now providsector # */ _bios_call( physibp ); /* Pass seg ibp address */ /* Sector is now set; now set dma address. */ ibp.req een setup for conditional assembly through 2 modules their names are lbiosasm.8kn and biosasm.8kn these have one equate which n 10. */ settrk(n) int n; { ibp.req = SETTRK; /* BIOS request number 10 */ ibp.p1 = (long) n; /* parameter = track #  the wrong number of args... */ usage() { printf("Usage: putboot \n"); exit(1); } ed with the system A new and working DDT.Z8K that portable and supports floatin point instructions note that there is a new= BSETDMA; /* BIOS Request number 12 */ ibp.p1 = map_adr( (long) addr, CDATA); /* param = seg address of I/O buffer */ controls the differences between the loader specific and normal bios assembler modules. By doing these modules this way the sy*/ _bios_call( physibp ); /* Pass seg ibp address */ } /* * Function to put block i of the boot track. */ putblk(trk entry in the bios memory region table for ddt.. A new version of the C compiler which fixes numerous bugs in all programming _bios_call( physibp ); /* Call BIOS */ /* Now can do a write */ ibp.req = WSECTOR; /* BIOS Request number 14 */ istem is reduced by 2k in size and removes the need for duplicate files. The bios.c module has changed little; added are sim, sec, addr) int trk, sec; char *addr; { register int n; _sel_disk(dsknum); /* select as current disk */ settrk(trk) areas. A much faster ld8k is provided A asz8k that supports floating point Numerous bug fixes to the library A ;**************************************************** ;* ;* Context Switch Routine ;* ;* xfer(context) ;* long contextr CP/M-8000(tm) BIOS ;* ;* 820927 S. Savitzky (Zilog) -- created. ;* 840815 R. Weiser (DRI) -- conditional assembly ;* __r2: 0 ;* returns ;* rr6: physical addr ;* ;* space codes: ;* 0: caller data ;* 1: caller program ;* 2: system data ;* 3m/User Memory Access ;* ;* _mem_cpy( source, dest, length) ;* long source, dest, length; ;* _map_adr( addr, space) -> pat a later date their will be a Segmented library provided a newer compiler, assembler,and linker. ; ;* ;* context is the physical (long) address of: ;* r0 ;* ... ;* r13 ;* r14 (normal r14) ;* r15 (normal r15) ;* ignoretext: .sect ;**************************************************** ;* ;* NOTE ;* The following system call interface routi: system program ;* 4: TPA data ;* 5: TPA program ;* ;* x+256 return segmented instruction address, ;* not data access adddr ;* long addr; int space; ;* ;* _map_adr( addr, -1) ;* sets user segment # from addr. ;* ;* _map_adr( addr, -2) ;* tra a later date their will be a Segmented library provided a newer compiler, assembler,and linker. d word ;* FCW (had better specify normal mode) ;* PC segment ;* PC offset ;* ;* The system stack pointer is not affected. nes ;* are designed to be called from non-segmented ;* C programs. ;* ;* Addresses are passed as LONGs. ;* ;*************dress ;* ;* FFFF set user-space segment from address ;* ;**************************************************** _mem_cpy:nsfer to context block at addr ;* ;* system call: mem_cpy ;* rr6: source ;* rr4: dest ;* rr2: length (0 < length <= 64K) ;* ;* Control never returns to the caller. ;* ;**************************************************** _xfer: ldl rr6,ARG*************************************** .global _xfer .global _mem_cpy .global _map_adr .global _bios .global _bdos ;copy memory C subroutine ;=== ldl rr6,ARG1(r15) ldl rr4,ARG3(r15) ldl rr2,ARG5(r15) sc #MEM_SC ret _map_adr;********** syscall.8kn cpm.sys + cpmldr.sys ******** ;* Copyright 1984, Digital Research Inc. ;* ;* System Call interface fo;* returns ;* registers unchanged ;* ;* system call: map_adr ;* rr6: logical addr ;* r5: space code ;* r4: ignored ;* r1(r15) ldl rr4,#-2 subl rr2,rr2 sc #XFER_SC ret ;**************************************************** ;* ;* Syste: ;map address C subroutine ;=== ldl rr6,ARG1(r15) ld r5, ARG3(r15) subl rr2,rr2 ; 0 length says map sc #MEM_SC rFILSIZEnt sector; /* CurPCPMx01.01  tbp = map_adr( (long) &ibp, CDATA ); nlsecs = SYSTRKS * LSPT; /* size / log seld r5,ARG1(r15) ldl rr6,ARG2(r15) sc #BDOS_SC ret .endif et .if LOADER .else ; not used by Loader Bios ;**************************************************** ;* ;* long _bios(ILSIZEcs per trk */ /* Pause for the user to insert disk */ /* pause(drvname); */ #ifdef OLIVETTI /* Olivetti Track 0 Se((8''PCOScode, p1, p2) ;* long _bdos(code, p1) ;* int code; ;* long p1, p2; ;* ;* BIOS, BDOS access ;* ;**************************__text__dataSYSSTK"rtc_extBPTHDRSIZEBOOTPSAS1SIZE_T0Slect original disk*/ ; { register int i; /* Handy index */ register int nlsecs; /************************** _bios: ld r3,ARG1(r15) ldl rr4,ARG2(r15) ldl rr6,ARG4(r15) sc #BIOS_SC ret _bdos: 0SYSPSASYSTEMSEG2_T1S1BPSs1dataSEG4 NBLKS_T1S0SYSSIZE* # logical sectors in boot*/ register char *p; /* ptr to next part of code */ int track; /* Current track */ i ld r5,ARG1(r15) ldl rr6,ARG2(r15) sc #BDOS_SC ret .endif