;************************************************ ;* * ;* MSDOS FOR Z80 -- MORROW MD-11 * ;* * ;* ** Software Publishers,inc. ** * ;* ** 2500 E. Randol Mill Rd. ** * ;* ** copyright 1983, 1984 ** * ;* * ;************************************************ ; LAST REVISED 05/19/84 ; 2 AM ; 05/19/84 ADDED CLOSE MSDOS.FIL FOR MD-11 ; 02/28/84 ADDED MORROW AND OSBORNE ; 02/21/84 ADDED IN SOME ADM3 CRT ; 02/14/84 MSDOS SIZE AND NEW CRT DRIVER ; 01/13/84 PUT IO.SYS AND MSDOS.SYS IN MSDOS.COM!!!!!!!!!! ; 01/12/84 PUT IN KP-10 HARD DISK ; 01/09/84 NOW ABLE TO LOAD FROM A, B, OR C DRIVE ; 01/04/84 MADE PORTS EASY TO CHANGE ; 12/30/83 FIXED WRITE AND READ SO THAY DID NOT HAVE TO KNOW SPT ; 12/28/83 REMOVED TEST SOFTWARE FROM IBM VIEDO ; 12/14/83 WENT TO MSDOS 2.0 ; FIXED KEYBOARD SCAN ; ADDED TRANSFER PROGRAM ; 10/17/83 FIXED FORMAT STACK PROBLEM ; 10/06/83 SPECIAL KEYBOARD DRIVER FOR KAYPRO ; 09/23/83 SPECIAL CRT DRIVER FOR KAYPRO ; 09/06/83 WENT TO PHYSICAL IO FOR SELECTED COMPUTERS .Z80 .SFCOND TRUE EQU 0FFH FALSE EQU 0 KP EQU FALSE KPE EQU FALSE KP10 EQU FALSE GNAT EQU FALSE OSBORNE EQU FALSE MORROW EQU TRUE IF KP ENDIF IF KP10 ENDIF IF KPE ENDIF IF GNAT ENDIF IF OSBORNE ENDIF IF MORROW ADM3 EQU TRUE SOROC EQU FALSE MEMMAP EQU FALSE DRVC EQU FALSE ENDIF EXT DISKDVR ;DISK DRIVER EXT COPY ;COPY BETWEEN MSDOS AND CPM EXT STACK ;STACK MUST BE ABOVE 04000H EXT IOMD ;IOSYS AND MSDOS EXT IOMDSK ;MSDOS BOOT DISK EXT HD_DBP IF MEMMAP ENDIF IF KP10 ENDIF EXT IOCMD,IOPNT,NSPT,TSPT,MSGADD,INIT,RESTORE,FINIT,FSTORE GLOBAL AINP,BIOS,SENDM IFF MEMMAP CONST EQU BIOS+6 ;KEYBOARD STATUS CONIN EQU BIOS+9 ;KEYBOARD IN CONOUT EQU BIOS+12 ;CRT OUT ENDIF BACKSP EQU 08H ;BACKSPACE TAB EQU 09H ;TAB CURUP EQU 0BH ;CURSOR UP CR EQU 0DH LF EQU 0AH ESC EQU 01BH ;ESC CHARACTER IOBYTE EQU 3 BDOS EQU 5 ;CPM LINK LLOC EQU 060H ;88 LOAD LOCATION MSSEC EQU 0E4H ;SIZE OF IO.SYS IN 128 BYTE SECTORS ; BIOS FUNCTION CODES PRINTM EQU 9 ;PRINT BUFFER OPENF EQU 15 ;OPEN FILE READF EQU 20 ;READ SEQUENTIAL SETDMA EQU 26 ;SET DMA ACK EQU 0FFH ;INTERRUPT ACK INTCT EQU 080H ;INTERRUPT COUNTER INIT COUNT CONCMD EQU 084H ;FAST CONOUT COMMAND SETUSER EQU 20H ;SET USER ; Data structure for disk i/o control block ;------------------------------------------ ; dskop equ 0 ;disk operation code dskdrv equ 1 ;drive# (with side# in bit 7) dsktrk equ 2 ;track# dsksec equ 3 ;sector# dskptr equ 5 ;read/write pointer dskaux equ 7 ;auxilliary parameters (2 bytes) dsksts equ 9 ;operation completion status ; 88 PROCESSOR TAKES LEAD, LOOK FOR MESSAGE FROM IT JR START IF KP OR GNAT ENDIF IF KP10 OR KPE ENDIF IF KPE ENDIF IF OSBORNE ENDIF IF MORROW STATP: DB 1 ;STATUS PORT DATAP: DB 0 ;DATA PORT ENDIF STEP:: DB 0 ;STEP RATE FOR DISK USER: JP START ;USER HOOK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DW HD_DBP START: LD SP,STACK LD C,SETUSER ;SET TO USER 0 LD E,0 CALL BDOS CALL INIT ; FIND BIOS AND SET UP TO TALK TO IT LD DE,(1) ;PICK UP WARM BOOT JUMP ADDRESS LD A,6 ; AND SET UP INTERFACE LD HL,BIOS+7 ;ADDRESS NEW BIOS JUMP TABLE LD B,15 MOVBIOS: LD E,A LD (HL),E INC HL LD (HL),D ADD A,3 INC HL INC HL DJNZ MOVBIOS XOR A ;CLEAR INTERRUPT COUNT LD (INTCNT),A LD (WRFLAG),A ;WRITE FLAG LD (IBMDSK),A LD (STATE),A ;ESC SEQUENCE STATE AINP: LD A,(STATP) ;GET STATUS PORT LD C,A AINPC: IN A,(C) ;COMMAND? BIT 7,A JR NZ,AINP1 ;BIF ONE FOUND AINPS: LD A,(INTCNT) ;TIME FOR ANOTHER INTERRUPT? CP 0 JR NZ,AINP ;BIF IF INTERRUPT IN PROCESS INTACT: CALL CONST OR A JR Z,AINP ;BIF NO CHARACTER READER LD D,A ;SAVE A LD A,(STATP) ;GET STATUS PORT LD C,A LD A,D OUT (C),A ;SET INTERRUPT IN 88 LD A,INTCT ;SET INTERRUPT COUNTER LD (INTCNT),A JR AINPC ;WAIT FOR ACK INTDEC: DEC A ;TIME FOR MORE ACTION? ; NEED TO SAVE BACK TO INTCNT IF TIMER IS NEEDED JR NZ,AINPC ;BIF NOT JR INTACT AINP2: CALL CONST OR A JR Z,AINP ;BIF NOT LD A,(STATP) ;GET STATUS PORT LD C,A IN A,(C) ;MAKE SURE TRANSMIT THRU BIT 0,A JR NZ,AINP2 ;BIF NOT LD A,(DATAP) ;GET DATA PORT LD C,A LD A,1 ;SEND INTERRUPT TYPE OUT (C),A AINP3: LD A,(STATP) ;GET STATUS PORT LD C,A IN A,(C) ;MAKE SURE TRANSMT THRU BIT 0,A JR NZ,AINP3 ;BIF NOT CALL CONIN ;GET CONSOLE CHARACTER PUSH AF LD A,(DATAP) ;GET DATA PORT LD C,A POP AF OUT (C),A ;OUTPUT CHARACTER LD A,0 LD (INTCNT),A JR AINP ;SCAN AGAIN AINP1: LD A,(DATAP) LD C,A IN A,(C) ;INPUT 1ST CHARACTER CP CONCMD ;IS THIS A FAST CONOUT? JP Z,CCMD ;BIF YES CP ACK ;IS THIS AN INTERRUPT ACK? JR Z,AINP2 ;BIF YES CP ENQ ;LOOK FOR ENQUIRE JR NZ,AINP ;BIF NOT CALL GETM ;WAIT FOR VALID MESSAGE LD HL,MSGADD ;GOT ONE, FIND OUT WHAT TO DO LD E,(HL) LD A,25 ;MAKE SURE IT IS IN RANGE CP E SLA E LD D,0 LD HL,FTBL ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) FTBL: DW RINIT ;0 - INIT DW RWBOOT ;1 - WARM BOOT DW RCONST ;2 - CONSOLE STATUS DW RCONIN ;3 - CONSOLE CHARACTER INPUT DW RCONOUT ;4 - CONSOLE CHARACTER OUTPUT DW RLIST ;5 - LISTING OUTPUT DW RPUNCH ;6 - PUNCH OUTPUT DW RREADER ;7 - READER INPUT DW RHOME ;8 - HOME DW RSELDSK ;9 - SELECT DISK DW RSELTRK ;10 - 0AH - SELECT TRACK DW RSELSEC ;11 - 0BH - SELECT SECTOR DW RREAD ;12 - 0CH - READ DISK DW RWRITE ;13 - 0DH - WRITE DISK DW RLSTAT ;14 - 0EH - LIST STATUS DW RGIO ;15 - 0FH - GET IO BYTE DW RSIO ;16 - 10H - SET IO BYTE DW AINP ;17 - 11H DW AINP ;18 - 12H DW AINP ;19 - 13H DW RZ80 ;20 - 14H - GIVE CONTROL BACK TO Z80 DW RLDCPM ;21 - 15H - START LOAD OF MSDOS IO ; 22 ( 016H ) IS USED FOR TRANSFERING CPM DW AINP ;22 - 16H DW FREAD ;23 - 17H - FAST READ DW FWRITE ;24 - 18H - FAST WRITE DW IBMVID ;25 - 19H - IBM VIEDO DW AINP DW AINP DW AINP DW DISKIO ;29 - 1DH - DO PHYSICAL IO DW COPY ;30 - 1EH - COPY BETWEEN MSDOS AND CPM DW USER ;31 - 1FH - USER HOOK IO: IF KP10 ENDIF CALL DISKDVR ;LINK TO DISK IO RET RINIT: RWBOOT: ;RESET DISK SYSTEM XOR A ;INITIALIZE Z80 SND: LD (MSGADD),A XOR A SND3: LD (MSGADD+1),A ;SET MESSAGE LENGTH SND1: CALL SENDM ;SEND MESSAGE JP AINP RCONST: CALL CONST LD (MSGADD+2),A ;SEND DATA TO 88 LD A,2 LD (MSGADD),A ;GET CONSOLE STATUS ICON: LD A,1 JR SND3 RCONIN: CALL CONIN ;GET CONSOLE CHARACTER LD (MSGADD+2),A ;SEND DATA TO 88 LD A,3 LD (MSGADD),A ;GET CONSOLE CHARACTER JR ICON ;REST SAME AS ICONST RCONOUT: ;OUTPUT CONSOLE CHARACTER LD A,(MSGADD+2) JR CCMD1 CCMD: LD A,(STATP) ;GET STATUS PORT LD C,A IN A,(C) ;WAIT FOR CHARACTER BIT 7,A JR Z,CCMD LD A,(DATAP) ;GET DATA PORT LD C,A IN A,(C) ;INPUT CHARACTER CCMD1: LD C,A IFF MEMMAP CALL ADVCUR ENDIF IF KP10 OR KPE OR GNAT ENDIF CALL CONOUT CCMDR: LD A,(STATP) ;GET STATUS PORT LD C,A JP AINPS IF KP10 OR KPE OR GNAT ENDIF ; MSGADD+2 AL ; +3 AH ; +4 BL ; +5 BH ; +6 CL ; +7 CH ; +8 DL ; +9 DH IF MEMMAP ENDIF CLSCR: ;CLEAR SCREEN AND HOME CRT LD HL,0 LD (CURADD),HL IF KP10 OR KPE OR GNAT ENDIF IF ADM3 LD C,01AH ;CLEAR SCREEN ** ADM3 ** ENDIF IF SOROC ENDIF CALL CONOUT JP AINP IFF MEMMAP IBMVID: ;IBM VIEDO LD A,(MSGADD+3) ;GET AH CP 0 ;SET MODE(CLEAR SCREEN)? JR Z,CLSCR ;BIF YES CP 2 ;CURSOR POSITION? JR Z,GOTOXY ;BIF YES CP 6 ;SCROLL UP OR CLEAR SCREEN? JP Z,SCRUP ;BIF YES CP 7 ;SCROLL DOWN? JP Z,SCRDN ;BIF YES CP 9 ;WRITE ATB/CHAR? JP Z,CHAROUT ;BIF YES CP 10 ;WRITE CHARACTER? JP Z,CHAROUT ;BIF YES CP 14 ;WRITE TTY? JP Z,TTY ;BIF YES JP AINP GOTOXY: LD HL,(MSGADD+8) ;GET XY POSITION LD (CURADD),HL ;SAVE CURSOR CALL POSSCR ;POSITION CURSOR JP AINP SCRUP: SCRUP1: ;SCROLL UP LD A,(MSGADD+2) ;CHECK FOR BLANK WINDOW OR A JR Z,SCRUP2 ;GO BLANK WINDOW IF TRUE LD HL,01700H ;POSITION AT BOTTOM OF SCREEN LD (CURADD),HL CALL POSSCR LD C,LF ;SEND LINE FEED CALL CONOUT JP AINP SCRUP2: LD HL,MSGADD+6 ;CHECK FOR TOTAL CLEAR SCREEN LD A,(HL) INC HL OR (HL) JR NZ,SCRUP3 ;BIF NOT INC HL LD A,(HL) CP 79 JR NZ,SCRUP3 ;BIF NOT INC HL LD A,(HL) CP 23 JR Z,CLSCR SCRUP3: CALL BLKWD JP AINP ; POSITION CRT CURSOR ; HL IS LOST POSSCR: ;POSITION SCREEN PUSH HL LD C,ESC ;SEND ESCAPE CALL CONOUT LD C,'=' ;SEQUENCE CALL CONOUT POP HL PUSH HL LD A,H ;X POSITION CP 24 ;CHECK LIMITS JR C,POSSCR1 ;BIF OK LD A,23 ;SET TO LIMIT POSSCR1: ADD A,20H ;ADD OFFSET LD C,A CALL CONOUT POP HL LD A,L ;Y POSITION CP 80 ;CHECK LIMITS JR C,POSSCR2 ;BIF OK LD A,79 ;SET TO LIMIT POSSCR2: ADD A,20H ;ADD OFFSET LD C,A CALL CONOUT RET SCRDN: ;SCROLL DOWN *********************** NOT IN LD A,(MSGADD+2) ;CHECK FOR BLANK WINDOW OR A JR Z,SCRDN1 ;BIF YES JP AINP SCRDN1: LD HL,MSGADD+6 ;CHECK FOR TOTAL CLEAR SCREEN LD A,(HL) INC HL OR (HL) JR NZ,SCRDN2 ;BIF NOT INC HL LD A,(HL) CP 79 JR NZ,SCRDN2 ;BIF NOT INC HL LD A,(HL) CP 23 JP Z,CLSCR SCRDN2: CALL BLKWD ;GO BLANK WINDOW IF TRUE JP AINP CHAROUT: ;OUTPUT CHARACTER TO SCREEN LD A,(MSGADD+6) ;GET COUNT OF CHARACTERS LD C,A LD A,(MSGADD+7) LD B,A CH1: LD A,(MSGADD+2) PUSH BC LD C,A CALL CONOUT POP BC DEC C JR NZ,CH1 ;BIF MORE LD A,B OR C JP Z,CH2 ;BIF THRU DEC B JR CH1 CH2: LD HL,(CURADD) ;REPOSITION CURSOR CALL POSSCR JP AINP TTY: ;OUTPUT CHARACTER TO SCREEN LD A,(MSGADD+2) LD C,A CALL ADVCUR ;ADVANCE CURSOR CALL CONOUT JP AINP ;THRU BLKWD: ;BLANK WINDOW LD A,(MSGADD+7) ;GET STARTING ROW CP 24 ;CHECK FOR LIMITS JR C,BLKWD1 LD A,23 BLKWD1: LD H,A ;SAVE LD A,(MSGADD+6) ;GET STARTING COU CP 80 ;CHECK FOR LIMITS JR C,BLKWD2 LD A,79 BLKWD2: LD L,A PUSH HL CALL POSSCR ;POSITION CURSOR LD A,(MSGADD+9) ;GET ROW TO STOP ON LD B,A ;NO NEED TO CHECK FOR 25TH LINE LD A,(MSGADD+8) ; BECAUSE OF LIMIT CHECKS LATER LD C,A ;COLUMN TO STOP ON BLKWD3: PUSH BC LD C,' ' ;OUTPUT A BLANK CALL CONOUT POP BC POP HL LD A,L CP C ;AT END COL? JR Z,BLKWD4 ;BIF YES BLKWD5: INC L ;ADVANCE COL PUSH HL LD A,L CP 80 ;AT END OF LINE? JR NZ,BLKWD3 ;GO DO NEXT SPACE LD A,H ;ALSO AT END OF SCREEN? CP 23 POP HL JR Z,BLKWDE ;GO GET OUT INC H LD L,0 PUSH HL LD C,CR ;ADVANCE TO NEXT LINE CALL CONOUT LD C,LF CALL CONOUT JR BLKWD3 BLKWD4: LD A,H ;AT END ROW? CP B JR NZ,BLKWD5 BLKWDE: LD HL,(CURADD) ;PUT CUSOR BACK CALL POSSCR ;POSITION CURSOR RET ADVCUR: ;ADVANCE CURSOR PUSH AF PUSH HL LD HL,(CURADD) LD A,C ;IS CHARACTER A CR? CP CR JR Z,ADVCUR2 ;BIF YES CP LF ;IS CHARACTER A LF? JR Z,ADVCUR3 ;BIF YES CP BACKSP ;IS THIS A BACKSPACE? JR Z,ADVCUR5 ;BIF IF YES CP TAB ;IS THIS A TAB? JR Z,ADVCUR6 ;BIF YES CP CURUP ;IS THIS A CURSOR UP? JR Z,ADVCUR7 ;BIF YES INC L LD A,L CP 80 ;IS IT OVER 80 COLUMNS? JR NC,ADVCUR1 ;BIF YES ADVCUR4: LD (CURADD),HL ADVCUR1: POP HL POP AF RET ADVCUR2: LD L,0 ;MOVE TO 1ST COLUMN JR ADVCUR4 ADVCUR3: INC H LD A,H CP 24 ;IS THIS THE LAST LINE? JR C,ADVCUR4 ;BIF NOT JR ADVCUR1 ADVCUR5: ;BACKSPACE LD A,L OR A JR Z,ADVCUR1 ;RETURN IF ALREADY AT 0 DEC L JR ADVCUR4 ADVCUR6: ;TAB LD A,L ADD A,8 SRL A ;MAKE MOD 8 SRL A SRL A SLA A SLA A SLA A CP 80 JR C,ADVCUR4 ;BIF NOT OVER COLUMN 80 LD L,79 ;FORCE IF OVER JR ADVCUR4 ADVCUR7: ;CURSOR UP LD A,H OR A JR Z,ADVCUR1 ;RETURN IF ALREADY AT 0 DEC H JR ADVCUR4 IBMGXY: ;GET CURRENT CUSOR POSITION LD HL,(CURADD) LD (MSGADD+2),HL ;SEND DATA TO 8088 LD A,2 JP SND3 IBMGCH: ;GET CHARACTER POINTED TO BY CUSOR LD A,'?' ;INDICATE PROBLEM LD (MSGADD+2),A ;SEND DATA TO 8088 LD A,0 LD (MSGADD+3),A LD A,2 JP SND3 ENDIF RLIST: ;OUTPUT PRINTER CHARACTER LD A,(MSGADD+2) LD C,A CALL BIOS+15 IF KP10 ENDIF JP AINPS ;TRY FOR KEYBOARD IN RPUNCH: ;OUTPUT PUNCH CHARACTER LD A,(MSGADD+2) LD C,A CALL BIOS+18 JP AINP RREADER: CALL BIOS+21 ;INPUT CHARACTER FROM READER LD (MSGADD+2),A ;SEND DATA TO 8088 LD A,7 LD (MSGADD),A ;GET DATA FROM READER LD A,1 JP SND3 RHOME: ; CALL BIOS+018H ;HOME DISK LD A,8 LD (MSGADD),A ;DISK HOME JP SND RSELDSK: ; LD A,(MSGADD+2) ;GET DISK ; LD C,A ; LD A,(MSGADD+3) ;SET DISK LOG ON STATUS ; LD E,A ; CALL BIOS+01BH ;SELECT DISK ; 1 - 0 = DRIVE DOES NOT EXIST ; LD A,H ; OR L ; LD (MSGADD+2),A ;SET ERROR STATUS ; 2 - 0 = DOUBLE DENSITY ; LD A,(HL) ;TRANSLATION TABLE ; INC HL ; OR (HL) ; LD (MSGADD+3),A ;SET NOT ZERO IF PRESENT ; DEC HL ;SAVE TRANSLATION TABLE ADDRESS ; LD A,(HL) ; LD (TNSLAT),A ; INC HL ; LD A,(HL) ; LD (TNSLAT+1),A ; LD DE,9 ;POINT TO PARAMETER BLOCK ; ADD HL,DE ; LD E,(HL) ; INC HL ; LD D,(HL) ; EX DE,HL ; LD A,(HL) ;SAVE NUMBER OF SECTORS PER TRACK ; CP 32 ;TEST FOR IBM 5 1/4" DISK ; JR Z,NIBM ; ; LD A,(ZDISK) ;IS THIS SET TO IBM? ; LD B,A ;SET WHICH DISK IS IBM ; OR A ; LD A,1 ; JR Z,SIBM1 ;BIF THIS IS DRIVE ZERO ;SIBM2: ; SLA A ; DJNZ SIBM2 ;SIBM1: ; LD B,A ; LD A,(IBMDSK) ; AND B ; LD A,0 ;ASSUME NO ; JR Z,NIBM ;BIF NOT IBM DISK SET ; INC A ; LD HL,IBMPRM ;SET UP IBM DISK DATA ;NIBM: LD (IBM),A ; 3 ; THRU ; 18 - DISK PARAMETER BLOCK ; LD BC,15 ; LD DE,MSGADD+4 ; LDIR ; LD A,9 ; LD (MSGADD),A ;SELECT DISK XOR A ;PUT 0'S IN ALL OTHER PLACES LD B,17 LD HL,MSGADD+2 CL1: LD (HL),A INC HL DJNZ CL1 LD A,17 ;SEND DISK DATA JP SND3 ;RSELD1: LD A,9 ; LD (MSGADD),A ;SELECT DISK ; LD A,2 ; JP SND3 RSELTRK: LD A,(MSGADD+2) LD C,A LD B,0 ;FIX SELECT TRACK TO USE BC ; CALL BIOS+01EH ;SELECT TRACK LD A,10 LD (MSGADD),A ;SELECT DISK TRACK JP SND RSELSEC: LD A,(MSGADD+2) LD C,A LD B,0 ;FIX SELECT SECTOR TO USE BC ; CALL SECTOR ;SELECT SECTOR LD A,11 LD (MSGADD),A ;SELECT DISK SECTOR JP SND ;REST SAVE AS IINIT RREAD: ; LD BC,MSGADD+2 ;SET DMA ; CALL BIOS+024H ; CALL BIOS+027H ;READ SECTOR (128 BYTES) ; LD B,A LD A,12 LD (MSGADD),A ;READ DISK ; LD A,B ; OR A ;TEST FOR ERROR ; JR NZ,RREAD1 ;BIF ERROR ; LD A,128 ;SET MESSAGE LENGTH ; JP SND3 RREAD1: LD (MSGADD+2),A LD A,1 JP SND3 RWRITE: LD BC,MSGADD+2 ;SET DMA ; CALL BIOS+024H ; LD A,(MSGADD+130) ;SET C REG ; LD C,A ; CALL BIOS+02AH ;WRITE SECTOR (128 BYTES) ; LD (MSGADD+2),A LD A,13 LD (MSGADD),A ;WRITE TO DISK JP ICON RLSTAT: CALL BIOS+02DH ;LIST DEVICE STATUS LD (MSGADD+2),A LD A,14 LD (MSGADD),A ;GET LIST STATUS JP ICON RZ80: IF ADM3 LD C,01AH ;CLEAR SCREEN ** ADM3 ** ENDIF IF SOROC ENDIF CALL BIOS+12 ;CRT OUT LD C,9 LD DE,CSMSG CALL BDOS CALL RESTORE JP 0 ;RETURN CONTROL TO Z80 CSMSG: DB CR,LF,LF,LF,LF,LF,LF,LF,LF DB LF,LF,LF,LF,LF,LF,LF,LF DB LF,LF,LF,LF,LF,LF,LF,LF DB '$' RGIO: LD A,15 LD (MSGADD),A ;GET I/O BYTE LD A,(IOBYTE) LD (MSGADD+2),A JP ICON RSIO: LD A,(MSGADD+2) ;SET I/O BYTE LD (IOBYTE),A JP AINP DISKIO: LD A,(MSGADD+2) ;GET OPCODE CP 1 ;READ SECTOR JP Z,FREAD ;BIF YES CP 2 ;WRITE SECTOR JP Z,FWRITE CP 4 ;FORMAT DISK JP Z,FORMAT ;GO FORMAT A DISK JP SND ;OPCODE NOT FOUND ; READ WITH NEW DISK HANDLER ; MSGADD 0 - ID ; 1 - SIZE OF MESSAGE ; 2 - DISK ; 3 - TRACK LOW BYTE ; 4 - TRACK HIGH BYTE ; 5 - SECTOR LOW BYTE ; 6 - TRACK HIGH BYTE FREAD: CALL READIO ;DO READ LD B,80H JR Z,IREAD1 ;BIF ERROR LD B,1 LD (MSGADD+2),A IREAD1: LD A,B LD (MSGADD+1),A LD A,23 LD (MSGADD),A ;READ DISK CALL SENDM ;SEND MESSAGE JP AINP ; SECTOR IS TO START WITH SECTOR 0 READIO: PUSH BC PUSH DE PUSH HL PUSH IX LD IX,IOCMD LD A,1 ;SET READ OPCODE LD (IX),A LD A,(MSGADD+2) ;SAVE DISK USED LD E,A ;PUT DRIVE IN DE LD D,0 IFF KP10 CP 2 ;IS THIS C DRIVE JR NZ,FREAD1C ;BIF IF NOT LD A,1 ;MAKE DRIVE B FREAD1C: ENDIF LD (IX+DSKDRV),A IF KP10 ENDIF LD A,(MSGADD+5) ;GET SECTOR LD L,A LD A,(MSGADD+6) LD H,A INC HL LD (IX+DSKSEC),L LD (IX+DSKSEC+1),H LD A,(MSGADD+7) ;IS THIS A DOUBLE SIDED DISK REQUEST OR A JR Z,FREAD1 ;BIF IF NOT DS REQUEST SET 7,(IX+DSKDRV) ;SET SIDE 2 FREAD1: FREAD2: LD A,(MSGADD+3) ;GET TRACK LD (IX+DSKTRK),A LD HL,SECSIZE ;SET SECTOR SIZE ADD HL,DE ADD HL,DE LD A,(HL) LD (IX+DSKAUX),A LD (SSCNT),A ;SAVE SIZE FOR MESSAGE INC HL LD A,(HL) LD (IX+DSKAUX+1),A LD (SSCNT+1),A IF KP10 ENDIF LD BC,MSGADD+2 ;SET DMA LD (IX+DSKPTR),C LD (IX+DSKPTR+1),B CALL IO ;READ PHYSICAL SECTOR LD A,(IX+DSKSTS) OR A ;TEST FOR ERROR POP IX ;LEAVE NZ STATUS IF ERROR POP HL POP DE POP BC RET IF KP10 ENDIF FWRITE: PUSH IX LD IX,IOCMD LD A,2 ;SET WRITE OPCODE LD (IX),A LD A,(MSGADD+2) ;SAVE DISK USED LD E,A LD D,0 IFF KP10 CP 2 ;IS THIS C DRIVE JR NZ,FREAD2C ;BIF IF NOT LD A,1 ;MAKE DRIVE B FREAD2C: ENDIF LD (IX+DSKDRV),A IF KP10 ENDIF LD A,(MSGADD+5) ;GET SECTOR LD L,A LD A,(MSGADD+6) LD H,A INC HL LD (IX+DSKSEC),L LD (IX+DSKSEC+1),H LD A,(MSGADD+7) ;IS THIS A DOUBLE SIDED REQUEST OR A JR Z,FWRITE1 ;BIF IF NOT A DS REQUEST SET 7,(IX+DSKDRV) ;SET SIDE 2 FWRITE1: FWRITE2: LD A,(MSGADD+3) ;GET TRACK LD (IX+DSKTRK),A LD HL,SECSIZE ;SET SECTOR SIZE ADD HL,DE ADD HL,DE LD A,(HL) LD (IX+DSKAUX),A LD C,A INC HL LD A,(HL) LD (IX+DSKAUX+1),A LD B,A ;GET DATA IN MEMORY IF KP10 ENDIF LD HL,MSGADD+8 LSWT1A: LD A,(STATP) ;GET STATUS PORT PUSH BC LD C,A LSWT1: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,LSWT1 ;BIF NOT LD A,(DATAP) ;GET DATA PORT LD C,A IN A,(C) ;INPUT DATA LD (HL),A INC HL POP BC DEC BC LD A,B OR C JR NZ,LSWT1A ;LOOP TILL THRU LD BC,MSGADD+8 ;SET DMA LD (IX+DSKPTR),C LD (IX+DSKPTR+1),B CALL IO ;WRITE PHYSICAL SECTOR LD A,24 LD (MSGADD),A ;WRITE DISK LD A,(IX+DSKSTS) LD (MSGADD+2),A ;STATUS POP IX LD A,1 LD (MSGADD+1),A CALL SENDM ;SEND MESSAGE JP AINP IF KP10 ENDIF FORMAT: ;FORMAT A DISK ; BIT 7 - HARD DISK ; BIT 6 - 8 SECTORS/TRACK ; BIT 5 - 10 SECTORS/TRACK ; BIT 4 - DOUBLE SIDED ; BIT 3 - CLEAR DISK WITHOUT FORMATING ;NA ; BIT 2 - O OPTION ;NA ; BIT 1 - VOLUME LABLE ;NA ; BIT 0 - SYSTEM DISK, NOT USED FOR FORMATING ;NA CALL FINIT LD IX,IOCMD LD A,4 ;SET FORMAT OPCODE LD (IX),A LD A,(MSGADD+3) ;SAVE DISK USED IF KP10 ENDIF LD (IX+DSKDRV),A LD HL,IOPNT ;SET POINTER TO FORMAT INFO LD (IX+DSKPTR),L LD (IX+DSKPTR+1),H LD A,(MSGADD+4) ;GET COMMAND LD IY,ESPT ;IS THIS 8 SECTORS/TRACK? BIT 6,A JR NZ,FMT2 ;BIF YES LD IY,TSPT ;IS THIS 10 SECTORS/TRACK? BIT 5,A JR NZ,FMT2 LD IY,NSPT ;DEFAULT TO 9 SECTORS/TRACK FMT2: LD A,(IY+1) LD (HL),A ;SET BYTES/SECTOR PUSH HL PUSH DE PUSH BC LD B,A LD A,(IX+DSKDRV) ;GET DISK USED LD E,A LD D,0 LD HL,SSTBL ;CONVERT TO WORD LD A,B OR A ;0? JR NZ,FMSS2 ;BIF NO INC A LD B,A FMSS2: INC HL INC HL DJNZ FMSS2 LD C,(HL) INC HL LD B,(HL) LD HL,SECSIZE ;SET SECTOR SIZE FOR LATER FAT WRITE ADD HL,DE ADD HL,DE LD (HL),C INC HL LD (HL),B POP BC POP DE POP HL INC HL LD A,(IY+2) LD (HL),A ;SET SECTORS/TRACK INC HL LD A,(IY+3) LD (HL),A ;SET GAP LENGTH INC HL LD A,0 ;START WITH 0 LD (IX+DSKTRK),A ; AND SET TRACK LD A,0E6H LD (HL),A ;SET FILL CHARACTER INC HL EX DE,HL ;SET SECTOR MAP PUSH IY POP HL INC HL INC HL INC HL INC HL LD BC,10 ;MAX NUMBER OF SECTORS NOW LDIR LD HL,6250 ;LENGTH OF TRACK IN BYTES LD (IX+DSKAUX),L LD (IX+DSKAUX+1),H LD B,(IY) ;SET UP TRACK LOOP FMT4: PUSH BC CALL IO ;DO FORMAT LD A,(IX+DSKSTS) ;CHECK FOR ERROR OR A JR NZ,FMT7 LD A,(MSGADD+4) ;GET COMMAND BIT 4,A ;DOUBLE SIDED JR Z,FMT5 ;BIF NOT SET 7,(IX+DSKDRV) ;SET DOUBLE SIDED CALL IO ;DO FORMAT RES 7,(IX+DSKDRV) ;RESET DOUBLE SIDED FMT5: INC (IX+DSKTRK) ;ADVANCE TRACK FMT7: POP BC LD A,(IX+DSKSTS) ;CHECK FOR ERROR OR A JR NZ,FMTERR ;BIF ERROR DJNZ FMT4 FMT6: XOR A FMTERR: LD (MSGADD+2),A LD A,1 ;SEND STATUS LD (MSGADD+1),A CALL FSTORE CALL SENDM ;SEND MESSAGE JP AINP ;SECTOR: LD DE,(TNSLAT) ;DO SECTOR TRANSLATION ; CALL BIOS+030H ;SECT3: LD B,H ; LD C,L ;SECT2: CALL BIOS+021H ;SELECT SECTOR ; RET ;SECT43: ; CALL BIOS+030H ; JR SECT3 ; LOAD Z80 AND 8088 SYSTEM RLDCPM: LD HL,HEADER ;SEND HEADER ( DEFINES LOCATION OF SYSTEM ) LD DE,MSGADD+2 LD BC,128 LDIR CALL IGET ;SEND DATA IF KP10 ENDIF RDERR1: LD DE,MSM ;SEND MSDOS MESSAGE LD C,PRINTM ;PRINT MESSAGE CALL BDOS RDMD1: CALL BIOS+9 ;GET CONSOLE STATUS CP 0DH ;CARRAGE RETURN? JR Z,RDMD1A ;BIF YES CP 'A' ;DRIVE A? JR Z,RDMD1A ;BIF YES CP 'a' JR Z,RDMD1A ;BIF YES CP 'B' ;DRIVE B? JR Z,RDMD1B ;BIF YES CP 'b' JR Z,RDMD1B ;BIF YES IF DRVC ENDIF JR RDMD1A ;DEFAULT TO DRIVE A RDMD1C: LD A,2 ;SET DRIVE C JR RCMPD RDMD1B: LD A,1 ;SET DRIVE B JR RCMPD ; GET MSDOS SYSTEM RDMD1A: LD A,0 ;SET DISK A RCMPD: LD (DISK),A IF KP10 ENDIF LD B,MSSEC ;NUMBER OF SECTORS TO READ LD A,(DISK) ;SET DISK DRIVE TO USE IF 1ST SECTOR INC A ;(ADJUST FOR MSDOS) LD (IOMDSK),A LD HL,IOMD ;START OF IO.SYS AND MSDOS.SYS RDMD4: PUSH BC LD BC,128 ;MOVE IN NEXT SECTOR LD DE,MSGADD+2 LDIR PUSH HL CALL IGET ;SEND MESSAGE (128 BYTE SECTORS) POP HL POP BC DJNZ RDMD4 JR RDMD7 ;BIF THRU RDMSG: LD C,PRINTM ;PRINT MESSAGE CALL BDOS RDEXIT: CALL EOFE ;INFORM 8088 JP 0 ;GO GET NEXT COMMAND RDMD7: CALL EOFM ;SEND END OF FILE JP CLSCR ;GO CLEAR SCREEN NOFILE: LD DE,NOFM ;SEND NO FILE MESSAGE LD C,PRINTM ;PRINT MESSAGE CALL BDOS CALL EOFE ;INFORM 8088 JP 0 ;GO GET NEXT COMMAND IGET: LD B,128 ;SET MESSAGE LENGTH TO 128 BYTES JR IGET1 EOFM: LD B,1 ;SET MESSAGE LENGTH TO 1 JR IGET1 EOFE: LD B,0 ;SET MESSAGE LENGTH TO 0 FOR END OF LOAD IGET1: LD HL,MSGADD LD A,22 ;NOTE LD (HL),A INC HL LD (HL),B CALL SENDM ;SEND MESSAGE RET MSM: DB 1AH DB ' ' DB '**********************************',CR,LF DB ' ' DB '** **',CR,LF DB ' ' DB '** MsDos for the Micro-Decision **',CR,LF DB ' ' DB '** Version 2.11 Revision 2.1 **',CR,LF DB ' ' DB '** **',CR,LF DB ' ' DB '** Software Publishers, Inc. **',CR,LF DB ' ' DB '** Copyright 1983,1984 **',CR,LF DB ' ' DB '** **',CR,LF DB ' ' DB '** Morrow Designs, Inc. **',cr,lf DB ' ' DB '** Copyright 1984 **',CR,LF DB ' ' DB '** **',CR,LF DB ' ' DB '**********************************',CR,LF,lf DB 'Place MSDOS disk in drive',CR,LF,LF DB 'Then type drive (A, B) to load system.' DB CR,LF,LF DB 'Any other drive defaults to drive A',CR,LF DB 'ie, RETURN without drive letter defaults to drive A:',CR,LF DB ' "A" boots MSODS on drive A:',CR,LF DB ' "B" boots MSDOS on drive B:',CR,LF DB ' "G" defaults to drive A:',CR,LF DB LF,'$' NOFM: DB 'NO MSDOS FILE!$' ;REM: DB 'READ ERROR ON LOAD!',CR,LF ; DB 'PLACE CPM DISK IN DRIVE A AND REBOOT. $' ;RFEMSG: DB 'READ ERROE ON FAT TABLE!',CR,LF ; DB 'PLACE CPM DISK IN DRIVE A AND REBOOT. $' ; INTERFACE PROGRAM FOR Z80 TO 8088 ; BIT 7 = DATA AVAILABLE FROM 8088 ; BIT 0 = TRANSMIT BUFFER FULL ENQ EQU 5 ;ENQUIRE SOM EQU 1 ;START OF MESSAGE EOT EQU 4 ;END OF TRANSMISSION ; SEND MESSAGE TO Z80 SENDM: PUSH HL PUSH DE PUSH BC LD DE,(STATP) ;GET STATUS AND DATA PORTS LD HL,MSGADD ;SET UP MESSAGE ADDRESS LD C,E DATO1: IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATO1 ;BIF YES LD A,ENQ ;SEND ENQUIRE LD C,D OUT (C),A ;OUTPUT DATA LD C,E DATO1A: IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATO1A ;BIF YES LD A,SOM ;SEND START OF MESSAGE LD C,D OUT (C),A ;OUTPUT DATA LD C,E DATAO2: IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATAO2 ;BIF YES LD A,(HL) ;SEND MESSAGE TYPE LD C,D OUT (C),A ;OUTPUT DATA INC HL ;ADVANCE POINTER LD C,E DATAO3: IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATAO3 ;BIF YES LD A,(HL) ;SEND MESSAGE SIZE LD C,D OUT (C),A ;OUTPUT DATA OR A ;IS DATA REQUIRED? JR Z,SENDM1 ;BIF NOT LD B,A ;SAVE COUNT INC HL CP 1 ;TEST FOR ERROR ON READ JR Z,DAT4B ;BIF YES LD A,(MSGADD) ;CHECK MESSAGE TYPE CP 12 ;DISK READ? JR Z,DATAO5 ;BIF YES CP 23 ;FAST DISK READ JR NZ,DAT4B ;BIF NO DATAO5A: LD BC,(SSCNT) ;GET SECTOR COUNT DAT5B1: PUSH BC DATAO5B: LD C,E IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATAO5B ;BIF YES LD A,(HL) LD C,D OUT (C),A ;OUTPUT DATA INC HL ;ADVANCE POINTER POP BC DEC BC LD A,B OR C JR NZ,DAT5B1 ;LOOP TILL THRU JR SENDM1 DATAO5: LD HL,(CDMA) ;ADDRESS DATA DAT4B: LD C,E DATAO4: IN A,(C) ;READ STATUS TO SEE IF BUFFER IS FULL BIT 0,A JR NZ,DATAO4 ;BIF YES LD A,(HL) LD C,D OUT (C),A ;OUTPUT DATA INC HL ;ADVANCE POINTER DJNZ DAT4B ;LOOP TILL THRU SENDM1: POP BC POP DE POP HL RET ; RECEIVE DATA GETM: PUSH HL PUSH DE PUSH BC LD DE,(STATP) ;GET STATUS AND DATA PORTS LD HL,MSGADD ;SET UP MESSAGE ADDRESS DAT1A1: LD C,E DATAI1A: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,DATAI1A ;BIF NOT LD C,D IN A,(C) ;INPUT DATA CP SOM ;LOOK FOR ENQUIRE JR NZ,GETM1 ;BIF NOT ENQ ; GET MESSAGE TYPE LD C,E DATAI2: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,DATAI2 ;BIF NOT LD C,D IN A,(C) ;INPUT DATA LD (HL),A ;SAVE MESSAGE TYPE INC HL ;ADVANCE POINTER CP 18H ;IS THIS A FAST WRITE? LD C,E JR Z,GFW ;BIF YES ; GET MESSAGE SIZE DATAI3: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,DATAI3 ;BIF NOT LD C,D IN A,(C) ;INPUT DATA CP 0 ;IS DATA REQUIRED? JR Z,GETM2 ;BIF NOT LD B,A ;SAVE COUNT LD (HL),A GETM3: INC HL ;ADVANCE POINTER LD C,E DATAI4: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,DATAI4 ;BIF NOT LD C,D IN A,(C) ;INPUT DATA LD (HL),A ;AND STORE DJNZ GETM3 GETM2: POP BC POP DE POP HL RET GETM1: CP ENQ ;LOOK FOR ENQUIRE JR Z,DAT1A1 ;BIF FOUND POP HL POP HL ;ADJUST STACK AND GET OUT POP HL POP HL JP AINP ;ERROR EXIT TO SCAN GFW: ; GET MESSAGE SIZE FOR FAST WRITE IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,GFW ;BIF NOT LD C,D IN A,(C) ;INPUT DATA CP 0 ;IS DATA REQUIRED? JR Z,GETM2 ;BIF NOT LD B,6 ;SAVE COUNT TO GET SIZE,DISK,TRACK,SECTOR LD (HL),B ; AND SIDE FLAG GFW2: INC HL ;ADVANCE POINTER LD C,E GFW1: IN A,(C) ;READ STATUS TO SEE IF DATA IS PRESENT BIT 7,A ;IS BIT SET? JR Z,GFW1 ;BIF NOT LD C,D IN A,(C) ;INPUT DATA LD (HL),A ;AND STORE DJNZ GFW2 POP BC POP DE POP HL RET GETERR: ; FORM ERROR MESSAGE AND TRY TO GET BACK IN SYNC JP GETM1 ;GO TRY AGAIN INTCNT: DB 0 ;INTERRUPT COUNT BIOS: JP 0 ;WARM BOOT JP 0 ;WARM BOOT DB 0C3H ;CONST DW 0 DB 0C3H ;CONIN DW 0 DB 0C3H ;CONOUT DW 0 DB 0C3H ;LIST DW 0 DB 0C3H ;PUNCH DW 0 DB 0C3H ;READER DW 0 DB 0C3H ;HOME DW 0 DB 0C3H ;SELDSK DW 0 DB 0C3H ;SETTRK DW 0 DB 0C3H ;SETSEC DW 0 DB 0C3H ;SETDMA DW 0 DB 0C3H ;READ DW 0 DB 0C3H ;WRITE DW 0 DB 0C3H ;LISTST DW 0 DB 0C3H ;SECTRAN DW 0 CTRACK: DW 0 ;CURRENT TRACK CSEC: DW 0 ;CURRENT SECTOR CDMA: DW 0 ;CURRENT DMA ZTRACK: DW 0 ;SELECTED TRACK ZSEC: DW 0 ;SELECTED SECTOR WRFLAG: DB 0 STATE: DB 0 ;ESC SEQUENCE STATE YCOL: DB 0 ;COL SAVE LSECNT: DB 0 ;SECTER READ COUNT IN LOAD LTRK: DB 0 ;LOAD CURRENT TRACK SSLTRK: DB 0 ;SIDE SELECT TRACK COUNTER SIDE: DB 0 ;SIDE CURADD: DW 0 ;CURRENT CURSOR POSITION IBM: DB 0 ;IBM DISK? 1 = YES IBMDSK: DB 0 ;WHICH DISK IS IBM STSEC: DB 0 ;STARTING SECTOR DISK 0 DB 0 ; 1 DB 0 ; 2 SPT: DB 0 ;SECTORS PER TRACK DISK 0 DB 0 ; 1 DB 0 ; 2 DISK: DB 0 ;SAVES DISK IN NEW DISK SELECT ; IF BOOT DISK SIZE NOT 512 BYTES/SECTOR THEN THIS WILL CHANGE OR ; LOAD CODE MUST CHANGE SECSIZE: DW 512 ;SECTOR SIZE DISK 0 DW 512 ; 1 DW 512 ; 2 SSCNT: DW 512 ;SECTOR COUNTER SSTBL: DW 128 ;SETOR SIZES CODE 0 DW 256 ; 1 DW 512 ; 2 DW 1024 ; 3 ESPT: DB 40 ;# OF TRACKS DB 2 ;512 BYTES/SECTOR DB 8 ;SECTORS/TRACK DB 32H ;GAP LENGTH DB 1,3,5,7 ;SECTOR SKEW TABLE (2) DB 2,4,6,8 ; DB 1,4,7 ;SECTOR SKEW TABLE (3) ; DB 2,5,8 ; DB 3,6 IF KP10 ENDIF HEADER: DB 1 ;GROUP FORMAT --- CODE GROUP DW 400H ;GROUP LENGTH --- NOT CORRECT (TOO BIG) DW LLOC ;GROUP LOCATION --- THIS IS ALL USED DS 123 WTYPE: DB 0 END