10
20
30
40
50
60
70
80
90
100 :
110 M%=7
120 IFFNfx(130,0)<>&FFFF:PRINT"Must be run in I/O processor":END
130 ON ERROR VDU11:REPORT:PROCCloseAll:PRINTSPC9:END
140 sz%=0:PROCasm:?IDEcommand=&08:REPEATUNTIL?IDEstatus<128:
150 DIM ctrl% 31,data% &1FF:half%=0:MODEM%:mem%=data%:IFM%=7:mem%=&7C00
160 sector%=1:cylinder%=0:head%=0:dev%=0:count%=1:PROCideSize(64,3)
170 PROCHelp:REPEAT:PROCRead:REPEATPROCDisplay:REPEAT:X%=ctrl%:Y%=X%DIV256
180 A$=GET$:IFA$>"_":A$=CHR$(ASCA$-32)
190 UNTILINSTR("ITFZXCVNM,.WD07HLS ",A$)
200 IFA$="I":PROCid
210
220 IFA$="T":PROCtest
230 IFA$="F":half%=half%EOR&100
240 UNTILINSTR("IT"+CHR$0,A$)=0
250 IFA$="N":head%=(head%-1)AND3
260 IFA$="M":head%=(head%+1)AND3
270 IFA$=".":sector%=(sector%+1)AND255
280 IFA$=",":sector%=(sector%-1)AND255
290 IFA$="C":cylinder%=(cylinder%-1)AND&FFFF
300 IFA$="V":cylinder%=(cylinder%+1)AND&FFFF
310 IFA$="Z":lau%=(lau%-1)AND(lau%>1):PROCLAUtoCHS
320 IFA$="X":lau%=(lau%+1)AND&FFFFFF:PROCLAUtoCHS
330 IFA$="W":sz%=sz%EOR1:PROCHelp
340 IFA$="D":dev%=dev%EOR1
350 IFA$="0":M%=&80:MODEM%:PROCHelp:mem%=data%
360 IFA$="7":M%=7:MODEM%:PROCHelp:mem%=&7C00
370 IFA$=" ":INPUT" Go to sector: &"A$:PRINTCHR$11;SPC(38);CHR$13;:IFA$<>"":lau%=EVAL("&"+A$):PROCLAUtoCHS:A$=""
380 IFA$=CHR$13:count%=count%+1
390 IFA$="_":count%=count%-1
400 IFA$="H":PROCcls:PROCHelp
410 IFA$="S":PROCsave:CLS:PROCHelp
420 IFA$="L":PROCload:CLS:PROCHelp
430 UNTIL0:END
440 :
450 DEFPROCcls:IFM%=&80:ENDPROC
460 PRINTTAB(0,17);:FORA%=1TO7:PRINTSPC(39):NEXT:PRINTSTRING$(7,CHR$11);:ENDPROC
470 DEFPROCDisplay:PRINTTAB(8-(M%AND7),17-(M%AND3));
480 PRINT"Sector:";FNh0(lau%,6);SPC2;"D:";dev%;SPC2;
490 PRINT"C:"FNh0(cylinder%,4);SPC2;"H:"FNh0(head%,2);SPC2;"S:"FNh0(sector%,2)
500 PRINT'SPC(16);CHR$13;:IFres%AND255:PRINT" Error: ";~res%
510 IFM%=7:PRINTTAB(0,23);:ENDPROC
520 PROCdump(mem%):PRINTTAB(0,23);:ENDPROC
530 :
540 DEFPROCHelp:PRINTTAB(7-(M%AND7),18-(M%AND3));
550 PRINTFNd(sz%*8+8,3);"bit";SPC2;"<-ZX-> D <-CV-> <NM> <-->"'
560 PRINT" <spc> Goto sector W: Toggle width"
570 PRINT" I: Investigate device T: Test speed":IFM%=&80:PRINTTAB(40,20);
580 PRINT" F: High/low 256 bytes L: Load data":IFM%=&80:PRINTTAB(40,21);
590 PRINT" ";7-(M%AND7);": Screen mode ";7-(M%AND7);" S: Save data"
600 IFM%=7:PRINTTAB(0,13);CHR$147;STRING$(38,",")'''''''
610 ENDPROC
620 :
630
640 :
650 DEFPROCdump(mem%)
660 VDU30:FORA%=half% TO half%+255 STEP16
670 PRINTFNh0(cylinder%,4)":"FNh0(head%,1)":"FNh0(sector%,2)" "FNh0(A%,4)" ";
680 FOR B%=A% TO A%+15:PRINTFNh0(mem%?B%,2);" ";:NEXT
690 FOR B%=A% TO A%+15:C%=mem%?B%:IFC%=127 OR C%<32:VDU46 ELSE VDUC%
700 NEXT:IFA%<&1F0:PRINT
710 NEXT:ENDPROC
720 :
730 DEFPROCRead:PROCCHStoLAU
740 !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=count%:num%?1=sz%:res%=USRrd%
750 ENDPROC
760 :
770 DEFPROCWrite:PROCCHStoLAU
780 !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=1:num%?1=sz%:res%=USRwr%:ENDPROC
790 :
800 DEFPROCCHStoLAU:lau%=(sector%-1)+64*head%+256*cylinder%+dev%*&400000:ENDPROC
810 :
820 DEFPROCLAUtoCHS:sector%=(lau%AND63)+1:head%=(lau%AND&C0)DIV64:cylinder%=(lau%AND&3FFFFF)DIV256:ENDPROC
830 :
840 DEFFNh0(A%,N%)=RIGHT$("0000000"+STR$~A%,N%)
850 DEFFNd(A%,N%)=RIGHT$(" "+STR$A%,N%)
860 :
870 DEFPROCid:LOCAL A%:PROCcls
880 FOR A%=0 TO 255 STEP4:mem%!A%=0:mem%!(A%+256)=0:NEXT
890 !addr%=mem%:A%=dev%*16:num%?1=sz%:CALL id%
900 IFsz%=0:FOR A%=255 TO 0 STEP -1:mem%?(A%*2+1)=0:mem%?(A%*2)=mem%?A%:NEXT
910
920 big%=FALSE:IFmem%?&74=0:big%=TRUE:mem%?&74=mem%?&72:mem%?&72=0
930 IFmem%?&3+mem%?&6D+mem%?&73=0:mem%?&6D=mem%?&74:mem%?&73=mem%?&6C:tot%=(256*mem%?&6D+mem%?&6C)*mem%?&6E*mem%?&70:mem%?&3=(tot%DIV((mem%?6)*(mem%?12)))DIV256
940 IFmem%?&79=0:mem%?&79=mem%?&6C
950 PROCinfo:ENDPROC
960 :
970 DEFPROCinfo:PRINTTAB(0,24-(M%AND7));
980 PRINT" Physical: C:&";FNhex(mem%+2);" H:";FNd(mem%?6,2);" S:";mem%?12
990 PRINT" Logical: C:&";FNhex(mem%+&6C);" H:";FNd(mem%?&6E,2);" S:";mem%?&70
1000 tot%=mem%!&78:
1010 tot%=mem%!&78
1020 PRINT" Size: &";FNhex(mem%+&7A);FNhex(mem%+&78);CHR$(32-10*big%);
1030 IFmem%?&73+mem%?&75:PRINT;" ";tot%DIV4;"K";" ";tot%DIV4096;"M ";CHR$127;
1040 PRINT'" Serial: "FNstr(mem%+20,10)
1050 PRINT" Firmware: "FNstr(mem%+46,4)
1060 PRINT" Model: "FNstr(mem%+54,20)
1070 ENDPROC
1080 :
1090 DEFPROCcalc:LOCAL A%,P%,L%:PROCid:size%=65536*mem%?116+mem%?114
1100 matches%=0:log%=-1:PRINTTAB(0,27-(M%AND4));
1110 FOR L%=0 TO 255:VDU11,11,11,11,11
1120 PRINT"Logical: C:&";FNh0(L%,2)'''''"Total &";
1130 tot%=(L%*256+mem%?&6C)*mem%?&6E*mem%?&70
1140 PRINTFNh0(tot%,8);" ";tot%DIV4;"K";" ";tot%DIV4096;"M"
1150 IF(tot%AND&00FF00FF)=size%:PRINT"Match at ";tot%DIV4096;"M";CHR$13;:matches%=matches%+1:log%=L%
1160 VDU11:NEXT:PRINTSPC(38)'SPC(30);:VDU13,11
1170 IFmatches%<>1:PRINT"Couldn't calculate size":ENDPROC
1180 L%=log%:tot%=(L%*256+mem%?&6C)*mem%?&6E*mem%?&70
1190 P%=tot%DIV((mem%?6)*(mem%?12)):mem%?3=P%DIV256:mem%?&6D=L%
1200 mem%?&73=(tot%AND&FF00)DIV256:mem%?&75=(tot%AND&7F000000)DIV(&1000000)
1210 PRINTSPC(20);CHR$13;:VDU11,11,11,11,11,11:PROCinfo
1220 ENDPROC
1230 :
1240 DEFFNhex(A%):LOCAL A$:A$=FNh0(?A%,2)
1250 IFA%?1:=FNh0(A%?1,2)+A$ ELSE ="xx"+A$
1260 :
1270 DEFFNstr(A%,N%):LOCAL A$:REPEAT
1280 IFA%?1>31:A$=A$+CHR$A%?1 ELSE A$=A$+"."
1290 IF?A%>31:A$=A$+CHR$?A% ELSE A$=A$+"."
1300 A%=A%+2:N%=N%-1:UNTILN%<1:=A$
1310 :
1320 DEFPROCideInit:PROCideSize(64,3):ENDPROC
1330 DEFPROCideSize(spt%,hds%)
1340 ?&FC42=spt%:?&FC43=spt%
1350 ?&FC46=hds%:?&FC47=&91:
1360 ENDPROC
1370 :
1380 DEFPROCrdMax
1390 ?&FC46=0:?&FC47=&F8
1400 REPEATUNTIL?&FC47<128
1410 IF?&FC47 AND 1:IF ?&FC41 AND 4:PRINT"Not supported":ENDPROC
1420 PRINT"Max: C:&";FNh0(?&FC45,2);FNh0(?&FC44,2);" H:";?&FC46 AND 15;" S:";?&FC43
1430 ENDPROC
1440 :
1450 DEFPROCtest:PROCcls:PRINT"Test transfer speed";:max%=256
1460 oldlau%=lau%:T%=TIME:FOR lau%=0 TO max%-1:!addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=count%:num%?1=sz%:U%=TIME:A%=USRrd%:U%=TIME-U%:NEXT:T%=TIME-T%
1470 VDU13:PRINT"Transfered ";max%*256*(sz%+1);" bytes in ";T%/100;"s"
1480 PRINT"Speed: ";max%*256*(sz%+1)DIV(T%/100);"cps over ";max%;" sectors"
1490 PRINT"Burst speed: ";25600*(sz%+1)DIVU%;"cps per ";256*(sz%+1);" bytes"
1500 lau%=oldlau%:VDU11,11,11:ENDPROC
1510 :
1520 DEFPROCwr:PROCcls:PRINT"Read/Write test - OVERWRITES DATA!":max%=256
1530 FOR lau%=0 TO max%-1:PRINTCHR$13;"Reading "FNh0(lau%,8);
1540 !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=count%:num%?1=sz%:A%=USRrd%:PRINT" - OK"
1550 $mem%="*TEST* SECTOR &"+FNh0(lau%,8):PRINT"Writing "FNh0(lau%,8);
1560 !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=count%:num%?1=sz%:A%=USRwr%:PRINT" - OK"
1570 PRINT"Verifying "FNh0(lau%,8);
1580 !addr%=mem%:sec%?2=lau%:sec%?1=(lau%AND&FF00)DIV256:sec%?0=(lau%AND&FF0000)DIV65536:?num%=count%:num%?1=sz%:A%=USRrd%
1590 IF$mem%="*TEST* SECTOR &"+FNh0(lau%,8):PRINT" - OK":VDU11,11,11 ELSE PRINT" - Failed"
1600 NEXT:ENDPROC
1610 :
1620 DEFFNsum:LOCAL sum%
1630 FOR A%=0 TO 254:sum%=sum%+mem%?A%:IFsum%>255:sum%=(sum%+1)AND&FF
1640 NEXT:=sum%AND&FF
1650 :
1660 DEFFNbyte(A%,X%,Y%)=((USR&FFF4)AND&FF00)DIV256
1670 DEFFNfx(A%,X%):LOCAL Y%:Y%=X%DIV256:=((USR&FFF4)AND&FFFF00)DIV256
1680 :
1690 DEFPROCasm
1700 mc%=mc%:IFmc%=0:DIMmc% 511
1710 addr%=&80:sec%=&85:cmd%=&84:num%=&88:ptr%=&8E:res%=0
1720 IDEdata=&FC40:IDEerror=&FC41:IDEcount=&FC42:IDEsector=&FC43
1730 IDEcylinder=&FC44:IDEhead=&FC46:IDEstatus=&FC47:IDEcommand=&FC47
1740 IF!IDEdata<>IDEdata!8:sz%=1
1750 FORP=0 TO 1
1760 P%=mc%:[OPT P*2
1770 .id%
1780 TAY:.idlp
1790 LDA &FF:BMI idescape
1800 LDA IDEstatus:BMI idlp
1810 TYA:AND #16:STA IDEhead :\ Device
1820 LDA #&EC :STA IDEcommand :\ &EC=Identify
1830 LDY #0:LDX #1:STX num%
1840 CLC:JMP TransferLoop
1850 .idescape
1860 RTS
1870 :
1880 .WaitForData
1890 LDA &FC47:AND #8:BEQ WaitForData
1900 LDA &FC47:RTS
1910 :
1920 .WaitNotBusy
1930 PHP:JSR L806F :\ Get IDE status
1940 AND #&80:BNE WaitNotBusy+1:PLP :\ Wait for IDE not busy
1950 BIT &CC:RTS
1960 :
1970 .L806F
1980 PHP:LDA &FC47:STA &8D
1990 LDA &FC47:CMP &8D:BNE L806F+1
2000 PLP:RTS
2010 :
2020 .rd%:LDA #&08:STA cmd%:CLC:BCC CommandStart
2030 .wr%:LDA #&0A:STA cmd%:SEC:BCS CommandStart
2040 :
2050 .CommandStart :\ C=R/W, ptr%=>block
2060 LDA #addr%-1:STA ptr%:LDA #0:STA ptr%+1 :\ ptr%=>block
2070 PHP:JSR SetGeometry:PLP
2080 .CommandLoop
2090 LDX #2:.Twice
2100 JSR SetSector:LDY #0 :\ Set sector, count, command
2110 .TransferLoop
2120 JSR WaitForData:AND #&21:BNE TransError
2130 \.TransferLoop
2140 BIT &CD:\BVS TransTube:BCC IORead
2150 :
2160 .IOWrite
2170 LDA num%+1:BEQ IOWrite8bit
2180 INY:LDA (addr%),Y:STA &FC48:DEY
2190 LDA (addr%),Y:STA &FC40
2200 INC addr%:BNE P%+4:INC addr%+1
2210 JMP TransferByte
2220 .IOWrite8bit
2230 LDA (addr%),Y:STA &FC40:JMP TransferByte
2240 :
2250 .IORead
2260 LDA &FC40:STA (addr%),Y:LDA num%+1:BEQ TransferByte
2270 INC addr%:BNE P%+4:INC addr%+1
2280 LDA &FC48:STA (addr%),Y:JMP TransferByte
2290 :
2300 .TransferByte
2310 LDA &FC47:AND #8:BEQ TransError :\ Run out of data
2320 INY:BNE TransferLoop :\ Loop for 256 bytes/words
2330 LDA &FC47:AND #&21:BNE TransError:\ Error occured
2340 DEX:BEQ Next :\ Done twice, do next sector
2350 LDA num%+1:BEQ Twice :\ 8-bit, addr unchanged
2360 DEC addr%+1:JMP Twice :\ Step addr back, do second pass
2370 :
2380 .Next
2390 INC sec%+2:BNE TransCount :\ Increment sector
2400 INC sec%+1:BNE TransCount:INC sec%
2410 .TransCount
2420 INC addr%+1:DEC num%:BNE CommandLoop :\ Loop for all sectors
2430 LDA #0 :\ Done, no errors
2440 .TransError
2450 LDX &FC47:LDA &FC41:RTS
2460 :
2470 .SetGeometry
2480 JSR WaitNotBusy :\ Should check device
2490 LDA #64:STA &FC42:STA &FC43 :\ 64 sectors per track
2500 LDA sec%:LSR A:LSR A:ORA #3:AND #&13
2510 STA &FC46:LDA #&91:STA &FC47 :\ 4 heads per cylinder
2520 RTS
2530 :
2540 .SetSector
2550 PHP:JSR WaitNotBusy :\ Save CC/CS Read/Write
2560 LDY #8:LDA #1:STA &FC42 :\ One sector
2570 CLC:LDA (ptr%),Y:AND #63:ADC #1:STA &FC43 :\ Set sector b0-b5
2580 DEY:LDA (ptr%),Y:STA &FC44 :\ Set sector b8-b15
2590 DEY:LDA (ptr%),Y:PHA:AND #&3F:STA &FC45 :\ Set sector b16-b20
2600 PLA:ROL A:ROL A:ROL A:ROL A :\ Get Drive 0/1
2610 INY:INY:EOR (ptr%),Y:AND #&02:EOR (ptr%),Y :\ Merge Drive and Head
2620 JSR SetDrive:DEY:DEY:DEY:LDA (ptr%),Y :\ Get command &08 or &0A
2630 .SetCommand
2640 AND #2:PHA:EOR #2:LSR A:LSR A :\ Copy ~b1 into Cy
2650 PLA:ASL A:ASL A:ASL A:ORA #&20 :\ Translate CS->&20 or CC->&30
2660 STA &FC47:PLP:RTS :\ Set command &08 or &0A
2670 :
2680 .SetDrive
2690 ROL A:ROL A:ROL A:AND #&13:STA &FC46:RTS :\ Set device + sector b6-b7
2700 :
2710 ]NEXT:ENDPROC
2720 DEFPROCCloseAll:in%=in%:IFin%:A%=in%:in%=0:CLOSE#A%
2730 out%=out%:IFout%:A%=out%:out%=0:CLOSE#A%
2740 ENDPROC
2750 DEFPROCgbpb(A%,ch%,ad%,nm%,pt%):?X%=ch%:X%!1=ad%:X%!5=nm%:X%!9=pt%:CALL&FFD1:ENDPROC
2760 DEFPROCsave:PROCcls:PRINT" Save data from IDE device"
2770 INPUT" File to save to: "f$:INPUT" Start sector: &"s$:INPUT" Number of sectors: "n$:SC%=EVAL("&"+s$):NM%=VALn$:out%=OPENOUT(f$):REPEATPRINTCHR$13;" ";FNh0(SC%,6);
2780 lau%=SC%:PROCLAUtoCHS:PROCRead:PROCgbpb(2,out%,mem%,256+256*sz%,0)
2790 SC%=SC%+1:NM%=NM%-1:UNTILNM%<1:CLOSE#out%:out%=0:ENDPROC
2800 DEFPROCload:PROCcls:PRINT" Load data to IDE device"
2810 INPUT" File to load from: "f$:INPUT" Start sector: &"s$:SC%=EVAL("&"+s$):in%=OPENIN(f$):REPEATPRINTCHR$13;" ";FNh0(SC%,6);
2820 lau%=SC%:PROCLAUtoCHS:PROCgbpb(4,in%,mem%,256+256*sz%,0):PROCWrite
2830 SC%=SC%+1:UNTILEOF#in%:CLOSE#in%:in%=0:ENDPROC