PAGE 62 ;P2BIOS.ASM aka ACIBS1K.ASM ;ALSPA COMPUTER, INC. Double Density Floppy Disk BIOS P2DOS/CPM2.2 ;****************************************************** ;EDIT HISTORY ; DATE: REL: MOD: ;01/11/82 - 02/01/82 1.8 ACIBS modified to 61K CPM, Blocking added ;02/01/82 - 02/02/82 Track mechanism fixed, side A:/B: code removed ;02/03/82 - 02/04/82 Diskswap fixed ;02/08/82 - 02/09/82 2.0 B: Logon fixed, sign-on 'glitch' fixed ;02/18/82 - 02/18/82 RCLOCK/WCLOCK timing fix, PIP/Density fixed ;02/25/82 2.1*SELDSK modified to delay disk change till R/W/SEEK ;03/02/82 2.2 Disk chg (dbl-sd PIP[V]) problem fixed ;03/05/82 D B: (rev A) problem fixed ;03/08/82 IBM format on B: option supported (rev xI) ;03/15/82 SYSFMT generated from IOBYTE, IOBYTE corrected ;03/16/82 - 03/25/82 2.3 Clock routines updated, IO routines re-done ;04/19/82 - 04/26/82 IOBYTE select, Coldboot in buffer, Autostart done. ;04/27/82 - 05/05/82 2.4 Add Motor on/off, User#/JumpTable saved in Wboot. ;05/07/82 2.5 System speed optimized. ;05/10/82 2.6 Wboot select error fixed. ;05/19/82 - 05/20/82 Select problem (when no Home after SELDSK) fixed. ;05/21/82 2.7*Select C:+ problem (drive# in Wboot) fixed. ;05/22/82 2.8*Tandon Motor-On speed mod. ;05/24/82 2.9 Motor-On mod improved (spindle-speed test added). ;08/23/82 - 08/25/82 3.0 1 Drive Side-select(B:dbl1/A:sngl0) bug fixed. ;10/27/82 - 11/02/82 Type-ahead buffer added (WordStar users rejoice). ;11/10/82 Density flag clear in HOME added (for JBS drives). ;11/10/82 - 11/11/82 Flush buffer on CONIN added. ;12/09/82 - 12/21/82 Autoswitch IOBYTE option added, Warmboot CCP only. ;12/21/82 - 01/17/83 3.1 Code for self-load of ACIDOS.COM file added. ;03/03/85 - 03/03/85 3.2%Added USER0 code ;09/18/87 3.3%Added USER0 warning (USER0 kills ZCPR3 & FCOPY) ;10/30/87 - 11/09/87 Added P2DOS support. ;11/10/87 - 11/12/87 made rev A code optional, to save a few bytes, ;11/15/87 Added 2-drive only flag and p2dos time function. ;11/17/87 Added clear of mem above BIOS on coldboot. ;11/21/87 Added ZCPR3 definitions. ;11/24/87 - 11/26/87 Added ZCPR3/P2DOS overlays and data areas. ;11/28/87 - 11/29/87 3.4%Added fix for motor-on problem. ;01/12/88 3.5%Upgraded for P2DOS v. 23 ;01/27/89 3.6%Added parallel printer status ;09/19/89 - 09/20/89 3.7%Modified to NOT use DIRBUF for scratch area. ; possible improvement - flush on nnnn*CONST (if no char is input)?? ; * Unreleased/Limited Release versions ; % Special version - Custom by W.O.S. ;****************************************************** MO EQU 09 ;LAST EDIT DATE DA EQU 20 YR EQU 89 REVNO EQU 37 ;REVISION # TRUE EQU 0FFFFH FALSE EQU NOT TRUE VER36 EQU FALSE ;Version3.6 code option (for restore after testing 3.7) ;************************************************************ ;* USER-SELECTED ASSEMBLY-TIME OPTIONS * ;************************************************************ IBMB EQU FALSE ;Set to true if IBM disk compatibility is desired. ;This will cause the system to use 'diskette' density ;when reading Track 1 of disks B:,C:,... (i.e. not A:). ;ALSPA disks always use double-density ;on track 1 to hold the system, even if disk density ;is single-d. Since the system on B: is not likely ;to be read (except, maybe, by 'Disk Editor' utilities) ;This should not affect normal operation. If an IBM-CPM ;translation utility is used, this option MUST be ;selected. LL EQU 0 ;DEFAULT PRINTER OPTION: (0,1,2,or 3) ;0=Parallel printer interface ;1=(console output) ;2=Serial interface, ETX/ACK protocol ;3=Serial interface, X-ON/X-OFF(or NO) protocol DD EQU 2 ;# OF PHYSICAL FLOPPY DISK DRIVES: (1 or 2) AA EQU 1 ;AUTOSWITCH OPTION: (0 OR 1) ;0=Autoswitch enabled ;1=Autoswitch disabled ;The Autoswitch option runs the Modem and Console ports ;in parallel, i.e. any character input from either ;port is accepted as console input, and is echoed to ;both Console and Modem output ports. SS SET 0 ;AUTOSTART OPTION: (0 OR 1) ;0=Autostart enabled (both Cold/Warmboot) ;1=Autostart disabled (Coldboot only) ;The Autostart option allows the user to insert a ;command in the CCP to be executed upon either coldboot ;or warmboot. If the option is disabled, the command in ;the CCP buffer will be ignored on warmboot, but ;executed upon coldboot(power-on or reset). ;Autostart MUST be ENABLED for ZCPR3! QSIZE EQU 25 ;Type-ahead buffer size (maximum: 255 characters) TYPEAHEAD EQU TRUE ;TYPE-AHEAD Option = TRUE or FALSE USER0 SET FALSE ;Add USER 0 = Public capability (patch CCP). ;USER0 MUST be FALSE for ZCPR3! P2DOS EQU FALSE ;TRUE if this is a P2DOS BIOS, FALSE for CP/M. ZCPR3 EQU TRUE ;TRUE if this BIOS is to be use with ZCPR3. DEBUG EQU FALSE ;Add debugging code - watch ENDDISK parameter! ;G = GoCPM dnn = drive# tnn = track# ;snn = sector# r = read w = write ;R = real read W = real write H = real home ;* = warmboot xnn = xlat sector NOREVA EQU TRUE ;If true, BIOS handles Alspa rev B boards only. ONLY2 EQU TRUE ;TRUE for 2-drive only version (saves code space). ;******************************************************************* if ZCPR3 SS SET 0 USER0 SET FALSE endif MSIZE EQU 61 ;MEMORY SIZE if not NOREVA REVA EQU 'A' ;VALUE OF CPU-BOARD=REV.A FLAG REVB EQU 'B' ;VALUE OF CPU-BOARD=REV.B FLAG endif ;SERIAL I/O PORTS (8251) MSTAT EQU 5 ;MODEM STATUS PORT MDATA EQU 4 ;MODEM DATA PORT CSTAT EQU 3 ;CONSOLE STATUS PORT CDATA EQU 2 ;CONSOLE DATA PORT LSTAT EQU 1 ;LIST STATUS PORT LDATA EQU 0 ;LIST DATA PORT ;PARALLEL I/O PORTS (8255 - REV B ONLY) PPORTA EQU 0D0H ;8255 PORT A PPORTB EQU PPORTA+1 ;8255 PORT B PPORTC EQU PPORTA+2 ;8255 PORT C PPCMD EQU PPORTA+3 ;8255 COMMAND PORT PPINIT EQU 91H ;A MODE0 IN, C HI OUT; B MODE0 OUT, C LO IN ;********************************************************** ;* SYSTEM CONFIGURATION: * ;* Both IOBYTE and SYSFMT are initialized from 'IOBYTA': * ;* IOBYTE=(IOBYTA AND IOBMSK) OR (DFTSY SHR 2 AND 1) * ;* SYSFMT=(IOBYTA AND SYSMSK) OR DFTSY * ;* This is done for continuity with earlier systems which * ;* used IOBYTE for all the system configuration functions.* ;********************************************************** IOBYTE EQU 0003H ;I/O BYTE: (Reserved Memory location) ;IOBYTE assignments: (Default = '*', optional defaults = '-') ;------------------------------------------------ ;ll: prn protocol pp: punch device ;-00 PARALLEL TTY: -00 PARALLEL PRN TTY: ;-01 (CONSOLE OUT) CRT: -01 (not used) PUN: ;-10 ETX/ACK LPT: *10 MODEM OUT UP1: ;*11 XON/XOFF(or NO) UL1: -11 CLOCK WRITE UP2: ; -------------------------------------- ;rr: reader device cc: console device ;-00 (not used) TTY: *00 CONSOLE TTY: ; 01 (not used) RDR: 01 CONSOLE/MODEM CRT: (autoswitch) ;*10 MODEM IN UR1: -10 MODEM I/O BAT: ; 11 CLOCK READ UR2: 11 CLOCK R/W UC1: ;------------------------------------------------ ;SYSFMT Sytem format byte: <---s-a-d> ;s: autostart mode a: autoswitch mode d: #drives ; 0 on (cold/warm) 0 on(modem&console) 0 2-drives ;*1 off (cold) *1 off(console only) *1 1-drive ;------------------------------------------------ SYSMSK EQU 05H ;(Mask for bits used in SYSFMT from IOBYTA) IOBMSK EQU (NOT SYSMSK) AND 0FFH ;(Mask for bits used in IOBYTE from IOBYTA) DFTIO EQU ((LL shl 6 or 28H) and iobmsk) ;Default IOBYTE DFTSY EQU (AA*4+(not (DD-1) and 1)+(SS*10H and 10H)) ;Default SYSFMT DFLTIOB EQU DFTIO or (DFTSY AND SYSMSK) ;Default IOBYTA ;******************************************************** CDISC EQU 0004H ;CP/M Reserved memory location - current disk ;DOUBLE DENSITY TEST CODE FLAG ;NOTE: FOR A DISK TO BE CONSIDERED DOUBLE DENSITY ;CODE3 MUST BE ALREADY ON THE DISK AT TRACK 0 ;SECTOR 1, BYTE 7F (LAST BYTE) ;CODE4 FOR DOUBLE DENSITY DOUBLE SIDE CODE3 EQU 0DDH CODE4 EQU 0D0H SINGL EQU 2 ;LOGDEN VALUE FOR SINGLE DENS. DISK ;BLOCKING/DEBLOCKING PARAMETERS WRALL EQU 0 ;WRITE TO ALLOCATED SECTOR*BDOS WRDIR EQU 1 ;WRITE TO DIRECTORY *CONSTANTS WRUAL EQU 2 ;WRITE TO UNALLOCATED SEC.* HSTSIZ EQU 1024 ;PHYSICAL SECTOR SIZE HSTSPT EQU 8 ;HOST SECTORS PER TRACK HSTBLK EQU HSTSIZ/128 ;CPM SECTORS/HOST SECTOR ;DISK IO PORTS DISK EQU 0F8H ;DISK BASE ADDRESS. DCOM EQU DISK ;DISK COMMAND PORT. DSTAT EQU DISK ;DISK STATUS PORT. TRACK EQU DISK+1 ;DISK TRACK PORT SECTP EQU DISK+2 ;DISK SECTOR PORT. DDATA EQU DISK+3 ;DISK DATA PORT. DSEL EQU DISK+5 ;DENSITY SELECT/MOTOR CONTROL PORT: ; CODE: | 01/02 | 04/08 | ; |density=dble/single|motor=on/off(revB)| DCONT EQU DISK+4 ;DISK CONTROL PORT: ; CODE: | 01/02 | 04/08 | ;REV B: |disk=B/A |side=1/0 | ;REV A: |disk/side| n/a | ;CPM PARAMETERS RTCNT EQU 10 ;RETRY COUNT BIAS EQU (MSIZE-20)*1024 ;BIAS FOR LARGER THAN 17K. CCP EQU BIAS+3400H ;START OF CPM. OFFSET EQU 980H-CCP ;OFFSET USED WITH DDT IN SYSTEM CONFIGURATION BDOS EQU CCP+806H ;BASE OF BDOS BIOS EQU CCP+1600H ;BASE OF BIOS CPML EQU BDOS-CCP ;LENGTH OF CPM CCP (re-loaded in warmboot). NSECTS EQU (CPML+127)/128 ;NUMBER OF CPM SECTORS IN IT. NPSECTS EQU (HSTSIZ-1+NSECTS*128)/HSTSIZ ;# OF PHYSICAL SECTORS MAXDRV EQU 1 ;DRIVES 0 - 1 VALID CCCONOT EQU CCP+8CH ;CCP: OUTPUT A TO CONSOLE CCGTUSR EQU CCP+113H ; GET USER NUMBER CCSTUSR EQU CCP+115H ; SET USER NUMBER CCOPFCB EQU CCP+0D0H ; CCP OPEN FILE (CPMFCB$) CCATTR EQU CCP+7D6H ; ATTRIBUTE FIELD IN CPMFCB$ CCDSK EQU CCP+7F0H ; DISK GIVEN IN COMMAND STRING CCERR EQU CCP+76BH ; TYPE ERROR STRING CCLOAD EQU CCP+6DEH ; IF FILE OPENS, GO HERE ;Character Equates CR EQU 0DH LF EQU 0AH ESC EQU 1BH BELL EQU 7 ;Z80 OPCODE EQUATES JR EQU 18H ;JR XX JRNZ EQU 20H ;JR NZ,XX JRZ EQU 28H ;JR Z,XX JRNC EQU 30H ;JR NC,XX JRC EQU 38H ;JR C,XX RRCB EQU 08CBH ;RRC B LDIR EQU 0B0EDH ;LDIR SRLA EQU 2FCBH ;SRL A DJNZ EQU 10H ;DJNZ XX PUSHIX EQU 0E5DDH ;PUSH IX LDIX EQU 21DDH ;LD IX,XXXX POPIX EQU 0E1DDH ;POP IX INI EQU 0A2EDH ;INI JPIX EQU 0E9DDH ;JP (IX) OUTI EQU 0A3EDH ;OUTI OUTCA EQU 79EDH ;OUT (C),A INAC EQU 78EDH ;IN A,(C) SBCHLDE EQU 52EDH ;SBC HL,DE RES2HL EQU 96CBH ;RES 2,(HL) RES3HL EQU 9ECBH ;RES 3,(HL) ;***********ACIDOS.COM PREFACE CODE**************** ;This code allows the ACIDOS.COM to be executed. If run ;(by mistake), it merely brings up the new operating system. ORG 0100H-OFFSET LXI H,CCP+OFFSET ;COPY (image in ram from .COM file) LXI D,CCP ; TO (executable address) LXI B,ENDISK-CCP ; (# of bytes of image) DW LDIR JMP BIOS ;COLDSTART (image at executable address) DB ' no copyright message here ' ;*************************************************** if USER0 ;***********USER0 PATCHES ON THE CCP**************** ;This code patches the CCP to look first on the A: drive, then in USER 0 ;for command files requested but not found in the current user number. ;It makes a call on a routine assembled intp the BIOS. ORG CCP+6DBH ;Replace 'jz ccerr' with 'jz patch' JZ CCPATCH ;Patch is called if file isn't found ;in current user. ORG CCP+7F2H ;Patch is placed in area of CCP occupied CCPATCH: ;by unused NOPs. LXI H,CCDSK ;Get drive spec'd in command ORA M ;If explicit drive given, look in USER0 JNZ CHKUSR0 INR M ;Else set A (was 0 on entry) to A: LXI D,CCATTR ; and retry (re-enter CCP) JMP CCP+6CDH ;*************************************************** endif ; I/O JUMP VECTOR ; THIS IS WHERE CPM CALLS WHENEVER IT NEEDS ; TO DO ANY INPUT/OUTPUT OPERATION. ; USER PROGRAMS MAY USE THESE ENTRY POINTS ORG BIOS JMP CBOOT ;FROM COLD START LOADER. WBOOTE: JMP WBOOT JMP LCONST JMP LCONIN JMP LCONOUT JMP LLIST JMP LPUNCH JMP LREADER JMP HOME JMP SELDSK JMP SETTRK JMP SETSEC ;SET SECTOR NUMBER. JMP SETDMA ;SET DISK STARTING ADR. JMP READ ;READ SELECTED RECORD JMP WRITE ;WRITE SELECTED RECORD JMP LLISTST ;RETURN LIST STATUS JMP SECTRAN ;SECTOR TRANSLATE ; this must be after 17th JUMP address DFLAGS: DB 0,0,0,0 ;DENSITY FLAGS *do CALL BLDPTR ;DENSITY SETTING ROUTINE*not CALL DENSITY ;FOR FCOPY PROGRAM *move RET ; *or IOBYTA: DB DFLTIOB ;DEFAULT I/O BYTE *change SYSFMT: DB DFTSY and IOBMSK ; * if not P2DOS DB 'Reserve';FOR FUTURE USE * endif if P2DOS JMP BTIME ;BIOS TIME ROUTINES * DB 'free' ;FOR FUTURE USE * endif UARTT: DB 0CEH ;USART MODE SELECT * UARTP: DB 0CEH ;CODES * UARTM: DB 0CEH ; * ;FIXED DATA TABLES FOR TWO-DRIVE STANDARD ;IBM-COMPATIBLE 8" DISKS (MODIFIED IN 'DENSITY'). ; DISK PARAMETER HEADER FOR DISK 00 -SNGL D DPBASE: DW TRANS,0000H DW 0000H,0000H DW DIRBF,DPSDBK DW CHK00,ALL00 ; DISK PARAMETER HEADER FOR DISK 01 -SNGL D DW TRANS,0000H DW 0000H,0000H DW DIRBF,DPSDBK DW CHK01,ALL01 ; SINGLE DENSITY SECTOR TRANSLATE VECTOR TRANS: DB 1,7,13,19 ;SECTORS 1,2,3,4 DB 25,5,11,17 ;SECTORS 5,6,7,8 DB 23,3,9,15 ;SECTORS 9,10,11,12 DB 21,2,8,14 ;SECTORS 13,14,15,16 DB 20,26,6,12 ;SECTORS 17,18,19,20 DB 18,24,4,10 ;SECTORS 21,22,23,24 DB 16,22 ;SECTORS 25,26 ; DOUBLE DENSITY SECTOR TRANSLATE VECTOR TRANSD: EQU 0 ;NO SECTOR TRANSLATION DPDDBK: ;DOUBLE DENSITY PARAMETER BLOCK DW 64 ;SECTORS PER TRACK - SPT DB 4 ;BLOCK SHIFT FACTOR - BSH DB 15 ;BLOCK MASK - BLM DB 0 ;NULL MASK - EXM DW 300-1 ;DISK SIZE IN BLOCKS - DSM DW 128-1 ;DIRECTORY MAX ENTRIES - DLM DB 0C0H ;DIR. ALLOC. MASK - AL0 DB 0 ;DIR. ALLOC. MASK - AL1 DW 128/4 ;DIR. CHECK SIZE - CKS DW 2 ;TRACK OFFSET - OFF DB 16 ;BLOCKSIZE/128 **************** DB 7 ;SECMASK *BLOCKING PARMS* DB 3+1 ;SECSHF * DO NOT MOVE * DB 64 ;CPMSPT **************** DPDDBK1: ;DOUBLE DENSITY PARAMETER BLOCK (2 side) DW 64 ;SECTORS PER TRACK - SPT DB 5 ;BLOCK SHIFT FACTOR - BSH DB 31 ;BLOCK MASK - BLM DB 1 ;NULL MASK - EXM DW 304-1 ;DISK SIZE IN BLOCKS - DSM DW 128-1 ;DIRECTORY MAX ENTRIES - DLM DB 80H ;DIR. ALLOC. MASK - AL0 DB 0 ;DIR. ALLOC. MASK - AL1 DW 128/4 ;DIR. CHECK SIZE - CKS DW 2 ;TRACK OFFSET - OFF DB 32 ;BLOCKSIZE/128 *BLOCKING PARMS * DB 7 ;SECMASK * =HSTSIZ/128-1 * DB 3+1 ;SECSHF *=LG2(SCMSK+1)+1* DB 64 ;CPMSPT *=HSTBLK*HSTSPT * DPSDBK: ;DISK PARAMETER BLOCK, SINGLE DENSITY DW 26 ;SECTORS PER TRACK DB 3 ;BLOCK SHIFT FACTOR DB 7 ;BLOCK MASK DB 0 ;NULL MASK DW 242 ;DISK SIZE-1 DW 63 ;DIRECTORY MAX DB 192 ;ALLOC 0 DB 0 ;ALLOC 1 DW 16 ;CHECK SIZE DW 2 ;TRACK OFFSET DB 8 ;BLOCKSIZE/128 **************** DB 0 ;SECMASK *BLOCKING PARMS* DB 0+1 ;SECSHF * DO NOT MOVE * DB 26 ;CPMSPT **************** ;******** END OF FIXED TABLES ************************************** ;******************* ; COLDBOOT: STARTUP ;******************* DB MO,DA,YR;THIS MUST PRECEDE CBOOT CBOOT: JMP BOOT ;BOOT CHANGES THIS TO WBOOT ;*************************************************************** ; WARM-BOOT: READ CCP AND PART OF BDOS BACK IN, THEN JUMP TO CCP. ;**************************************************************** ;*** THIS CODE BYTE MUST BE ALWAYS BE THE BYTE BEFORE LABEL WBOOT: *** DB 0DDH ;*** DO NOT MOVE OR REMOVE *** WBOOT: if DEBUG MVI A,'*' CALL CONOUTA endif LXI SP,80H ;SET STACK POINTER. LDA SEKDSK ;SAVE DISK NUMBER. PUSH PSW ; XRA A ;CLEAR BLOCKING FLAGS STA HSTACT ; -HOSTBUFFER INACTIVE STA UNACNT ; -UNALLOC CT=0 STA HSTWRT ; -NO PENDING WRITE STA SEKDSK ;SET DISK=0 (A:) CALL CLRDFLGS;CLEAR DENSITY FLAGS CALL CHKSD ;SELECT A: MVI A,1 ; CALL SEEK ;SET TRACK=1 MVI A,1 ;SECTOR=E=1 OUT SECTP ; MOV E,A ; LXI H,CCP ;HL -> CCP MVI C,DDATA ;C -> DATAPORT(1793) MVI A,8CH ;A=(READ W/15MS DELAY)COMMAND WBOOT2: CALL RLOOP ; READ SECTOR(E) => (HL) IN DSTAT ; IF (ERROR) THEN EXIT(RDERR) ANI 9DH ; DB JRNZ,BTERR-$-1 INR E ; INCREMENT SECTOR MOV A,E ; IF (SECTOR=NPSECTS) THEN EXIT(DONE) CPI NPSECTS+1 ; DB JRZ,WBOOT3-$-1 OUT SECTP ; SET SECTOR(E) MVI A,88H ; A=(READ W/NO DELAY)COMMAND DB JR,WBOOT2-$+0FFH ; END WBOOT3: POP PSW ;RESTORE DISK NUMBER. STA SEKDSK ; if not P2DOS LDA SYSFMT ;IF (AUTOSTART OFF) DISABLE CCP COMMAND ANI 10H DB JRZ,GOCPM-$-1 XRA A STA CCP+7 endif GOCPM: if DEBUG MVI A,'G' CALL CONOUTA endif MVI A,0C3H ;PUT JMP TO WBOOT STA 0 ;ADR AT ZERO. LXI H,WBOOTE SHLD 1 STA 5 LXI H,BDOS ;PUT JUMP TO BDOS SHLD 6 ;AT ADR 5,6,7. LXI H,80H ;SET DEFAULT DMA ADR. SHLD DMAADD LDA SEKDSK ;GET LAST REQUESTED DISK# MOV C,A PUSH B CALL CHKDS1 ;SET UP DRIVE POP B LDA CDISC ANI 0F0H ;GET USER# (if c:+ requested, cdisc is wrong) ORA C ;GET (REAL) DRIVE # MOV C,A if P2DOS and ZCPR3 JMP P2CWBT ;Do extra ZCPR3 warmboot stuff (reinit Submit FCB). endif if (not P2DOS) or (not ZCPR3) JMP CCP ;JUMP TO CCP. endif BTERR: LXI H,BTMSG ;GET ADDRESS OF "BOOT ERROR". CALL ERMSG ;PRINT IT. CALL LCONIN ;READ A CHAR FROM CONSOLE. JMP WBOOT ;DO A WARM BOOT. CLRDFLGS: LXI H,0 ;CLEAR DENSITY FLAGS SHLD DFLAGS ; SHLD DFLAGS+2; RET ;**************************************************************** ;SELDSK: SELECT DISK NUMBER ACCORDING TO REGISTER C. ;BLDPTR: BUILD POINTER (IN HL) TO DISK PARM BLK HEADER ;**************************************************************** SELDSK: if DEBUG MVI A,'d' CALL CONOUTA MOV A,C CALL PHEX endif LDA SEKDSK ;SAME AS LAST DRIVE REQUESTED? CMP C ; DB JRZ,BLDPTR-$-1; YES, JUST BUILD DRIVE HEADER POINTER. MOV A,C ; CPI MAXDRV+1;SEE IF DRIVE NO. IS VALID LXI H,0 ; (IF INVALID, RETURN HL=0) RNC ;ERROR - RETURN IF OUT OF RANGE PUSH PSW ;IF WRITE PENDING THEN CALL FLUSH ; FLUSH BUFFER POP PSW ; STA SEKDSK ;SEKDSK=NEW DRIVE SELECTED MOV C,A ;BUILD DPB HEADER POINTER CALL BLDPTR ; JMP DENSITY ;GET DENSITY PARMS BLDPTR: ;COMPUTE SEL. DRIVE HEADER VECTOR MOV L,C ;DISK NO. MVI H,0 ;AS 16 BIT QTY. DAD H ;*2 (BUILD 16-BYTE OFFSET) DAD H ;*4 DAD H ;*8 DAD H ;*16 LXI D,DPBASE;TABLE BASE DAD D ;EFFECTIVE ADDRESS OF VECTOR RET ; ;**************************************************** ;CHKSD: CHECK THAT CURRENT DISK=SELECTED DISK & ;CHKDSK: CHECK THAT DISK (C) =SELECTED DISK & ; & SELECT IF NOT ;**************************************************** CHKSD: LDA SEKDSK ;C=SEKDSK CHKDSA: MOV C,A CHKDSK: LDA CURDSK ;A=CURDSK CMP C ;IF (A=C) THEN RETURN(&TURN MOTORS ON) JZ MTRON ; CHKDS1: ;/******* ENTRY FOR BOOT (A=C=0)*******/ ;/*FROM HERE ON, C=DISK TO BE SELECTED*/ MOV E,A ;HL => TRACKTABLE(LASTDRIVE) MVI D,0 ; LXI H,TRTAB ; DAD D ; IN TRACK ;A = 1793 TRACK REGISTER (ADJUSTED) CALL INTRK ; MOV M,A ;M(HL) = A MOV E,C ;HL => TRACKTABLE(NEWDRIVE) LXI H,TRTAB ; DAD D ; MOV A,M ; CALL OUTRK ; OUT TRACK ;1793 TRACK REG = TRKTBL(NWDR) (ADJUSTED) if not ONLY2 LDA SYSFMT ;IF (1 DRIVE SYSTEM) THEN DO MOV B,A ; RAR ; DB JRNC,TWODR-$-1;SWAP DISKS: PUSH H ;THE FOLLOWING IS SINGLE DRIVE PUSH B ;DISK SWAP CODE LDA CURDSK ; CMP C ;CHECK IF CHANGE IN DISK & DB JRZ,CHKDS2-$-1 ; MOV A,C ;PUT DISK REFERENCE IN MESSAGE ADI 'A' ; STA SWDSK ; LXI H,SWMSG ;PROMPT FOR DISK SWAP CALL PMSG ; CALL LCONIN ;WAIT FOR KEY TO BE HIT CALL PCRLF ;PRINT CRLF CHKDS2: POP B ; POP H ; DB JR,CHKDS4-$-1 ; endif TWODR: MOV A,C ;ELSE CHANGE DRIVE INR A ; CMA ; ANI 3 ; OUT DCONT ; CHKDS4: MOV A,M ;IF (TRACK=0FFH) DO INR A ; DB JRNZ,CHKDS6-$-1 if not NOREVA LDA CPUREV ; IF (REV.B) OR (REV.A AND 2DRIVE SYSTEM) DO CPI 'B' DB JRZ,CHKDS5-$-1 MOV A,B RAR DB JRNC,CHKDS6-$-1 endif CHKDS5: PUSH B ; /*This is the 1st time this disk is*/ CALL OUTRK ; SET SIDE 0 /*accessed. We don't know where the*/ OUT TRACK ; /*head is, so we HOME it. */ CALL HOME1 ; HOME DRIVE POP B ; ENDIF CHKDS6: CALL MTRON ;WAIT FOR DRIVE READY(TURN MOTOR ON, ALSO) MOV A,C ;SET CURDSK=SELECTED DRIVE STA CURDSK ; CALL BLDPTR ;BUILD POINTER TO PARM. HDR. ;SET DENSITY PARMS FOR DISK (C). ;*********************************************** ;DENSITY: SET DRIVE PARMS FOR DRIVE # (C) ; C: DRIVE # (0-3) ; HL: -> DISK PARAMETER HEADER (IN DPBASE:) ; KILLS: A,BC,DE,FLAGS ;DETERMINE DENSITY OF NEW DISK, SELECT TRANSLATE TABLE ;AND DISK PARM BLOCK, IN DPBASE ;*********************************************** DENSITY: PUSH H ;SAVE DISKPARM HEADER PTR LXI H,DFLAGS;HL -> DENSITY FLAGS MVI B,0 ; DAD B ; MOV A,M ; ORA A ;GET DENSITY FLAG(C) JM LOGED ;SKIP IF LOGGED IN BEFORE PUSH H ; SAVE DENSITYFLAGPTR CALL CHKDSK ; CHECK IF SELECTED ALREADY, DO SO IF NOT. IF VER36 LDA SEKSEC ; SAVE SECTOR PUSH PSW ; LHLD DMAADD ; SAVE DMAADD PUSH H ; CALL HOME1 ; DENSITYFLAG=F(TRACK0,SECTOR1,BYTE7FH) MVI C,1 CALL SETSEC LXI B,DIRBF CALL SETDMA CALL READ POP H ; RESTORE DMADD SHLD DMAADD POP PSW ; RESTORE SECTOR STA SEKSEC POP H ; RESTORE DENSITYFLAGPTR LDA DIRBF+07FH;(DENSITYFLAG BYTE) ENDIF IF NOT VER36 CALL HOME1 LXI H,ERCNT MVI M,RTCNT DENS1: MVI A,0D0H ;FORCE INTERRUPT OUT DCOM XTHL ;KILL TIME XTHL XTHL XTHL MVI A,1 ;SET SECTOR OUT SECTP IN DSTAT ;LOOK AT HEAD LOAD BIT ANI 20H MVI A,8CH ;READ WITH HEAD LOAD DELAY DB JRZ,DENS2-$-1 MVI A,88H ; READ WITH NO HEAD LOAD DELAY DENS2: DW PUSHIX CALL XRLOOP ;READ SECTOR AND REATIN (ONLY) LAST BYTE DW POPIX MOV B,A IN DSTAT ;CHECK FOR ERRORS ANI 9DH DB JRZ,DENS3-$-1 ;NONE FOUND DCR M ;ERROR FOUND - DECREMENT ERRORCOUNT DB JRNZ,DENS1-$+0FFH ;RETRY CALL ERMSG0 ;PRINT ERRMSGS (RETURNS 0 WHICH WE USE FOR SSSD) DENS3: POP H ;RESTORE PTR TO DENSITY FLAG MOV A,B ENDIF CPI 0DDH ;CODE3 DB JRZ,LOGDD-$-1 CPI 0D0H ;CODE4 DB JRZ,LOGD0-$-1 LOG00: MVI A,82H ;LOGGED DISK IS SINGLE DENSITY LXI B,TRANS ; LXI D,DPSDBK; DB JR,LOGDRV-$-1 LOGED: CPI 081H ;TEST PREVIOUSLY LOGGED DRIVE PARM DB JRZ,LOGDD-$-1 ;AND BRANCH APPROPRIATELY CPI 085H ; DB JRNZ,LOG00-$+0FFH LOGD0: MVI A,85H ;LOGGED DISK IS DBL SIDE, DBL DENSITY LXI B,TRANSD; LXI D,DPDDBK1; DB JR,LOGDRV-$-1 LOGDD: MVI A,81H ;LOGGED DISK IS SNGL SIDE, DBL DENSITY LXI B,TRANSD; LXI D,DPDDBK; LOGDRV: MOV M,A ;SAVE DISKTYPE IN DENSITY FLAGS ANI 3 ;STRIP OFF LOGGED IN BIT STA LOGDEN ;SAVE DENSITY OF LOGGED IN DRIVE OUT DSEL ;SET IT POP H ;GET DISKPARMHDR PTR PUSH H ;SAVE IT FOR RETURN MOV M,C ;SET UP TRANSLATE TABLE PTR IN BLOCK INX H MOV M,B ; LXI B,9 ;SET UP DISK PARM PTR IN BLOCK DAD B ; MOV M,E ; INX H ; MOV M,D ; LXI H,15 ;LET HL->BLOCKING PARMS (SET BLKG PRMS FOR DISK) DAD D ; LXI D,CPMSPB;LET DE->LOGGEDDRIVE BLOCKINGPARM AREA LXI B,4 ;LET BC=#ITEMS TO MOVE DW LDIR ;(MOVE (HL)=>(DE),BC ITEMS) POP H ;RETURN DISKPARMHDR POINTER RET ; XRLOOP: DW LDIX,XRL1 OUT DCOM EI XRL1: HLT ;WAIT FOR F/D CONTROLLER TO START AGAIN... IN DDATA EI DW JPIX ;**************************************************************** ; SET TRACK NUMBER TO REGISTER C. ;**************************************************************** SETTRK: if DEBUG MVI A,'t' CALL CONOUTA MOV A,C CALL PHEX endif MVI H,0 ;SAVE TRACK NUMBER MOV L,C SHLD SEKTRK RET ;**************************************************************** ; SET DISK SECTOR NUMBER. ;**************************************************************** SETSEC: if DEBUG MVI A,'s' CALL CONOUTA MOV A,C CALL PHEX endif MOV A,C ;GET SECTOR NUMBER. STA SEKSEC RET ;RETURN FROM SETSEC. ;**************************************************************** ; SET DISK DMA ADDRESS. ;**************************************************************** SETDMA: MOV H,B ;MOVE B&C TO H&L. MOV L,C SHLD DMAADD ;PUT AT DMA ADR ADDRESS. RET ;RETURN FROM SETDMA. ;**************************************************************** ;TRANSLATE SECTOR IN BC TO HL USING TABLE POINTED AT BY DE. ;**************************************************************** SECTRAN: if DEBUG MVI A,'x' CALL CONOUTA MOV A,B CALL PHEX MOV A,C CALL PHEX endif MOV A,E ;TEST IF TABLE TRANSLATION IS REQUESTED ORA D ; (I.E. DE<>0) DB JRNZ,SECTR1-$-1 ; YES, DO IT MOV L,C ; NO, LET HL=BC+1 MOV H,B ; INX H ; RET ; SECTR1: XCHG ;GET TABLE ADDR IN HL DAD B ;INDEX INTO TABLE MOV L,M ;HL=M(BC+DE) MVI H,0 ; RET ; ;***************************************************** ;* Read CPM sector (record) from SEKDSK, * ;* SEKTRK,SEKSEC, to M(DMAADD). * ;***************************************************** READ: if DEBUG MVI A,'r' CALL CONOUTA endif XRA A STA UNACNT INR A STA READOP ;read operation STA RSFLAG ;must read data MVI A,WRUAL STA WRTYPE ;treat as unalloc DB JR,RWOPER-$-1 ;to perform the read ;***************************************************** ;* Write CPM sector (record) from M(DMAADD) * ;* to SEKDSK,SEKTRK,SEKSEC. * ;***************************************************** WRITE: if DEBUG MVI A,'w' CALL CONOUTA endif XRA A ;0 to accumulator STA READOP ;not a read operation MOV A,C ;write type in c STA WRTYPE LDA LOGDEN ;IF (SD), NEVER RD BEFORE WR CPI SINGL ; DB JRZ,NOOVF-$-1 ; MOV A,C ; CPI WRUAL ;write unallocated? DB JRNZ,CHKUNA-$-1 ;check for unalloc ;write to unallocated, set parameters LDA CPMSPB ;next unalloc recs STA UNACNT LXI H,SEKDSK ;Copy SEEK parms to UNALLOC parms LXI D,UNADSK LXI B,5 DW LDIR CHKUNA: ;check for write to unallocated sector LDA UNACNT ;any unalloc remain? ORA A DB JRZ,ALLOC-$-1 ;skip if not ;more unallocated records remain DCR A ;unacnt = unacnt-1 STA UNACNT LDA SEKDSK ;same disk? LXI H,UNADSK CMP M ;sekdsk = unadsk? DB JRNZ,ALLOC-$-1 ;skip if not ;disks are the same LHLD UNATRK CALL SEKTRKCMP ;sektrk = unatrk? DB JRNZ,ALLOC-$-1 ;skip if not ;tracks are the same LDA SEKSEC ;same sector? LXI H,UNASEC CMP M ;seksec = unasec? DB JRNZ,ALLOC-$-1 ;skip if not ;match, move to next sector for future ref INR M ;unasec = unasec+1 LDA CPMSPT ;end of track? CMP M ;count CP/M sectors DB JRNC,NOOVF-$-1 ;skip if no overflow ;overflow to next track MVI M,1 ;unasec = 1 LHLD UNATRK INX H SHLD UNATRK ;unatrk = unatrk+1 NOOVF: ;match found, mark as unnecessary read XRA A STA RSFLAG ;rsflag = 0 DB JR,RWOPER-$-1 ;to perform the write ALLOC: ;not an unallocated record, requires pre-read XRA A STA UNACNT ;unacnt = 0 INR A STA RSFLAG ;rsflag = 1 ;***************************************************** ;* * ;* Common code for READ and WRITE follows * ;* * ;***************************************************** RWOPER: if TYPEAHEAD CALL TESTI ;(TEST CONSOLE INPUT) endif LDA SECSHF ;COMPUTE HOST SECTOR MOV B,A LDA SEKSEC ;HOSTSECTOR=((SEEKSECTOR)-1 SHR SEKSHF)+1 DCR A DB JR,RWOPR2-$-1 RWOPR1: DW SRLA RWOPR2: DB DJNZ,RWOPR1-$+0FFH INR A STA SEKHST ;host sector to seek ;active host sector? LXI H,HSTACT ;host active flag MOV A,M MVI M,1 ;always becomes 1 ORA A ;was it already? DB JRZ,FILHST-$-1 ;fill host if not ;host buffer active, same as seek buffer? LDA SEKDSK LXI H,HSTDSK CMP M ;sekdsk = hstdsk? DB JRNZ,NOMATCH-$-1 LHLD HSTTRK CALL SEKTRKCMP ;sektrk = hsttrk? DB JRNZ,NOMATCH-$-1 LDA SEKHST LXI H,HSTSEC ;sekhst = hstsec? CMP M DB JRZ,MATCH-$-1 ;skip if match NOMATCH: ;not correct sector CALL FLUSH ;flush buffer STA ERFLAG ;REPORT ANY ERRORS FILHST: ;fill the host buffer LXI H,SEKDSK ;Copy SEEK parms to HOSTBUFFER parms LXI D,HSTDSK LXI B,5 DW LDIR LDA RSFLAG ;need to read? ORA A CNZ READHST ;yes, if 1 LXI H,ERFLAG ;REPORT ANY ERRORS ORA M MOV M,A XRA A STA HSTWRT ;no pending write MATCH: ;copy data to or from buffer LDA SEKSEC ;mask buffer number DCR A ; HL=((SEKSEC-1) AND SECMSK) SHL 7 MOV L,A LDA SECMSK ANA L RAR MOV H,A MVI A,0 RAR MOV L,A ; HL has relative host buffer address LXI D,HSTBUF DAD D ;hl = host address XCHG ;now in DE LHLD DMAADD ;get/put CP/M data XCHG LXI B,128 ;length of move LDA READOP ;which way? ORA A DB JRNZ,RWMOVE-$-1 ;skip if read ;write operation, mark and switch direction MVI A,1 STA HSTWRT ;hstwrt = 1 XCHG ;source/dest swap RWMOVE: DW LDIR ;BC initially 128, HL is source, DE is dest ;data has been moved to/from host buffer LDA WRTYPE ;write type CPI WRDIR ;to directory? LDA ERFLAG ;IF NOT THEN EXIT WITH FLAG RNZ ;clear host buffer for directory write ORA A ;errors? CZ WRITEHST;IF NOT, WRITE BUFFER RET ;***************************************************** ;* Compare M(HL)=SEKTRK, 16-bit compare * ;***************************************************** SEKTRKCMP: ;HL = .unatrk or .hsttrk, compare with sektrk XCHG LHLD SEKTRK ORA A ;(clear carry) DW SBCHLDE ;SBC HL,DE set Z/NZ on compare RET ;**************************************************************** ; READ THE SECTOR AT HSTSEC, HSTTRK, HSTDSK. ; USE HOSTBUFFER. ;**************************************************************** READHST: if DEBUG MVI A,'R' CALL CONOUTA endif LDA HSTDSK CALL CHKDSA ;SELECT HOST DISK CALL CHKTRK ;CHECK FOR CORRECT CURRENT TRACK, & MOVE MVI A,RTCNT ;GET RETRY COUNT. RRETRY: STA ERCNT ;STORE IN ERROR CTR. if TYPEAHEAD CALL TESTI endif LXI H,HSTBUF;GET STARTING ADR. MVI A,0D0H ;CAUSE INTERRUPT. OUT DCOM XTHL ;SOME DELAY. XTHL XTHL XTHL LDA HSTSEC ;GET SECTOR NUMBER. OUT SECTP ;SET SECTOR INTO 1793. IN DSTAT ;READ STATUS. ANI 20H ;LOOK AT HLD BIT. MVI A,8CH ;READ WITH HEAD LOAD DELAY DB JRZ,READ3-$-1 ;HEAD NOT LOADED. MVI A,88H ;CODE FOR READ W/O HD LD DELAY READ3: MVI C,DDATA ;SEND COMMAND TO 1793 DW PUSHIX CALL RLOOP DW POPIX IN DSTAT ;DONE: READ DISK STATUS. ANI 9DH ;LOOK AT ERROR BITS. JZ MTROFF ;IF NO ERROR THEN RETURN (&TURN MOTOR OFF) CALL ERCHK ;CHECK FOR SEEK ERROR. LXI H,RECNT ;GET RD ERR COUNT ADDR. INR M ;ONE MORE ERROR. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. DB JRNZ,RRETRY-$+0FFH ;TRY TO READ AGAIN. ERMSG0: LXI H,RDMSG ;PRINT "READ ". ERMSG: CALL PMSG ;PRINT ORIGIN MESSAGE. ERMSG1: MOV A,D ;GET ERROR BITS. RAL ;IF BIT 7 HIGH, LXI H,NRMSG ;"NOT READY". DB JRC,ERMSG2-$-1 MOV A,D ;GET ERROR BITS. ANI 10H ;IF BIT 4 IS HIGH, LXI H,RNMSG ;PRINT "RECORD NOT FOUND" CNZ PMSG MOV A,D ;GET ERROR BITS. ANI 8H ;IF BIT 3 IS HIGH, LXI H,CRCMSG ;PRINT "CRC ERROR". CNZ PMSG MOV A,D ;GET ERROR BITS. ANI 4H ;IF BIT 2 IS HIGH, LXI H,LDMSG ;PRINT "LOST DATA". CNZ PMSG MOV A,D ;GET ERROR BITS. RAR ;IF BIT 1 IS HIGH, LXI H,BSYMSG;PRINT "BUSY". CC PMSG PERMSG: LXI H,ERRMSG ;PRINT "ERROR." ERMSG2: CALL PMSG MVI A,1 ;SET FOR BDOS ERR. ORA A JMP MTROFF ;TURN MOTOR OFF RLOOP: DW LDIX,RL1 OUT DCOM ; EI ; RL1: HLT ; DW INI ; EI ; DW JPIX ; ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR. ERCHK: MOV D,A ;SAVE ERROR BITS IN D. ANI 10H ;IF RECORD NOT FOUND, CNZ CHKSK ;DO A CHECK ON SEEK. MOV A,D ;RESTORE BITS ORA A ;SET FLAGS, RET ;AND RETURN. ;CHECK FOR SEEK TO CORRECT TRACK, ;AND CHANGE IF NECESSARY. CHKSK: PUSH H ; MVI A,0C4H ;COMMAND TO READ ADDRESS MVI C,DDATA ; LXI H,ADDRBF ; DW PUSHIX CALL RLOOP ; DW POPIX LDA ADDRBF ; MOV B,A ; POP H ;DMAADD: TRK,SIDE,SECTOR,SECL,CRC,CRC CHKS3: IN DSTAT ;READ DISK STATUS. ORA A ;SET FLAGS. DB JRZ,CHKS4-$-1 ;READ ADR OK IF 0. CALL HOME1 ;OTHERWISE, HOME FIRST. DB JR,CHKTRK-$-1 CHKS4: MOV A,B ;UPDATE TRACK REGISTER. CALL OUTRK ;ADJUST IF 2SIDE OUT TRACK ; ;********************************************* ;CHKTRK: IF CURRENT TRACK <> HOST TRACK, GOTO HOSTTRACK ;********************************************* CHKTRK: IN TRACK CALL INTRK LXI H,HSTTRK CMP M RZ ;TRACKS ARE THE SAME, RETURN MOV A,M ;TRACKS NOT SAME, CORRECT JMP SEEK ; ;**************************************************************** ; FLUSH THE BUFFER IF A WRITE OPERATION IS PENDING ;**************************************************************** FLUSH: LDA HSTWRT ; ORA A ; RZ ;**************************************************************** ; WRITE THE SECTOR AT HSTSEC, HSTTRK, HSTDSK. ; USE HOST BUFFER. ;**************************************************************** WRITEHST: if DEBUG MVI A,'W' CALL CONOUTA endif LDA HSTDSK ;CHECK FOR CORRECT DISK, AND SELECT CALL CHKDSA ; CALL CHKTRK ;GO TO CORRECT TRACK MVI A,RTCNT ;GET RETRY COUNT. WRETRY: STA ERCNT ;STORE IN ERROR COUNTER. if TYPEAHEAD CALL TESTI endif LXI H,HSTBUF ;GET STARTING ADR. MVI A,0D0H ;STATUS INTERUPT FOR 1793. OUT DCOM ;COMMAND 1793. XTHL XTHL XTHL XTHL LDA HSTSEC ;GET SECTOR NUMBER. OUT SECTP ;SET THE SECTOR INTO 1793. IN DSTAT ;GET 1793 STATUS. ANI 20H ;CHECK FOR HEAD LOAD. MVI A,0ACH ;SET UP 1793 FOR WRITE. DB JRZ,WRITE2-$-1 ;HEAD IS NOT LOADED. MVI A,0A8H ;CODE FOR WRITE W/O HD LD. WRITE2: MVI C,DDATA DW PUSHIX CALL WLOOP DW POPIX IN DSTAT ;DONE: READ DISK STATUS. ANI 0FDH ;LOOK AT THESE BITS. STA HSTWRT ;CLEAR PENDINGWRITEFLAG IF NO ERROR JZ MTROFF ;RETURN IF NO ERROR (&TURN MOTOR OFF). CALL ERCHK ;CHECK/CORRECT SEEK ERR. LXI H,WECNT ;GET ADR OF WRITE ERR CTR. INR M ;ONE MORE WRITE ERROR. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. DB JRNZ,WRETRY-$+0FFH ;TRY TO WRITE AGAIN. LXI H,WTMSG ;PRINT "WRITE ". CALL PMSG MOV A,D ;GET ERROR BITS. ANI 40H ;LOOK AT BIT 6. LXI H,WPMSG ;PRINT "PROTECT ". CNZ PMSG MOV A,D ;GET ERROR BITS. ANI 20H ;LOOK AT BIT 5. LXI H,WFMSG ;PRINT "FAULT ". CNZ PMSG JMP ERMSG1 ;DO COMMON MESSAGES. WLOOP: DW LDIX,WL1 OUT DCOM EI WL1: HLT DW OUTI EI DW JPIX ;**************************************************************** ; HOME DISK DRIVE (RETURN TO TRACK 0) ;**************************************************************** HOME: if DEBUG MVI A,'H' CALL CONOUTA endif CALL FLUSH ;IF (BUFFER WRITE PENDING) THEN WRITE BUFFER ; (SPEEDS UP SAVE & PIP) CALL CLRDFLGS;CLEAR DENSITY FLAGS CALL CHKSD ;CHECK FOR SEKDSK AND SELECT IF NECESSARY HOME1: MVI A,2 OUT DSEL ;SINGLE DENSITY MVI C,0 CALL SETTRK CALL MTRON ;TURN MOTOR ON XRA A OUT DDATA ;TRACK # 0 MVI A,1CH ;3MS SEEK W/ HEAD LOAD & VERIFY CALL DCOMM IN DSTAT ;READ STATUS. ANI 91H ;LOOK AT BITS. RZ ;OK IF ZERO. MVI A,9 ;6MS RESTORE W/BEGIN HEAD LOAD CALL DCOMM ; IN DSTAT ANI 91H DB JRZ,HOME2-$-1 ;IF NOT OK, SEEK TRACK 0 XRA A CALL SEEK HOME2: JMP MTROFF ;RETURN (&TURN MOTOR OFF) ;**************************************************************** ;SEEK: MOVE THE HEAD TO THE TRACK IN REGISTER A (= 0-153). ;**************************************************************** SEEK: PUSH B ;SAVE B&C. PUSH PSW ; CALL MTRON ;(TURN MOTOR ON) POP PSW ; MOV B,A ;SAVE DESTINATION TRACK. XRA A ; STA SECNT ;CLEAR SEEK ERROR CTR MOV A,B ; ORA A ; IF (TK 0) THEN MVI A,2 ; SET UP FOR SINGLE DENS DB JRZ,SEEK1-$-1 MVI A,1 ; IF (TK 1) THEN CMP B ; SET UP FOR DOUBLE DENSITY if not IBMB DB JRZ,SEEK1-$-1 endif if IBMB DB JRNZ,SEEK0-$-1; (UNLESS NOT A: AND IBM OPTION SELECTED) LDA CURDSK ; (IN WHICH CASE, TRK1 DENSITY=LOGDEN) ORA A ; MVI A,1 ; DB JRZ,SEEK1-$-1 SEEK0: ; endif LDA LOGDEN ;ELSE GET DENSITY OF LOGGED DRIVE. SEEK1: OUT DSEL ;SET DENSITY IN 1793 MVI A,RTCNT ;GET RETRY COUNT. SRETRY: STA SERCNT ;STORE IN ERROR COUNTER. IN TRACK ;READ PRESENT TRACK NO. CALL INTRK ;ADJUST IF 2SIDE MOV C,A ;SAVE IN C. (CURR TK) CMP B ;SAME AS SEEK TRACK NO.? (A IS CURR TK) MOV A,B ;RESTORE A FROM B. (MAKE A DESIRED TK) DB JRZ,THERE-$-1 ;IF (THERE) THEN EXIT MVI A,0D0H ;TERMINATE COMMAND AND/OR BUSY OUT DCOM ; XTHL ;WASTE XTHL ;TIME MOV A,B ;GET TRACK CALL OUTRK ;ADJUST FOR 2-SIDE OUT DDATA ;OUTPUT (SEEK TRACK #) MVI A,1CH ;3MS SEEK W/ HEAD LOAD & VERIFY CALL DCOMM ; IN DSTAT ;READ STATUS. ANI 91H ;LOOK AT BITS. DB JRZ,THERE-$-1 ;OK IF ZERO. MOV B,A ;SAVE STATUS IN B LDA SECNT ; INR A ; STA SECNT ;ADD 1 TO SEEK ERR CTR LDA SERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. DB JRNZ,SRETRY-$+0FFH ;RETRY SEK. MOV D,B ;RESTORE STATUS TO D REG POP B ;RESTORE B&C. LXI H,SKMSG ;PRINT "SEEK ". JMP ERMSG ;DO COMMON ERR MESSAGES. THERE: POP B RET DCOMM: OUT DCOM EI HLT ;INTERUPT CAUSES RETURN RET ;WHEN COMMAND COMPLETE ;***************************************************** ; INTRK/OUTRK ADJUST TRACK NUMBERS IF >77 ;***************************************************** INTRK: ;TRACK # IN A INCREASED BY 77 IF SIDEFLG NON-ZERO PUSH PSW LDA SIDEFLG ORA A ;Z:=(TRACK<77) DB JRZ,INTRK1-$-1 POP PSW ADI 77 RET OUTRK: ;TRACK # IN A REDUCED BY 77 IF >76 AND SET SIDEFLG NON-ZERO PUSH PSW CPI 77 if not NOREVA LDA CPUREV ;A=CPU BD REV endif DB JRC,OUTRK1-$-1 if not NOREVA CPI REVB ; (>=T77) endif MVI A,4 ; (REV B) if not NOREVA DB JRZ,OUTRK0-$-1 MVI A,1 ; (REV A) endif OUTRK0: STA SIDEFLG OUT DCONT POP PSW SUI 77 RET OUTRK1: if not NOREVA CPI REVB ; ( Table Item DAD D DAD D MOV E,M ;HL = Table Item INX H MOV D,M XCHG PUSH B ;Push B (TOS=Caller's HL,DE) LXI D,DISP2 ;Push return address PUSH D if TYPEAHEAD CALL TESTI ;Test console input endif PCHL ;GOTO TABLE ROUTINE DISP2: POP B ;Restore caller's regs (except psw) POP H POP D RET CONST: ;IF(CONSOLE RDY) THEN RETURN (NZ) if TYPEAHEAD LDA ICOUNT ORA A endif if not TYPEAHEAD IN CSTAT ;IF (RX CHAR RDY) DO ANI 2 endif DB JRNZ,CONST1-$-1 RET AUTST: CALL CONST RNZ MODST: IN MSTAT ;RETURN (MODEM STATUS) ANI 2 RZ CONST1: ORI 0FFH RET CONIN: CALL FLUSH ;FLUSH BUFFER if TYPEAHEAD CALL TESTI LXI H,ICOUNT ;IF (CON CHAR NOT RDY) GOTO CONIN MOV A,M ORA A DB JRZ,CONIN-$+0FFH DCR M LXI H,ICHARQ+1; ELSE DO LXI D,ICHARQ MOV C,A MVI B,0 LDAX D ; A=CHAR DW LDIR ; DROP QUEUE endif if not TYPEAHEAD IN CSTAT ;IF (CON CHAR NOT RDY) GOTO CONIN ANI 2 DB JRZ,CONIN-$+0FFH IN CDATA ;ELSE RETURN (A=CHAR AND 7FH) endif ANI 7FH RET if TYPEAHEAD TESTI: IN CSTAT ;IF (RX CHAR RDY) DO ANI 2 RZ LDA ICOUNT ; IF (QUEUE 'M') THEN RETURN RNC DCR A CPI 6 DB JRNC,WCLOC0-$-1 ADI 2 CPI 6 DB JRC,WCLOC0-$-1 SUI 6 WCLOC0: INR A MOV C,A MVI A,40H OUT 0C0H ;ISSUE HOLD COMMAND MVI A,0BFH+14;PORT BASE ADDRESS SUB C ;ADD ADDRESS TO BASE PORT MOV C,A ;('A'=13, 'M'=1) MOV A,B MVI B,62+6 ;HOLD 200uS (+10% MARGIN) TIML1: DB DJNZ,TIML1-$+0FFH ADI 40H ;SET UP ADDRESS DW OUTCA ;OUT (C),A XTHL XTHL ;DELAY ORI 20H ;TURN ON WRITE DW OUTCA XTHL XTHL ;DELAY ANI 4FH ;TURN OFF WRITE DW OUTCA XRA A OUT 0C0H ;TURN OFF CLOCK INR M ;RESET DIRECTOR RET WCLK2: CPI 'A'-'0' RC ;RETURN IF < ASCII "A" CPI 'M'-'0'+1 RNC ;RETURN IF > ASCII "M" ANI 0FH ;STRIP OFF ASCII MOV M,A ;STORE DIRECTOR RET SWAP: MOV B,A XRA A ;SWAP BITS 0-4,1-3 CALL SWAP1 SWAP1: DW RRCB RAL DW RRCB RAL RET if P2DOS ;Set Time c==0FFH, de == &buffer: ; NDAYS: DW 0 ;(binary count) #days since 1/1/1978 ; HOURS: DB 0 ;(in BCD) 0000H<=ndays<=0FFFFH, ; MINUTE: DB 0 ;(in BCD) i.e. only 1978-2157, ; SECOND: DB 0 ;(in BCD) 179 years. ;Get Time c==00H; return hl == &buffer ;Note: calls to rclock return mmddyyWhhmmss ; pm: hx D2==1, 24: hx D3==1, leap: dx= D2==1 BTIME: INR C RC ;Cannot set time (yet?) GTIME: MVI A,0DH ;synchronise rclock STA PASSADD LXI D,TBUFMO ;read clock information into buffer MVI B,13 GTIME2: PUSH B CALL RCLOCK POP B ANI 0FH STAX D INX D DB djnz,GTIME2-$+0FFH GTIME3: MVI A,15H ;reset rclock STA PASSADD ;days = day_of_month-1; LXI H,TBUFYR ;for(yr -= 1978; yr>0; --y) CALL PAKBIN ; days += 365 + leap(yr); SUI 78 ;(We assume 1900s here, subtract just 0078) MOV B,A ;(b = p2dos year) PUSH B ;(save b for later calculations) LXI H,TBUFDY DW res2hl ;(clear "leap year" bit from clock chip) CALL PAKBIN ;(init hl = day of month - 1) DCX H LXI D,365 GTIME4: DCR B JM GTIME5 DAD D CALL LEAP DB jrnz,GTIME4-$+0FFH INX H DB jr,GTIME4-$+0FFH GTIME5: POP B ;(restore b=year#) XCHG ; m = mon-1; while (m-- > 0) LXI H,TBUFMO ; day += md[m] + (m == 1 && leap (y)); CALL PAKBIN DCR A MOV C,A ;(b=year,c=month,de=day,hl->md[m]) LXI H,MD-1 ADD L MOV L,A DB jrnc,GTIME6-$-1 INR H GTIME6: DCR C JM GTIME9 MOV A,M DCX H ADD E MOV E,A DB jrnc,GTIME7-$-1 INR D GTIME7: MOV A,C ;(is month == 1?) DCR A DB jrnz,GTIME6-$+0FFH CALL LEAP ;(yes, now is it a leap year?) DB jrnz,GTIME6-$+0FFH INX D ;(yup, increment #days by 1) DB jr,GTIME6-$+0FFH GTIME9: ;Save number of days since 1/1/1978 XCHG SHLD P2NDAY LXI D,P2HR LXI H,TBUFHR DW res3hl DW res2hl CALL PAKBCD CALL PAKBCD CALL PAKBCD LXI H,P2NDAY RET PAKBCD: MOV A,M ;Pack two successive bcd bytes into bcd byte RLC RLC RLC RLC INX H ADD M INX H STAX D INX D RET ;leap - Return Z if p2dos year is a leap year, NZ otherwise. ; year 1978 = p2dos year 0, and maximum p2dos year = 2157 LEAP: MOV A,B ;B = years since 1978 ; CPI 122 ; if (y = 122) return (NZ) /*year 2100*/ ; DB jrz,LEAP1-$-1 ADI 2 ;correction needed: year 2 is leap year, year 0 is not LEAP1: ANI 3 ; return (y % 4) RET MD: DB 31,28,31,30,31,30,31,31,30,31,30 ;Don't need December ;Pack two successive bytes into binary word PAKBIN: MOV A,M RLC RLC ADD M RLC INX H ADD M MOV L,A MVI H,0 RET endif ;************************************************************* ; End of I/O routines ;************************************************************* RNMSG: DB 'ID NOT FOUN','D'+80H CRCMSG: DB 'CR','C'+80H LDMSG: DB 'LOST DAT','A'+80H BSYMSG: DB 'BUS','Y'+80H WPMSG: DB 'PROTEC','T'+80H WFMSG: DB 'FAUL','T'+80H NRMSG: DB 'READY' ERRMSG: DB ' ERRO','R'+80H BTMSG: DB 'BOOT',' '+80H RDMSG: DB 0DH,0AH,'READ',' '+80H WTMSG: DB 0DH,0AH,'WRITE',' '+80H SKMSG: DB 0DH,0AH,'SEEK',' '+80H HEMSG: DB 0DH,0AH,'HOME',' '+80H if not ONLY2 SWMSG: DB 0DH,0AH,'insert ' SWDSK: DB '?: disk then key retur','n'+80H endif ;******************************************************** ;PRE-INITIALIZED DATA VARIABLES: ; These items are set to initial values when loaded ; during cold-load. ;******************************************************** ; Error counts. These locations keep track of the number ; of errors occurring during Read, Write, or Seek. RECNT: DB 0 ;READ ERROR COUNT. WECNT: DB 0 ;WRITE ERROR COUNT. SECNT: DB 0 ;SEEK ERROR COUNT. ERFLAG: DB 0 ;CPM BLOCKING ERROR FLAG SIDEFLG: DB 0 ;HEAD 2 SELECT FLAG (0=SIDE 1, NZ=SIDE 2) TRTAB: DB 0FFH,0FFH,0FFH,0FFH ;TRACK TABLE: PRESENT HEAD POSITION ;FOR FOUR DRIVES. PASSADD:DB 15H ;PASS COUNT & CLOCK REG PTR CLKDIR: DB 00H ;CLOCK DIGIT 'DIRECTOR' CURDSK: DB 0 ;Currently Selected Disk (Init=A:) UNACNT: DB 0 ;Blocking - Unallocated Record count HSTACT: DB 0 ; - Hostbuffer Active flag HSTWRT: DB 0 ; - Hostbuffer Write Pending flag if TYPEAHEAD ICOUNT: DB 0 ;INPUT QUEUE - number of characters endif if USER0 CHKUSR0: CALL CCGTUSR ;Get current user number ORA A JZ CCERR ;If already 0, print error message MOV E,A ;Save user number PUSH D MVI E,0 ;Set user = 0 CALL CCSTUSR CALL CCOPFCB ;Try to open file POP D PUSH PSW ;Restore user number CALL CCSTUSR POP PSW JNZ CCLOAD ;If file found, get it JMP CCERR ;Else print error endif ;******************************************************** HSTBUF: ;Start of Host-Buffer (For 1 physical sector) * ;Reserve HSTSIZ bytes * ;The Cold-Boot routine here will be overwritten * ;******************************************************** BOOT: LXI H,WBOOT ;RE-DIRECT CBOOT TO WBOOT SHLD CBOOT+1 LXI SP,7FH ;SET STACK POINTER. MVI A,0A6H ;INIT 8251 I/O PORTS CALL INITSIO MVI A,40H CALL INITSIO LDA UARTT OUT CSTAT LDA UARTP OUT LSTAT LDA UARTM OUT MSTAT MVI A,27H CALL INITSIO MVI A,PPINIT;INIT 8255 OUT PPCMD if not NOREVA MVI A,41H ;TEST IF 8255 IS PRESENT CALL TESTB ;IF SO, THIS IS REV B BOARD CMA ;(TEST TWICE, TO BE SURE) CALL TESTB ; endif XRA A ;SET DISK SELECT TO A: & USER# TO 0 STA SEKDSK STA CDISC LXI H,SYSFMT;INIT IOBYTE &SYSFMT MOV A,M ANI 4 RAR RAR MOV C,A LDA IOBYTA MOV B,A ANI IOBMSK ORA C STA IOBYTE MOV A,B ANI SYSMSK ORA M MOV M,A LXI H,SMSG ;PRINT OPENING MESSAGE. CALL PMSG LDA 07FH ;DISK OPTIONS: (temp addr. of density flag) LXI H,VDD ; DBL-D CPI 0DDH DB JRZ,DEN1-$-1 LXI H,VDSD ; DBL-SD (always DBL-D) CPI 0D0H DB JRZ,DEN1-$-1 LXI H,VSD ; SINGL-D DEN1: CALL PMSG if not ONLY2 MOV A,B ANI 1 ;DRIVE OPTIONS: endif LXI H,V2D ; 2DRIVE if not ONLY2 DB JRZ,STAT2-$-1 LXI H,V1D ; 1DRIVE endif STAT2: CALL PMSG MOV A,B ;PRINTER OPTIONS: ANI 0C0H LXI H,VPLL ; PARALLEL DB JRZ,STAT5-$-1 CPI 80H LXI H,VEA ; ETX-ACK DB JRZ,STAT6-$-1 LXI H,VXO ; XON/XOFF OR NO DB JRC,STAT7-$-1; CONSOLE, SAY NOTHING STAT5: CALL PMSG LXI H,PROTCL;'PRINTER PROTOCOL' STAT6: CALL PMSG if ZCPR3 LXI H,ENDISK-1 ;Clear rest of memory LXI D,ENDISK LXI B,0FFFFH-ENDISK+1 DW LDIR endif STAT7: if P2DOS and ZCPR3 JMP P2CBT ;Do extra initialisation for P2DOS/ZCPR3 endif if (not P2DOS) or (not ZCPR3) JMP GOCPM endif INITSIO: OUT CSTAT OUT LSTAT OUT MSTAT RET if not NOREVA TESTB: MOV B,A ;TEST 8255 PORT B WITH BYTE IN A: OUT PPORTB ; OUTPUT BYTE TO PORT. IN PPORTB ; READ BACK IN. CMP B ; IF SAME, TEST PASSES, RETURN. RZ ; MVI A,REVA ; ELSE CHANGE FLAG TO 'A' AND RETURN. STA CPUREV ; (NOTE: FLAG IS IN SIGN-ON MESSAGE) RET endif SMSG: DB CR, LF, LF, 'ACI ' DB MSIZE/10+'0', MSIZE MOD 10 +'0', 'K ' if P2DOS DB 'P2DOS' endif if not P2DOS DB 'CP/M' endif DB ' v' DB REVNO/10+'0', '.', REVNO MOD 10 +'0' if not NOREVA CPUREV: DB 'B' endif if IBMB DB 'I' endif if USER0 DB 'U' endif CRLF: DB CR,LF+80H if not ONLY2 V2D: DB '2 drive,',' '+80H ;DRIVE OPTIONS V1D: DB '1 drive,',' '+80H ; endif if ONLY2 V2D: DB '2 drive only,',' '+80H ; endif VPLL: DB 'PARALLE','L'+80H ;PRINTER OPTIONS VXO: DB 'XON/XOFF(or NO',')'+80H ; VEA: DB 'ETX/ACK' ; PROTCL: DB ' printe','r'+80H ; VSD: DB 'Single density,',' '+80H ;DISK OPTIONS VDD: DB 'Double density,',' '+80H ; VDSD: DB 'Double side,',' '+80H ; if ZCPR3 DB 0 ;byte to clear mem to. endif ENDISK: ;End of CP/M image required to be stored on disk. ;************************************************************************ if not ((HSTSIZ-($-HSTBUF)) SHR 15)*TRUE ;If not enough * DS (HSTSIZ-($-HSTBUF)) ;space is used, * endif ;reserve it * ;************************************************************************ ;**************************************************************** ; THE REMAINDER OF THE CBIOS IS RESERVED UNINITIALIZED ; DATA AREA, AND DOES NOT NEED TO BE A PART OF THE ; SYSTEM MEMORY IMAGE (THE SPACE MUST BE AVAILABLE, ; HOWEVER AS SCRATCH RAM AREA FOR BDOS USE). INITIALIZATION ; IS DONE FOR 'CONVENIENCE', AND IS SET TO PROBABLY ; CORRECT VALUES (FOR SINGLE-DENSITY DISKS). ;**************************************************************** ERCNT: DB 0 ;ERROR COUNT FOR RETRIES. SERCNT: DB 0 ;SEEK RETRY COUNTER. SEKDSK: DB 0 ;CURRENTLY REQUESTED DISK. *DON'T SEKTRK: DW 0 ;CURRENTLY REQUESTED TRACK. *RE-ARRANGE SEKHST: DB 1 ;CURRENTLY REQUESTED HOST SECTOR* SEKSEC: DB 1 ;CURRENTLY REQUESTED SECTOR. * HSTDSK: DB 0FFH ;HOSTBUFFER DISK. *DON'T HSTTRK: DW 0FFFFH ;HOSTBUFFER TRACK. *RE-ARRANGE HSTSEC: DB 0FFH ;HOSTBUFFER SECTOR. * DB 0FFH ;not used, reserved * UNADSK: DB 0 ;LAST UNALLOCATED DISK. *DON'T UNATRK: DW 0 ;LAST UNALLOCATED TRACK. *RE-ARRANGE DB 0 ;not used, reserved * UNASEC: DB 0 ;LAST UNALLOCATED SECTOR. * CPMSPB: DB 8 ;BLOCKSIZE/128 *******BLOCKING PARMS******** SECMSK: DB 0 ;HSTSIZ/128-1 ** DON'T RE-ARRANGE ** SECSHF: DB 0+1 ;LOG2(HSTSIZ/128)+1 **PARMS ARE FOR LOGGED DISK** CPMSPT: DB 26 ;TRACKSIZE/128 ***************************** LOGDEN: DB 2 ;DENSITY OF LOGGED DRIVE (2=SGL,1=DBL) RSFLAG: DB 0 ;READ SECTOR FLAG READOP: DB 0 ;READ OPERATION FLAG WRTYPE: DB 0 ;WRITE OPERATION TYPE DMAADD: DW 0080H ;CURRENT READ/WRITE ADDRESS. PCOUNT: DB 80H ;COUNTER FOR ETXACK: if TYPEAHEAD ICHARQ: DS QSIZE ;INPUT CHARACTER QUEUE endif DIRBF: DS 128 ;SCRATCH DIRECTORY AREA ALL00: DS 39 ;ALLOCATION VECTOR 0 ALL01: DS 39 ;ALLOCATION VECTOR 1 CHK00: DS 128/4 ;CHECK VECTOR 0 CHK01: DS 128/4 ;CHECK VECTOR 1 ADDRBF: DS 7 ;READ ADDRESS BUFFER (1 EXTRA BYTE RESERVED) if P2DOS ;data buffer for P2DOS time function - doesn't need initialization TBUFMO: DB 0,1 ;month TBUFDY: DB 0,1 ;day TBUFYR: DB 7,8 ;year DB 0 ;day of week (Sunday) TBUFHR: DB 0,0 ;hours 12-1-11 am, 52-41-51 pm TBUFMI: DB 0,0 ;minutes TBUFSC: DB 0,0 ;seconds P2NDAY: DW 0 ;#days since 1/1/78 P2HR: DB 0 ;bcd hours P2MIN: DB 0 ;bcd minutes P2SEC: DB 0 ;bcd seconds endif ;P2DOS if ZCPR3 ;This area needs to be cleared to all zeros on coldboot, with exceptions ;noted (and initialized by CBOOT. ZCPR3 must have these addresses defined ;in Z3BASE.HDR, exactly as they appear here. ;ZCPR3 Shell Stack SHSTK: DS 4*32 ;ZCPR3 Message Buffer Z3MSG: DS 80 ;80 byte command buffer for ZCPR3. Set Z3CL and Z3CLS (=80) in Z3BASE.HDR. Z3CL: DW 0 ;(Must be initialized to Z3BF by CBOOT) Z3SIZ: DB 0 ;(Must be initialized to 80 by CBOOT) Z3CT: DB 0 Z3BF: DS 80 ;Named directory buffer for ZCPR3. Set Z3NDIR and Z3NDIRS (=14) in Z3BASE. Z3NDIR: DS 14*18 + 1 ;External Stack for ZCPR3. Set EXTSTK in Z3BASE. Always uses 48 bytes. EXTSTK: DS 48 ;External FCB for ZCPR3. Set EXTFCB in Z3BASe. Always uses 36 byes. EXTFCB: DS 36 ;(Could this be put in the end of P2DOS also?) endif ;endif ZCPR3 if P2DOS ;External Stack for P2DOS. Set P2STK in P2DOS.MAC. Uses 62 bytes (v23) P2STK: DS 62 endif ;endif P2DOS if ZCPR3 ORG 0FF00H ;External ZCPR3 Environment ;Because this holds the pointers to the other data areas, this gets fixed ;at top of memory. It is initialized by the loader LDR. Z3ENV: DS 2*128 endif ;endif ZCPR3 ORG BIOS-115 ;Overlay code on top of P2DOS blank area ;Only 115 bytes are available in P2DOS v23. ;Note: P2DOS MUST have external stack. if P2DOS and ZCPR3 ;ZCPR3 External Command Executive Name (CMDRUN option) EXTRUN: DB 0 ;(A0:?) DB 'CMDRUN ' DB 'COM' ;ZCPR3 External Search Path EXTPATH: DB '$$' ;This drive, this user# DB '$',0 ;This drive, user 0 DB 1,0 ;Drive A: user 0 DB 0 ;ZCPR3 External Submit File FCB: ;EXTSUB in Z3BASE.LIB must be set either to the value given here for SUBFCB, ;or to zero. BE VERY SURE you aren't using this area for the ZCPR stack. The ;part of this that is commented out does not need to be initialised, there- ;fore it overlays the cold-boot code that may follow. P2CWBT: LXI H,0 ;Clear Submit FCB SHLD SUBEXT JMP CCP EXTSUB: DB 1 ;Default Drive A: DB '$$$ ' ;Submit filename DB 'SUB' ;Submit filetype SUBEXT: endif ;P2DOS and ZCPR3 if FALSE ;(force it to overlay) DB 0 ;Extent number - clear this on warmboot DB 0 ;s1 SUBFS2: DB 0 ;s2 SUBFRC: DB 0 ;record count DS 16 ;Disk Group Map SUBFCR: DS 1 ;Current Record Number endif ;FALSE if P2DOS and ZCPR3 ;ZCPR3 Command Line Initialisation: ;Because this code is used during coldboot only, which precedes the use of ;either the Submit facility or ZCPR3, this code will be overlayed by the ;Submit FCB area from below, and possibly by the ZCPR3 Stack from above. P2CBT: LXI H,Z3CNIT LXI D,Z3CL LXI B,P2CBTE-Z3CNIT DW LDIR JMP GOCPM ;Resume coldboot initialisation Z3CNIT: DW Z3BF ;Command Line image, must be same size as Z3CL DB 80 ;80 characters DB 0 ;Character count DB 'LDR SYS.ENV,SYS.NDR' ;coldboot command P2CBTE: endif ;ZCPR3 and P2DOS ACIDOS EQU (ENDISK+OFFSET+0FFH)/100H ;'SAVE xx ACIDOS.COM' END