;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 ; 0100 ORG 0100H ;ORIGIN OF THIS PROGRAM ;BDOS ENTRY POINT ADDRESS BDOSADR: 0100 0000 DW $-$;LDR WILL FILL THIS IN ; ;HRDISK PROCESS DESCRIPTOR HRDISKPD: 0102 0000 DW 0;LINK 0104 00 DB 0;STATUS 0105 0A DB 10;PRIORITY (INITIAL) 0106 1002 DW STACK+38;STACK POINTER 0108 4852444953 DB 'HRDISK ';NAME IN UPPER CASE PDCONSOLE: 0110 00 DB 0;CONSOLE 0111 FF DB 0FFH;MEMSEG (FF=RESIDENT) 0112 DS 2;B 0114 DS 2;THREAD 0116 3602 DW BUFF;SET DISK DMA ADDRESS 0118 DS 1;USER CODE AND DISK SELECT 0119 DS 2;DCNT 011B DS 1;SEARCHL 011C DS 2;SEARCHA 011E DS 2;ACTIVE DRIVES 0120 DS 20;REGISTER SAVE AREA 0134 DS 2;SCRATCH ; ;LINKED QUEUE CONTROL BLOCK HRDLQCB: 0136 0000 DW 0;LINK 0138 4852444953 DB 'HRDISK ';NAME UPPER CASE 0140 4800 DW 72;MSGLEN 0142 0100 DW 1;NMBMSGS 0144 DS 2;DQPH 0146 DS 2;NQPH 0148 DS 2;MH 014A DS 2;MT 014C DS 2;BH 014E DS 74;BUF (72+2 BYTE LIN) ; ;USER QUEUE CONTROL BLOCK HRDUSERQCB: 0198 3601 DW HRDLQCB;POINTER 019A 9C01 DW FIELD;MSGADR ; ;FIELD FOR MESSAGE READ FROM TYPE LINKED QUE QCB FIELD: 019C DS 1;DISK SELECT CONSOLE: 019D DS 1;CONSOLE FILENAME: 019E DS 72;MESSAGE BODY ; ;PARSE FILE NAME CONTROL BLOCK PCB: 01E6 9E01 DW FILENAME;FILENAME ADDRESS 01E8 1202 DW FCB;FILE CONTROL BLOCK A ; STACK: 01EA DS 38;20 LEVEL STACK 0210 BA02 DW HRDISK;PROCESS ENTRY POINT ; 0212 FCB: DS 36;FILE CONTROL BLOCK 0236 BUFF: DS 128;FILE BUFFER ; ;BDOS CALL PROCEDURE PBDOS: 02B6 2A0001 LHLD BDOSADR;HL = BDOS ADDRESS 02B9 E9 PCHL; ; ;MAIN DISK BIOS JUMP TABLE SWAP HRDISK: 02BA 0E86 MVI C,086H;MAKE QUE 02BC 113601 LXI D, HRDLQCB; 02BF CDB602 CALL PBDOS;MAKE QUEUE 02C2 0E91 MVI C, 091H;SET PRIORITY 02C4 110002 LXI D, 200H;PRIORITY = 200 02C7 CDB602 CALL PBDOS;TELL OP-SYS ; LOOP1: 02CA 0E89 MVI C, 089H;READ QUEUE COMMAND 02CC 119801 LXI D, HRDUSERQCB; 02CF CDB602 CALL PBDOS; 02D2 2A2993 LHLD B1+25;BASE OF BIOS1+25=HOME JMP TABLE 02D5 2219F3 SHLD B2+25;BASE OF BIOS2 JMP TABLE 02D8 2A2C93 LHLD B1+28;REPEATED FOR ALL DISK JUMPS,OK 02DB 221CF3 SHLD B2+28; 02DE 2A2F93 LHLD B1+31; 02E1 221FF3 SHLD B2+31; 02E4 2A3293 LHLD B1+34; 02E7 2222F3 SHLD B2+34; 02EA 2A3593 LHLD B1+37; 02ED 2225F3 SHLD B2+37; 02F0 2A3893 LHLD B1+40; 02F3 2228F3 SHLD B2+40; 02F6 2A3B93 LHLD B1+43; 02F9 222BF3 SHLD B2+43; 02FC 2A4193 LHLD B1+49; 02FF 2231F3 SHLD B2+49; 0302 3A9D01 LDA CONSOLE; 0305 321001 STA PDCONSOLE; 0308 0E93 MVI C, 093H;DETACH COMMAND 030A CDB602 CALL PBDOS;GIVE COMMAND TO MPM 030D C3CA02 JMP LOOP1;FOREVER ; 00B9 = NSECTS EQU 0B9H;FAKE IT ;NSECTS EQU ($-CCP)/128 ;WARM START SECTOR COUNT ; ; JUMP VECTOR FOR INDIVIDUAL SUBROUTINES 0310 C36A04 JMP BOOT ;COLD START 0313 C3BD04 WBOOTE: JMP WBOOT ;WARM START 0316 C33005 JMP CONST ;CONSOLE STATUS 0319 C33905 JMP CONIN ;CONSOLE CHARACTER IN 031C C34505 JMP CONOUT ;CONSOLE CHARACTER OUT 031F C35005 JMP LIST ;LIST CHARACTER OUT 0322 C36B05 JMP PUNCH ;PUNCH CHARACTER OUT 0325 C36D05 JMP READER ;READER CHARACTER OUT 0328 C37205 JMP HOME ;MOVE HEAD TO HOME POSITION 032B C37905 JMP SELDSK ;SELECT DISK 032E C39505 JMP SETTRK ;SET TRACK NUMBER 0331 C39E05 JMP SETSEC ;SET SECTOR NUMBER 0334 C3B105 JMP SETDMA ;SET DMA ADDRESS 0337 C3B705 JMP READ ;READ DISK 033A C3BD05 JMP WRITE ;WRITE DISK 033D C35D05 JMP LISTST ;RETURN LIST STATUS 0340 C3A605 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) 0343 23040000 DW TRANS,0000H 0347 00000000 DW 0000H,0000H 034B 6D0B3D04 DW DIRBF,DPBLK 034F 2B15ED0B DW CHK00,ALL00 ;2ND FLOPPIE 0353 23040000 DW TRANS,0000H 0357 00000000 DW 0000H,0000H 035B 6D0B3D04 DW DIRBF,DPBLK 035F 3B150C0C 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 0363 00000000 DW 0000H,0000H 0367 00000000 DW 0000H,0000H 036B 6D0B4C04 DW DIRBF,DPBLK2 036F 4B152B0C DW CHK02,ALL02 ; DISK PARAMETER TABLE FOR HARD DISK,TOP PLATTER,INSIDE TRACKS 0373 00000000 DW 0000H,0000H 0377 00000000 DW 0000H,0000H 037B 6D0B4C04 DW DIRBF,DPBLK2 037F 4B156B0E DW CHK03,ALL03 ; DISK PARAMETER TABLE FOR HARD DISK,BOTTOM SIDE,OUTSIDE TRACKS. 0383 00000000 DW 0000H,0000H 0387 00000000 DW 0000H,0000H 038B 6D0B5B04 DW DIRBF,DPBLK3 038F 4B15EB0C DW CHK04,ALL04 ; DISK PARAMETER TABLE FOR HARD DISK,BOTTOM SIDE,INSIDE TRACKS 0393 00000000 DW 0000H,0000H 0397 00000000 DW 0000H,0000H 039B 6D0B5B04 DW DIRBF,DPBLK3 039F 4B15AB0D DW CHK05,ALL05 ; 03A3 00000000 DW 0000H,0000H 03A7 00000000 DW 0000H,0000H 03AB 6D0B5B04 DW DIRBF,DPBLK3 03AF 4B152B0F DW CHK06,ALL06 ; 03B3 00000000 DW 0000H,0000H 03B7 00000000 DW 0000H,0000H 03BB 6D0B5B04 DW DIRBF,DPBLK3 03BF 4B15EB0F DW CHK07,ALL07 ; 03C3 00000000 DW 0000H,0000H 03C7 00000000 DW 0000H,0000H 03CB 6D0B5B04 DW DIRBF,DPBLK3 03CF 4B15AB10 DW CHK08,ALL08 ; 03D3 00000000 DW 0000H,0000H 03D7 00000000 DW 0000H,0000H 03DB 6D0B5B04 DW DIRBF,DPBLK3 03DF 4B156B11 DW CHK09,ALL09 ; 03E3 00000000 DW 0000H,0000H 03E7 00000000 DW 0000H,0000H 03EB 6D0B5B04 DW DIRBF,DPBLK3 03EF 4B152B12 DW CHK10,ALL10 ; 03F3 00000000 DW 0000H,0000H 03F7 00000000 DW 0000H,0000H 03FB 6D0B5B04 DW DIRBF,DPBLK3 03FF 4B15EB12 DW CHK11,ALL11 ; 0403 00000000 DW 0000H,0000H 0407 00000000 DW 0000H,0000H 040B 6D0B5B04 DW DIRBF,DPBLK3 040F 4B15AB13 DW CHK12,ALL12 ; 0413 00000000 DW 0000H,0000H 0417 00000000 DW 0000H,0000H 041B 6D0B5B04 DW DIRBF,DPBLK3 041F 4B156B14 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 0423 01070D13 TRANS: DB 1,7,13,19 ;SECTORS 1,2,3,4 0427 19050B11 DB 25,5,11,17 ;SECTORS 5,6,7,8 042B 1703090F DB 23,3,9,15 ;SECTORS 9,10,11,12 042F 1502080E DB 21,2,8,14 ;SECTORS 13,14,15,16 0433 141A060C DB 20,26,6,12 ;SECTORS 17,18,19,20 0437 1218040A DB 18,24,4,10 ;SECTORS 21,22,23,24 043B 1016 DB 16,22 ;SECTORS 25,26 ; DPBLK: ;DISK PARAMETER BLOCK, FLOPPIES 043D 1A00 DW 26 ;SECTORS PER TRACK 043F 03 DB 3 ;BLOCK SHIFT FACTOR 0440 07 DB 7 ;BLOCK MASK 0441 00 DB 0 ;NULL MASK 0442 F200 DW 242 ;DISK SIZE-1 0444 3F00 DW 63 ;DIRECTORY MAX 0446 C0 DB 192 ;ALLOC 0 0447 00 DB 0 ;ALLOC 1 0448 1000 DW 16 ;CHECK SIZE 044A 0200 DW 2 ;TRACK OFFSET 044C 8C00 DPBLK2 DW 140 ;SECTORS PER TRACK 044E 06 DB 6 ;BLOCK SHIFT FACTOR FOR BLS=8,192 044F 3F DB 63 ;BLM 0450 03 DB 3 ;EXM 0451 F305 DW 1523 ;DISK SIZE-1 0453 FF01 DW 511 ;DIRECTORY MAX 0455 C0 DB 0C0H ;ALLOC0 0456 00 DB 00H ;ALLOC1 0457 0000 DW 0 ;NO CHECK - DISK IS FIXED 0459 0200 DW 2 ;OFFSET 045B 8C00 DPBLK3 DW 140 045D 06 DB 6 045E 3F DB 63 045F 03 DB 3 0460 F305 DW 1523 0462 FF01 DW 511 ;DIRECTORY MAX,(FIXED REQUIRES NO CHECK ; SO THE DIRECTOR IS LARGER, = BLS 8K) 0464 C0 DB 0C0H 0465 00 DB 00H 0466 0000 DW 0 ;0 FOR FIXED 0468 0200 DW 2 ;OFFSET ; ; END OF FIXED TABLES ; ; INDIVIDUAL SUBROUTINES TO PERFORM EACH FUNCTION BOOT: ;SIMPLEST CASE IS TO JUST PERFORM PARAMETER INITIALIZATION 046A 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.) ; 046D 3E40 MVI A,40H;RESET COMMAND 046F D3C5 OUT CSTAT 0471 D3C9 OUT LPSTAT 0473 3ECD MVI A,0CDH ;USED TO BE 0CEH & 27 BELOW WAS 37 0475 D3C5 OUT CSTAT 0477 D3C9 OUT LPSTAT 0479 3E27 MVI A,027H 047B D3C5 OUT CSTAT 047D D3C9 OUT LPSTAT ENDIF IF MAPEN ;IF TRACK MAP OPTION IS ENABLED, MAKE MAP 047F CDC20A CALL SMAPPER ENDIF 0482 AF XRA A ;ZERO IN THE ACCUM 0483 320300 STA IOBYTE ;CLEAR THE IOBYTE 0486 320400 STA CDISK ;SELECT DISK ZERO 0489 219204 LXI H,SINGMES ;PRINT THE SIGN ON MESSAGE 048C CDA20A 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 048F C3BD04 JMP WBOOT ;INITIALIZE AND GO TO CP/M 0492 0D0A SINGMES DB 0DH,0AH 0494 414D504552 DB 'AMPERIF - MAID-III (CPM 2.2 - MAPBIOS3) ' 04BC 00 DB 0 ; WBOOT: ;SIMPLEST CASE IS TO READ THE DISK UNTIL ALL SECTORS LOADED 04BD AF XRA A 04BE 325415 STA HSTACT ;HOST BUFFER INACTIVE 04C1 325615 STA UNACNT ;CLEAR UNALLOCATED COUNT 04C4 318000 LXI SP,80H ;USE SPACE BELOW BUFFER FOR STACK 04C7 0E00 MVI C,0 ;SELECT DISK 0 04C9 CD7905 CALL SELDSK 04CC CD7205 CALL HOME ;GO TO TRACK 00 ; 04CF 06B9 MVI B,NSECTS ;B COUNTS # OF SECTORS TO LOAD 04D1 0E00 MVI C,0 ;C HAS THE CURRENT TRACK NUMBER 04D3 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 04D5 210063 LXI H,CCP ;BASE OF CP/M (INITIAL LOAD POINT) LOAD1: ;LOAD ONE MORE SECTOR 04D8 C5 PUSH B ;SAVE SECTOR COUNT, CURRENT TRACK 04D9 D5 PUSH D ;SAVE NEXT SECTOR TO READ 04DA E5 PUSH H ;SAVE DMA ADDRESS 04DB 4A MOV C,D ;GET SECTOR ADDRESS TO REGISTER C 04DC CD9E05 CALL SETSEC ;SET SECTOR ADDRESS FROM REGISTER C 04DF C1 POP B ;RECALL DMA ADDRESS TO B,C 04E0 C5 PUSH B ;REPLACE ON STACK FOR LATER RECALL 04E1 CDB105 CALL SETDMA ;SET DMA ADDRESS FROM B,C ; ; DRIVE SET TO 0, TRACK SET, SECTOR SET, DMA ADDRESS SET 04E4 CDB705 CALL READ 04E7 FE00 CPI 00H ;ANY ERRORS? 04E9 C2BD04 JNZ WBOOT ;RETRY THE ENTIRE BOOT IF AN ERROR OCCURS ; ; NO ERROR, MOVE TO NEXT SECTOR 04EC E1 POP H ;RECALL DMA ADDRESS 04ED 118000 LXI D,128 ;DMA=DMA+128 04F0 19 DAD D ;NEW DMA ADDRESS IS IN H,L 04F1 D1 POP D ;RECALL SECTOR ADDRESS 04F2 C1 POP B ;RECALL NUMBER OF SECTORS REMAINING, AND CURRENT TRK 04F3 05 DCR B ;SECTORS=SECTORS-1 04F4 CA0D05 JZ GOCPM ;TRANSFER TO CP/M IF ALL HAVE BEEN LOADED ; ; MORE SECTORS REMAIN TO LOAD, CHECK FOR TRACK CHANGE 04F7 14 INR D 04F8 7A MOV A,D ;SECTOR=27?, IF SO, CHANGE TRACKS 04F9 FE1B CPI 27 ; REMOVE FOLLOWING TO BOOT OFF FLOPPY ; REMOVED - JMP LOAD1 04FB DAD804 JC LOAD1 ;CARRY GENERATED IF SECTOR<27 ; ; END OF CURRENT TRACK, GO TO NEXT TRACK 04FE 1601 MVI D,1 ;BEGIN WITH FIRST SECTOR OF NEXT TRACK 0500 0C INR C ;TRACK=TRACK+1 ; ; SAVE REGISTER STATE, AND CHANGE TRACKS 0501 C5 PUSH B 0502 D5 PUSH D 0503 E5 PUSH H 0504 CD9505 CALL SETTRK ;TRACK ADDRESS SET FROM REGISTER C 0507 E1 POP H 0508 D1 POP D 0509 C1 POP B 050A C3D804 JMP LOAD1 ;FOR ANOTHER SECTOR ; ; END OF LOAD OPERATION, SET PARAMETERS AND GO TO CP/M GOCPM: 050D 3EC3 MVI A,0C3H ;C3 IS A JMP INSTRUCTION 050F 320000 STA 0 ;FOR JMP TO WBOOT 0512 211303 LXI H,WBOOTE ;WBOOT ENTRY POINT 0515 220100 SHLD 1 ;SET ADDRESS FIELD FOR JMP AT 0 ; 0518 320500 STA 5 ;FOR JMP TO BDOS 051B 21066B LXI H,BDOS ;BDOS ENTRY POINT 051E 220600 SHLD 6 ;ADDRESS FIELD OF JUMP AT 5 TO BDOS ; 0521 018000 LXI B,80H ;DEFAULT DMA ADDRESS IS 80H 0524 CDB105 CALL SETDMA ; ;EI ;ENABLE THE INTERRUPT SYSTEM ;MVI A,00H ;ALWAYS SELECT UNIT 0 0527 3A0400 LDA CDISK ;GET CURRENT DISK NUMBER 052A 4F MOV C,A;SEND TO CCP 052B 0600 MVI B,0 ;SEE IF THIS FIXES BUG 052D 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 0530 DBC5 IN CSTAT ;READ CONSOLE STATUS 0532 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: 0534 3E00 MVI A,0 ;IF NOT READY A=0 0536 C8 RZ 0537 2F CMA ;IF READY A=FF 0538 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 0539 DBC5 IN CSTAT ;READ CONSOLE STATUS PORT 053B E602 ANI CKBR ;WAIT UNTIL READY IF PC JZ MODEMI ;NOT READY CHECK PARALLEL PORT(MODEM) ENDIF IF NOT PC 053D CA3905 JZ CONIN ENDIF 0540 DBC4 IN CDATA ;READ DATA PORT 0542 E67F ANI 7FH ;CLEAR BIT 7 0544 C9 RET ; CONOUT: ;CONSOLE CHARACTER OUTPUT FROM REGISTER C 0545 DBC5 IN CSTAT ;READ CONSOLE STATUS 0547 E601 ANI CPTR ;WAIT IF NOT READY 0549 CA4505 JZ CONOUT 054C 79 MOV A,C ;GET DATA CHARACTER 054D D3C4 OUT CDATA ;OUTPUT IT IF PC CALL MODEMO ;MODEM OUT(PARALLEL CONSOLE) ENDIF 054F C9 RET;HAVE PROGRAM DELETE THIS LOC.(RET) FOR AUTO CONSOLE PRINTER ; LIST: ;LIST CHARACTER FROM REGISTER C 0550 DBC9 IN LPSTAT ;READ LIST STATUS 0552 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 0554 EE04 XRI LRPOL ;SELECT READY POLARITYS 0556 C25005 JNZ LIST ;WAIT UNTIL NOT BUSY 0559 79 MOV A,C ;GET DATA BYTE 055A D3C8 OUT LDATA ;PRINT IT 055C C9 RET ; LISTST: ;RETURN LIST STATUS (0 IF NOT READY, 1 IF READY) 055D DBC9 IN LPSTAT ;READ LIST STATUS 055F E604 ANI LRBIT ;SELECT READY BITS 0561 EE04 XRI LRPOL ;SELECT READY POLARITY 0563 CA6805 JZ LISRDY 0566 AF XRA A ;RETURN 0 IF NOT READY 0567 C9 RET 0568 3E01 LISRDY: MVI A,1 ;RETURN 1 IF READY 056A 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 056B 79 MOV A,C ;CHARACTER TO REGISTER A 056C C9 RET ;NULL SUBROUTINE ; ; READER: ;READ CHARACTER INTO REGISTER A FROM READER DEVICE 056D 3E1A MVI A,1AH ;ENTER END OF FILE FOR NOW (REPLACE LATER) 056F E67F ANI 7FH ;REMEMBER TO STRIP PARITY BIT 0571 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 0572 010000 LXI B,0 ;SET TRACK TO ZERO 0575 CD9505 CALL SETTRK 0578 C9 RET ;WE WILL MOVE TO 00 ON FIRST READ/WRITE ; SELDSK: ;SELECT DISK GIVEN BY REGISTER C 0579 210000 LXI H,0000H ;ERROR RETURN CODE 057C 79 MOV A,C 057D 32690B STA DISKNO 0580 324B15 STA SEKDSK ;FOR BLOCK/DEBLOCK 0583 FE0E CPI NUMDSK ;MUST BE BETWEEN 0 AND NUMDSK-1 0585 D0 RNC ;NO CARRY IF 4,5,... ; DISK NUMBER IS IN THE PROPER RANGE ; COMPUTE PROPER DISK PARAMETER HEADER ADDRESS 0586 3A690B LDA DISKNO 0589 6F MOV L,A ;L=DISK NUMBER 0,1,2,3 058A 2600 MVI H,0 ;HIGH ORDER ZERO 058C 29 DAD H ;*2 058D 29 DAD H ;*4 058E 29 DAD H ;*8 058F 29 DAD H ;*16 (SIZE OF EACH HEADER) 0590 114303 LXI D,DPBASE 0593 19 DAD D ;HL=.DPBASE(DISKNO*16) 0594 C9 RET ; SETTRK: ;SET TRACK GIVEN BY REGISTER C 0595 60 MOV H,B 0596 69 MOV L,C 0597 224C15 SHLD SEKTRK ;FOR BLOCK/DEBLOCK 059A 22630B SHLD TRACK ;FOR FLOPPY 059D C9 RET ; SETSEC: ;SET SECTOR GIVEN BY REGISTER C 059E 79 MOV A,C 059F 32650B STA SECTOR 05A2 324E15 STA SEKSEC ;FOR BLOCK/DEBLOCK 05A5 C9 RET ; SECTRAN: ;TRANSLATE THE SECTOR GIVEN BY BC USING THE ;TRANSLATE TABLE GIVEN BY DE 05A6 7A MOV A,D 05A7 B3 ORA E 05A8 60 MOV H,B 05A9 69 MOV L,C 05AA C8 RZ 05AB EB XCHG ;HL=.TRANS 05AC 09 DAD B ;HL=.TRANS(SECTOR) 05AD 6E MOV L,M ;L = TRANS(SECTOR) 05AE 2600 MVI H,0 ;HL= TRANS(SECTOR) 05B0 C9 RET ;WITH VALUE IN HL ; SETDMA: ;SET DMA ADDRESS GIVEN BY REGISTERS B AND C 05B1 69 MOV L,C ;LOW ORDER ADDRESS 05B2 60 MOV H,B ;HIGH ORDER ADDRESS 05B3 22670B SHLD DMAAD ;SAVE THE ADDRESS 05B6 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) 05B7 F5 PUSH PSW 05B8 3EFF MVI A,0FFH ;READ 05BA C3C305 JMP WAITIO ; WRITE: ;PERFORM A WRITE OPERATION 05BD F5 PUSH PSW 05BE 79 MOV A,C 05BF 325D15 STA WRTYPE 05C2 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. ; 05C3 22E517 SHLD HLSAV ;SAVE HL REGISTER 05C6 210000 LXI H,0 ;GET OLD STACK ADDRESS 05C9 39 DAD SP 05CA 22E317 SHLD OLDSP 05CD 310518 LXI SP,NSTACK ;SETUP NEW STACK 05D0 C5 PUSH B 05D1 D5 PUSH D 05D2 326A0B STA RORW ;READ OR WRITE SWITCH 05D5 AF XRA A ;DEFAULT I/O OK 05D6 326B0B STA DIOST 05D9 C3E105 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 ; 05DC 00 CCODE: DB 0 ;CURRENT SELECT CODE LATCH CONTENTS 05DD 00060A12 SELCODE: DB 00H,06H,0AH,12H ; ; ; SELECT DESIRED DISK DRIVE ; 05E1 3A690B 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 05E4 FE02 CPI NUMDSK-NUMHRD 05E6 D2ED06 JNC HRDDSK ENDIF 05E9 5F MOV E,A 05EA AF XRA A 05EB 57 MOV D,A 05EC 3AE106 LDA CURDSK ;CURRENT DRIVE NR TO A 05EF BB CMP E ;SAME DRIVE? 05F0 CA1A06 JZ TSEEK ;YES - SKIP SELECT 05F3 3E04 MVI A,4 ;FORCE HEADLOAD 05F5 326C0B STA HDLD 05F8 3A690B LDA DISKNO ;SET SELECTED DRIVE NR IF NOT FLP1ST SBI NUMHRD ENDIF 05FB 32E106 STA CURDSK 05FE 21DD05 LXI H,SELCODE ;LOOKUP SELECT CODE 0601 19 DAD D 0602 7E MOV A,M 0603 D3EC OUT DVSEL ;SELECT THE DRIVE 0605 32DC05 STA CCODE ;SAVE LATCH CONTENTS 0608 3AE206 LDA CURTRK ;SAVE CURRENT DRIVES 060B 2AEB06 LHLD CTADR ;CURRENT TRACK INDICATOR 060E 77 MOV M,A 060F 21E306 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 0612 19 DAD D 0613 22EB06 SHLD CTADR ;SAVE THIS DRIVES CURRENT TRACK POINTER 0616 7E MOV A,M ;AND ITS CURRENT TRACK 0617 32E206 STA CURTRK ; ; ; SEEK DESIRED TRACK ; 061A 3A630B TSEEK: LDA TRACK ;IS THE DESIRED TRACK 061D 5F MOV E,A 061E 3AE206 LDA CURTRK ;THE SAME AS THE 0621 BB CMP E ;CURRENT TRACK? 0622 CA6406 JZ DOIO ;YES. GO DO I/O 0625 FEFF CPI 0FFH ;HOME DISK NEEDED? 0627 C24506 JNZ DOSEEK ;NO - DO SEEK ; IF NOT PERSCI 062A DBE8 HBSY: IN DSTAT ;WAIT FOR NOT BUSY 062C 0F RRC 062D DA2A06 JC HBSY 0630 3E02 MVI A,RSTCMD ;RESTORE COMMAND 0632 D3E8 OUT DCOM 0634 DBEC IN DWAIT ;WAIT FOR INTRQ (OPCOMP) 0636 00 NOP 0637 DBE8 IN DSTAT 0639 E604 ANI 4 ;LOOK AT STATUS 063B CA2A06 JZ HBSY ;RETRY RESTORE IF ERROR 063E AF XRA A 063F 32E206 STA CURTRK ;SET CURRENT TRACK TO ZERO 0642 C31A06 JMP TSEEK ;GO CHECK FOR SEEK 0645 7B DOSEEK: MOV A,E ;SEND DESIRED TRACK 0646 D3EB OUT DDATA 0648 DBE8 SBSY: IN DSTAT ;WAIT FOR NOT BUSY 064A 0F RRC 064B DA4806 JC SBSY 064E 3E1A MVI A,SEKCMD ;SEEK WITH VERIFY COMMAND 0650 D3E8 OUT DCOM 0652 DBEC IN DWAIT ;WAIT FOR INTRQ (OPCOMP) 0654 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 ; 0655 DBE8 SDONE: IN DSTAT ;IF ERROR 0657 32E806 STA SSTAT 065A E691 ANI 091H 065C C22A06 JNZ HBSY ;GO RE-HOME DRIVE 065F DBE9 IN DTRACK 0661 32E206 STA CURTRK ;SAVE NEW CURRENT TRACK ; ; NOW DO THE READ OR WRITE SECTOR ; 0664 3E0B DOIO: MVI A,11 ;RETRY COUNT +1 0666 47 MOV B,A 0667 C37306 JMP TRY1 066A 05 RETRY: DCR B ;DECREMENT RETRY 066B CAC706 JZ ERROR ;EXIT IF HARD ERROR 066E 3E04 MVI A,04H ;REQUIRE HEADLOAD ON ALL RETRYS 0670 326C0B STA HDLD 0673 3A650B TRY1: LDA SECTOR 0676 D3EA OUT DSECT ;ISSUE SECTOR DESIRED 0678 2A670B LHLD DMAAD ;AND SET I/O BUFFER ADDRESS 067B 3A6A0B LDA RORW ;SELECT READ OR WRITE 067E FE00 CPI 0 0680 CAA506 JZ DWRITE ;GO WRITE SECTOR ; IF INTRP 0683 F3 DI ;DISABLE INTERRUPTS ENDIF 0684 3A6C0B LDA HDLD ;SELECT HEADLOAD OPTION 0687 F688 ORI 088H ;READ COMMAND 0689 D3E8 OUT DCOM 068B DBEC RLOOP: IN DWAIT ;WAIT FOR DRQ 068D B7 ORA A ;CHECK FOR INTRQ (OPCOMP) 068E F29806 JP RDONE 0691 DBEB IN DDATA ;GET BYTE 0693 77 MOV M,A ;STORE IT 0694 23 INX H ;BUMP POINTER 0695 C38B06 JMP RLOOP ;GO GET NEXT BYTE 0698 DBE8 RDONE: IN DSTAT ;READ STATUS IF INTRP ;EI ;RE-ENABLE INTERRUPTS ENDIF 069A 32E706 STA LSTAT 069D E69D ANI 09DH ;RETRY IF ERROR 069F C26A06 JNZ RETRY 06A2 C3CF06 JMP DDONE ;READ COMPLETE ; DWRITE: ; IF INTRP 06A5 F3 DI ;DISABLE INTERRUPTS ENDIF 06A6 3A6C0B LDA HDLD ;SELECT HEADLOAD OPTION 06A9 F6A8 ORI 0A8H ;WRITE COMMAND 06AB D3E8 OUT DCOM 06AD DBEC WLOOP: IN DWAIT ;CHECK DRQ 06AF B7 ORA A 06B0 F2BA06 JP WDONE ;END IF INTRQ (ENDOP) 06B3 7E MOV A,M ;GET DATA 06B4 D3EB OUT DDATA ;AND SEND IT 06B6 23 INX H ;BUMP POINTER 06B7 C3AD06 JMP WLOOP ;GO FOR NEXT BYTE 06BA DBE8 WDONE: IN DSTAT ;WRITE OP STATUS IF INTRP ;EI ;RE-ENABLE INTERRUPTS ENDIF 06BC 32E706 STA LSTAT 06BF E6FD ANI 0FDH ;RETRY IF ERROR 06C1 C26A06 JNZ RETRY 06C4 C3CF06 JMP DDONE ;WRITE COMPLETE 06C7 3E01 ERROR: MVI A,1 ;DISK I/O ERROR 06C9 326B0B STA DIOST 06CC C3D306 JMP EDONE ; ; ; ; I/O COMPLETE. DDONE: ; DISK I/O DONE IF HLOPT 06CF AF XRA A ;CLEAR HEADLOAD REQUIRED 06D0 326C0B STA HDLD ENDIF 06D3 D1 EDONE: POP D ;RESTORE DE AND BC FROM NSTACK 06D4 C1 POP B 06D5 2AE317 LHLD OLDSP ;RESTORE OLD STACK 06D8 F9 SPHL 06D9 2AE517 LHLD HLSAV ;RESTORE HL 06DC F1 POP PSW 06DD 3A6B0B LDA DIOST ;0 I/O OK, ELSE FAIL 06E0 C9 RET ; 06E1 FF CURDSK: DB 0FFH ;CURRENT DISK (FF TO INITIALIZE) 06E2 FF CURTRK: DB 0FFH ;CURRENT DISKS CURRENT TRACK 06E3 FF DK0CT: DB 0FFH ;DRIVE 0 CURRENT TRACK 06E4 FF DK1CT: DB 0FFH ;DRIVE 1 CURRENT TRACK 06E5 FF DK2CT: DB 0FFH ;DRIVE 2 CURRENT TRACK 06E6 FF DK3CT: DB 0FFH ;DRIVE 3 CURRENT TRACK 06E7 FF LSTAT DB 0FFH ;LAST R/W STATUS 06E8 FF SSTAT: DB 0FFH ;LAST SEEK STATUS 06E9 00 LSTSEK: DB 0 ;LAST SEEK COMMAND 06EA FF STPS: DB 0FFH ;NR STEPS LAST SEEK 06EB E306 CTADR: DW DK0CT ;CURRENT TRACK RESTORE ADDRESS ; 06ED 3A6A0B HRDDSK LDA RORW 06F0 FE00 CPI 0 06F2 CA0907 JZ WRITEH ;IF RORW IS ZERO THEN WRITE THE HARD DISK READH: ;READ THE SELECTED CP/M SECTOR 06F5 AF XRA A 06F6 325615 STA UNACNT ;UNACNT = 0 06F9 3E01 MVI A,1 06FB 325C15 STA READOP ;READ OPERATION 06FE 325B15 STA RSFLAG ;MUST READ DATA 0701 3E02 MVI A,WRUAL 0703 325D15 STA WRTYPE ;TREAT AS UNALLOC 0706 C37307 JMP RWOPER ;TO PERFORM THE READ WRITEH: ;WRITE THE SELECTED CP/M SECTOR 0709 AF XRA A 070A 325C15 STA READOP ;NOT A READ OPERATION 070D 3A5D15 LDA WRTYPE 0710 FE02 CPI WRUAL ;WRITE UNALLOCATED? 0712 C22C07 JNZ CHKUNA ;CHECK FOR UNALLOC ; WRITE TO UNALLOCATED, SET PARAMETERS 0715 3E80 MVI A,128 ;NEXT UNALLOC RECS 0717 325615 STA UNACNT 071A 3A4B15 LDA SEKDSK ;UNADSK = SEKDSK 071D 325715 STA UNADSK 0720 2A4C15 LHLD SEKTRK 0723 225815 SHLD UNATRK ;UNATRK = SECTRK 0726 3A4E15 LDA SEKSEC 0729 325A15 STA UNASEC ;UNASEC = SEKSEC CHKUNA: ;CHECK FOR WRITE TO UNALLOCATED SECTOR 072C 3A5615 LDA UNACNT ;ANY UNALLOC REMAIN? 072F B7 ORA A 0730 CA6B07 JZ ALLOC ;SKIP IF NOT ; MORE UNALLOCATED RECORDS REMAIN 0733 3D DCR A 0734 325615 STA UNACNT 0737 3A4B15 LDA SEKDSK ;SAME DISK? 073A 215715 LXI H,UNADSK 073D BE CMP M ;SEKDSK = UNADSK 073E C26B07 JNZ ALLOC ; DISK ARE THE SAME 0741 215815 LXI H,UNATRK 0744 CD1408 CALL SEKTRKCMP ;SEKTRK = UNATRK? 0747 C26B07 JNZ ALLOC ;SKIP IF NOT ; TRACKS ARE THE SAME 074A 3A4E15 LDA SEKSEC ;SAME SECTOR? 074D 215A15 LXI H,UNASEC 0750 BE CMP M ;SEKSEC = UNASEC? 0751 C26B07 JNZ ALLOC ;SKIP IF NOT ; MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF 0754 34 INR M ;UNASEC = UNASEC+1 0755 7E MOV A,M ;END OF TRACK? 0756 FE8C CPI CPMSPT ;COUNT CPM SECTORA 0758 DA6407 JC NOOVF ;SKIP IF NO OVERFLOW ; OVERFLOW TO NEXT TRACK 075B 3600 MVI M,0 ;UNASEC = 0 075D 2A5815 LHLD UNATRK 0760 23 INX H 0761 225815 SHLD UNATRK ;UNATRK = UNATRK+1 NOOVF: ; MATCH FOUND, MARK AS UNNECESSARY READ 0764 AF XRA A ;0 TO ACCUMULATOR 0765 325B15 STA RSFLAG 0768 C37307 JMP RWOPER ;TO PERFORM THE WRITE ALLOC: ;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ 076B AF XRA A ;0 TO ACCUMULATOR 076C 325615 STA UNACNT ;UNACNT = 0 076F 3C INR A ;1 TO ACCUM 0770 325B15 STA RSFLAG ;RSFLAG = 1 ; ;********************************************************* ;* * ;* COMMON CODE FOR READ AD WRITE FOLLOWS ;* * ;********************************************************* ; RWOPER: ;ENTER HERE TO PERFORM THE READ/WRITE 0773 AF XRA A ;ZERO TO ACCUM 0774 326B0B STA DIOST ;NO ERRORS (YET) 0777 3A4E15 LDA SEKSEC 077A B7 ORA A ;CARRY = 0 077B 1F RAR ;SHIFT RIGHT 077C B7 ORA A 077D 1F RAR 077E 325315 STA SEKHST ;HOST SECTOR TO SEEK ; ACTIVE HOST SECTOR? 0781 215415 LXI H,HSTACT ;HOST ACTIVE FLAG 0784 7E MOV A,M 0785 3601 MVI M,1 ;ALWAYS BECOMES 1 0787 B7 ORA A ;WAS IT ALREADY? 0788 CAAF07 JZ FILHST ;FILL HOST IF NOT ; HOST BUFFER ACTIVE,SAVE AS SEEK BUFFER? 078B 3A4B15 LDA SEKDSK 078E 214F15 LXI H,HSTDSK 0791 BE CMP M ;SEKDSK = HSTDSK? 0792 C2A807 JNZ NOMATCH ; SAME DISK, SAME TRACK? 0795 215015 LXI H,HSTTRK 0798 CD1408 CALL SEKTRKCMP 079B C2A807 JNZ NOMATCH ; SAME DISK,SAME TRACK, SAME BUFFER? 079E 3A5315 LDA SEKHST 07A1 215215 LXI H,HSTSEC ;SEKHST = HSTSEC? 07A4 BE CMP M 07A5 CACC07 JZ MATCH ;SKIP IF MATCH NOMATCH: ;PROPER DSK, BUT NOT CORRECT SECTOR 07A8 3A5515 LDA HSTWRT ;HOST WRITTEN? 07AB B7 ORA A 07AC C42008 CNZ WRITEHST ;CLEAR HOST BUFF FILHST: ;MAY HAVE TO FILL THE HOST BUFFER 07AF 3A4B15 LDA SEKDSK 07B2 324F15 STA HSTDSK 07B5 2A4C15 LHLD SEKTRK 07B8 225015 SHLD HSTTRK 07BB 3A5315 LDA SEKHST 07BE 325215 STA HSTSEC 07C1 3A5B15 LDA RSFLAG ;NEED TO READ? 07C4 B7 ORA A 07C5 C46208 CNZ READHST ;YES, IF 1 07C8 AF XRA A ;ZERO TO ACCUMULATOR 07C9 325515 STA HSTWRT ;NO PENDING WRITE MATCH: ;COPY DATA TO OR FROM BUFFER 07CC 3A4E15 LDA SEKSEC ;MASK BUFFER NUMBER 07CF E603 ANI SECMSK ;LEAST SIGNIF BITS 07D1 6F MOV L,A 07D2 2600 MVI H,0 ;DOUBLE COUNT 07D4 29 DAD H 07D5 29 DAD H 07D6 29 DAD H 07D7 29 DAD H 07D8 29 DAD H 07D9 29 DAD H 07DA 29 DAD H ; HL HAS RELATIVE HOST BUFFER ADDRESS 07DB 115E15 LXI D,HSTBUF 07DE 19 DAD D ;HL = HOST ADDRESS 07DF EB XCHG 07E0 2A670B LHLD DMAAD ;GET/PUT CP/M DATA 07E3 0E80 MVI C,128 ;LENGTH OF MOVE 07E5 3A5C15 LDA READOP ;WHICH WAY? 07E8 B7 ORA A 07E9 C2F207 JNZ RWMOVE ;SKIP IF READ ; WRITE OPERATION, MARK AND SWITHC DIRECTION 07EC 3E01 MVI A,1 07EE 325515 STA HSTWRT ;HSTWRT = 1 07F1 EB XCHG RWMOVE: ;C INITIALLY 128, DE IS SOURCE, HL IS DEST 07F2 1A LDAX D ;SOURCE CHARACTER 07F3 13 INX D 07F4 77 MOV M,A 07F5 23 INX H 07F6 0D DCR C ;LOOP 128 TIMES 07F7 C2F207 JNZ RWMOVE ;SKIP IF READ ; DATA HAS BEEN MOVED TO/FROM HOST BUFFER 07FA 3A5D15 LDA WRTYPE ;WRITE TYPE 07FD FE01 CPI WRDIR ;TO DIRECTORY? 07FF 3A6B0B LDA DIOST ;IN CASE OF ERRORS 0802 C2D306 JNZ EDONE ;NO FURTHER PROCESSING ; CLEAR HOST BUFFER FOR DIRECTORY WRITE 0805 B7 ORA A ;ERRORS? 0806 C0 RNZ ;SKIP IF SO 0807 AF XRA A ;0TO ACCUMULATOR 0808 325515 STA HSTWRT ;BUFFER WRITEN 080B CD2008 CALL WRITEHST 080E 3A6B0B LDA DIOST 0811 C3D306 JMP EDONE ; SEKTRKCMP: ;HL = .UNATRK OR .HSTTRK, COMPARE WITH SEKTRK 0814 EB XCHG 0815 214C15 LXI H,SEKTRK 0818 1A LDAX D ;LOW BYTE COMPARE? 0819 BE CMP M ;SAME? 081A C0 RNZ ;RETURN IF NOT ; LOW BYTES EQUAL, TEST HIGH BYTES 081B 13 INX D 081C 23 INX H 081D 1A LDAX D 081E BE CMP M ;SET FLAGS 081F 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 0820 CD0009 CALL KCOMMON ;SETS SECTOR,DMA,HEAD,TRACK,UNIT 0823 D8 RC ;ERROR RETURN 0824 AF XRA A ;CLEAR BUS 0825 D391 OUT BUSL 0827 D390 OUT BUSU ;BUS IS NOW CLEARED 0829 D397 OUT STATU ;SECTOR BUFFER NOW ZEROED ; WRITE THE HEADER NOW (TRACK MSB,TRACK LSB,HEAD,SECTOR) 082B 215B0B LXI H,PTRK ;POINT TO THE TRACK 082E 0604 MVI B,4 ;HEADER BYTE COUNT 0830 7E HEADWT MOV A,M ;GET BYTE IN ACUMULATOR 0831 D394 OUT SCTBU ;SEND IT 0833 23 INX H 0834 05 DCR B ;DECREMENT COUNT 0835 C23008 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 ;*************************** 0838 215E15 LXI H,HSTBUF;IO WRITE LOOP 083B 110002 LXI D,HSTSIZ 083E 7E NXIOW MOV A,M 083F D394 OUT SCTBU 0841 23 INX H 0842 1D DCR E 0843 C23E08 JNZ NXIOW 0846 15 DCR D 0847 C23E08 JNZ NXIOW ENDIF ;************************** 084A D397 OUT STATU 084C 3E01 MVI A,1 ;DISK WRITE COMMAND 084E D392 OUT CMND ;DO THE WRITE 0850 CD1F0A CALL WT ;WAIT FOR IT TO FINISH 0853 3E41 MVI A,'A' ;ERROR A IS A TIMEOUT 0855 DA540A JC ERREPORT ;IF TIMEOUT, PRINT A 0858 DB97 IN STATU ;GET STATU 085A E620 ANI 20H ;IS FAULT ON? 085C 3E42 MVI A,'B' 085E C2540A JNZ ERREPORT ;PRINT B IF WRITE FAULT ;REPORT END STATUS 0861 C9 RET ;DONE WITH WRITE READHST: ;READ SUBROUTINE. READS VIA READINT THEN DOES DMA 0862 CD7808 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 ;**************************** 0865 215E15 LXI H,HSTBUF;IO READ LOOP 0868 110002 LXI D,HSTSIZ 086B DB94 NXIOR IN SCTBU 086D 77 MOV M,A 086E 23 INX H 086F 1D DCR E 0870 C26B08 JNZ NXIOR 0873 15 DCR D 0874 C26B08 JNZ NXIOR ENDIF ;**************************** 0877 C9 RET ;RETURN READINT: ;READ TO SECTOR BUFFER 0878 CD0009 CALL KCOMMON ;SET SECTOR,DMA,TRACK,HEAD,AND UNIT 087B D8 RC ;ERROR RETURN 087C AF XRA A ;GENERATE A ZERO 087D D391 OUT BUSL ;CLEAN UP LOWER BUS 087F D390 OUT BUSU ;CLEAN UP UPPER BUS 0881 32590B STA CERRC ;ZERO THE ERROR COUNT 0884 D397 RDKON OUT STATU ;SET BUFFER TO ZERO 0886 3E88 MVI A,88H ;DISK READ COMMAND 0888 D392 OUT CMND ;DO THE READ 088A CD1F0A CALL WT ;WAIT FOR DONE 088D 3E43 MVI A,'C' 088F DC540A CC ERREPORT ;PRINT C IF TIMEOUT ERROR 0892 DABC08 JC RCOVRE ;GO ATTEMPT TO RECOVER THE TIMEOUT 0895 DB97 IN STATU ;GET ENDING STATUS 0897 E604 ANI 4H ;IS CHECKSUM ON? 0899 C2AF08 JNZ CHKRECOV ;GO REPORT/RECOVER ; WE WILL NOW TEST THE HEADER 089C 215B0B LXI H,PTRK ;POINT TO THE TRACK 089F 0604 MVI B,4 ;NUMBER OF HEADER BYTES 08A1 D397 OUT STATU ;ZERO BUFFER ADDRESS 08A3 DB94 HDRTST IN SCTBU ;GET HEADER READ 08A5 BE CMP M 08A6 C2B708 JNZ FRMTRCV ;RECOVER IF DIFFERENT 08A9 05 DCR B 08AA 23 INX H 08AB C2A308 JNZ HDRTST ;IF HEADER COUNT IS NON ZERO TEST ONE MORE ; WHEN WE ARIVE HERE THE READ IS DONE. 08AE C9 RET ; ; ; READ RECOVERY PROGRAM FOLLOWS CHKRECOV: 08AF 3E44 MVI A,'D' 08B1 CD540A CALL ERREPORT ;PRINT A D IF CHECKSUM ERROR 08B4 C3BC08 JMP RCOVRE 08B7 3E45 FRMTRCV MVI A,'E' 08B9 CD540A CALL ERREPORT ;PRINT A E IF FORMAT ERROR 08BC 3A590B RCOVRE: LDA CERRC 08BF 3C INR A ;INCREMENT THE COUNT 08C0 32590B STA CERRC ;SAVE THE NEW COUNT 08C3 4F MOV C,A ;SAVE THE ERROR COUNT 08C4 E603 ANI 3 ;GET LAST 2 BITS,STROBE EARLY AND LATE 08C6 FE03 CPI 3 ;NOT LEGAL TO HAVE BOTH ON 08C8 CABC08 JZ RCOVRE ;IF ILLEGAL, GO TO NEXT CERRC 08CB 79 MOV A,C ;GET THE ERROR COUNT 08CC E618 ANI 18H ;GET THE OFFSET MINUS AND PLUS BITS 08CE FE18 CPI 18H ;ARE THE BOTH ON? 08D0 CABC08 JZ RCOVRE ;IF SO GO TO THE NEXT COUNT 08D3 79 MOV A,C ;RESTORE THE ERROR COUNT 08D4 FE20 CPI 20H ;IS THIS THE START OF THE SECOND PASS? 08D6 CC310A CZ PANIC ;IF 20H WE WILL RETRY SEL,SEEK,MAPPER ETC. 08D9 3A590B LDA CERRC ;RESTORE THE ERROR COUNT 08DC 4F MOV C,A ;PLACE IT IN C FOR FUTURE RECALL 08DD C6DC ADI 0DCH ;TIME TO GIVE UP? 08DF DAF108 JC HARDRDER ;IF CARRY WE HAVE A HARD READ ERROR ; IF WE GET HERE WE ARE READY TO SET RECOVERY BITS AND TRY AGAIN 08E2 79 MOV A,C ;RESTORE ERROR COUNT 08E3 0F RRC ;POSITION BITS 08E4 E68C ANI 8CH ;GET OFFSETS PLUS STROBE EARLY 08E6 D391 OUT BUSL ;SET THE BITS 08E8 79 MOV A,C ;RESTORE ERROR COUNT 08E9 0F RRC ;POSITION BITS 08EA E601 ANI 1 ;STROBE LATE BIT 08EC D390 OUT BUSU ;BUS NOW COMPLETE 08EE C38408 JMP RDKON ;GO DO THE READ RECOVERY HARDRDER: ;HARD DISK READ ERROR 08F1 DB97 IN STATU ;SET THE READ BUFFER TO ADDRESS 4 08F3 DB94 IN SCTBU 08F5 DB94 IN SCTBU 08F7 DB94 IN SCTBU 08F9 DB94 IN SCTBU 08FB 3E46 MVI A,'F' ;HARD ERROR 08FD C3540A 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: 0900 AF XRA A ;MAKE A ZERO 0901 326B0B STA DIOST ;SET ERROR FLAG TO ZERO 0904 215E15 LXI H,HSTBUF ;PLACE DMA ADDRESS IN H&L 0907 7D MOV A,L ;GET LSB OF DMA ADDRESS 0908 D395 OUT DMACL ;SET LSB OF DMA ADDRESS 090A 7C MOV A,H ;GET MSB OF DMA ADDRESS 090B D396 OUT DMACU ;SET MSB OF DMA ADDRESS 090D AF XRA A ;MAKE A ZERO 090E D391 OUT BUSL ;CLEAR THE LOWER BUS 0910 D390 OUT BUSU ;CLEAR THE UPPER BUS 0912 CD1809 CALL HSTPHY 0915 C35909 JMP COMCON HSTPHY ;CALCULATE THE PHYSICAL ADDRESS 0918 2A5015 LHLD HSTTRK 091B 116EFE LXI D,-402 ;402 IS MAX TRACK PER UNIT 091E 19 DAD D ;IF CARRY TRACK IS ILLEGAL 091F 3E4E MVI A,'N' ;ERROR N IS ILLEGAL TRACK 0921 DC540A CC ERREPORT 0924 D8 RC 0925 119201 LXI D,402 ;OFFSET FOR INNER TRACKS 0928 2A5015 LHLD HSTTRK ;CPM TRACK 092B 3A4F15 LDA HSTDSK ;0 FOR A, 1 FOR B, ETC IF FLP1ST 092E D602 SUI NUMDSK-NUMHRD ENDIF 0930 0F RRC ;PLACE LSB IN CARRY 0931 D23509 JNC INNER ;DO NOT ADD 402 IF INNER 0934 19 DAD D ;ADD 402 IF OUTER 0935 E60F INNER ANI 0FH ;REMOVE END AROUND CARRY 0937 0600 MVI B,0 ;B=UNIT, INITIALLY 0 0939 FE0C NUNIT CPI HEADQ ;IS HEADQ LARGER THEN HSTDSK? 093B DA4109 JC UNDONE ;B IS UNIT, A IS HEAD 093E DE0C SBI HEADQ ;DECREMENT BY THE NUMBER OF HEADS PER UNIT 0940 04 INR B ;INCREMENT THE UNIT 0941 325D0B UNDONE STA PHEAD ;REMAINDER IS THE PHYSICAL HEAD 0944 78 MOV A,B 0945 325A0B STA PUNIT ;UNIT IS THE QUOTIENT 0948 7C MOV A,H ;MSB OF TRACK 0949 325B0B STA PTRK ;STORE IT IN PHYSICAL UPPER TRACK 094C 7D MOV A,L ;LSB OF TRACK; 094D 325C0B STA PTRK+1 ;STORE IT IN PHYSICAL LOWER TRACK 0950 3A5215 LDA HSTSEC 0953 D393 OUT SCTAD 0955 325E0B STA PSECTOR 0958 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 0959 DB97 IN STATU ;GET THE STATUS 095B 0F RRC ;PLACE SELECTED BIT INTO CARRY 095C D27409 JNC NEWADD ;IF NOT SELECT FORCE NEW ADDRESS ; TEST NEW VS OLD ADDRESS 095F 215F0B LXI H,OLDUNIT ;H,L POINT TO OLD ADDRESS 0962 115A0B LXI D,PUNIT ;D&E POINT TO NEW ADDRESS 0965 0604 MVI B,4 ;NUMBER OF BYTES TO CHECK 0967 1A ADCMP LDAX D ;GET NEW ADDRESS BYTE 0968 BE CMP M ;COMPARE IT TO OLD 0969 C27409 JNZ NEWADD ;IF DIFERENT GO TO NEW ADDRESS 096C 05 DCR B 096D 23 INX H ;INCREMENT THE POINTER TO CURRENT ADDRESS 096E 13 INX D ;INCREMENT THE POINTER TO DESIRED ADDRESS 096F C26709 JNZ ADCMP ;IF LOOP IS NOT DONE COMPARE ONE MORE ; RETURN WITHOUT ERROR, SAME ADDRESS 0972 AF XRA A ;CLEAR CARRY 0973 C9 RET NEWADD: ; SET OLD TO PHYSICAL 0974 115F0B LXI D,OLDUNIT 0977 215A0B LXI H,PUNIT 097A 0604 MVI B,4 ;COUNT 097C 7E UPDATE MOV A,M ;GET NEW 097D 12 STAX D ;UPDATE OLD 097E 13 INX D 097F 23 INX H 0980 05 DCR B 0981 C27C09 JNZ UPDATE 0984 3A5A0B LDA PUNIT ;GET THE PHYSICAL UNIT 0987 0F RRC ;UNIT IS UPPER HALF OF BYTE 0988 0F RRC 0989 0F RRC 098A 0F RRC 098B D390 OUT BUSU ;PLACE IT ON THE BUS 098D 3E10 MVI A,10H ;SELECT COMMAND 098F D392 OUT CMND ;SELECT I 0991 DB97 IN STATU ;GET STATUS 0993 0F RRC ;PLACE SELECT IN CARRY 0994 3F CMC ;CARRY 1 IF NOT SELECTED 0995 3E47 MVI A,'G' ;SELECT ERROR 0997 DA540A JC ERREPORT ;PRINT IT 099A 3A5D0B LDA PHEAD ; IF CMD CPI 0 JZ HDJUST ;IS HEAD ZERO LEAVE ALLONE ADI 15 ;ADD 15 TO SET LOLUME TAG ENDIF 099D D391 HDJUST OUT BUSL ;SET IT ON THE BUS 099F 3E40 MVI A,40H ;SET HEAD COMMAND 09A1 D392 OUT CMND ;DO THE HEAD SELECT 09A3 DB97 IN STATU ;GET THE STATUS 09A5 E620 ANI 20H ;TEST DISK FAULT BUT 09A7 3E48 MVI A,'H' 09A9 C2540A JNZ ERREPORT ;IF FAULT IS ONE, REPORT IT ; ; ; SEEK ROUTINE ; TRACK SUBSTITUTION INCLUDED ; 09AC CDC109 SEEK: CALL GSEEK ;GO PERFORM THE SEEK 09AF D0 RNC ;RETURN IF SEEK WAS GOOD(NO CARRY) ; IF HERE, FIRST SEEK ATTEMPT FAILED 09B0 CD3D0A CALL RECAL ;RECAL DRIVE TO ATTEMMPT TO CLEAR ERROR 09B3 CDC109 CALL GSEEK ;GIVE IT ONE MORE TRY 09B6 D0 RNC ;IF NO ERROR IT RECOVERED ; IF HERE, HARD SEEK ERROR OCCURED 09B7 3EFF MVI A,0FFH ;SET A TO ALL ONES 09B9 325F0B STA OLDUNIT ;THIS WILL CAUSE A SELECT AND SEEK UPON ; NEXT ACCESS 09BC 3E49 MVI A,'I' 09BE C3540A JMP ERREPORT ;REPORT THE SEEK ERROR GSEEK: ; COMPRIZE COMMPOSITE ADDRESS TO SEARCH TRACK TABLE FOR 09C1 3A5B0B LDA PTRK 09C4 57 MOV D,A 09C5 3A5C0B LDA PTRK+1 09C8 5F MOV E,A IF MAPEN ;MAP THE TRACK IF MAP IS ENABLED 09C9 3A5D0B LDA PHEAD ;GET THE HEAD NUMBER 09CC 07 RLC 09CD 07 RLC ;PLACE HEAD IN BITS 5-2 09CE E61C ANI 1CH ;STRIP ANY ENTRA JUNK 09D0 B2 ORA D ;OR IN MSB OF TRACK 09D1 57 MOV D,A 09D2 3A5A0B LDA PUNIT ;GET UNIT NUMBER 09D5 0F RRC 09D6 0F RRC 09D7 0F RRC ;UNIT NOW IN 6-4 09D8 E660 ANI 60H 09DA B2 ORA D ;OR HEAD TO UNIT/TRACK 09DB 57 MOV D,A ;D IS NOW HEAD,UNIT,TRACKMSB 09DC 0E00 MVI C,0 ;SET B,C,TABLE ENTRY PIONTER, TO ZERO 09DE 215E17 FINDT LXI H,SUBTBL ;H&L NOW POINT TO THE TABLE 09E1 7E FINDN MOV A,M ;GET BYTE FORM THE TABLE, FIRST HALF 09E2 C680 ADI 80H ;ADD MSB TO SEE IF IT WAS ON 09E4 DA0A0A JC SUBDONE ;IF CARRY THE SUBSTITUTION IS DONE 09E7 7A MOV A,D ;LSB OF DESIRED 09E8 BE CMP M ;IS IT THE SAME? 09E9 23 INX H ;INCREMENT THE POINTER 09EA C2F209 JNZ NOCMP ;JMP NO COMPARE IF DIFFERENT 09ED 7B MOV A,E ;MSB OF DESIRED 09EE BE CMP M ;IS IT THE SAME 09EF CA000A JZ SUBT ;IF ZERO GO DO THE SUBSTITUTION 09F2 23 NOCMP INX H ;INCREMENT THE POINTER 09F3 0C INR C ;INCREMENT THE LOCATION IN THE TABLE 09F4 79 MOV A,C ;GET TABLE POSITION 09F5 FE42 CPI MAXMAP+1 ;CAUSE CARRY IF MAXMAP OR LESS 09F7 3F CMC ;INVERT CARRY, 09F8 3E4D MVI A,'M' ;M IS MAP OVERRUN ERROR 09FA DC540A CC ERREPORT ;PRINT M IF CARRY 09FD C3E109 JMP FINDN ;GO TEST THE NEXT ENTRY 0A00 0600 SUBT: MVI B,0 ;B,C=THE TABLE ENTRY WHERE THE MATCH OCCURED 0A02 21BC02 LXI H,MAXTRK+1 ;THE BEGIN OF THE SUBSTITUTION TRACKS 0A05 09 DAD B ;H&L NOW EQUAL THE NEW TRACK 0A06 EB XCHG ;D&E NOW EQUAL THE NEW TRACK 0A07 C3DE09 JMP FINDT ;GO SEE IF THE SPARE IS MAPPED ENDIF ; ;SUBSTITUTION IS DONE, DO THE SEEK TO THE TRACK IN D&E SUBDONE 0A0A 7B MOV A,E ;LSB OF TRACK 0A0B D391 OUT BUSL 0A0D 7A MOV A,D ;MSB OF TRACK 0A0E E603 ANI 3 ;STRIP ALL BUT TRACK 0A10 D390 OUT BUSU ;BUS NOW SET TO TRACK 0A12 3E20 MVI A,20H ;SEEK COMMAND 0A14 D392 OUT CMND ;DO THE SEEK 0A16 CD1F0A CALL WT ;WAIT FOR DONE 0A19 3E4A MVI A,'J' 0A1B DA540A JC ERREPORT ;PRINT J IF SEEK TIMEOUT 0A1E C9 RET ; WAIT FOR DONE, RETURN WITH CARRY OFF WHEN DONE, ; AND CARRY SET IF TIMEOUT. 0A1F 26FF WT MVI H,0FFH ;H&L WILL BE DECREMENTED FOR A GROSS TIMEOUT 0A21 2B WZ DCX H ;DECREMENT COUNT 0A22 7C MOV A,H ;PLACE MSB OF COUNT INTO A 0A23 B5 ORA L ;OR IN LSB TO SEE IF ANY BIT IS NON-ZERO 0A24 CA2F0A JZ TIMEOUT ;TIMEOUT IF HL ZERO BEFOR DONE 0A27 DB97 IN STATU ;GET STATUS 0A29 E680 ANI 80H ;IS DONE ON? 0A2B CA210A JZ WZ ;IF NOT DONE WAIT 0A2E C9 RET ;GOOD RETURN, CARRY OFF FROM THE ANI 80H 0A2F 37 TIMEOUT STC ;SET CARRY 0A30 C9 RET ;ERROR RETURN ; ; PANIC ROUTINE FOLLOWS ; DO FAULT RESET, RECALL, KILL OLDUNIT, CALL KCOMMON 0A31 CD3D0A PANIC CALL RECAL ;RECAL UNIT 0A34 3EFF MVI A,0FFH 0A36 325F0B STA OLDUNIT ;KILL OLD UNIT TO FORCE A SEEK AND SELECT 0A39 CD0009 CALL KCOMMON 0A3C C9 RET 0A3D AF RECAL XRA A ;MAKE A ZERO 0A3E D390 OUT BUSU ;ZERO UPPER BUS 0A40 3E50 MVI A,50H ;FAULT CLEAR AND RECAL BITS 0A42 D391 OUT BUSL ;SET ONTO BUS 0A44 3E80 MVI A,80H ;FAULT RECOVERY COMMAND 0A46 D392 OUT CMND ;START FAULT RECOVERY 0A48 AF XRA A ;MAKE ANOTHER ZERO 0A49 D392 OUT CMND ;TURN OFF THE FAULT COMMAND 0A4B CD1F0A CALL WT ;WAIT FOR DONE 0A4E 3E4B MVI A,'K' 0A50 DC540A CC ERREPORT ;PRINT A K IF RECAL TIMEOUT 0A53 C9 RET ; ; HARD DISK ERROR PRINT ; ERREPORT: 0A54 326B0B STA DIOST ;SET ERROR FLAG 0A57 21AF0A LXI H,ERRORMES 0A5A CDA20A CALL PRMSG 0A5D 3A6B0B LDA DIOST ;GET ERROR LETTER 0A60 4F MOV C,A ;PLACE ASCII CHARACTER IN C 0A61 CD4505 CALL CONOUT ; PRINT THE ERROR LETTER 0A64 CD9D0A CALL SPACE ;PRINT THE ADDRESS 0A67 21590B NX8 LXI H,CERRC 0A6A 0E06 MVI C,6 0A6C CD760A NX8N CALL X8 0A6F 23 INX H 0A70 0D DCR C 0A71 C26C0A JNZ NX8N 0A74 37 STC 0A75 C9 RET 0A76 7E X8 MOV A,M 0A77 E6F0 ANI 0F0H 0A79 0F RRC 0A7A 0F RRC 0A7B 0F RRC 0A7C 0F RRC 0A7D CD8B0A CALL HEXOUT 0A80 7E MOV A,M 0A81 E60F ANI 0FH 0A83 CD8B0A CALL HEXOUT 0A86 CD9D0A CALL SPACE 0A89 37 STC 0A8A C9 RET 0A8B F630 HEXOUT ORI 30H 0A8D FE3A CPI 3AH 0A8F DA940A JC GOODNUM 0A92 C607 ADI 7 GOODNUM 0A94 E5 PUSH H 0A95 C5 PUSH B 0A96 4F MOV C,A 0A97 CD4505 CALL CONOUT 0A9A C1 POP B 0A9B E1 POP H 0A9C C9 RET 0A9D 3E20 SPACE MVI A,' ' 0A9F C3940A 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: 0AA2 7E MOV A,M ;PRINT MESSAGE AT H&L TO 0 0AA3 B7 ORA A 0AA4 C8 RZ ; MORE TO PRINT 0AA5 E5 PUSH H 0AA6 4F MOV C,A 0AA7 CD4505 CALL CONOUT 0AAA E1 POP H 0AAB 23 INX H 0AAC C3A20A JMP PRMSG ERRORMES: 0AAF 0D0A DB 0DH,0AH 0AB1 4841524420 DB 'HARD DISK ERROR ' 0AC1 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 0AC2 AF XRA A ;MAKE A ZERO 0AC3 325015 STA HSTTRK 0AC6 325115 STA HSTTRK+1 0AC9 324F15 STA HSTDSK 0ACC 215E17 LXI H,SUBTBL 0ACF 22E117 SHLD SUBPNT 0AD2 3E22 MVI A,HSTSPT-1 ;LAST SECTOR NUMBER 0AD4 325215 STA HSTSEC ;SET IT FOR KCOMMON ; CLEAR THE MAP 0AD7 3EE5 MVI A,0E5H 0AD9 0683 MVI B,2*MAXMAP+1 0ADB 77 CLRMAP MOV M,A 0ADC 23 INX H 0ADD 05 DCR B 0ADE C2DB0A JNZ CLRMAP GETMAP ;SEE IF SURFACE IS PRESENT 0AE1 CD1809 CALL HSTPHY 0AE4 3A5A0B LDA PUNIT 0AE7 07 RLC 0AE8 07 RLC 0AE9 07 RLC 0AEA 07 RLC 0AEB D390 OUT BUSU 0AED 3E10 MVI A,10H ;SELECT UNIT COMMAND 0AEF D392 OUT CMND 0AF1 DB97 IN STATU ;CHECK UNIT STATUS 0AF3 E601 ANI 1 0AF5 CA480B JZ NEXTMAP ;IF NOT SELECTED GO TO NEXTMAP 0AF8 3A5D0B LDA PHEAD IF CMD CPI 0 JZ CARTH ;IF CARTRIDGE THE HEAD ADDRESS IS GOOD ADI 15 ;OTHERWISE SET VOLUMN BIT ENDIF 0AFB D391 CARTH OUT BUSL 0AFD 3E40 MVI A,40H 0AFF D392 OUT CMND ;SELECT HEAD 0B01 DB97 IN STATU 0B03 E620 ANI 20H 0B05 C2480B JNZ NEXTMAP 0B08 CD7808 CALL READINT ;READ WITHOUT DMA 0B0B DA480B JC NEXTMAP RDMAPBUF: 0B0E 2AE117 LHLD SUBPNT ;SET H<O MAP ADDRESS 0B11 DB94 NBADTRK IN SCTBU ;GET FIRST BYTW 0B13 FEE5 CPI 0E5H ;IS IT THE END 0B15 CA480B JZ NEXTMAP ;IF END DO THE NEXT SURFACE 0B18 47 MOV B,A ;PUT BYTE IN B (TRACK MSB) 0B19 3A5A0B LDA PUNIT ;GET THE UNIT NUMBER 0B1C 0F RRC ;POISITION UNIT BITS 0B1D 0F RRC 0B1E 0F RRC 0B1F E660 ANI 60H ;GET RID OF ANY OTHER JUNK 0B21 B0 ORA B 0B22 47 MOV B,A ;PUT TRACK AND UNIT IN B 0B23 3A5D0B LDA PHEAD ;GET HEAD 0B26 07 RLC ;POISITION BITS 0B27 07 RLC 0B28 E61C ANI 1CH 0B2A B0 ORA B ;OR WITH TRACK AND UNIT 0B2B 77 MOV M,A ;PLACE INTO TABLE 0B2C 23 INX H ;POINT TO NEXT BYTE IN TABLE 0B2D DB94 IN SCTBU ;GET SECOND BYTE OF TABLE 0B2F 77 MOV M,A ;ENTRY IS COMPLETE 0B30 23 INX H ;POINT TO NEXT 0B31 36E5 MVI M,0E5H ;SET END OF TABLE ; TEST FOR FULL 0B33 11E017 LXI D,SUBTBL+2*MAXMAP 0B36 7C MOV A,H 0B37 BA CMP D 0B38 C2110B JNZ NBADTRK 0B3B 7D MOV A,L 0B3C BB CMP E 0B3D C2110B JNZ NBADTRK 0B40 3E4D MVI A,'M' 0B42 CD540A CALL ERREPORT 0B45 C3110B JMP NBADTRK ;GO GET ADDRESS OF NEXT BAD TRACK NEXTMAP: 0B48 22E117 SHLD SUBPNT 0B4B 3A4F15 LDA HSTDSK 0B4E 3C INR A 0B4F 3C INR A 0B50 324F15 STA HSTDSK 0B53 FE18 CPI 2*HEADQ ;ARE WE DONE ? 0B55 C8 RZ ;IF SO, RETURN 0B56 C3E10A JMP GETMAP ENDIF ; IF HERE WE ARE DONE! ; DO NOT CHANGE THE ORDER OF THE NEXT 9 BYTES 0B59 00 CERRC DB 0 ;ERROR COUNTER 0B5A PUNIT DS 1 ;DESIRED PHYSICAL UNIT 0B5B PTRK DS 2 ;DESIRED REAL TRACK ADDRESS 0B5D PHEAD DS 1 ;DESIRED HEAD 0B5E PSECTOR DS 1 ;DESIRED SECTOR,512 BYTE 0B5F FF OLDUNIT DB 0FFH ;LAST HEAD SELECTED, FF TO CAUSE INITIAL SEL. 0B60 FFFF OLDTRK DW 0FFFFH ;LAST TRACK SEEKED 0B62 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"). ; 0B63 TRACK: DS 2 ;TWO BYTES FOR EXPANSION 0B65 SECTOR: DS 2 ;TWO BYTES FOR EXPANSION 0B67 DMAAD: DS 2 ;DIRECT MEMORY ADDRESS 0B69 DISKNO: DS 1 ;DISK NUMBER 0-15 0B6A RORW: DS 1 ;READ OR WRITE SELECTED 0B6B DIOST: DS 1 ;I/O RETURN STATUS 0 OK 0B6C HDLD: DS 1 ;HEADLOAD FLAG BIT ; ; ; SCRATCH RAM AREA FOR BDOS USE 0B6D = BEGDAT EQU $ ;BEGINNING OF DATA AREA 0B6D DIRBF: DS 128 ;SCRATCH DIRECTORY AREA 0BED ALL00: DS 31 ;ALLOCATION VECTOR 0 0C0C ALL01: DS 31 ;ALLOCATION VECTOR 1 0C2B ALL02: DS 192 ;ALLOCATION VECTOR 2 0CEB ALL04: DS 192 ;ALLOCATION VECTOR 4 0DAB ALL05: DS 192 ;ALLOCATION VECTOR 5 0E6B ALL03: DS 192 ;ALLOCATION VECTOR 3 0F2B ALL06 DS 192 0FEB ALL07 DS 192 10AB ALL08 DS 192 116B ALL09 DS 192 122B ALL10 DS 192 12EB ALL11 DS 192 13AB ALL12 DS 192 146B ALL13 DS 192 152B CHK00: DS 16 ;CHECK VECTOR 0 153B CHK01: DS 16 ;CHECK VECTOR 1 154B = CHK02: EQU $ ;FIXED DRIVE - NO STORAGE REQUIRED 154B = CHK03: EQU $ ;FIXED DRIVE - NO STORAGE REQUIRED 154B = CHK04 EQU $ ;NO STORAGE REQUIRED 154B = CHK05 EQU $ ;NO STORAGE REQUIRED 154B = CHK06 EQU $ 154B = CHK07 EQU $ 154B = CHK08 EQU $ 154B = CHK09 EQU $ 154B = CHK10 EQU $ 154B = CHK11 EQU $ 154B = CHK12 EQU $ 154B = CHK13 EQU $ 154B SEKDSK: DS 1 ;SEEK DISK NUMBER 154C SEKTRK: DS 2 ;SEEK TRACK NUMBER 154E SEKSEC: DS 1 ;SEEK SECTOR NUMBER ; 154F HSTDSK: DS 1 ;HOST DISK NUMBER 1550 HSTTRK: DS 2 ;HOST TRACK NUMBER 1552 HSTSEC: DS 1 ;HOST SECTOR NUMBER ; 1553 SEKHST: DS 1 ;SEEK SHR SECSHF 1554 HSTACT: DS 1 ;HOST ACTIVE FLAG 1555 HSTWRT: DS 1 ;HOST WRITTEN FLAG ; 1556 UNACNT: DS 1 ;UNALLOC REC CNT 1557 UNADSK: DS 1 ;LAST UNALLOC DISK 1558 UNATRK: DS 2 ;LAST UNALLOC TRACK 155A UNASEC: DS 1 ;LAST UNALLOC SECTOR ; 155B RSFLAG: DS 1 ;READ SECTOR FLAG 155C READOP: DS 1 ;1 IF READ OPERATION 155D WRTYPE: DS 1 ;WRITE OPERATION TYPE 155E HSTBUF: DS HSTSIZ ;HOST BUFFER 175E SUBTBL: DS 2*MAXMAP+1 17E1 SUBPNT DS 2 ; 17E3 = ENDDAT EQU $ ;END OF DATA AREA 0C76 = DATSIZ EQU $-BEGDAT;SIZE OF DATA AREA ; ; READ/WRITE STACK SAVE AREA ; 17E3 0000 OLDSP: DW 0 17E5 0000 HLSAV: DW 0 17E7 DS 30 1805 NSTACK: DS 2 ; ; THE ADDRESS OF NSTACK MUST FALL WITHIN ; THE AVAILABLE RAM STORAGE. 1807 00 DB 00H;MPM - RSP REQUIREMENT 1808 END