;MPM CO - VERSION 1.0 ;RUNS AS RESIDENT SYSTEM PROCESS (RSP) ;INTERCEPTS DISK BIOS ENTRY POINTS AND SET JUMPS TO ;HARD DISK BIOS ENTRY POINTS (DISK ONLY) ; ;* * * FIXES AND MODS BY RUSSELL BUSHNELL JR. FEB. 1986 * * * ; ; *************************************** ; * * ; * MAPBIOS3 FOR THE CMD * ; * 02-05-81 * ; * * ; *************************************** ; ; THIS BIOS IS SET UP FOR IMSAI SIO, TARBELL FLOPPIES ; AS DRIVES M AND N, AND A CDC PHOENIX AS ; DRIVES A THRU L. ; BLOCKING AND DEBLOCKING HAVE BEEN INCORPORATED!! ; TRACK MAPPING ADDED ; REQUIRES USE OF A "NORMAL BOOT ROM", NOT A CMD ROM. ; THIS IS BECAUSE THE LSB OF HEAD IS NOT INVERTED. ;MSIZE EQU 64 ;CP/M VERSION MEMORY SIZE IN KILOBYTES ; CPM IS GENERATED BY MOVCPM 45 * ; "BIAS" IS ADDRESS OFFSET FROM 3400H FOR MEMORY SYSTEMS ; THAN 16K (REFERRED TO AS "B" THROUGHOUT THE TEXT). ; 00C5 = CSTAT EQU 0C5H ;CONSOLE STATUS PORT 00C4 = CDATA EQU 0C4H ;CONSOLE DATA PORT 0002 = CKBR EQU 2 ;KEYBOARD READY BIT 0001 = CPTR EQU 1 ;DISPLAY READY BIT ; 00C9 = LPSTAT EQU 0C9H ;LIST DEVICE STATUS PORT 00C8 = LDATA EQU 0C8H ;LIST DEVICE DATA PORT 0004 = LRBIT EQU 4H ;LIST READY BITS 0004 = LRPOL EQU 4H ;LIST POLARITY BITS 00E3 = LPST2 EQU 0E3H ;LIST DEV. STAT.PORT 2 0004 = LPRB2 EQU 04H ;LIST DEV. READY BIT 2 ; 0000 = FALSE EQU 0 FFFF = TRUE EQU NOT FALSE 0000 = PC EQU FALSE ;INCLUDE PARALLEL CONSOLE 0000 = PCST EQU FALSE;INCLUDE SO THAT PARALLEL CONSOLE CAN ABORT LONG ;PRINT OUTS VIA RETURN KEY. SET TO FALSE IF MODEM ;NOISE ABORTS DISPLAYING PROGRAMS. ;ALLOWS XON & XOFF TO WORK ALSO. ;MODEM MUST ALWAYS BE TURNED ON WITH PCST EQU TRUE! 0000 = SECURITY EQU FALSE ;SET TRUE FOR PASSWORD 0005 = RETRYS EQU 05H ;RETRYS FOR PARALLEL CONSOLE UNTIL DISCONNECT FFFF = I8251 EQU TRUE ;TRUE IF CONSOLE & PRINTER USE 8251 SIO FFFF = INTRP EQU TRUE ;TRUE IF INTERRUPTS IN SYSTEM 0000 = PERSCI EQU FALSE ;TRUE IF FLOPPY IS FAST SEEK 0000 = DUAL EQU FALSE ;TRUE IF FLOPPY HAS 2 DRIVES/SPINDLE FFFF = HLOPT EQU TRUE ;TRUE IF HEADLOAD OPTION CODE 0000 = DMA EQU FALSE ;SET TRUE ONLY IF YOU CAN RUN DMA ; 000E = NUMDSK EQU 14 ;NO.OF LOGICAL DISKS 000C = NUMHRD EQU 12 ;NO.OF LOGICAL HARD DISKS FFFF = FLP1ST EQU TRUE ;FALSE IF FLOPS LAST, TRUE IF 1ST 000C = HEADQ EQU 12 02BB = MAXTRK EQU 699 0000 = CMD EQU FALSE ; ;BIAS EQU (MSIZE-20)*1024 ;USES CPM45.COM!!! 2F00 = BIAS EQU 12032;BIAS FOR LARGER THEN 20K 6300 = CCP EQU 3400H+BIAS ;BASE OF CCP (-200 NEEDED FOR SOME 2.2) 6B06 = BDOS EQU CCP+806H ;BASE OF BDOS 7900 = BIOS EQU CCP+1600H ;BASE OF BIOS 0004 = CDISK EQU 0004H ;CURRENT DISK NUMBER 0=A,...,15=P 0003 = IOBYTE EQU 0003H ;INTEL I/O BYTE 0000 = WRALL EQU 0 ;WRITE TO ALOCATED 0001 = WRDIR EQU 1 ;WRITE TO DIRECTORY 0002 = WRUAL EQU 2 ;WRITE TO UNALLOCATED 4000 = BLKSIZE EQU 16384 ; 0200 = HSTSIZ EQU 512 ;HARD DISK SECTOR SIZE 0023 = HSTSPT EQU 35 ;SECTORS PER TRACK ON HARD DISK 0004 = HSTBLK EQU HSTSIZ/128 ;CPM SECTORS PER HARD DISK SECTOR 0003 = SECMSK EQU HSTBLK-1 ;SECTOR MASK 008C = CPMSPT EQU HSTBLK*HSTSPT 0002 = SECSHF EQU 2 FFFF = MAPEN EQU TRUE ;DISABLE MAPPING BY SETTING FALSE 0789 = MPMB EQU 0789H;LOCATION OF MPM BIOS TO END + 0100H EXTRA F300 = B2 EQU 0F300H;BASE OF BIOS1 JUMP TABLE 9310 = B1 EQU 09310H;BASE OF BIOS2 JUMP TABLE ; 0000 ORG 0000H ;ORIGIN OF THIS PROGRAM ;BDOS ENTRY POINT ADDRESS BDOSADR: 0000 0000 DW $-$;LDR WILL FILL THIS IN ; ;HRDISK PROCESS DESCRIPTOR HRDISKPD: 0002 0000 DW 0;LINK 0004 00 DB 0;STATUS 0005 0A DB 10;PRIORITY (INITIAL) 0006 1001 DW STACK+38;STACK POINTER 0008 4852444953 DB 'HRDISK ';NAME IN UPPER CASE PDCONSOLE: 0010 00 DB 0;CONSOLE 0011 FF DB 0FFH;MEMSEG (FF=RESIDENT) 0012 DS 2;B 0014 DS 2;THREAD 0016 3601 DW BUFF;SET DISK DMA ADDRESS 0018 DS 1;USER CODE AND DISK SELECT 0019 DS 2;DCNT 001B DS 1;SEARCHL 001C DS 2;SEARCHA 001E DS 2;ACTIVE DRIVES 0020 DS 20;REGISTER SAVE AREA 0034 DS 2;SCRATCH ; ;LINKED QUEUE CONTROL BLOCK HRDLQCB: 0036 0000 DW 0;LINK 0038 4852444953 DB 'HRDISK ';NAME UPPER CASE 0040 4800 DW 72;MSGLEN 0042 0100 DW 1;NMBMSGS 0044 DS 2;DQPH 0046 DS 2;NQPH 0048 DS 2;MH 004A DS 2;MT 004C DS 2;BH 004E DS 74;BUF (72+2 BYTE LIN) ; ;USER QUEUE CONTROL BLOCK HRDUSERQCB: 0098 3600 DW HRDLQCB;POINTER 009A 9C00 DW FIELD;MSGADR ; ;FIELD FOR MESSAGE READ FROM TYPE LINKED QUE QCB FIELD: 009C DS 1;DISK SELECT CONSOLE: 009D DS 1;CONSOLE FILENAME: 009E DS 72;MESSAGE BODY ; ;PARSE FILE NAME CONTROL BLOCK PCB: 00E6 9E00 DW FILENAME;FILENAME ADDRESS 00E8 1201 DW FCB;FILE CONTROL BLOCK A ; STACK: 00EA DS 38;20 LEVEL STACK 0110 BA01 DW HRDISK;PROCESS ENTRY POINT ; 0112 FCB: DS 36;FILE CONTROL BLOCK 0136 BUFF: DS 128;FILE BUFFER ; ;BDOS CALL PROCEDURE PBDOS: 01B6 2A0000 LHLD BDOSADR;HL = BDOS ADDRESS 01B9 E9 PCHL; ; ;MAIN DISK BIOS JUMP TABLE SWAP HRDISK: 01BA 0E86 MVI C,086H;MAKE QUE 01BC 113600 LXI D, HRDLQCB; 01BF CDB601 CALL PBDOS;MAKE QUEUE 01C2 0E91 MVI C, 091H;SET PRIORITY 01C4 110002 LXI D, 200H;PRIORITY = 200 01C7 CDB601 CALL PBDOS;TELL OP-SYS ; LOOP1: 01CA 0E89 MVI C, 089H;READ QUEUE COMMAND 01CC 119800 LXI D, HRDUSERQCB; 01CF CDB601 CALL PBDOS; 01D2 2A2993 LHLD B1+25;BASE OF BIOS1+25=HOME JMP TABLE 01D5 2219F3 SHLD B2+25;BASE OF BIOS2 JMP TABLE 01D8 2A2C93 LHLD B1+28;REPEATED FOR ALL DISK JUMPS,OK 01DB 221CF3 SHLD B2+28; 01DE 2A2F93 LHLD B1+31; 01E1 221FF3 SHLD B2+31; 01E4 2A3293 LHLD B1+34; 01E7 2222F3 SHLD B2+34; 01EA 2A3593 LHLD B1+37; 01ED 2225F3 SHLD B2+37; 01F0 2A3893 LHLD B1+40; 01F3 2228F3 SHLD B2+40; 01F6 2A3B93 LHLD B1+43; 01F9 222BF3 SHLD B2+43; 01FC 2A4193 LHLD B1+49; 01FF 2231F3 SHLD B2+49; 0202 3A9D00 LDA CONSOLE; 0205 321000 STA PDCONSOLE; 0208 0E93 MVI C, 093H;DETACH COMMAND 020A CDB601 CALL PBDOS;GIVE COMMAND TO MPM 020D C3CA01 JMP LOOP1;FOREVER ; 00B9 = NSECTS EQU 0B9H;FAKE IT ;NSECTS EQU ($-CCP)/128 ;WARM START SECTOR COUNT ; ; JUMP VECTOR FOR INDIVIDUAL SUBROUTINES 0210 C36A03 JMP BOOT ;COLD START 0213 C3BD03 WBOOTE: JMP WBOOT ;WARM START 0216 C33004 JMP CONST ;CONSOLE STATUS 0219 C33904 JMP CONIN ;CONSOLE CHARACTER IN 021C C34504 JMP CONOUT ;CONSOLE CHARACTER OUT 021F C35004 JMP LIST ;LIST CHARACTER OUT 0222 C36B04 JMP PUNCH ;PUNCH CHARACTER OUT 0225 C36D04 JMP READER ;READER CHARACTER OUT 0228 C37204 JMP HOME ;MOVE HEAD TO HOME POSITION 022B C37904 JMP SELDSK ;SELECT DISK 022E C39504 JMP SETTRK ;SET TRACK NUMBER 0231 C39E04 JMP SETSEC ;SET SECTOR NUMBER 0234 C3B104 JMP SETDMA ;SET DMA ADDRESS 0237 C3B704 JMP READ ;READ DISK 023A C3BD04 JMP WRITE ;WRITE DISK 023D C35D04 JMP LISTST ;RETURN LIST STATUS 0240 C3A604 JMP SECTRAN ;SECTOR TRANSLATE ; ; TABLES FOR TWO FLOPPIES AND ONE CMD DRIVE ;DISK PARAMETER TABLE IF FLOPPIES = 0,1,2,3 (FIRST) IF FLP1ST DPBASE:;USED BY CPM SELECT DISK (COMPUTE DPH) 0243 23030000 DW TRANS,0000H 0247 00000000 DW 0000H,0000H 024B 6D0A3D03 DW DIRBF,DPBLK 024F 2B14ED0A DW CHK00,ALL00 ;2ND FLOPPIE 0253 23030000 DW TRANS,0000H 0257 00000000 DW 0000H,0000H 025B 6D0A3D03 DW DIRBF,DPBLK 025F 3B140C0B DW CHK01,ALL01 ENDIF ; DISK PARAMETER TABLE FOR HARD DISK,TOP PLATTER,OUTSIDE TRACKS IF NOT FLP1ST DPBASE:;USED BY CPM SELECT DISK (COMPUTE DPH) ENDIF 0263 00000000 DW 0000H,0000H 0267 00000000 DW 0000H,0000H 026B 6D0A4C03 DW DIRBF,DPBLK2 026F 4B142B0B DW CHK02,ALL02 ; DISK PARAMETER TABLE FOR HARD DISK,TOP PLATTER,INSIDE TRACKS 0273 00000000 DW 0000H,0000H 0277 00000000 DW 0000H,0000H 027B 6D0A4C03 DW DIRBF,DPBLK2 027F 4B146B0D DW CHK03,ALL03 ; DISK PARAMETER TABLE FOR HARD DISK,BOTTOM SIDE,OUTSIDE TRACKS. 0283 00000000 DW 0000H,0000H 0287 00000000 DW 0000H,0000H 028B 6D0A5B03 DW DIRBF,DPBLK3 028F 4B14EB0B DW CHK04,ALL04 ; DISK PARAMETER TABLE FOR HARD DISK,BOTTOM SIDE,INSIDE TRACKS 0293 00000000 DW 0000H,0000H 0297 00000000 DW 0000H,0000H 029B 6D0A5B03 DW DIRBF,DPBLK3 029F 4B14AB0C DW CHK05,ALL05 ; 02A3 00000000 DW 0000H,0000H 02A7 00000000 DW 0000H,0000H 02AB 6D0A5B03 DW DIRBF,DPBLK3 02AF 4B142B0E DW CHK06,ALL06 ; 02B3 00000000 DW 0000H,0000H 02B7 00000000 DW 0000H,0000H 02BB 6D0A5B03 DW DIRBF,DPBLK3 02BF 4B14EB0E DW CHK07,ALL07 ; 02C3 00000000 DW 0000H,0000H 02C7 00000000 DW 0000H,0000H 02CB 6D0A5B03 DW DIRBF,DPBLK3 02CF 4B14AB0F DW CHK08,ALL08 ; 02D3 00000000 DW 0000H,0000H 02D7 00000000 DW 0000H,0000H 02DB 6D0A5B03 DW DIRBF,DPBLK3 02DF 4B146B10 DW CHK09,ALL09 ; 02E3 00000000 DW 0000H,0000H 02E7 00000000 DW 0000H,0000H 02EB 6D0A5B03 DW DIRBF,DPBLK3 02EF 4B142B11 DW CHK10,ALL10 ; 02F3 00000000 DW 0000H,0000H 02F7 00000000 DW 0000H,0000H 02FB 6D0A5B03 DW DIRBF,DPBLK3 02FF 4B14EB11 DW CHK11,ALL11 ; 0303 00000000 DW 0000H,0000H 0307 00000000 DW 0000H,0000H 030B 6D0A5B03 DW DIRBF,DPBLK3 030F 4B14AB12 DW CHK12,ALL12 ; 0313 00000000 DW 0000H,0000H 0317 00000000 DW 0000H,0000H 031B 6D0A5B03 DW DIRBF,DPBLK3 031F 4B146B13 DW CHK13,ALL13 ; ; DISK PARAMETER TABLES FOR FLOPPIES (LAST 13,14,15,16) IF NOT FLP1ST DW TRANS,0000H DW 0000H,0000H DW DIRBF,DPBLK DW CHK00,ALL00 DW TRANS,000H DW 0000H,0000H DW DIRBF,DPBLK DW CHK01,ALL01 ENDIF ; ; SECTOR TRANSLATE TABLE, FOR FLOPPIES ONLY 0323 01070D13 TRANS: DB 1,7,13,19 ;SECTORS 1,2,3,4 0327 19050B11 DB 25,5,11,17 ;SECTORS 5,6,7,8 032B 1703090F DB 23,3,9,15 ;SECTORS 9,10,11,12 032F 1502080E DB 21,2,8,14 ;SECTORS 13,14,15,16 0333 141A060C DB 20,26,6,12 ;SECTORS 17,18,19,20 0337 1218040A DB 18,24,4,10 ;SECTORS 21,22,23,24 033B 1016 DB 16,22 ;SECTORS 25,26 ; DPBLK: ;DISK PARAMETER BLOCK, FLOPPIES 033D 1A00 DW 26 ;SECTORS PER TRACK 033F 03 DB 3 ;BLOCK SHIFT FACTOR 0340 07 DB 7 ;BLOCK MASK 0341 00 DB 0 ;NULL MASK 0342 F200 DW 242 ;DISK SIZE-1 0344 3F00 DW 63 ;DIRECTORY MAX 0346 C0 DB 192 ;ALLOC 0 0347 00 DB 0 ;ALLOC 1 0348 1000 DW 16 ;CHECK SIZE 034A 0200 DW 2 ;TRACK OFFSET 034C 8C00 DPBLK2 DW 140 ;SECTORS PER TRACK 034E 06 DB 6 ;BLOCK SHIFT FACTOR FOR BLS=8,192 034F 3F DB 63 ;BLM 0350 03 DB 3 ;EXM 0351 F305 DW 1523 ;DISK SIZE-1 0353 FF01 DW 511 ;DIRECTORY MAX 0355 C0 DB 0C0H ;ALLOC0 0356 00 DB 00H ;ALLOC1 0357 0000 DW 0 ;NO CHECK - DISK IS FIXED 0359 0200 DW 2 ;OFFSET 035B 8C00 DPBLK3 DW 140 035D 06 DB 6 035E 3F DB 63 035F 03 DB 3 0360 F305 DW 1523 0362 FF01 DW 511 ;DIRECTORY MAX,(FIXED REQUIRES NO CHECK ; SO THE DIRECTOR IS LARGER, = BLS 8K) 0364 C0 DB 0C0H 0365 00 DB 00H 0366 0000 DW 0 ;0 FOR FIXED 0368 0200 DW 2 ;OFFSET ; ; END OF FIXED TABLES ; ; INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNCTION BOOT: ;SIMPLEST CASE IS TO JUST PERFORM PARAMETER INITIALIZATION 036A 318000 LXI SP,80H ;SET STACK TO TPA TOP -2 IF PC ;ADDED FOR A PARALLEL CONSOLE PPIC EQU 0CEH MODEMS EQU 0C1H MODDAT EQU 0C0H LIMOD EQU 0CFH HIMOD EQU 0CEH IFLAG: DB 00H XFLAG: DB 00H CMD51 EQU 27H MVI A,LIMOD OUT MODEMS MVI A,CMD51 OUT MODEMS IN MODDAT IN MODDAT MVI A,00H STA IFLAG STA XFLAG ENDIF IF SECURITY IIFLAG: DB 00H ENDIF IF I8251 ;NO INIT. CODE FOR MAIN COMM. BRD. (DONE VIA FIRST BOOT OP.) ; 036D 3E40 MVI A,40H;RESET COMMAND 036F D3C5 OUT CSTAT 0371 D3C9 OUT LPSTAT 0373 3ECD MVI A,0CDH ;USED TO BE 0CEH & 27 BELOW WAS 37 0375 D3C5 OUT CSTAT 0377 D3C9 OUT LPSTAT 0379 3E27 MVI A,027H 037B D3C5 OUT CSTAT 037D D3C9 OUT LPSTAT ENDIF IF MAPEN ;IF TRACK MAP OPTION IS ENABLED, MAKE MAP 037F CDC209 CALL SMAPPER ENDIF 0382 AF XRA A ;ZERO IN THE ACCUM 0383 320300 STA IOBYTE ;CLEAR THE IOBYTE 0386 320400 STA CDISK ;SELECT DISK ZERO 0389 219203 LXI H,SINGMES ;PRINT THE SIGN ON MESSAGE 038C CDA209 CALL PRMSG IF SECURITY SECUR: MVI A,01H ;GOOD PASS VALUE STA IIFLAG ;SET AS GOOD CALL PASWRD ;GO GET IT AND CHECK IT LDA IIFLAG ;GET SCRATCH BYTE SET AS GOOD ORA A ;SET FLAG JZ SECUR ;WAS IT A GOOD PASSWORD MVI A,00H ;CLEAR SCRATCH FLAG FOR PAR. CON. STA IIFLAG ;DO IT ENDIF 038F C3BD03 JMP WBOOT ;INITIALIZE AND GO TO CP/M 0392 0D0A SINGMES DB 0DH,0AH 0394 414D504552 DB 'AMPERIF - MAID-III (CPM 2.2 - MAPBIOS3) ' 03BC 00 DB 0 ; WBOOT: ;SIMPLEST CASE IS TO READ THE DISK UNTIL ALL SECTORS LOADED 03BD AF XRA A 03BE 325414 STA HSTACT ;HOST BUFFER INACTIVE 03C1 325614 STA UNACNT ;CLEAR UNALLOCATED COUNT 03C4 318000 LXI SP,80H ;USE SPACE BELOW BUFFER FOR STACK 03C7 0E00 MVI C,0 ;SELECT DISK 0 03C9 CD7904 CALL SELDSK 03CC CD7204 CALL HOME ;GO TO TRACK 00 ; 03CF 06B9 MVI B,NSECTS ;B COUNTS # OF SECTORS TO LOAD 03D1 0E00 MVI C,0 ;C HAS THE CURRENT TRACK NUMBER 03D3 1602 MVI D,2 ;D HAS THE NEXT SECTOR TO READ (2 = FLOPPIE, 4 = HARD) ; NOTE THAT WE BEGIN WITH CPM SECTOR 4, THE SECOND PHYSICAL ; SECTOR ON THE HARD DISK 03D5 210063 LXI H,CCP ;BASE OF CP/M (INITIAL LOAD POINT) LOAD1: ;LOAD ONE MORE SECTOR 03D8 C5 PUSH B ;SAVE SECTOR COUNT, CURRENT TRACK 03D9 D5 PUSH D ;SAVE NEXT SECTOR TO READ 03DA E5 PUSH H ;SAVE DMA ADDRESS 03DB 4A MOV C,D ;GET SECTOR ADDRESS TO REGISTER C 03DC CD9E04 CALL SETSEC ;SET SECTOR ADDRESS FROM REGISTER C 03DF C1 POP B ;RECALL DMA ADDRESS TO B,C 03E0 C5 PUSH B ;REPLACE ON STACK FOR LATER RECALL 03E1 CDB104 CALL SETDMA ;SET DMA ADDRESS FROM B,C ; ; DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET 03E4 CDB704 CALL READ 03E7 FE00 CPI 00H ;ANY ERRORS? 03E9 C2BD03 JNZ WBOOT ;RETRY THE ENTIRE BOOT IF AN ERROR OCCURS ; ; NO ERROR, MOVE TO NEXT SECTOR 03EC E1 POP H ;RECALL DMA ADDRESS 03ED 118000 LXI D,128 ;DMA=DMA+128 03F0 19 DAD D ;NEW DMA ADDRESS IS IN H,L 03F1 D1 POP D ;RECALL SECTOR ADDRESS 03F2 C1 POP B ;RECALL NUMBER OF SECTORS REMAINING, AND CURRENT TRK 03F3 05 DCR B ;SECTORS=SECTORS-1 03F4 CA0D04 JZ GOCPM ;TRANSFER TO CP/M IF ALL HAVE BEEN LOADED ; ; MORE SECTORS REMAIN TO LOAD, CHECK FOR TRACK CHANGE 03F7 14 INR D 03F8 7A MOV A,D ;SECTOR=27?, IF SO, CHANGE TRACKS 03F9 FE1B CPI 27 ; REMOVE FOLLOWING TO BOOT OFF FLOPPY ; REMOVED - JMP LOAD1 03FB DAD803 JC LOAD1 ;CARRY GENERATED IF SECTOR<27 ; ; END OF CURRENT TRACK, GO TO NEXT TRACK 03FE 1601 MVI D,1 ;BEGIN WITH FIRST SECTOR OF NEXT TRACK 0400 0C INR C ;TRACK=TRACK+1 ; ; SAVE REGISTER STATE, AND CHANGE TRACKS 0401 C5 PUSH B 0402 D5 PUSH D 0403 E5 PUSH H 0404 CD9504 CALL SETTRK ;TRACK ADDRESS SET FROM REGISTER C 0407 E1 POP H 0408 D1 POP D 0409 C1 POP B 040A C3D803 JMP LOAD1 ;FOR ANOTHER SECTOR ; ; END OF LOAD OPERATION, SET PARAMETERS AND GO TO CP/M GOCPM: 040D 3EC3 MVI A,0C3H ;C3 IS A JMP INSTRUCTION 040F 320000 STA 0 ;FOR JMP TO WBOOT 0412 211302 LXI H,WBOOTE ;WBOOT ENTRY POINT 0415 220100 SHLD 1 ;SET ADDRESS FIELD FOR JMP AT 0 ; 0418 320500 STA 5 ;FOR JMP TO BDOS 041B 21066B LXI H,BDOS ;BDOS ENTRY POINT 041E 220600 SHLD 6 ;ADDRESS FIELD OF JUMP AT 5 TO BDOS ; 0421 018000 LXI B,80H ;DEFAULT DMA ADDRESS IS 80H 0424 CDB104 CALL SETDMA ; ;EI ;ENABLE THE INTERRUPT SYSTEM ;MVI A,00H ;ALWAYS SELECT UNIT 0 0427 3A0400 LDA CDISK ;GET CURRENT DISK NUMBER 042A 4F MOV C,A;SEND TO CCP 042B 0600 MVI B,0 ;SEE IF THIS FIXES BUG 042D C30063 JMP CCP ;GO TO CP/M FOR FURTHER PROCESSING ; ; ; PHYSICAL DEVICE I/O DRIVERS FOLLOW. ; ;IF PCST = TRUE THIS ROUTINE SHOWS STATUS FOR REG. & PARALLEL CONSOLE ; CONST: ;CONSOLE STATUS, RETURN 0FFH IF CHARACTER READY, 00H IF NOT 0430 DBC5 IN CSTAT ;READ CONSOLE STATUS 0432 E602 ANI CKBR ;LOOK AT READY BIT IF PC IF PCST CALL STAT$RET CZ MODST;THEN DOES MODEM WANT TO INPUT(ABORT DISPLAY) RET ENDIF ENDIF STAT$RET: 0434 3E00 MVI A,0 ;IF NOT READY A=0 0436 C8 RZ 0437 2F CMA ;IF READY A=FF 0438 C9 RET ; IF PC IF PCST MODST: IN PPIC;PPI PORT C ANI 10H;DCD1 BIT(RS-232-C) MVI A,00H;SET A = 0 FOR RETURN RNZ ;NO DCD1 (ON NOT ZERO) IN MODEMS;GET STATUS ANI CKBR ;LOOK AT FLAG BIT CALL STAT$RET;MAKE GOOD STATUS FOR CPM RET ENDIF ENDIF CONIN: ;CONSOLE CHARACTER INTO REGISTER A 0439 DBC5 IN CSTAT ;READ CONSOLE STATUS PORT 043B E602 ANI CKBR ;WAIT UNTIL READY IF PC JZ MODEMI ;NOT READY CHECK PARALLEL PORT(MODEM) ENDIF IF NOT PC 043D CA3904 JZ CONIN ENDIF 0440 DBC4 IN CDATA ;READ DATA PORT 0442 E67F ANI 7FH ;CLEAR BIT 7 0444 C9 RET ; CONOUT: ;CONSOLE CHARACTER OUTPUT FROM REGISTER C 0445 DBC5 IN CSTAT ;READ CONSOLE STATUS 0447 E601 ANI CPTR ;WAIT IF NOT READY 0449 CA4504 JZ CONOUT 044C 79 MOV A,C ;GET DATA CHARACTER 044D D3C4 OUT CDATA ;OUTPUT IT IF PC CALL MODEMO ;MODEM OUT(PARALLEL CONSOLE) ENDIF 044F C9 RET;HAVE PROGRAM DELETE THIS LOC.(RET) FOR AUTO CONSOLE PRINTER ; LIST: ;LIST CHARACTER FROM REGISTER C 0450 DBC9 IN LPSTAT ;READ LIST STATUS 0452 E604 ANI LRBIT ;LOOK AT READY BITS ;JZ LIST ;THIS & NEXT 3 LINES REPLACE ;LIST2 IN LPST2 ;FOLLOWING 2 LINES (XRI & JNZ) ;ANI LPRB2 ;JNZ LIST2 0454 EE04 XRI LRPOL ;SELECT READY POLARITYS 0456 C25004 JNZ LIST ;WAIT UNTIL NOT BUSY 0459 79 MOV A,C ;GET DATA BYTE 045A D3C8 OUT LDATA ;PRINT IT 045C C9 RET ; LISTST: ;RETURN LIST STATUS (0 IF NOT READY, 1 IF READY) 045D DBC9 IN LPSTAT ;READ LIST STATUS 045F E604 ANI LRBIT ;SELECT READY BITS 0461 EE04 XRI LRPOL ;SELECT READY POLARITY 0463 CA6804 JZ LISRDY 0466 AF XRA A ;RETURN 0 IF NOT READY 0467 C9 RET 0468 3E01 LISRDY: MVI A,1 ;RETURN 1 IF READY 046A C9 RET ; IF PC ;ADDED FOR PARALLEL CONSOLE MODEMO: IN PPIC;PPI PORT C ANI 10H;DCD1 BIT (RS-232-C) LDA IFLAG;INITILIZE FLAG STA XFLAG;SCRATCH FLAG MVI A,00H; STA IFLAG; RNZ ;NO DCD1 ON NOT ZERO LDA XFLAG;PUT BACK STA IFLAG;PUT BACK - CARRIER STILL SAME CALL BAUDS;NEED TO INIT. OR CHG. MODEM SPEED??? MODOST: IN MODEMS;USART STATUS PORT ANI CPTR ; JZ MODOST;LOOP UNTIL READY MOV A,C ;GET CHARACTER AGAIN OUT MODDAT;PRINT IT(MODEM DATA PORT) RET MODEMI: IN PPIC;PPI PORT C ANI 10H;DCD1 BIT (RS-232-C) LDA IFLAG;INITILIZE FLAG STA XFLAG;SCRATCH FLAG MVI A,00H; STA IFLAG; JNZ CONIN;NO DCD1 (ON NOT ZERO) LDA XFLAG;PUT BACK STA IFLAG;PUT BACK - CARRIER STILL SAME CALL BAUDS;NEED TO INIT. OR CHG. MODEM SPEED??? IN MODEMS;GET STATUS ANI CKBR ;LOOK AT FLAG BIT CALL STAT$RET;MAKE GOOD STATUS FOR CPM ORA A ; JZ CONIN ;NOT READY IN MODDAT;GET DATA(MODEM DATA PORT) ANI 7FH ;MAKE MOST SIG. BIT = 0 RET BAUDS: LDA IFLAG; ANI 01H ;INITILIZED READY BIT RNZ ;ALREADY INITILIZED MVI A,00H;NOT INITILIZED STA XFLAG;CLEAR XFLAG MVI A,01H;INIT. READY BIT STA IFLAG;SET IT INIT. (ABOUT TO AT LEAST) ;WAIT FOR VALID SPEED SIGNAL MVI A,0FFH;TIME TO WAIT WTHSLS: DCR A JNZ WTHSLS;NOW I WONT HAVE TO CALL TWICE TO CHANGE SPEED IN PPIC;GET MODEMS SPEED(DSRS1 - HIGH = SLOW SPEED) ANI 80H ;MODEM HIGH SPEED BIT CNZ LOWS ;8 BIT, SET LOW SPEED CZ HIGHS;THEN SET HIGH SPEED IF SECURITY IN MODDAT IN MODDAT CALL PASWRD LDA IIFLAG;WAS IT A BAD PASSWORD ORA A ;SET FLAG RZ ;NO SIGNON MESSAGE ON BAD PASSWORD ENDIF ;ADD FOR SIGNON MESSAGE LXI H,SINGMES;LOC. OF SIGNON MESSAGE CALL PRMSG;DISPLAY IT RET HIGHS: MVI A,40H;USART RESET (IR) OUT MODEMS;SEND RESET MVI A,HIMOD;GET HIGH SPEED INIT. WRD. OUT MODEMS;OUT USART CNTRL. PORT MVI A,CMD51;GET 8251 CMD. WRD. OUT MODEMS;SEND TO USART RET LOWS: MVI A,40H;USART RESET (IR) OUT MODEMS;SEND RESET MVI A,LIMOD;GET LOW SPEED INIT. WRD. OUT MODEMS;OUT USART CNTRL. PORT MVI A,CMD51;GET 8251 CMD. WRD. OUT MODEMS;SEND TO USART RET ENDIF IF SECURITY ;MAIN PASSWORD ROUTINE PASSWORD:DB '8CE8CE' DB 13 ;CR AFTER PASSWORD PASMSG: DB 10,13 ;LF,CR DB 'ENTER PASSWORD ',0 DNYMSG: DB 10,13 ;LF,CR DB 'SORRY - ACCESS DENIED ',0 PASBUF: DS 7 PASWRD: MVI B,RETRYS ;GET RETRY COUNT MVI A,01H STA IIFLAG RETRYP: LXI H,PASMSG CALL PRMSG MVI D,07H ;PASSWORD LENGTH LXI H,PASBUF IPASS: CALL CONIN MOV M,A INX H DCR D JNZ IPASS CALL CMPPAS RET CMPPAS: LXI H,PASBUF ;COMPARE PASSWORD LXI D,PASSWORD MVI C,07H ;7 BYTES TO COMPARE CMPLOOP:LDAX D CMP M JNZ BADPAS INX D INX H DCR C JNZ CMPLOOP RET BADPAS: DCR B JNZ RETRYP LXI H,DNYMSG CALL PRMSG MVI A,00H OUT MODEMS ;DISABLE MODEM (USART) STA IFLAG STA IIFLAG MVI D,0FFH MVI E,0FFH DSCTIM: DCX D MOV A,D ORA A JNZ DSCTIM ;DISCONNECT TIME MVI A,CMD51 ;ENABLE MODEM VALUE OUT MODEMS ;DO IT RET ENDIF PUNCH: ;PUNCH CHARACTER FROM REGISTER C 046B 79 MOV A,C ;CHARACTER TO REGISTER A 046C C9 RET ;NULL SUBROUTINE ; ; READER: ;READ CHARACTER INTO REGISTER A FROM READER DEVICE 046D 3E1A MVI A,1AH ;ENTER END OF FILE FOR NOW (REPLACE LATER) 046F E67F ANI 7FH ;REMEMBER TO STRIP PARITY BIT 0471 C9 RET ; ; ; I/O DRIVERS FOR THE DISK FOLLOW ; FOR NOW, WE WILL SIMPLY STORE THE PARAMETERS AWAY FOR USE ; IN THE READ AND WRITE SUBROUTINES ; HOME: ;MOVE TO THE TRACK 00 POSITION OF CURRENT DRIVE ; TRANSLATE THIS CALL INTO A SETTRK CALL WITH PARAMETER 00 0472 010000 LXI B,0 ;SET TRACK TO ZERO 0475 CD9504 CALL SETTRK 0478 C9 RET ;WE WILL MOVE TO 00 ON FIRST READ/WRITE ; SELDSK: ;SELECT DISK GIVEN BY REGISTER C 0479 210000 LXI H,0000H ;ERROR RETURN CODE 047C 79 MOV A,C 047D 32690A STA DISKNO 0480 324B14 STA SEKDSK ;FOR BLOCK/DEBLOCK 0483 FE0E CPI NUMDSK ;MUST BE BETWEEN 0 AND NUMDSK-1 0485 D0 RNC ;NO CARRY IF 4,5,... ; DISK NUMBER IS IN THE PROPER RANGE ; COMPUTE PROPER DISK PARAMETER HEADER ADDRESS 0486 3A690A LDA DISKNO 0489 6F MOV L,A ;L=DISK NUMBER 0,1,2,3 048A 2600 MVI H,0 ;HIGH ORDER ZERO 048C 29 DAD H ;*2 048D 29 DAD H ;*4 048E 29 DAD H ;*8 048F 29 DAD H ;*16 (SIZE OF EACH HEADER) 0490 114302 LXI D,DPBASE 0493 19 DAD D ;HL=.DPBASE(DISKNO*16) 0494 C9 RET ; SETTRK: ;SET TRACK GIVEN BY REGISTER C 0495 60 MOV H,B 0496 69 MOV L,C 0497 224C14 SHLD SEKTRK ;FOR BLOCK/DEBLOCK 049A 22630A SHLD TRACK ;FOR FLOPPY 049D C9 RET ; SETSEC: ;SET SECTOR GIVEN BY REGISTER C 049E 79 MOV A,C 049F 32650A STA SECTOR 04A2 324E14 STA SEKSEC ;FOR BLOCK/DEBLOCK 04A5 C9 RET ; SECTRAN: ;TRANSLATE THE SECTOR GIVEN BY BC USING THE ;TRANSLATE TABLE GIVEN BY DE 04A6 7A MOV A,D 04A7 B3 ORA E 04A8 60 MOV H,B 04A9 69 MOV L,C 04AA C8 RZ 04AB EB XCHG ;HL=.TRANS 04AC 09 DAD B ;HL=.TRANS(SECTOR) 04AD 6E MOV L,M ;L = TRANS(SECTOR) 04AE 2600 MVI H,0 ;HL= TRANS(SECTOR) 04B0 C9 RET ;WITH VALUE IN HL ; SETDMA: ;SET DMA ADDRESS GIVEN BY REGISTERS B AND C 04B1 69 MOV L,C ;LOW ORDER ADDRESS 04B2 60 MOV H,B ;HIGH ORDER ADDRESS 04B3 22670A SHLD DMAAD ;SAVE THE ADDRESS 04B6 C9 RET ; READ: ;PERFORM READ OPERATION (USUALLY THIS IS SIMILAR TO WRITE ; SO WE WILL ALLOW SPACE TO SET UP READ COMMAND, THEN USE ; COMMON CODE IN WRITE) 04B7 F5 PUSH PSW 04B8 3EFF MVI A,0FFH ;READ 04BA C3C304 JMP WAITIO ; WRITE: ;PERFORM A WRITE OPERATION 04BD F5 PUSH PSW 04BE 79 MOV A,C 04BF 325D14 STA WRTYPE 04C2 AF XRA A ;WRITE ; WAITIO: ;ENTER HERE FROM READ AND WRITE TO PERFORM THE ACTUAL I/O ; OPERATION. RETURN A 00H IN REGISTER A IF THE OPERATION COMPLETES ; PROPERLY, AND 01H IF AN ERROR OCCURS DURING THE READ OR WRITE ; ; NOTE ABOUT THE STATE SAVE: ; SOME SOFTWARE (NOTEABLY MICROSOFT, AND WORD PROCESSORS) ; LEAVE VERY LITTLE ROOM ON THE STACK. TO INSURE A MAX ; STACK USAGE OF 2 WORDS (CALL AND PSW SAVE) AND ALLOW I/O ; DRIVERS TO USE SUBROUTINES, A STACK SWITCH AND STATE ; SAVE IS USED, TO PROTECT FOOLS FROM THEMSELVES. ; 04C3 22E516 SHLD HLSAV ;SAVE HL REGISTER 04C6 210000 LXI H,0 ;GET OLD STACK ADDRESS 04C9 39 DAD SP 04CA 22E316 SHLD OLDSP 04CD 310517 LXI SP,NSTACK ;SETUP NEW STACK 04D0 C5 PUSH B 04D1 D5 PUSH D 04D2 326A0A STA RORW ;READ OR WRITE SWITCH 04D5 AF XRA A ;DEFAULT I/O OK 04D6 326B0A STA DIOST 04D9 C3E104 JMP DSEL ; ; ; ; IN THIS CASE, WE HAVE SAVED THE DISK NUMBER IN 'DISKNO' (0-3) ; THE TRACK NUMBER IN 'TRACK' (0-76) ; THE SECTOR NUMBER IN 'SECTOR' (1-26) ; THE DMA ADDRESS IN 'DMAAD' (0-65535) ; THE READ (0FF) OR WRITE (0) CODE ; IN 'RORW' ; THE DEFAULT I/O STATUS OF OK ; IN 'DIOST' ; ; THE CURRENT SELECTED DISK NR IS IN 'CURDSK' (0-3) ; THE CURRENT DISK'S CURRENT TRACK IS IN 'CURTRK' ; ; ; DISK CONTROLLER PROCEDURE FOR THE TARBELL FLOPPY DISK CONTROLLER ; 00EC = DVSEL: EQU 0ECH ;DRIVE SELECT PORT 00E8 = DCOM: EQU 0E8H ;COMMAND PORT 00E8 = DSTAT: EQU 0E8H ;DEVICE STATUS 00EC = DWAIT: EQU 0ECH ;I/O WAIT READ PORT 00EB = DDATA: EQU 0EBH ;FDC DATA PORT 00E9 = DTRACK: EQU 0E9H ;TRACK PORT 00EA = DSECT: EQU 0EAH ;SECTOR PORT 0002 = STPRAT: EQU 2 ;0,1,2, OR 3 STEP RATE (SEE 1771 D.S.) 00D0 = CLRCMD: EQU 0D0H ;CLEAR 1771 COMMAND 0002 = RSTCMD: EQU 0+STPRAT ;RESTORE COMMAND 001A = SEKCMD: EQU 18H+STPRAT ;SEEK COMMAND (SLOW) 0048 = SICMD: EQU 48H ;STEP IN COMMAND 0068 = SOCMD: EQU 68H ;STEP OUT COMMAND ; 04DC 00 CCODE: DB 0 ;CURRENT SELECT CODE LATCH CONTENTS 04DD 00060A12 SELCODE: DB 00H,06H,0AH,12H ; ; ; SELECT DESIRED DISK DRIVE ; 04E1 3A690A DSEL: LDA DISKNO ;DESIRED DRIVE NR TO DE IF NOT FLP1ST CPI NUMHRD JC HRDDSK ;HARDDISK IS 0-3, OTHERS FLOPPIES SBI NUMHRD ENDIF IF FLP1ST 04E4 FE02 CPI NUMDSK-NUMHRD 04E6 D2ED05 JNC HRDDSK ENDIF 04E9 5F MOV E,A 04EA AF XRA A 04EB 57 MOV D,A 04EC 3AE105 LDA CURDSK ;CURRENT DRIVE NR TO A 04EF BB CMP E ;SAME DRIVE? 04F0 CA1A05 JZ TSEEK ;YES - SKIP SELECT 04F3 3E04 MVI A,4 ;FORCE HEADLOAD 04F5 326C0A STA HDLD 04F8 3A690A LDA DISKNO ;SET SELECTED DRIVE NR IF NOT FLP1ST SBI NUMHRD ENDIF 04FB 32E105 STA CURDSK 04FE 21DD04 LXI H,SELCODE ;LOOKUP SELECT CODE 0501 19 DAD D 0502 7E MOV A,M 0503 D3EC OUT DVSEL ;SELECT THE DRIVE 0505 32DC04 STA CCODE ;SAVE LATCH CONTENTS 0508 3AE205 LDA CURTRK ;SAVE CURRENT DRIVES 050B 2AEB05 LHLD CTADR ;CURRENT TRACK INDICATOR 050E 77 MOV M,A 050F 21E305 LXI H,DK0CT ;LOOKUP CURRENT TRACK IF DUAL MOV A,E ;FOR DUAL DRIVES USE ANI 0FEH ; DRIVE 0 AND 2 MOV E,A ;CURRENT TRACK STORAGE ENDIF 0512 19 DAD D 0513 22EB05 SHLD CTADR ;SAVE THIS DRIVES CURRENT TRACK POINTER 0516 7E MOV A,M ;AND ITS CURRENT TRACK 0517 32E205 STA CURTRK ; ; ; SEEK DESIRED TRACK ; 051A 3A630A TSEEK: LDA TRACK ;IS THE DESIRED TRACK 051D 5F MOV E,A 051E 3AE205 LDA CURTRK ;THE SAME AS THE 0521 BB CMP E ;CURRENT TRACK? 0522 CA6405 JZ DOIO ;YES. GO DO I/O 0525 FEFF CPI 0FFH ;HOME DISK NEEDED? 0527 C24505 JNZ DOSEEK ;NO - DO SEEK ; IF NOT PERSCI 052A DBE8 HBSY: IN DSTAT ;WAIT FOR NOT BUSY 052C 0F RRC 052D DA2A05 JC HBSY 0530 3E02 MVI A,RSTCMD ;RESTORE COMMAND 0532 D3E8 OUT DCOM 0534 DBEC IN DWAIT ;WAIT FOR INTRQ (OPCOMP) 0536 00 NOP 0537 DBE8 IN DSTAT 0539 E604 ANI 4 ;LOOK AT STATUS 053B CA2A05 JZ HBSY ;RETRY RESTORE IF ERROR 053E AF XRA A 053F 32E205 STA CURTRK ;SET CURRENT TRACK TO ZERO 0542 C31A05 JMP TSEEK ;GO CHECK FOR SEEK 0545 7B DOSEEK: MOV A,E ;SEND DESIRED TRACK 0546 D3EB OUT DDATA 0548 DBE8 SBSY: IN DSTAT ;WAIT FOR NOT BUSY 054A 0F RRC 054B DA4805 JC SBSY 054E 3E1A MVI A,SEKCMD ;SEEK WITH VERIFY COMMAND 0550 D3E8 OUT DCOM 0552 DBEC IN DWAIT ;WAIT FOR INTRQ (OPCOMP) 0554 00 NOP ENDIF ; IF PERSCI HBSY: MVI A,CLRCMD ;CLEAR ANY CURRENT OPN OUT DCOM IWT: IN DSTAT ;WAIT NOT BUSY ANI 1 JNZ IWT LDA CCODE ;ISSUE PERSCI RESTORE ANI 0BFH OUT DVSEL MVI A,RSTCMD ;ISSUE 1771 RESTORE OUT DCOM IN DWAIT ;WAIT FOR COMPLETION LDA CCODE ;RE-SELECT DRIVE OUT DVSEL XRA A ;SET CURRENT TRACK 0 STA CURTRK JMP TSEEK ;NOW DO TRACK SEEK DOSEEK: SUB E ;CURRENT-DESIRED TRACK MOV B,A ;NR STEPS TO B JP STPOUT ;POSITIVE - STEP OUT B TRACKS CMA ;-A TO A INR A MOV B,A ;NR STEPS TO B MVI A,SICMD ;SELECT STEP IN JMP GOSEEK STPOUT: MVI A,SOCMD ;SELECT STEP OUT GOSEEK: OUT DCOM ;ISSUE STEP COMMAND STA LSTSEK ;SAVE LAST SEEK COMMAND MOV A,B ;SAVE NR OF STEPS STA STPS MVI C,20H ;WAIT FOR DIRECTION LINE STLUP: DCR C ;TO SETTLE JNZ STLUP MVI A,1 SPLUP: OUT DVSEL ;ISSUE STEP PULSES DCR B JNZ SPLUP IN DWAIT ;CLEAR 1771 MOV A,E OUT DTRACK ;UPDATE 1771 TRACK REGISTER LDA CCODE ;ISSUE WAIT FOR SEEK COMPLETE ANI 72H ;CODE OUT DVSEL IN DWAIT ;WAIT FOR SEEK COMPLETE LDA CCODE OUT DVSEL ;NOW RESELECT DISK DRIVE ENDIF ; 0555 DBE8 SDONE: IN DSTAT ;IF ERROR 0557 32E805 STA SSTAT 055A E691 ANI 091H 055C C22A05 JNZ HBSY ;GO RE-HOME DRIVE 055F DBE9 IN DTRACK 0561 32E205 STA CURTRK ;SAVE NEW CURRENT TRACK ; ; NOW DO THE READ OR WRITE SECTOR ; 0564 3E0B DOIO: MVI A,11 ;RETRY COUNT +1 0566 47 MOV B,A 0567 C37305 JMP TRY1 056A 05 RETRY: DCR B ;DECREMENT RETRY 056B CAC705 JZ ERROR ;EXIT IF HARD ERROR 056E 3E04 MVI A,04H ;REQUIRE HEADLOAD ON ALL RETRYS 0570 326C0A STA HDLD 0573 3A650A TRY1: LDA SECTOR 0576 D3EA OUT DSECT ;ISSUE SECTOR DESIRED 0578 2A670A LHLD DMAAD ;AND SET I/O BUFFER ADDRESS 057B 3A6A0A LDA RORW ;SELECT READ OR WRITE 057E FE00 CPI 0 0580 CAA505 JZ DWRITE ;GO WRITE SECTOR ; IF INTRP 0583 F3 DI ;DISABLE INTERRUPTS ENDIF 0584 3A6C0A LDA HDLD ;SELECT HEADLOAD OPTION 0587 F688 ORI 088H ;READ COMMAND 0589 D3E8 OUT DCOM 058B DBEC RLOOP: IN DWAIT ;WAIT FOR DRQ 058D B7 ORA A ;CHECK FOR INTRQ (OPCOMP) 058E F29805 JP RDONE 0591 DBEB IN DDATA ;GET BYTE 0593 77 MOV M,A ;STORE IT 0594 23 INX H ;BUMP POINTER 0595 C38B05 JMP RLOOP ;GO GET NEXT BYTE 0598 DBE8 RDONE: IN DSTAT ;READ STATUS IF INTRP ;EI ;RE-ENABLE INTERRUPTS ENDIF 059A 32E705 STA LSTAT 059D E69D ANI 09DH ;RETRY IF ERROR 059F C26A05 JNZ RETRY 05A2 C3CF05 JMP DDONE ;READ COMPLETE ; DWRITE: ; IF INTRP 05A5 F3 DI ;DISABLE INTERRUPTS ENDIF 05A6 3A6C0A LDA HDLD ;SELECT HEADLOAD OPTION 05A9 F6A8 ORI 0A8H ;WRITE COMMAND 05AB D3E8 OUT DCOM 05AD DBEC WLOOP: IN DWAIT ;CHECK DRQ 05AF B7 ORA A 05B0 F2BA05 JP WDONE ;END IF INTRQ (ENDOP) 05B3 7E MOV A,M ;GET DATA 05B4 D3EB OUT DDATA ;AND SEND IT 05B6 23 INX H ;BUMP POINTER 05B7 C3AD05 JMP WLOOP ;GO FOR NEXT BYTE 05BA DBE8 WDONE: IN DSTAT ;WRITE OP STATUS IF INTRP ;EI ;RE-ENABLE INTERRUPTS ENDIF 05BC 32E705 STA LSTAT 05BF E6FD ANI 0FDH ;RETRY IF ERROR 05C1 C26A05 JNZ RETRY 05C4 C3CF05 JMP DDONE ;WRITE COMPLETE 05C7 3E01 ERROR: MVI A,1 ;DISK I/O ERROR 05C9 326B0A STA DIOST 05CC C3D305 JMP EDONE ; ; ; ; I/O COMPLETE. DDONE: ; DISK I/O DONE IF HLOPT 05CF AF XRA A ;CLEAR HEADLOAD REQUIRED 05D0 326C0A STA HDLD ENDIF 05D3 D1 EDONE: POP D ;RESTORE DE AND BC FROM NSTACK 05D4 C1 POP B 05D5 2AE316 LHLD OLDSP ;RESTORE OLD STACK 05D8 F9 SPHL 05D9 2AE516 LHLD HLSAV ;RESTORE HL 05DC F1 POP PSW 05DD 3A6B0A LDA DIOST ;0 I/O OK, ELSE FAIL 05E0 C9 RET ; 05E1 FF CURDSK: DB 0FFH ;CURRENT DISK (FF TO INITIALIZE) 05E2 FF CURTRK: DB 0FFH ;CURRENT DISKS CURRENT TRACK 05E3 FF DK0CT: DB 0FFH ;DRIVE 0 CURRENT TRACK 05E4 FF DK1CT: DB 0FFH ;DRIVE 1 CURRENT TRACK 05E5 FF DK2CT: DB 0FFH ;DRIVE 2 CURRENT TRACK 05E6 FF DK3CT: DB 0FFH ;DRIVE 3 CURRENT TRACK 05E7 FF LSTAT DB 0FFH ;LAST R/W STATUS 05E8 FF SSTAT: DB 0FFH ;LAST SEEK STATUS 05E9 00 LSTSEK: DB 0 ;LAST SEEK COMMAND 05EA FF STPS: DB 0FFH ;NR STEPS LAST SEEK 05EB E305 CTADR: DW DK0CT ;CURRENT TRACK RESTORE ADDRESS ; 05ED 3A6A0A HRDDSK LDA RORW 05F0 FE00 CPI 0 05F2 CA0906 JZ WRITEH ;IF RORW IS ZERO THEN WRITE THE HARD DISK READH: ;READ THE SELECTED CP/M SECTOR 05F5 AF XRA A 05F6 325614 STA UNACNT ;UNACNT = 0 05F9 3E01 MVI A,1 05FB 325C14 STA READOP ;READ OPERATION 05FE 325B14 STA RSFLAG ;MUST READ DATA 0601 3E02 MVI A,WRUAL 0603 325D14 STA WRTYPE ;TREAT AS UNALLOC 0606 C37306 JMP RWOPER ;TO PERFORM THE READ WRITEH: ;WRITE THE SELECTED CP/M SECTOR 0609 AF XRA A 060A 325C14 STA READOP ;NOT A READ OPERATION 060D 3A5D14 LDA WRTYPE 0610 FE02 CPI WRUAL ;WRITE UNALLOCATED? 0612 C22C06 JNZ CHKUNA ;CHECK FOR UNALLOC ; WRITE TO UNALLOCATED, SET PARAMETERS 0615 3E80 MVI A,128 ;NEXT UNALLOC RECS 0617 325614 STA UNACNT 061A 3A4B14 LDA SEKDSK ;UNADSK = SEKDSK 061D 325714 STA UNADSK 0620 2A4C14 LHLD SEKTRK 0623 225814 SHLD UNATRK ;UNATRK = SECTRK 0626 3A4E14 LDA SEKSEC 0629 325A14 STA UNASEC ;UNASEC = SEKSEC CHKUNA: ;CHECK FOR WRITE TO UNALLOCATED SECTOR 062C 3A5614 LDA UNACNT ;ANY UNALLOC REMAIN? 062F B7 ORA A 0630 CA6B06 JZ ALLOC ;SKIP IF NOT ; MORE UNALLOCATED RECORDS REMAIN 0633 3D DCR A 0634 325614 STA UNACNT 0637 3A4B14 LDA SEKDSK ;SAME DISK? 063A 215714 LXI H,UNADSK 063D BE CMP M ;SEKDSK = UNADSK 063E C26B06 JNZ ALLOC ; DISK ARE THE SAME 0641 215814 LXI H,UNATRK 0644 CD1407 CALL SEKTRKCMP ;SEKTRK = UNATRK? 0647 C26B06 JNZ ALLOC ;SKIP IF NOT ; TRACKS ARE THE SAME 064A 3A4E14 LDA SEKSEC ;SAME SECTOR? 064D 215A14 LXI H,UNASEC 0650 BE CMP M ;SEKSEC = UNASEC? 0651 C26B06 JNZ ALLOC ;SKIP IF NOT ; MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF 0654 34 INR M ;UNASEC = UNASEC+1 0655 7E MOV A,M ;END OF TRACK? 0656 FE8C CPI CPMSPT ;COUNT CPM SECTORA 0658 DA6406 JC NOOVF ;SKIP IF NO OVERFLOW ; OVERFLOW TO NEXT TRACK 065B 3600 MVI M,0 ;UNASEC = 0 065D 2A5814 LHLD UNATRK 0660 23 INX H 0661 225814 SHLD UNATRK ;UNATRK = UNATRK+1 NOOVF: ; MATCH FOUND, MARK AS UNNECESSARY READ 0664 AF XRA A ;0 TO ACCUMULATOR 0665 325B14 STA RSFLAG 0668 C37306 JMP RWOPER ;TO PERFORM THE WRITE ALLOC: ;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ 066B AF XRA A ;0 TO ACCUMULATOR 066C 325614 STA UNACNT ;UNACNT = 0 066F 3C INR A ;1 TO ACCUM 0670 325B14 STA RSFLAG ;RSFLAG = 1 ; ;********************************************************* ;* * ;* COMMON CODE FOR READ AD WRITE FOLLOWS ;* * ;********************************************************* ; RWOPER: ;ENTER HERE TO PERFORM THE READ/WRITE 0673 AF XRA A ;ZERO TO ACCUM 0674 326B0A STA DIOST ;NO ERRORS (YET) 0677 3A4E14 LDA SEKSEC 067A B7 ORA A ;CARRY = 0 067B 1F RAR ;SHIFT RIGHT 067C B7 ORA A 067D 1F RAR 067E 325314 STA SEKHST ;HOST SECTOR TO SEEK ; ACTIVE HOST SECTOR? 0681 215414 LXI H,HSTACT ;HOST ACTIVE FLAG 0684 7E MOV A,M 0685 3601 MVI M,1 ;ALWAYS BECOMES 1 0687 B7 ORA A ;WAS IT ALREADY? 0688 CAAF06 JZ FILHST ;FILL HOST IF NOT ; HOST BUFFER ACTIVE,SAVE AS SEEK BUFFER? 068B 3A4B14 LDA SEKDSK 068E 214F14 LXI H,HSTDSK 0691 BE CMP M ;SEKDSK = HSTDSK? 0692 C2A806 JNZ NOMATCH ; SAME DISK, SAME TRACK? 0695 215014 LXI H,HSTTRK 0698 CD1407 CALL SEKTRKCMP 069B C2A806 JNZ NOMATCH ; SAME DISK,SAME TRACK, SAME BUFFER? 069E 3A5314 LDA SEKHST 06A1 215214 LXI H,HSTSEC ;SEKHST = HSTSEC? 06A4 BE CMP M 06A5 CACC06 JZ MATCH ;SKIP IF MATCH NOMATCH: ;PROPER DSK, BUT NOT CORRECT SECTOR 06A8 3A5514 LDA HSTWRT ;HOST WRITTEN? 06AB B7 ORA A 06AC C42007 CNZ WRITEHST ;CLEAR HOST BUFF FILHST: ;MAY HAVE TO FILL THE HOST BUFFER 06AF 3A4B14 LDA SEKDSK 06B2 324F14 STA HSTDSK 06B5 2A4C14 LHLD SEKTRK 06B8 225014 SHLD HSTTRK 06BB 3A5314 LDA SEKHST 06BE 325214 STA HSTSEC 06C1 3A5B14 LDA RSFLAG ;NEED TO READ? 06C4 B7 ORA A 06C5 C46207 CNZ READHST ;YES, IF 1 06C8 AF XRA A ;ZERO TO ACCUMULATOR 06C9 325514 STA HSTWRT ;NO PENDING WRITE MATCH: ;COPY DATA TO OR FROM BUFFER 06CC 3A4E14 LDA SEKSEC ;MASK BUFFER NUMBER 06CF E603 ANI SECMSK ;LEAST SIGNIF BITS 06D1 6F MOV L,A 06D2 2600 MVI H,0 ;DOUBLE COUNT 06D4 29 DAD H 06D5 29 DAD H 06D6 29 DAD H 06D7 29 DAD H 06D8 29 DAD H 06D9 29 DAD H 06DA 29 DAD H ; HL HAS RELATIVE HOST BUFFER ADDRESS 06DB 115E14 LXI D,HSTBUF 06DE 19 DAD D ;HL = HOST ADDRESS 06DF EB XCHG 06E0 2A670A LHLD DMAAD ;GET/PUT CP/M DATA 06E3 0E80 MVI C,128 ;LENGTH OF MOVE 06E5 3A5C14 LDA READOP ;WHICH WAY? 06E8 B7 ORA A 06E9 C2F206 JNZ RWMOVE ;SKIP IF READ ; WRITE OPERATION, MARK AND SWITHC DIRECTION 06EC 3E01 MVI A,1 06EE 325514 STA HSTWRT ;HSTWRT = 1 06F1 EB XCHG RWMOVE: ;C INITIALLY 128, DE IS SOURCE, HL IS DEST 06F2 1A LDAX D ;SOURCE CHARACTER 06F3 13 INX D 06F4 77 MOV M,A 06F5 23 INX H 06F6 0D DCR C ;LOOP 128 TIMES 06F7 C2F206 JNZ RWMOVE ;SKIP IF READ ; DATA HAS BEEN MOVED TO/FROM HOST BUFFER 06FA 3A5D14 LDA WRTYPE ;WRITE TYPE 06FD FE01 CPI WRDIR ;TO DIRECTORY? 06FF 3A6B0A LDA DIOST ;IN CASE OF ERRORS 0702 C2D305 JNZ EDONE ;NO FURTHER PROCESSING ; CLEAR HOST BUFFER FOR DIRECTORY WRITE 0705 B7 ORA A ;ERRORS? 0706 C0 RNZ ;SKIP IF SO 0707 AF XRA A ;0TO ACCUMULATOR 0708 325514 STA HSTWRT ;BUFFER WRITEN 070B CD2007 CALL WRITEHST 070E 3A6B0A LDA DIOST 0711 C3D305 JMP EDONE ; SEKTRKCMP: ;HL = .UNATRK OR .HSTTRK, COMPARE WITH SEKTRK 0714 EB XCHG 0715 214C14 LXI H,SEKTRK 0718 1A LDAX D ;LOW BYTE COMPARE? 0719 BE CMP M ;SAME? 071A C0 RNZ ;RETURN IF NOT ; LOW BYTES EQUAL, TEST HIGH BYTES 071B 13 INX D 071C 23 INX H 071D 1A LDAX D 071E BE CMP M ;SET FLAGS 071F C9 RET ; THE KONAN HARD DISK DRIVER FOLLOWS. ; 0090 = IOBASE EQU 90H 0090 = BUSU EQU IOBASE 0091 = BUSL EQU IOBASE+1 0092 = CMND EQU IOBASE+2 0093 = SCTAD EQU IOBASE+3 0094 = SCTBU EQU IOBASE+4 0095 = DMACL EQU IOBASE+5 0096 = DMACU EQU IOBASE+6 0097 = STATU EQU IOBASE+7 WRITEHST: ;ENTRY INTO THE WRITE PROGRAM 0720 CD0008 CALL KCOMMON ;SETS SECTOR,DMA,HEAD,TRACK,UNIT 0723 D8 RC ;ERROR RETURN 0724 AF XRA A ;CLEAR BUS 0725 D391 OUT BUSL 0727 D390 OUT BUSU ;BUS IS NOW CLEARED 0729 D397 OUT STATU ;SECTOR BUFFER NOW ZEROED ; WRITE THE HEADER NOW (TRACK MSB,TRACK LSB,HEAD,SECTOR) 072B 215B0A LXI H,PTRK ;POINT TO THE TRACK 072E 0604 MVI B,4 ;HEADER BYTE COUNT 0730 7E HEADWT MOV A,M ;GET BYTE IN ACUMULATOR 0731 D394 OUT SCTBU ;SEND IT 0733 23 INX H 0734 05 DCR B ;DECREMENT COUNT 0735 C23007 JNZ HEADWT ;IF NOT DONE JMP TO HEADER WRITE IF DMA ;*************************** MVI A,02 ;DMA WRITE COMMAND OUT CMND ;DO THE WRITE ENDIF ;*************************** IF NOT DMA ;*************************** 0738 215E14 LXI H,HSTBUF;IO WRITE LOOP 073B 110002 LXI D,HSTSIZ 073E 7E NXIOW MOV A,M 073F D394 OUT SCTBU 0741 23 INX H 0742 1D DCR E 0743 C23E07 JNZ NXIOW 0746 15 DCR D 0747 C23E07 JNZ NXIOW ENDIF ;************************** 074A D397 OUT STATU 074C 3E01 MVI A,1 ;DISK WRITE COMMAND 074E D392 OUT CMND ;DO THE WRITE 0750 CD1F09 CALL WT ;WAIT FOR IT TO FINISH 0753 3E41 MVI A,'A' ;ERROR A IS A TIMEOUT 0755 DA5409 JC ERREPORT ;IF TIMEOUT, PRINT A 0758 DB97 IN STATU ;GET STATU 075A E620 ANI 20H ;IS FAULT ON? 075C 3E42 MVI A,'B' 075E C25409 JNZ ERREPORT ;PRINT B IF WRITE FAULT ;REPORT END STATUS 0761 C9 RET ;DONE WITH WRITE READHST: ;READ SUBROUTINE. READS VIA READINT THEN DOES DMA 0762 CD7807 CALL READINT ;PLACE DATA INTO THE SECTOR BUFFER IF DMA ;**************************** MVI A,04H ;DMA READ COMMAND OUT CMND ;DO THE READ ENDIF IF NOT DMA ;**************************** 0765 215E14 LXI H,HSTBUF;IO READ LOOP 0768 110002 LXI D,HSTSIZ 076B DB94 NXIOR IN SCTBU 076D 77 MOV M,A 076E 23 INX H 076F 1D DCR E 0770 C26B07 JNZ NXIOR 0773 15 DCR D 0774 C26B07 JNZ NXIOR ENDIF ;**************************** 0777 C9 RET ;RETURN READINT: ;READ TO SECTOR BUFFER 0778 CD0008 CALL KCOMMON ;SET SECTOR,DMA,TRACK,HEAD,AND UNIT 077B D8 RC ;ERROR RETURN 077C AF XRA A ;GENERATE A ZERO 077D D391 OUT BUSL ;CLEAN UP LOWER BUS 077F D390 OUT BUSU ;CLEAN UP UPPER BUS 0781 32590A STA CERRC ;ZERO THE ERROR COUNT 0784 D397 RDKON OUT STATU ;SET BUFFER TO ZERO 0786 3E88 MVI A,88H ;DISK READ COMMAND 0788 D392 OUT CMND ;DO THE READ 078A CD1F09 CALL WT ;WAIT FOR DONE 078D 3E43 MVI A,'C' 078F DC5409 CC ERREPORT ;PRINT C IF TIMEOUT ERROR 0792 DABC07 JC RCOVRE ;GO ATTEMPT TO RECOVER THE TIMEOUT 0795 DB97 IN STATU ;GET ENDING STATUS 0797 E604 ANI 4H ;IS CHECKSUM ON? 0799 C2AF07 JNZ CHKRECOV ;GO REPORT/RECOVER ; WE WILL NOW TEST THE HEADER 079C 215B0A LXI H,PTRK ;POINT TO THE TRACK 079F 0604 MVI B,4 ;NUMBER OF HEADER BYTES 07A1 D397 OUT STATU ;ZERO BUFFER ADDRESS 07A3 DB94 HDRTST IN SCTBU ;GET HEADER READ 07A5 BE CMP M 07A6 C2B707 JNZ FRMTRCV ;RECOVER IF DIFFERENT 07A9 05 DCR B 07AA 23 INX H 07AB C2A307 JNZ HDRTST ;IF HEADER COUNT IS NON ZERO TEST ONE MORE ; WHEN WE ARIVE HERE THE READ IS DONE. 07AE C9 RET ; ; ; READ RECOVERY PROGRAM FOLLOWS CHKRECOV: 07AF 3E44 MVI A,'D' 07B1 CD5409 CALL ERREPORT ;PRINT A D IF CHECKSUM ERROR 07B4 C3BC07 JMP RCOVRE 07B7 3E45 FRMTRCV MVI A,'E' 07B9 CD5409 CALL ERREPORT ;PRINT A E IF FORMAT ERROR 07BC 3A590A RCOVRE: LDA CERRC 07BF 3C INR A ;INCREMENT THE COUNT 07C0 32590A STA CERRC ;SAVE THE NEW COUNT 07C3 4F MOV C,A ;SAVE THE ERROR COUNT 07C4 E603 ANI 3 ;GET LAST 2 BITS,STROBE EARLY AND LATE 07C6 FE03 CPI 3 ;NOT LEGAL TO HAVE BOTH ON 07C8 CABC07 JZ RCOVRE ;IF ILLEGAL, GO TO NEXT CERRC 07CB 79 MOV A,C ;GET THE ERROR COUNT 07CC E618 ANI 18H ;GET THE OFFSET MINUS AND PLUS BITS 07CE FE18 CPI 18H ;ARE THE BOTH ON? 07D0 CABC07 JZ RCOVRE ;IF SO GO TO THE NEXT COUNT 07D3 79 MOV A,C ;RESTORE THE ERROR COUNT 07D4 FE20 CPI 20H ;IS THIS THE START OF THE SECOND PASS? 07D6 CC3109 CZ PANIC ;IF 20H WE WILL RETRY SEL,SEEK,MAPPER ETC. 07D9 3A590A LDA CERRC ;RESTORE THE ERROR COUNT 07DC 4F MOV C,A ;PLACE IT IN C FOR FUTURE RECALL 07DD C6DC ADI 0DCH ;TIME TO GIVE UP? 07DF DAF107 JC HARDRDER ;IF CARRY WE HAVE A HARD READ ERROR ; IF WE GET HERE WE ARE READY TO SET RECOVERY BITS AND TRY AGAIN 07E2 79 MOV A,C ;RESTORE ERROR COUNT 07E3 0F RRC ;POSITION BITS 07E4 E68C ANI 8CH ;GET OFFSETS PLUS STROBE EARLY 07E6 D391 OUT BUSL ;SET THE BITS 07E8 79 MOV A,C ;RESTORE ERROR COUNT 07E9 0F RRC ;POSITION BITS 07EA E601 ANI 1 ;STROBE LATE BIT 07EC D390 OUT BUSU ;BUS NOW COMPLETE 07EE C38407 JMP RDKON ;GO DO THE READ RECOVERY HARDRDER: ;HARD DISK READ ERROR 07F1 DB97 IN STATU ;SET THE READ BUFFER TO ADDRESS 4 07F3 DB94 IN SCTBU 07F5 DB94 IN SCTBU 07F7 DB94 IN SCTBU 07F9 DB94 IN SCTBU 07FB 3E46 MVI A,'F' ;HARD ERROR 07FD C35409 JMP ERREPORT ; ; KONAN DISK READ AND WRITE COMMON ROUTINE ; SETS THE SECTOR, DMA, UNIT, HEAD, AND TRACK ; ADDRESSES. NOTE THAT EVERY HEAD SELECT IS ; FOLLOWED BY A SEEK TO MAINTAIN COMPATIBILITY ; WITH CMD DRIVES. ; RETURNS WITH CARRY SET IF ERROR, RESET IF NOT ; KCOMMON: 0800 AF XRA A ;MAKE A ZERO 0801 326B0A STA DIOST ;SET ERROR FLAG TO ZERO 0804 215E14 LXI H,HSTBUF ;PLACE DMA ADDRESS IN H&L 0807 7D MOV A,L ;GET LSB OF DMA ADDRESS 0808 D395 OUT DMACL ;SET LSB OF DMA ADDRESS 080A 7C MOV A,H ;GET MSB OF DMA ADDRESS 080B D396 OUT DMACU ;SET MSB OF DMA ADDRESS 080D AF XRA A ;MAKE A ZERO 080E D391 OUT BUSL ;CLEAR THE LOWER BUS 0810 D390 OUT BUSU ;CLEAR THE UPPER BUS 0812 CD1808 CALL HSTPHY 0815 C35908 JMP COMCON HSTPHY ;CALCULATE THE PHYSICAL ADDRESS 0818 2A5014 LHLD HSTTRK 081B 116EFE LXI D,-402 ;402 IS MAX TRACK PER UNIT 081E 19 DAD D ;IF CARRY TRACK IS ILLEGAL 081F 3E4E MVI A,'N' ;ERROR N IS ILLEGAL TRACK 0821 DC5409 CC ERREPORT 0824 D8 RC 0825 119201 LXI D,402 ;OFFSET FOR INNER TRACKS 0828 2A5014 LHLD HSTTRK ;CPM TRACK 082B 3A4F14 LDA HSTDSK ;0 FOR A, 1 FOR B, ETC IF FLP1ST 082E D602 SUI NUMDSK-NUMHRD ENDIF 0830 0F RRC ;PLACE LSB IN CARRY 0831 D23508 JNC INNER ;DO NOT ADD 402 IF INNER 0834 19 DAD D ;ADD 402 IF OUTER 0835 E60F INNER ANI 0FH ;REMOVE END AROUND CARRY 0837 0600 MVI B,0 ;B=UNIT, INITIALLY 0 0839 FE0C NUNIT CPI HEADQ ;IS HEADQ LARGER THEN HSTDSK? 083B DA4108 JC UNDONE ;B IS UNIT, A IS HEAD 083E DE0C SBI HEADQ ;DECREMENT BY THE NUMBER OF HEADS PER UNIT 0840 04 INR B ;INCREMENT THE UNIT 0841 325D0A UNDONE STA PHEAD ;REMAINDER IS THE PHYSICAL HEAD 0844 78 MOV A,B 0845 325A0A STA PUNIT ;UNIT IS THE QUOTIENT 0848 7C MOV A,H ;MSB OF TRACK 0849 325B0A STA PTRK ;STORE IT IN PHYSICAL UPPER TRACK 084C 7D MOV A,L ;LSB OF TRACK; 084D 325C0A STA PTRK+1 ;STORE IT IN PHYSICAL LOWER TRACK 0850 3A5214 LDA HSTSEC 0853 D393 OUT SCTAD 0855 325E0A STA PSECTOR 0858 C9 RET ; PHYSICAL ADDRESS IS NOW SET ; ;WE WILL NOW CHECK TO SEE IF SELECT IS TRUE, AND IF THE TRACK ;, HEAD, AND UNIT ADDRESSES ARE THE SAME AS THE LAST TRANSFER, ;STORED IN OLDUNIT, OLDTRK, AND OLDHEAD. ; COMCON 0859 DB97 IN STATU ;GET THE STATUS 085B 0F RRC ;PLACE SELECTED BIT INTO CARRY 085C D27408 JNC NEWADD ;IF NOT SELECT FORCE NEW ADDRESS ; TEST NEW VS OLD ADDRESS 085F 215F0A LXI H,OLDUNIT ;H,L POINT TO OLD ADDRESS 0862 115A0A LXI D,PUNIT ;D&E POINT TO NEW ADDRESS 0865 0604 MVI B,4 ;NUMBER OF BYTES TO CHECK 0867 1A ADCMP LDAX D ;GET NEW ADDRESS BYTE 0868 BE CMP M ;COMPARE IT TO OLD 0869 C27408 JNZ NEWADD ;IF DIFERENT GO TO NEW ADDRESS 086C 05 DCR B 086D 23 INX H ;INCREMENT THE POINTER TO CURRENT ADDRESS 086E 13 INX D ;INCREMENT THE POINTER TO DESIRED ADDRESS 086F C26708 JNZ ADCMP ;IF LOOP IS NOT DONE COMPARE ONE MORE ; RETURN WITHOUT ERROR, SAME ADDRESS 0872 AF XRA A ;CLEAR CARRY 0873 C9 RET NEWADD: ; SET OLD TO PHYSICAL 0874 115F0A LXI D,OLDUNIT 0877 215A0A LXI H,PUNIT 087A 0604 MVI B,4 ;COUNT 087C 7E UPDATE MOV A,M ;GET NEW 087D 12 STAX D ;UPDATE OLD 087E 13 INX D 087F 23 INX H 0880 05 DCR B 0881 C27C08 JNZ UPDATE 0884 3A5A0A LDA PUNIT ;GET THE PHYSICAL UNIT 0887 0F RRC ;UNIT IS UPPER HALF OF BYTE 0888 0F RRC 0889 0F RRC 088A 0F RRC 088B D390 OUT BUSU ;PLACE IT ON THE BUS 088D 3E10 MVI A,10H ;SELECT COMMAND 088F D392 OUT CMND ;SELECT I 0891 DB97 IN STATU ;GET STATUS 0893 0F RRC ;PLACE SELECT IN CARRY 0894 3F CMC ;CARRY 1 IF NOT SELECTED 0895 3E47 MVI A,'G' ;SELECT ERROR 0897 DA5409 JC ERREPORT ;PRINT IT 089A 3A5D0A LDA PHEAD ; IF CMD CPI 0 JZ HDJUST ;IS HEAD ZERO LEAVE ALLONE ADI 15 ;ADD 15 TO SET LOLUME TAG ENDIF 089D D391 HDJUST OUT BUSL ;SET IT ON THE BUS 089F 3E40 MVI A,40H ;SET HEAD COMMAND 08A1 D392 OUT CMND ;DO THE HEAD SELECT 08A3 DB97 IN STATU ;GET THE STATUS 08A5 E620 ANI 20H ;TEST DISK FAULT BUT 08A7 3E48 MVI A,'H' 08A9 C25409 JNZ ERREPORT ;IF FAULT IS ONE, REPORT IT ; ; ; SEEK ROUTINE ; TRACK SUBSTITUTION INCLUDED ; 08AC CDC108 SEEK: CALL GSEEK ;GO PERFORM THE SEEK 08AF D0 RNC ;RETURN IF SEEK WAS GOOD(NO CARRY) ; IF HERE, FIRST SEEK ATTEMPT FAILED 08B0 CD3D09 CALL RECAL ;RECAL DRIVE TO ATTEMMPT TO CLEAR ERROR 08B3 CDC108 CALL GSEEK ;GIVE IT ONE MORE TRY 08B6 D0 RNC ;IF NO ERROR IT RECOVERED ; IF HERE, HARD SEEK ERROR OCCURED 08B7 3EFF MVI A,0FFH ;SET A TO ALL ONES 08B9 325F0A STA OLDUNIT ;THIS WILL CAUSE A SELECT AND SEEK UPON ; NEXT ACCESS 08BC 3E49 MVI A,'I' 08BE C35409 JMP ERREPORT ;REPORT THE SEEK ERROR GSEEK: ; COMPRIZE COMMPOSITE ADDRESS TO SEARCH TRACK TABLE FOR 08C1 3A5B0A LDA PTRK 08C4 57 MOV D,A 08C5 3A5C0A LDA PTRK+1 08C8 5F MOV E,A IF MAPEN ;MAP THE TRACK IF MAP IS ENABLED 08C9 3A5D0A LDA PHEAD ;GET THE HEAD NUMBER 08CC 07 RLC 08CD 07 RLC ;PLACE HEAD IN BITS 5-2 08CE E61C ANI 1CH ;STRIP ANY ENTRA JUNK 08D0 B2 ORA D ;OR IN MSB OF TRACK 08D1 57 MOV D,A 08D2 3A5A0A LDA PUNIT ;GET UNIT NUMBER 08D5 0F RRC 08D6 0F RRC 08D7 0F RRC ;UNIT NOW IN 6-4 08D8 E660 ANI 60H 08DA B2 ORA D ;OR HEAD TO UNIT/TRACK 08DB 57 MOV D,A ;D IS NOW HEAD,UNIT,TRACKMSB 08DC 0E00 MVI C,0 ;SET B,C,TABLE ENTRY PIONTER, TO ZERO 08DE 215E16 FINDT LXI H,SUBTBL ;H&L NOW POINT TO THE TABLE 08E1 7E FINDN MOV A,M ;GET BYTE FORM THE TABLE, FIRST HALF 08E2 C680 ADI 80H ;ADD MSB TO SEE IF IT WAS ON 08E4 DA0A09 JC SUBDONE ;IF CARRY THE SUBSTITUTION IS DONE 08E7 7A MOV A,D ;LSB OF DESIRED 08E8 BE CMP M ;IS IT THE SAME? 08E9 23 INX H ;INCREMENT THE POINTER 08EA C2F208 JNZ NOCMP ;JMP NO COMPARE IF DIFFERENT 08ED 7B MOV A,E ;MSB OF DESIRED 08EE BE CMP M ;IS IT THE SAME 08EF CA0009 JZ SUBT ;IF ZERO GO DO THE SUBSTITUTION 08F2 23 NOCMP INX H ;INCREMENT THE POINTER 08F3 0C INR C ;INCREMENT THE LOCATION IN THE TABLE 08F4 79 MOV A,C ;GET TABLE POSITION 08F5 FE42 CPI MAXMAP+1 ;CAUSE CARRY IF MAXMAP OR LESS 08F7 3F CMC ;INVERT CARRY, 08F8 3E4D MVI A,'M' ;M IS MAP OVERRUN ERROR 08FA DC5409 CC ERREPORT ;PRINT M IF CARRY 08FD C3E108 JMP FINDN ;GO TEST THE NEXT ENTRY 0900 0600 SUBT: MVI B,0 ;B,C=THE TABLE ENTRY WHERE THE MATCH OCCURED 0902 21BC02 LXI H,MAXTRK+1 ;THE BEGIN OF THE SUBSTITUTION TRACKS 0905 09 DAD B ;H&L NOW EQUAL THE NEW TRACK 0906 EB XCHG ;D&E NOW EQUAL THE NEW TRACK 0907 C3DE08 JMP FINDT ;GO SEE IF THE SPARE IS MAPPED ENDIF ; ;SUBSTITUTION IS DONE, DO THE SEEK TO THE TRACK IN D&E SUBDONE 090A 7B MOV A,E ;LSB OF TRACK 090B D391 OUT BUSL 090D 7A MOV A,D ;MSB OF TRACK 090E E603 ANI 3 ;STRIP ALL BUT TRACK 0910 D390 OUT BUSU ;BUS NOW SET TO TRACK 0912 3E20 MVI A,20H ;SEEK COMMAND 0914 D392 OUT CMND ;DO THE SEEK 0916 CD1F09 CALL WT ;WAIT FOR DONE 0919 3E4A MVI A,'J' 091B DA5409 JC ERREPORT ;PRINT J IF SEEK TIMEOUT 091E C9 RET ; WAIT FOR DONE, RETURN WITH CARRY OFF WHEN DONE, ; AND CARRY SET IF TIMEOUT. 091F 26FF WT MVI H,0FFH ;H&L WILL BE DECREMENTED FOR A GROSS TIMEOUT 0921 2B WZ DCX H ;DECREMENT COUNT 0922 7C MOV A,H ;PLACE MSB OF COUNT INTO A 0923 B5 ORA L ;OR IN LSB TO SEE IF ANY BIT IS NON-ZERO 0924 CA2F09 JZ TIMEOUT ;TIMEOUT IF HL ZERO BEFOR DONE 0927 DB97 IN STATU ;GET STATUS 0929 E680 ANI 80H ;IS DONE ON? 092B CA2109 JZ WZ ;IF NOT DONE WAIT 092E C9 RET ;GOOD RETURN, CARRY OFF FROM THE ANI 80H 092F 37 TIMEOUT STC ;SET CARRY 0930 C9 RET ;ERROR RETURN ; ; PANIC ROUTINE FOLLOWS ; DO FAULT RESET, RECALL, KILL OLDUNIT, CALL KCOMMON 0931 CD3D09 PANIC CALL RECAL ;RECAL UNIT 0934 3EFF MVI A,0FFH 0936 325F0A STA OLDUNIT ;KILL OLD UNIT TO FORCE A SEEK AND SELECT 0939 CD0008 CALL KCOMMON 093C C9 RET 093D AF RECAL XRA A ;MAKE A ZERO 093E D390 OUT BUSU ;ZERO UPPER BUS 0940 3E50 MVI A,50H ;FAULT CLEAR AND RECAL BITS 0942 D391 OUT BUSL ;SET ONTO BUS 0944 3E80 MVI A,80H ;FAULT RECOVERY COMMAND 0946 D392 OUT CMND ;START FAULT RECOVERY 0948 AF XRA A ;MAKE ANOTHER ZERO 0949 D392 OUT CMND ;TURN OFF THE FAULT COMMAND 094B CD1F09 CALL WT ;WAIT FOR DONE 094E 3E4B MVI A,'K' 0950 DC5409 CC ERREPORT ;PRINT A K IF RECAL TIMEOUT 0953 C9 RET ; ; HARD DISK ERROR PRINT ; ERREPORT: 0954 326B0A STA DIOST ;SET ERROR FLAG 0957 21AF09 LXI H,ERRORMES 095A CDA209 CALL PRMSG 095D 3A6B0A LDA DIOST ;GET ERROR LETTER 0960 4F MOV C,A ;PLACE ASCII CHARACTER IN C 0961 CD4504 CALL CONOUT ; PRINT THE ERROR LETTER 0964 CD9D09 CALL SPACE ;PRINT THE ADDRESS 0967 21590A NX8 LXI H,CERRC 096A 0E06 MVI C,6 096C CD7609 NX8N CALL X8 096F 23 INX H 0970 0D DCR C 0971 C26C09 JNZ NX8N 0974 37 STC 0975 C9 RET 0976 7E X8 MOV A,M 0977 E6F0 ANI 0F0H 0979 0F RRC 097A 0F RRC 097B 0F RRC 097C 0F RRC 097D CD8B09 CALL HEXOUT 0980 7E MOV A,M 0981 E60F ANI 0FH 0983 CD8B09 CALL HEXOUT 0986 CD9D09 CALL SPACE 0989 37 STC 098A C9 RET 098B F630 HEXOUT ORI 30H 098D FE3A CPI 3AH 098F DA9409 JC GOODNUM 0992 C607 ADI 7 GOODNUM 0994 E5 PUSH H 0995 C5 PUSH B 0996 4F MOV C,A 0997 CD4504 CALL CONOUT 099A C1 POP B 099B E1 POP H 099C C9 RET 099D 3E20 SPACE MVI A,' ' 099F C39409 JMP GOODNUM ; ERRORS INCLUDE; ; A WRITE TIMEOUT ERROR ; B WRITE FAULT ; C READ TIMEOUT ; D CHECKWORD ; E FORMAT ; F HARD READ ERROR ; G UNIT SELECT ERROR ; H HEAD SELECT ERROR ; I HARD SEEK ERROR ; J SEEK TIMEOUT ; K RECAL TIMEOUT ; L MAPPER ERROR ; M MAP OVERRUN PRMSG: 09A2 7E MOV A,M ;PRINT MESSAGE AT H&L TO 0 09A3 B7 ORA A 09A4 C8 RZ ; MORE TO PRINT 09A5 E5 PUSH H 09A6 4F MOV C,A 09A7 CD4504 CALL CONOUT 09AA E1 POP H 09AB 23 INX H 09AC C3A209 JMP PRMSG ERRORMES: 09AF 0D0A DB 0DH,0AH 09B1 4841524420 DB 'HARD DISK ERROR ' 09C1 00 DB 0 ; ; MAPPER ROUTINE ; GETS THE MAPS OFF EACH DISK AND MAKES A SYSTEM WIDE ; MAP OF ALL BAD TRACKS 0041 = MAXMAP EQU 65 ;20 ENTRIES ALLOWED 0001 = MAXUNIT EQU 1 ;NUMBER OF DISK UNITS IF MAPEN ;ASSEMBLE ONLY IF MAP IS ENABLED SMAPPER ; SET PHYSICAL ADDRESS TO FIRST 09C2 AF XRA A ;MAKE A ZERO 09C3 325014 STA HSTTRK 09C6 325114 STA HSTTRK+1 09C9 324F14 STA HSTDSK 09CC 215E16 LXI H,SUBTBL 09CF 22E116 SHLD SUBPNT 09D2 3E22 MVI A,HSTSPT-1 ;LAST SECTOR NUMBER 09D4 325214 STA HSTSEC ;SET IT FOR KCOMMON ; CLEAR THE MAP 09D7 3EE5 MVI A,0E5H 09D9 0683 MVI B,2*MAXMAP+1 09DB 77 CLRMAP MOV M,A 09DC 23 INX H 09DD 05 DCR B 09DE C2DB09 JNZ CLRMAP GETMAP ;SEE IF SURFACE IS PRESENT 09E1 CD1808 CALL HSTPHY 09E4 3A5A0A LDA PUNIT 09E7 07 RLC 09E8 07 RLC 09E9 07 RLC 09EA 07 RLC 09EB D390 OUT BUSU 09ED 3E10 MVI A,10H ;SELECT UNIT COMMAND 09EF D392 OUT CMND 09F1 DB97 IN STATU ;CHECK UNIT STATUS 09F3 E601 ANI 1 09F5 CA480A JZ NEXTMAP ;IF NOT SELECTED GO TO NEXTMAP 09F8 3A5D0A LDA PHEAD IF CMD CPI 0 JZ CARTH ;IF CARTRIDGE THE HEAD ADDRESS IS GOOD ADI 15 ;OTHERWISE SET VOLUMN BIT ENDIF 09FB D391 CARTH OUT BUSL 09FD 3E40 MVI A,40H 09FF D392 OUT CMND ;SELECT HEAD 0A01 DB97 IN STATU 0A03 E620 ANI 20H 0A05 C2480A JNZ NEXTMAP 0A08 CD7807 CALL READINT ;READ WITHOUT DMA 0A0B DA480A JC NEXTMAP RDMAPBUF: 0A0E 2AE116 LHLD SUBPNT ;SET H<O MAP ADDRESS 0A11 DB94 NBADTRK IN SCTBU ;GET FIRST BYTW 0A13 FEE5 CPI 0E5H ;IS IT THE END 0A15 CA480A JZ NEXTMAP ;IF END DO THE NEXT SURFACE 0A18 47 MOV B,A ;PUT BYTE IN B (TRACK MSB) 0A19 3A5A0A LDA PUNIT ;GET THE UNIT NUMBER 0A1C 0F RRC ;POISITION UNIT BITS 0A1D 0F RRC 0A1E 0F RRC 0A1F E660 ANI 60H ;GET RID OF ANY OTHER JUNK 0A21 B0 ORA B 0A22 47 MOV B,A ;PUT TRACK AND UNIT IN B 0A23 3A5D0A LDA PHEAD ;GET HEAD 0A26 07 RLC ;POISITION BITS 0A27 07 RLC 0A28 E61C ANI 1CH 0A2A B0 ORA B ;OR WITH TRACK AND UNIT 0A2B 77 MOV M,A ;PLACE INTO TABLE 0A2C 23 INX H ;POINT TO NEXT BYTE IN TABLE 0A2D DB94 IN SCTBU ;GET SECOND BYTE OF TABLE 0A2F 77 MOV M,A ;ENTRY IS COMPLETE 0A30 23 INX H ;POINT TO NEXT 0A31 36E5 MVI M,0E5H ;SET END OF TABLE ; TEST FOR FULL 0A33 11E016 LXI D,SUBTBL+2*MAXMAP 0A36 7C MOV A,H 0A37 BA CMP D 0A38 C2110A JNZ NBADTRK 0A3B 7D MOV A,L 0A3C BB CMP E 0A3D C2110A JNZ NBADTRK 0A40 3E4D MVI A,'M' 0A42 CD5409 CALL ERREPORT 0A45 C3110A JMP NBADTRK ;GO GET ADDRESS OF NEXT BAD TRACK NEXTMAP: 0A48 22E116 SHLD SUBPNT 0A4B 3A4F14 LDA HSTDSK 0A4E 3C INR A 0A4F 3C INR A 0A50 324F14 STA HSTDSK 0A53 FE18 CPI 2*HEADQ ;ARE WE DONE ? 0A55 C8 RZ ;IF SO, RETURN 0A56 C3E109 JMP GETMAP ENDIF ; IF HERE WE ARE DONE! ; DO NOT CHANGE THE ORDER OF THE NEXT 9 BYTES 0A59 00 CERRC DB 0 ;ERROR COUNTER 0A5A PUNIT DS 1 ;DESIRED PHYSICAL UNIT 0A5B PTRK DS 2 ;DESIRED REAL TRACK ADDRESS 0A5D PHEAD DS 1 ;DESIRED HEAD 0A5E PSECTOR DS 1 ;DESIRED SECTOR,512 BYTE 0A5F FF OLDUNIT DB 0FFH ;LAST HEAD SELECTED, FF TO CAUSE INITIAL SEL. 0A60 FFFF OLDTRK DW 0FFFFH ;LAST TRACK SEEKED 0A62 FF OLDHEAD DB 0FFH ;LAST HEAD ACCESSED ; ; 7C7F = LASTLD: EQU BIOS+(7*128)-1 ;LAST RAM LOADED FROM DISK ; ; 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, BETWEEN "BEGDAT" AND "ENDDAT"). ; 0A63 TRACK: DS 2 ;TWO BYTES FOR EXPANSION 0A65 SECTOR: DS 2 ;TWO BYTES FOR EXPANSION 0A67 DMAAD: DS 2 ;DIRECT MEMORY ADDRESS 0A69 DISKNO: DS 1 ;DISK NUMBER 0-15 0A6A RORW: DS 1 ;READ OR WRITE SELECTED 0A6B DIOST: DS 1 ;I/O RETURN STATUS 0 OK 0A6C HDLD: DS 1 ;HEADLOAD FLAG BIT ; ; ; SCRATCH RAM AREA FOR BDOS USE 0A6D = BEGDAT EQU $ ;BEGINNING OF DATA AREA 0A6D DIRBF: DS 128 ;SCRATCH DIRECTORY AREA 0AED ALL00: DS 31 ;ALLOCATION VECTOR 0 0B0C ALL01: DS 31 ;ALLOCATION VECTOR 1 0B2B ALL02: DS 192 ;ALLOCATION VECTOR 2 0BEB ALL04: DS 192 ;ALLOCATION VECTOR 4 0CAB ALL05: DS 192 ;ALLOCATION VECTOR 5 0D6B ALL03: DS 192 ;ALLOCATION VECTOR 3 0E2B ALL06 DS 192 0EEB ALL07 DS 192 0FAB ALL08 DS 192 106B ALL09 DS 192 112B ALL10 DS 192 11EB ALL11 DS 192 12AB ALL12 DS 192 136B ALL13 DS 192 142B CHK00: DS 16 ;CHECK VECTOR 0 143B CHK01: DS 16 ;CHECK VECTOR 1 144B = CHK02: EQU $ ;FIXED DRIVE - NO STORAGE REQUIRED 144B = CHK03: EQU $ ;FIXED DRIVE - NO STORAGE REQUIRED 144B = CHK04 EQU $ ;NO STORAGE REQUIRED 144B = CHK05 EQU $ ;NO STORAGE REQUIRED 144B = CHK06 EQU $ 144B = CHK07 EQU $ 144B = CHK08 EQU $ 144B = CHK09 EQU $ 144B = CHK10 EQU $ 144B = CHK11 EQU $ 144B = CHK12 EQU $ 144B = CHK13 EQU $ 144B SEKDSK: DS 1 ;SEEK DISK NUMBER 144C SEKTRK: DS 2 ;SEEK TRACK NUMBER 144E SEKSEC: DS 1 ;SEEK SECTOR NUMBER ; 144F HSTDSK: DS 1 ;HOST DISK NUMBER 1450 HSTTRK: DS 2 ;HOST TRACK NUMBER 1452 HSTSEC: DS 1 ;HOST SECTOR NUMBER ; 1453 SEKHST: DS 1 ;SEEK SHR SECSHF 1454 HSTACT: DS 1 ;HOST ACTIVE FLAG 1455 HSTWRT: DS 1 ;HOST WRITTEN FLAG ; 1456 UNACNT: DS 1 ;UNALLOC REC CNT 1457 UNADSK: DS 1 ;LAST UNALLOC DISK 1458 UNATRK: DS 2 ;LAST UNALLOC TRACK 145A UNASEC: DS 1 ;LAST UNALLOC SECTOR ; 145B RSFLAG: DS 1 ;READ SECTOR FLAG 145C READOP: DS 1 ;1 IF READ OPERATION 145D WRTYPE: DS 1 ;WRITE OPERATION TYPE 145E HSTBUF: DS HSTSIZ ;HOST BUFFER 165E SUBTBL: DS 2*MAXMAP+1 16E1 SUBPNT DS 2 ; 16E3 = ENDDAT EQU $ ;END OF DATA AREA 0C76 = DATSIZ EQU $-BEGDAT;SIZE OF DATA AREA ; ; READ/WRITE STACK SAVE AREA ; 16E3 0000 OLDSP: DW 0 16E5 0000 HLSAV: DW 0 16E7 DS 30 1705 NSTACK: DS 2 ; ; THE ADDRESS OF NSTACK MUST FALL WITHIN ; THE AVAILABLE RAM STORAGE. 1707 00 DB 00H;MPM - RSP REQUIREMENT 1708 END