;************************************************** ; HARDDISK Utility ;************************************************** ;Autor Wilfried Schmitten, Heidebloeck 16, 2 Hamburg 74 ;letzte Aenderung : 21.2.1989 rev: equ 11 nein equ 0 ja equ not nein ;------------------------ TEST equ nein ;------------------------ ; Voraussetzung ; -------------- ; a) Controller OMTI 5520 A ; b) Organisation der Festplatte wie in HARDDISK.ASM fuer CP/M 3.0 ; Aenderungsstand juenger als 8.9.88 ; c) jedes logische HD-Laufwerk (ausser 0) hat ; im dpb fuer reserved tracks = spare eingetragen ; d) Definition Controller-Adressen Plattendaten in CDEF.LIB ; cyl$num equ (cylinder-1)/loghd ; last$cyl equ cylinder-((loghd-1)*cyl$num) ; spare Reserve fuer evtl. Defektspuren ; loghd Anzahl logische Drives ; ; hierzu gehoeren die INCLUDE Files ; ; HDDEF.MAC ; HDLOWLEV.MAC ; HDFUNKT.MAC maclib cdef.lib ; SYSLIB extrn madc, ma2hc, mhldc, acase3, eval, eval10 extrn sort, sksp, instr ; GSXLIB extrn openstation, closestation extrn textmode extrn wcreate, wclose, wselect, wchange extrn writetext, cursorat, getposition, normal, reverse extrn cursordown, cursorhome extrn erasescreenend, eraselineend extrn linefeed, carreturn, newline bdos equ 5 fenster macro kng,x,y,breite,hoehe,label,xstart,ystart,anzahl,mark dseg kng&nr db 0 if nul label kng&lbl db 0 else kng&lbl db label,0 endif if not nul anzahl kng&anz dw anzahl * 256 or mark endif cseg if not nul xstart kng&st equ xstart * 256 or ystart endif ld hl,x * 256 or y ld de,breite * 256 or hoehe ld bc,kng&lbl call wcreate ld (kng&nr),a endm cseg eject subttl Bedienung Atext: db ' Harddisk Utility WS V' db rev/10+'0','.' db rev mod 10+'0' if test db 0dh,0ah db ' Test Version' endif db 0 startutl: ld sp,stack call openstation call textmode if test fenster A,30,0,30,4 else fenster A,30,0,30,3 ;Fenster Sign on message endif ld hl,Atext call epstr ;Text dazu in a,(hd$config) sub hd$jumper jr nz,fatalerror ld (lun),a ;LUN 0 einstellen call testw jp testw2 fatalerror: fenster C,23,5,50,5 in a,(hd$config) ld de,tfist call ma2hc ld a,hd$jumper ld de,tfsoll call ma2hc ld hl,tferror call epstr call wjn jp testend tferror: db ' Controller Jumper Soll: ' tfsoll: db 0,0 db ' Ist: ' tfist: db 0,0 db 0dh,0ah db ' Programm wird beendet' db 0 testw: out (hd$reset),a xor a out (hd$mask),a fenster D,24,5,42,16 ld hl,cylinder ld de,tfcyl call mhldc ld a,(lun) or a jr z,te1 ld a,1 te1: ld de,tflun call madc ld a,spare * hd$head * (loghd-1) ld de,tfalt call madc ld a,hd$head ld de,tfhead call madc ld hl,red$wrcur ld de,tfred call mhldc ld hl,wr$pre$comp ld de,tfpre call mhldc ld hl,parkcyl ld de,tfpark call mhldc ld hl,tfinit call epstr call setp call c,sumerror call wjn call wclose ret tfinit: db ' Controller wird initialisiert',0dh,0ah db ' -----------------------------',0dh,0ah db ' Logical Unit ' tflun: db 0,0,0 db 0dh,0ah,' ' tfcyl: db 0,0,0,0,0 db ' Cylinder',0dh,0ah,' ' tfhead: db 0,0,0 db ' Koepfe',0dh,0ah db ' 17 Sektoren',0dh,0ah db ' 512 Byte/Sektor',0dh,0ah,0ah db 'Reduzierter Schreibstrom Cylinder ' tfred: db 0,0,0,0,0,0dh,0ah db 'Schreib Pre-Kompensation Cylinder ' tfpre: db 0,0,0,0,0,0dh,0ah db 'Park-Cylinder ' tfpark: db 0,0,0,0,0,0dh,0ah db 'Alternate Tracks reserviert ' tfalt: db 0,0,0,0dh,0ah db ' -----------------------------',0dh,0ah db 0 men1: db 0 db 'zerstoerungsfreie Test''s',0 db 'zerstoerende Test''s ',0 db 'formatieren ',0 db 'Ende ',0 m1table: db m1anz ;Anzahl Eintraege dw test4 ;no match = Ende db 1 ;Vergleichzahl dw simpletest db 2 dw ztest db 3 dw mformat m1anz equ ($-m1table)/3 testw2: fenster B,5,5,28,6,'HAUPTMENUE',2,1,m1anz,1 ld hl,men1 ld de,Bst ld bc,(Banz) call select ;Auswahl ld a,m1anz cp c jr z,test3 jr test1 test2: ;wiederholter Aufruf ld a,(Bnr) ;wenn Fenster bereits eroeffnet call wselect ;und Menuetext geschrieben ld bc,(Banz) ld de,Bst ld hl,men1 call select1 test1: ld (Banz),bc ld a,c ld de,m1table call acase3 ;Verzweigung entsprechend select jp test2 ;Return vom aufgerufenen Up test4: pop hl ;Return Adr vernichten call wclose test3: call wclose testend: call closestation jp 0 ;* Ausgang * fsmen db 0 db 'Controller Diagnostic ',0 db 'Drive Diagnostic ',0 db 'Verify Drive ',0 db 'Drive Read Ident ',0 db 'Koepfe parken ',0 db 'Eingabe Parameter ',0 db 'Ende ',0 fsmtable: db fsmanz ;Anzahl Eintraege dw simp4 ;no match = Ende db 1 ;Vergleichzahl dw sramdiag db 2 dw drdiag db 3 dw verdr db 4 dw drrdid db 5 dw kpark db 6 fsm1: dw input fsmanz equ ($-fsmtable)/3 simpletest: fenster E,9,8,28,9,'ZERSTOERUNGSFREIER TEST',2,1,fsmanz,1 ld hl,fsmen ld de,Est ld bc,(Eanz) call select ;Auswahl ld a,fsmanz cp c jr z,simp3 ;Ende push bc ;hier Ergebnisfenster fuer die ;Teste oeffnen fenster F,40,5,50,25,'DIAGNOSE' pop bc jr simp1 simp2: ;wiederholter Aufruf ld a,(Enr) ;wenn Fenster bereits eroeffnet call wselect ;und Menuetext geschrieben ld bc,(Eanz) ld de,Est ld hl,fsmen call select1 simp1: ld (Eanz),bc ld a,c ld de,fsmtable call acase3 ;Verzweigung entsprechend select jp simp2 ;Return vom aufgerufenen Up simp4: pop hl call wclose ld a,(knr) ;Return von Ende or a ;Parameter Fenster da? jr z,simp3 ;nein call wclose ;ja, schliessen ld hl,input ;Umleitung aufheben ld (fsm1),hl ld (fzt1),hl xor a ld (knr),a ;Ergebnisfenster bereits geschlossen simp3: call wclose ;Menue Fenster ebenfalls schliessen ret fimen: db 0 fim1 db 'Start Cylinder (' fim11 db 0,0,0,0,0,') :' db 0 ;term fim2 db ' Head (' fim21 db 0,0,0,0,0,') :' db 0 ;term fim3 db ' Sector (' fim31 db 0,0,0,0,0,') :' db 0 ;term fim4 db 'Ende Cylinder (' fim41 db 0,0,0,0,0,') :' db 0 ;term fim5 db ' Head (' fim51 db 0,0,0,0,0,') :' db 0 ;term fim6 db ' Sector (' fim61 db 0,0,0,0,0,') :' db 0 ;term fim7 db 'Interleave Factor (' fim71 db 0,0,0,0,0,') :' db 0 fim8 db 'Logical Unit (' fim81 db 0,0,0,0,0,') :' db 0 fim9 db 'Anz.Wdhlg.(rwtest)(' fim91 db 0,0,0,0,0,') :' db 0 input: fenster K,1,20,35,12,'PARAMETER' ld hl,input1 ld (fsm1),hl ;bei naechstem Aufruf ld (fzt1),hl ;umleiten jr inp6 input1: ld a,(knr) call wselect call cursorhome call erasescreenend inp6: ld ix,chtab ld b,iwerte inp1: ld l,(ix+0) ;Wert holen ld h,(ix+1) ld e,(ix+2) ld d,(ix+3) call mhldc ld de,chtabl add ix,de djnz inp1 ld b,iwerte ld hl,fim1 inp2: call epstr push hl call newline pop hl djnz inp2 ;bis alle Texte geschrieben call cursorhome ld ix,chtab ld b,iwerte inp3: push bc inp4: ld l,(ix+0) ;Wert in String einsetzen ld h,(ix+1) ld e,(ix+2) ld d,(ix+3) call mhldc ld l,(ix+4) ld h,(ix+5) call epstr ;Text ausgeben call eraselineend ld hl,inpbuf ld (hl),5 ;max Laenge buffer ex de,hl ld c,10 call bdos pp: ld hl,inpbuf+1 ld a,(hl) or a jr z,pp2 ;kein Input inc hl ;Zeiger auf 1.Zeichen push hl add a,l ld l,a ld a,h adc a,0 ld h,a ld (hl),0 ;Endemarke zufuegen pop hl call eval jr nc,px inp5: ld e,'G'-'@' ld c,2 call bdos ;Piep call carreturn ;carry Fehler jr inp4 px: ld (ix+0),e ld (ix+1),d pp2: ex (sp),hl ld b,h ex (sp),hl call chvalid jr c,inp5 ;Fehler call carreturn ld l,(ix+0) ;Wert in String einsetzen ld h,(ix+1) ld e,(ix+2) ld d,(ix+3) call mhldc ld l,(ix+4) ld h,(ix+5) call epstr ;Text ausgeben call newline ld de,chtabl add ix,de pop bc djnz inp3 ld a,(luninp) or a jr z,inp7 ld a,20h inp7: ld hl,lun cp (hl) ret z ld (lun),a call testw ret inpbuf: ds 12 ; Pr}fung der Eingaben auf ; Plausibilitaet ;Aufbau der Tabelle ;Startwert ;Pointer Text der Variablen ;Pointer Textzeile ;Ende Minimum zulassig chtab: scyl: dw 0 dw fim11 dw fim1 dw 0 ;dummy shead: dw 0 dw fim21 dw fim2 dw 0 ;dummy ssector:dw 0 dw fim31 dw fim3 dw 0 ;dummy ecyl: dw cylinder-1 dw fim41 dw fim4 ecmin: dw 0 ;dynamisch ehead: dw hd$head-1 dw fim51 dw fim5 ehmin: dw hd$head-1 ;dynamisch esector:dw sector$nmb-1 dw fim61 dw fim6 esmin: dw sector$nmb-1 ;dynamisch interleave: dw ilval dw fim71 dw fim7 ilmin: dw 1 luninp: dw 0 dw fim81 dw fim8 lunmin dw 0 wdhlg: dw 2 dw fim91 dw fim9 wdhmin: dw 2 chtabl equ shead-scyl iwerte equ ($-chtab)/chtabl chvalid: ld de,(scyl) ld hl,cylinder-1 xor a ;Pruefung scyl <= cyl max sbc hl,de jr nc,chv1 ld hl,0 ;Fehler scyl > cyl max ld (scyl),hl ret ;Fehlerausgang chv1: ld hl,(scyl) ld (ecmin),hl ;wird Minimum End cyl ;Pruefung ecyl >= cyl min ld de,(ecmin) ld hl,(ecyl) sbc hl,de jr nc,chv2 ld (ecyl),de ;Fehler ld a,b ;ausser bei den ersten cp iwerte-2 ;drei s.Werten ret c ;* ret chv2: ld de,(ecyl) ;Pruefung ecyl <= cyl max ld hl,cylinder-1 sbc hl,de jr nc,chv3 ld hl,cylinder-1 ld (ecyl),hl ld a,b ;ausser bei den ersten cp iwerte-2 ;drei s.Werten ret c ;* ret ; Pruefung head ; Sonderfall wenn endcyl=startcyl chv3: ld hl,0 ld (ehmin),hl ld hl,(ecyl) ;scyl und ecyl muessen gueltig sein ld de,(scyl) sbc hl,de jr nz,chv4 ;wenn scyl=ecyl ld hl,(shead) ld (ehmin),hl ;Minimum head setzen, da sonst ruecklauefig chv4: ld de,(shead) ld hl,hd$head-1 xor a ;Pruefung shead <= Koepfe max sbc hl,de jr nc,chv5 ld hl,0 ;Fehler shead > Koepfe max ld (shead),hl ret ;Fehlerausgang chv5: ;Pruefung ehead >= Koepfe min ld de,(ehmin) ld hl,(ehead) sbc hl,de jr nc,chv6 ld (ehead),de ;Fehler ld a,b ;ausser bei den ersten cp iwerte-2 ;drei s.Werten ret c ;* ret chv6: ld de,(ehead) ;Pruefung ehead <= head max ld hl,hd$head-1 sbc hl,de jr nc,chv7 ld hl,hd$head-1 ld (ehead),hl ld a,b ;ausser bei den ersten cp iwerte-2 ;drei s.Werten ret c ;* ret ;Fehler ; Pruefung Sector ; Sonderfall wenn endcyl=startcyl und endhead=starthead chv7: ld hl,0 ld (esmin),hl ld hl,(ecyl) ;scyl und ecyl muessen gueltig sein ld de,(scyl) sbc hl,de jr nz,chv8 ld hl,(ehead) ld de,(shead) xor a sbc hl,de jr nz,chv8 ;wenn scyl=ecyl und shead=ehead ld hl,(ssector) ld (esmin),hl ;Minimum sector setzen, da sonst ruecklauefig chv8: ld de,(ssector) ld hl,sector$nmb-1 xor a ;Pruefung ssector <= sector max sbc hl,de jr nc,chv9 ld hl,0 ;Fehler ssector > sector max ld (ssector),hl ret ;Fehlerausgang chv9: ;Pruefung esector >= sector min ld de,(esmin) ld hl,(esector) sbc hl,de jr nc,chv10 ld (esector),de ;Fehler ld a,b ;ausser bei den ersten cp iwerte-2 ;drei s.Werten ret c ;* ret chv10: ld de,(esector) ;Pruefung esector <= sector max ld hl,sector$nmb-1 sbc hl,de jr nc,chv11 ld hl,sector$nmb-1 ld (esector),hl ret ;Fehler chv11: ld de,(interleave) ;Pruefung Interleave <= intl.max ld hl,sector$nmb-1 sbc hl,de jr nc,chv12 chv13: ld hl,ilval ld (interleave),hl ret ;Fehler chv12: ld a,e cp 1 jr c,chv13 ;< 1 Fehler ld de,(luninp) ;Pruefung log.unit <= 1 ld hl,1 sbc hl,de jr nc,chv14 ld hl,0 ld (luninp),hl chv14: ;Wiederholungszaehler ld hl,(wdhlg) ld a,h ;fuer r/w Test or a jr z,chv15 ld hl,0ffh ;Wert zu gross ld (wdhlg),hl ;Maximum setzen scf ret chv15: ld a,l ld hl,(wdhmin) cp l jr nc,chv16 ;> Minimum ld a,l ;sonst Minimum setzen chv16: ld (wdhlg),a ret fzmen db 0 db 'Format Cylinder ',0 db 'Read/Write Test ',0 db 'Eingabe Parameter ',0 db 'Ende ',0 fztable: db fzmanz ;Anzahl Eintraege dw zt4 ;no match = Ende db 1 ;Vergleichzahl dw fscyl db 2 dw rwtest db 3 fzt1: dw input fzmanz equ ($-fztable)/3 ztest: fenster G,9,8,28,6,'ZERSTOERENDER TEST',2,1,fzmanz,1 ld hl,fzmen ld de,Gst ld bc,(Ganz) call select ;Auswahl ld a,fzmanz cp c jr z,zt3 push bc ;hier Ergebnisfenster fuer die ;Teste oeffnen fenster H,40,5,50,25,'TEST' pop bc jr zt1 zt2: ;wiederholter Aufruf ld a,(Gnr) ;wenn Fenster bereits eroeffnet call wselect ;und Menuetext geschrieben ld bc,(Ganz) ld de,Est ld hl,fzmen call select1 zt1: ld (Ganz),bc ld a,c ld de,fztable call acase3 ;Verzweigung entsprechend select jp zt2 ;Return vom aufgerufenen Up zt4: pop hl ;Return Adresse call wclose ;vernichten ld a,(knr) or a ;Parameter Fenster da? jr z,zt3 ;nein call wclose ;ja, schliessen ld hl,input ;Umleitung aufheben ld (fsm1),hl ld (fzt1),hl xor a ld (knr),a ;Ergebnisfenster bereits geschlossen zt3: call wclose ;Menue Fenster ebenfalls schliessen ret ;Cursor letzte Zeile und Warten auf beliebige Taste wjn: call carreturn ld b,15 wjn1: call cursordown djnz wjn1 ; call eraselineend ld hl,twjn call writetext ld c,6 ld e,0fdh jp bdos twjn: db ' weiter mit beliebiger Taste',0 ;Menue Auswahl ;Eingang Pointer Texte ; x,y Koordinate ; Anzahl Textzeilen ; Ordnungsnr. Auswahl xykoord: dw 0 ptexte: dw 0 count: dw 0 select: ld (xykoord),de ld (ptexte),hl ld (count),bc sel1: ex de,hl call cursorat ex de,hl call stext call writetext inc e djnz sel1 jr selloop select1: ;zweiter Eingang ;wenn Fenster bereits eroeffnet ;und Menuetext geschrieben ld (xykoord),de ld (ptexte),hl ld (count),bc selloop: ld a,b cp c call nz,mark ;Auswahl alt <> aktuell push bc ld c,6 ld e,0fdh call bdos pop bc cp 'M'-'@' ;Cr? jr nz,sel4 ld a,(count+1) ld b,a ret sel4: cp 'E'-'@' ;Cursor auf jr nz,sel3 dec c jr nz,selloop ;Auswahl = max setzen ld a,(count+1) ld c,a jr selloop sel3: cp 'X'-'@' ;Cursor ab jr nz,selloop inc c ld a,(count+1) cp c jr nc,selloop ld c,1 jr selloop ;Markierung der angewaehlten Funktion ; Auswahl alt ; Auswahl aktuell mark: xor a cp b jr z,mark1 ;Auswahl alt nicht vorhanden ld hl,(xykoord) ld a,l add a,b dec a ld l,a call cursorat ld hl,(ptexte) mark2: call stext djnz mark2 call normal call writetext mark1: ld hl,(xykoord) ld a,l add a,c dec a ld l,a call cursorat call reverse ld hl,(ptexte) ld b,c mark3: call stext djnz mark3 call writetext call normal ld b,c ret ;Ausgabe via Window mit Steuerzeichen im String ;ersetzt Routine epstr aus der SYSLIB dseg wpuf ds 96 cseg epstr: push bc push de ld b,0 ;Zaehler Stringlaenge ld de,wpuf push hl epsl: pop hl eps4: ld a,(hl) inc hl cp 20h ;Steuerzeichen? jr c,epsst ld (de),a inc de inc b jr eps4 epsst: push af ;Zeichen merken ld a,b or a ;Zeichen im Puffer? jr z,eps1 ;nein xor a ;Puffer leeren ld (de),a ;Endemarkierung ld de,wpuf ;Stringanfang ex de,hl call writetext ex de,hl ld b,0 ;Zaehler 0 eps1: pop af or a jr nz,eps2 pop de ;Ausgang bei Endemarkierung pop bc ret eps2: push hl cp 0dh jr nz,eps3 call carreturn ;CR jr epsl eps3: cp 0ah jr nz,epsl call linefeed ;LF jr epsl mfmen db 0 db 'Edit defect list ',0 db 'Format Drive ',0 db 'Format Alternate Track ',0 db 'Ende ',0 mftable: db mfmanz ;Anzahl Eintraege dw mform5 ;no match = Ende db 1 dw defedit db 2 ;Vergleichzahl dw format db 3 dw fsalt mfmanz equ ($-mftable)/3 mformat: fenster I,9,8,28,6,'FORMATIERE DRIVE',2,1,mfmanz,1 ld hl,mfmen ld de,Ist ld bc,(Ianz) call select ;Auswahl mform4: ld a,mfmanz cp c jr z,mform1 ;Ende ? ld a,1 ;Kennung defedit cp c jr z,mform1 push bc ;hier Ergebnisfenster fuer die ;Teste oeffnen fenster J,40,5,50,25,'FORMAT' pop bc jr mform1 mform2: ld a,(Inr) ;wenn Fenster bereits eroeffnet call wselect ;und Menuetext geschrieben ld bc,(Ianz) ld de,Ist ld hl,mfmen call select1 ld a,(jnr) ;Ergebnisfenster eroeffnet? or a jr z,mform4 ;nein mform1: ld (Ianz),bc ld a,c ld de,mftable call acase3 ;Verzweigung entsprechend select jp mform2 ;Return vom aufgerufenen Up mform5: pop hl ;Return von Ende call wclose ;Ergebnis-Fenster schliessen mform3: ld a,(jnr) or a ret z xor a ;als geloescht markieren ld (jnr),a ;hier wichtig wegen Untermenue DEFEKT call wclose ;Menue Fenster ebenfalls schliessen ret include HDDEF.MAC include HDLOWLEV.MAC include HDFUNKT.MAC dseg ds 100 stack: cseg end startutl include HDDEF.MAC include HDLOWLEV.MAC include HDFUNKT.