;---------------------------------------------------------------------- ; *** PROGRAMMIERUNG DER WDC-KARTE *** ; *** Hard-Disk (Winchester) *** ;---------------------------------------------------------------------- ; CPU Z80A, CTC, 8K PROM, 6K RAM, Host-Schnittstelle, Disk-Schnittstelle ; Programmierung fuer die Arbeit mit bis zu drei Laufwerken ;---------------------------------------------------------------------- begin 0 jr entry string text 'WDC_4.2' sc_len equ 512 ;Laenge des Datenfeldes eines Sektors (Byte) ; I/O-Adressen CTC equ 70h ;Grundadresse des CTC DSKEA equ 08h ;Disk-Endadresse (8282) CNTST equ 18h ;Steuer- und Statusport (OUT-Port, 8212) BM_T equ 28h ;Port fuer die Ausgabe des Taktbitmuster fuer Marken BM_D equ 38h ;Port fuer die Ausgabe des Datenbitmusters fuer Marken DSKC1 equ 48h ;Disk-Schnittstellenport 1 (8282) DSKC2 equ 58h ;Disk-Schnittstellenport 2 (8212) IMPAUS equ 68h ;Port zum Ausschalten der DSS IMPATV equ 78h ;Impuls /ATV (Anzeige Takt vorwaerts) ST_PRT equ 88h ;Status-Port (IN-Port, DL541) ;----------------------------------------------------------------------------- ; PROM-Adressen ;----------------------------------------------------------------------------- crc_0 equ 1ff8h ;CRC-Wert EPROM 0 crc_0n equ 1ffah ;CRC-Wert EPROM 0 negiert crc_1 equ 1ffch ;CRC-Wert EPROM 1 crc_1n equ 1ffeh ;CRC-Wert EPROM 1 negiert ;----------------------------------------------------------------------------- ; RAM-Adressen ;----------------------------------------------------------------------------- ; Adressen aus dem Lese-Schreibbereich ram equ 2000h ;Anfangsadresse RAM dt equ 2ff5h ;Anfangsadresse fuer die Datenbereiche ; Stackbereich stk_br equ 3080h ; Startadressentabelle fuer ISR (CTC-Kanaele 0, 1, 2, 3) isr_mk equ 30a0h isr_dk equ 30a2h isr_hs equ 30a4h isr_ix equ 30a6h ; Kommandoeingabebereich cmd_br equ 30bfh ; Fehlerausgabe err_br equ 30c7h ;-------- Parametertabelle (vom Laufwerk) ------------------------------ p_str equ 30d0h ;8 Byte, Firmware-Version (aus string) p_blk equ 30d8h ;13 Byte, Beschreibung Laufwerkstyp ;1 Byte frei ;1 Byte frei cyls equ 30e7h ;2 Byte, Zylinderanzahl hds equ 30e9h ;1 Byte, Kopfanzahl secs equ 30eah ;1 Byte, Sektoranzahl pre_cy equ 30ebh ;2 Byte, Zylindernummer der Praekompensation rp_mod equ 30edh ;1 Byte, Ramp-Mode-Einschaltung ;6 Byte frei ztk_40 equ 30f4h ;1 Byte, Zeitkonstante Formatieren 40 MHz ztk_41 equ 30f5h ;1 Byte, Zeitkonstante formatieren 41,4 Mhz zmn_40 equ 30f6h ;1 Byte, u. Grenze fuer Zeitm. IX-Impulse 40 MHz zmx_40 equ 30f7h ;1 Byte, o. Grenze fuer Zeitm. IX-Impulse 40 MHz zmn_41 equ 30f8h ;1 Byte, u. Grenze fuer Zeitm. IX-Impulse 41,4 MHz zmx_41 equ 30f9h ;1 Byte, o. Grenze fuer Zeitm. IX-Impulse 41,4 MHz ;-------- Ende der Parametertabelle ------------------------------------ bl_dr0 equ 3115h ;2 Byte, Anzahl der Bloecke auf einem LW (Low) bl_dr1 equ 3117h ;2 Byte, Anzahl der Bloecke auf einem LW (High) bl_zyl equ 3119h ;2 Byte, Anzahl der Bloecke auf einem Zyl (Low) bl_zyh equ 311bh ;2 Byte, Anzahl der Bloecke auf einem Zyl (High) ;1 Byte frei ;1 Byte frei sav_fb equ 311fh ;1 Byte, Rettungsbyte fuer FB l_inc equ 3120h ;1 Byte, Spurinkrementierungen bei Mehrblockzugr. c_s_ix equ 3121h ;1 Byte, Zaehler fuer erlaubte falsche Sektor- ;nummern nach Index hst_bl equ 3122h ;1 Byte, Blockzaehler fuer HS-Treiber hst_by equ 3123h ;1 Byte, Besetztanzeiger fuer HS-Treiber ident equ 3124h ;7 Byte, Kennfeld FE CY CY HD SC CRC CRC cnt_st equ 312bh ;1 Byte, Ausgabebyte fuer CNTST dsk_c1 equ 312ch ;1 Byte, Ausgabebyte fuer DSKC1 dsk_c2 equ 312dh ;1 Byte, Ausgabebyte fuer DSKC2 ch_cyl equ 312eh ;1 Byte, Zylinderwechsel waehrend eines Zugriffs err_in equ 312fh ;1 Byte, Fehler waehrend der Initialisierung dt_len equ 3130h ;2 Byte, Datenlaenge (Zwischenspeicher) rd_mod equ 3132h ;1 Byte, Modus beim Lesen k_flg equ 3133h ;1 Byte, Steuerung der Sektorsuche sc_akt equ 3134h ;1 Byte, angeforderte Sektornummer (beim Schreiben) ;2 Byte frei s_rdy equ 3137h ;1 Byte, 'Soft'-Ready-Byte (PAR- & BTT-Zustand) d_rdy equ 3138h ;1 Byte, Ready-Byte fuer Laufwerke ctc_st equ 3139h ;1 Byte, CTC-Programmierwort (Kanal2) sc_cnt equ 313ah ;1 Byte, Sektorzaehler ; Steuerbytes fuer die Disk-Schnittstelle cl_crc equ 317ah ;1 Byte st_ina equ 317bh ;1 Byte st_akt equ 317ch ;1 Byte st_min equ 317dh ;1 Byte st_vb equ 317eh ;1 Byte st_dak equ 317fh ;1 Byte st_wa equ 3180h ;1 Byte st_wm equ 3181h ;1 Byte st_wc equ 3182h ;1 Byte d_akt equ 3183h ;1 Byte d_inak equ 3184h ;1 Byte men_ia equ 3185h ;1 Byte ; Disk-Adresszaehler dsk_ad equ 3186h ;2 Byte dsk_az equ 3188h ;2 Byte ; Durchlaufzaehler fuer Formatieren dl_f equ 3192h ;1 Byte dl_r equ 3193h ;1 Byte ; Tabelle der Zylinderpositionen der Laufwerke cy_tab equ 3194h ;6 Byte ; Fehlercode und Fehlerzaehlerinitialisierung err_cd equ 31a0h ;1 Byte, Fehlercode c_zt equ 31a1h ;1 Byte c_cd equ 31a2h ;1 Byte c_sc equ 31a3h ;1 Byte c_ci equ 31a4h ;1 Byte c_cj equ 31a5h ;1 Byte c_fb equ 31a6h ;1 Byte c_ki equ 31a7h ;1 Byte ; Fehlerzaehler ; Keine Marken erkannt (Zeitueberwachung) sum_zt equ 31aah mx_zt equ 31ach max_zt equ 31adh ct_zt equ 31aeh ; CRC-Fehler im Identifier(1) sum_ck equ 31afh mx_ck equ 31b1h max_ck equ 31b2h ct_ck equ 31b3h ; CRC-Fehler im Identifier(2) sum_cj equ 31b4h mx_cj equ 31b6h max_cj equ 31b7h ct_cj equ 31b8h ; Falsche Sektornummern (nach Distanzinterrupt) sum_sc equ 31b9h mx_sc equ 31bbh max_sc equ 31bch ct_sc equ 31bdh ; Kein richtiges Kennfeld sum_ki equ 31beh mx_ki equ 31c0h max_ki equ 31c1h ct_ki equ 31c2h ; Falsches Datenfeldkennzeichen nach richtigem Kennfeld sum_fb equ 31c3h mx_fb equ 31c5h max_fb equ 31c6h ct_fb equ 31c7h ; CRC-Fehler im Datenfeld sum_cd equ 31c8h mx_cd equ 31cah max_cd equ 31cbh ct_cd equ 31cch ; Schreibwiederholungen bei 'Read after Write' sum_ra equ 31cdh mx_ra equ 31cfh max_ra equ 31d0h ct_ra equ 31d1h ; Falsche Sektornummer beim Schreiben sum_wi equ 31d2h mx_wi equ 31d4h max_wi equ 31d5h ct_wi equ 31d6h ; 'Fault Write'-Fehler sum_fw equ 31d7h mx_fw equ 31d9h max_fw equ 31dah ct_fw equ 31dbh ; Zugriffszaehler z_cnt equ 31dch ;10 Byte fuer Zugriffsanzahl,beginnend mit 'lowest' ; Fehlerzaehler fuer das Testlesen t_cnt equ 31f0h t_kf equ 31f1h f_0f equ 31f2h f_ebit equ 31f3h f_ausr equ 31f4h f_unkl equ 31f5h f_ande equ 31f6h f_eb equ 31f7h ; Blockverwaltung p_kf equ 31f8h ;2 Byte, Zeiger im 'kf-Feld' p_dt equ 31fah ;2 Byte, Zeiger im 'dt-Feld' kf_br equ 31fch ;2 Byte, aktuelle Anfangsadresse von kf dt_br equ 31feh ;2 Byte, aktuelle Anfangsadresse von dt ; Defektspurtabellen der Laufwerke df_end equ 3200h ;2 Byte, Adresse des aktuellen Werts von dfendx df_tab equ 3202h ;2 Byte, Adresse des aktuellen Werts von dftabx dfend0 equ 3204h ;2 Byte, Ende-Adresse der BTT fuer LW0 dftab0 equ 3206h ;120(78h) Byte, BTT des LW0 (40*3 Byte Laenge) ; 327eh ;3 Byte, Bereich fuer moegliches Endekennzeichen dfend1 equ 3281h ;2 Byte, Ende-Adresse der BTT fuer LW0 dftab1 equ 3283h ;120(78h) Byte, BTT des LW1 (40*3 Byte Laenge) ; 32fbh ;3 Byte, Bereich fuer moegliches Endekennzeichen dfend2 equ 32feh ;2 Byte, Ende-Adresse der BTT fuer LW0 dftab2 equ 3300h ;120(78h) Byte, BTT des LW2 (40*3 Byte Laenge) ; 3378h ;3 Byte, Bereich fuer moegliches Endekennzeichen ; Hilfsgroessen fuer die Zeitkonstantenbestimmung beim Formatieren ztk equ 3380h ;1 Byte, Zeitkonstante ztk_f equ 3381h ;8 Byte, Feld fuer Hilfsgroessen ; Rettungsbereich s_prae equ 3590h ;10h Byte fuer Praeambelbereich (Schreiben) s_post equ 35a0h ;10h Byte fuer Postambelbereich (Schreiben) sav_20 equ 35b0h ;20h Byte 36b0...36cf fs_tab equ 35e0h ;20h Byte (32), Sektorfolge fuer Formatieren ; 3600h bis 378fh Bereich fuer Sektorkennfelder kf_top equ 3600h kf equ 3603h ; Bereiche fuer das Umladen von Zugriffszaehler und Fehlerzellen s_zcnt equ 37c0h ;10 Byte, Zugriffszaehler s_errz equ 37cah ;50 Byte, Fehlerzellen eject ;-------------------------------------------------------- ; Systemanlauf und Initialisierungen ;-------------------------------------------------------- entry ld sp,stk_br+1 ; Test der CRC-Werte fuer beide EPROM's ld hl,(crc_0) ;CRC-Wert fuer 1.EPROM ld de,(crc_0n) ;negierter CRC-Wert add hl,de inc hl ld a,h or l jp nz,err_pr ld hl,(crc_1) ;CRC-Wert fuer 2.EPROM ld de,(crc_1n) ;negierter CRC-Wert add hl,de inc hl ld a,h or l jp nz,err_pr ld hl,0 ;Anfangsadresse 1.EPROM ld bc,1000h ;4K Byte call crc_br ;CRC-Berechnung ld hl,(crc_0) ;abgelegter CRC-Wert fuer 1.EPROM ld a,d ld d,e ld e,a xor a sbc hl,de jp nz,err_pr ld hl,1000h ;Anfangsadresse 2. EPROM ld bc,0ff8h ;4K Byte - 8 call crc_br ;CRC-Berechnung ld hl,(crc_1) ;abgelegter CRC-Wert fuer 2. EPROM ld a,d ld d,e ld e,a xor a sbc hl,de jp z,crc_ok err_pr ld a,06h ;Status 6 out (CNTST),a ;Statusausgabe halt ; Umladen Zugriffszaehler crc_ok ld de,s_zcnt ld hl,z_cnt ld bc,10 ldir ; Umladen Fehlerzellen ld hl,ct_fw ld bc,sum_zt xor a sbc hl,bc inc hl push hl pop bc ld de,s_errz ld hl,sum_zt ldir ; Loeschen Gesamt-RAM ld hl,2000h ld de,2001h ld (hl),081h ld bc,017bfh ldir ; Interrupt-Initialisierung ld hl,isr_mk ld a,h ld i,a ;High-Teil Interruptvektor im 2 ei ld a,3 ;Reset fuer die CTC-Kanaele out (CTC),a out (CTC+1),a out (CTC+2),a out (CTC+3),a ld a,l ;Low-Teil Interruptvektor out (CTC),a ; ISR-Tabelle initialisieren ld hl,isr_m1 ld (isr_mk),hl ld hl,isr_al ld (isr_dk),hl ld hl,isr_h0 ld (isr_hs),hl ld hl,isr_al ld (isr_ix),hl ; Loeschen Zugriffszaehler ld b,10 ld hl,z_cnt cl_zc ld (hl),0 inc hl djnz cl_zc ; Loeschen Fehlercode und Fehlerzellen xor a ld (err_in),a ld (err_cd),a ld (s_rdy),a ld hl,ct_fw ;Ende der Fehlerzellen ld bc,sum_zt ;Beginn der Fehlerzellen sbc hl,bc ld b,l inc b ld hl,sum_zt xor a cl_sum ld (hl),a inc hl djnz cl_sum ; Loeschen Zeitkonstante und Hilfsfeld (Formatierungshilfsmittel) ld b,9 xor a ld hl,ztk cl_ztk ld (hl),a inc hl djnz cl_ztk ; Loeschen Besetztzeiger und Blockzaehler des HS-Treibers ld (hst_by),a ld (hst_bl),a ; Initialisieren 'cnt_st' fuer CNTST (nach Reset) ld a,0 ;Status '0' nach Reset (8212 hat CLR-Eingang) ld (cnt_st),a ; Initialisieren 'dsk_c2' fuer DSKC2 ld a,92h ;FR & Harddisk & Select0 & 'DEN=inaktiv' ; & 'MEN=inaktiv' & 'CRCEN=inaktiv' ; & 'WG=inaktiv' out (DSKC2),a ld a,12h ;FR ruecksetzen ld (dsk_c2),a out (DSKC2),a ; Initialisieren 'dsk_c1' fuer DSKC1 ld a,0 ;HS0 & 'SD=inaktiv' (nach aussen) ; & 'STEP=inaktiv' & Motor aus & 'HL=inaktiv' ld (dsk_c1),a out (DSKC1),a ; Loeschen der Positionstabelle ld hl,-1 ld (cy_tab),hl ld (cy_tab+2),hl ld (cy_tab+4),hl ;-------------------------------------------------------- ; Bestimmung der DSKC2-Steuerbytes (DEN, MEN, CRCEN, WG) ;-------------------------------------------------------- ld a,(dsk_c2) and 0f0h ld b,a ;alle Steuerbits = 0 ; Steuerbytes fuer das Lesen ('WG=inaktiv') or 7 ;'DEN=aktiv' & 'MEN=inaktiv' & 'CRCEN=aktiv' ld (cl_crc),a ;Steuerbits zum CRC-Loeschen auf 'ff' ld a,b or 2 ;alles inaktiv ld (st_ina),a ;Steuerbits zum Abschalten der Schnittstelle ld a,b or 5 ;alles aktiv ld (st_akt),a ;Steuerbits zur Aktivierung der Markenerkennung ld a,b or 7 ;'MEN=inaktiv' & 'DEN=aktiv' & 'CRCEN=aktiv' ld (st_min),a ;Steuerbits fuer den CRC-Test ld a,b or 3 ;'MEN=inaktiv' & 'DEN=aktiv' & 'CRCEN=inaktiv' ld (st_dak),a ;Steuerbits waehrend langer Transfers ld a,b or 4 ;'DEN=inaktiv' & 'CRCEN=aktiv' & 'MEN=aktiv' ld (st_vb),a ;Steuerbits fuer die Vorbereitung der ;inaktiven Disk-Ansteuerung ; Steuerbytes fuer das Schreiben ('WG=aktiv') set 3,b ;'WG=aktiv' ld a,b or 0dh ld (st_wa),a ;alles aktiv ld a,b or 0bh ;'DEN=aktiv' & 'MEN=inaktiv' & 'CRCEN=inak' ld (st_wm),a ld a,b or 0fh ;auch 'CRCEN'=aktiv ld (st_wc),a ; Initialisierung der Parametertabelle mit vorlaeufigen Werten ld hl,100 ld (cyls),hl ld (pre_cy),hl ld a,2 ld (hds),a ld a,18 ld (secs),a ld a,1 ld (rp_mod),a ; Initialisierung von 'kf_br' und 'dt_br' ld hl,kf ld (kf_br),hl ld hl,dt ld (dt_br),hl ; Berechnung des Disk-Adresszaehlers fuer das Kennfeld ld hl,(kf_br) call b_daz ld (dsk_ad),hl ;------------------------------------------------- ; Ready-Test der angeschlossenen Laufwerke ;------------------------------------------------- ; Loeschen Ready-Byte ld a,87h ;INIT-Bit gesetzt ld (d_rdy),a ; Ready-Test Laufwerk 0 (mit Abwarten der Startzeit) ld b,30 ;max. Startzeit (in sec.) inc b inc b ld a,12h out (DSKC2),a ;Select LW0 rdy0 in a,(ST_PRT) bit 2,a jr z,rdy1 ;Sprung, wenn "ready" ld de,100 ;100 * 10ms = 1s call time2 ;ca 10 ms djnz rdy0 ld hl,d_rdy ;Ready-Byte res 0,(hl) ;LW nicht "ready" ; Ready-Test Laufwerk 1 (mit Abwarten der Restzeit) rdy1 ld b,2 ld a,22h out (DSKC2),a ;Select LW1 rdy11 in a,(ST_PRT) bit 2,a jr z,rdy2 ;Sprung, wenn "ready" ld de,100 ;100 * 10ms = 1s call time2 ;ca 10 ms djnz rdy11 ld hl,d_rdy ;Ready-Byte res 1,(hl) ;LW nicht "ready" ; Ready-Test Laufwerk 2 (mit Abwarten der Restzeit) rdy2 ld b,2 ld a,32h out (DSKC2),a ;Select LW2 rdy21 in a,(ST_PRT) bit 2,a jr z,rdy_ok ;Sprung, wenn "ready" ld de,100 ;100 * 10ms = 1s call time2 ;ca 10 ms djnz rdy21 ld hl,d_rdy ;Ready-Byte res 2,(hl) ;LW nicht "ready" rdy_ok ld hl,d_rdy ld a,(hl) cp 80h ;kein LW "ready" ? jr nz,posit0 set 6,(hl) ;ERR_IN-Bit setzen jp begin ;------------------------------------------------------- ; Positionieren der Koepfe der Ready-Laufwerke auf Zyl 0 ;------------------------------------------------------- ; Richtung der Kopfbewegung posit0 ld a,(dsk_c1) res 3,a ;SD nach aussen ld (dsk_c1),a out (DSKC1),a ; Laufwerk 0 ld hl,d_rdy bit 0,(hl) jp z,p_lw1 ld a,12h out (DSKC2),a call pos_t0 jr z,p_lw00 ld hl,d_rdy set 3,(hl) ;Zyl 0 bei LW 0 nicht erreicht res 0,(hl) ;READY-Bit fuer LW 0 ruecksetzen set 6,(hl) ;Fehler waehrend der Initialisierung jr p_lw1 p_lw00 ld hl,0 ;Kopfposition eintragen ld (cy_tab),hl ; Laufwerk 1 p_lw1 ld hl,d_rdy bit 1,(hl) jp z,p_lw2 ld a,22h out (DSKC2),a call pos_t0 jr z,p_lw10 ld hl,d_rdy set 4,(hl) ;Zyl 0 bei LW 1 nicht erreicht res 1,(hl) ;READY-Bit fuer LW 1 ruecksetzen set 6,(hl) ;Fehler waehrend der Initialisierung jr p_lw2 p_lw10 ld hl,0 ;Kopfposition eintragen ld (cy_tab+2),hl ; Laufwerk 2 p_lw2 ld hl,d_rdy bit 2,(hl) jp z,t0_ok ld a,32h out (DSKC2),a call pos_t0 jr z,p_lw20 ld hl,d_rdy set 5,(hl) ;Zyl 0 bei LW 2 nicht erreicht res 2,(hl) ;READY-Bit fuer LW 2 ruecksetzen set 6,(hl) ;Fehler waehrend der Initialisierung jr t0_ok p_lw20 ld hl,0 ;Kopfposition eintragen ld (cy_tab+4),hl t0_ok ;---------------------------------------------------------------- ; Lesen der Sektoren 0/0/1 der Laufwerke ; Ueberpruefung der Parameter- und der Defektspurtabellen ;---------------------------------------------------------------- ; Laufwerk 0 ld hl,d_rdy ;Ready-Byte bit 0,(hl) jp z,df_1 ld hl,cl_crc ;Tabelle der Steuerbytes der DSS ld b,9 ld c,10h ;Select LW0 sdf0 ld a,(hl) and 0fh ;Loeschen der Select-Bits or c ld (hl),a inc hl djnz sdf0 ld a,0 ld (cmd_br-7),a ;LW im Kommandobereich call def_ad call rd_dfk ;Lesen des Sektors 0/0/1 jr nz,df_00 ;Sprung, wenn Lesefehler call t_par ;Ueberpruefung der Parametertabelle jr nz,df_01 call v_par ;Umladen der Parameter ld hl,s_rdy set 0,(hl) jr df_03 df_01 ld hl,err_in set 3,(hl) ld hl,d_rdy set 6,(hl) ;ERR_IN-Bit setzen jr df_1 df_03 call t_btt ;Ueberpruefung der BTT jr nz,df_02 call v_btt ;Umladen der BTT ld hl,s_rdy set 3,(hl) jr df_1 df_02 ld hl,err_in set 3,(hl) ld hl,d_rdy set 6,(hl) jr df_1 df_00 ld hl,err_in set 0,(hl) ld hl,d_rdy set 6,(hl) ; Laufwerk 1 df_1 ld hl,d_rdy ;Ready-Byte bit 1,(hl) jp z,df_2 ld hl,cl_crc ;Tabelle der Steuerbytes der DSS ld b,9 ld c,20h ;Select LW1 sdf1 ld a,(hl) and 0fh ;Loeschen der Select-Bits or c ld (hl),a inc hl djnz sdf1 ld a,1 ld (cmd_br-7),a ;LW im Kommandobereich call def_ad call rd_dfk ;Lesen des Sektors 0/0/1 jr nz,df_10 call t_par ;Ueberpruefung der Parameter jr nz,df_11 ;Sprung, wenn Fehler ld hl,s_rdy bit 0,(hl) jr z,df_12 call parram ;Uebereinstimmung PAR mit RAM-Eintrag ? jr z,df_13 ;Sprung, wenn PAR ok df_11 ld hl,err_in set 4,(hl) ld hl,d_rdy set 6,(hl) ld hl,s_rdy bit 0,(hl) jr nz,df_14 jr df_2 df_12 call v_par ;Umladen der Parameter df_13 ld hl,s_rdy set 1,(hl) df_14 call t_btt ;Ueberpruefung der BTT jr nz,df_15 call v_btt ld hl,s_rdy set 4,(hl) jr df_2 df_15 ld hl,err_in set 4,(hl) ld hl,d_rdy set 6,(hl) jr df_2 df_10 ld hl,err_in set 1,(hl) ld hl,d_rdy set 6,(hl) ; Laufwerk 2 df_2 ld hl,d_rdy ;Ready-Byte bit 2,(hl) jp z,df_3 ld hl,cl_crc ;Tabelle der Steuerbytes der DSS ld b,9 ld c,30h ;Select LW2 sdf2 ld a,(hl) and 0fh ;Loeschen der Select-Bits or c ld (hl),a inc hl djnz sdf2 ld a,2 ld (cmd_br-7),a ;LW im Kommandobereich call def_ad call rd_dfk ;Lesen des Sektors 0/0/1 jp nz,df_20 call t_par ;Ueberprufung der Parameter jr nz,df_22 ld hl,s_rdy bit 0,(hl) jr nz,df_21 bit 1,(hl) jr nz,df_21 call v_par ;Eintragen der Parameter df_23 ld hl,s_rdy set 2,(hl) jr df_24 df_21 call parram ;Uebereinstimmung mit eingetr. Par. ? jr z,df_23 df_22 ld hl,err_in set 5,(hl) ld hl,d_rdy set 6,(hl) ld hl,s_rdy bit 0,(hl) ;PAR-Bit-LW0 jr nz,df_24 ;Sprung, wenn PAR-Tab von LW0 ok bit 1,(hl) ;PAR-Bit-LW1 jr z,df_3 ;Sprung, wenn PAR-Tab von LW1 nicht ok df_24 call t_btt ;Ueberpruefung der BTT jr nz,df_25 call v_btt ;Umladen der BTT ld hl,s_rdy set 5,(hl) jr df_3 df_25 ld hl,err_in set 5,(hl) ld hl,d_rdy set 6,(hl) jr df_3 df_20 ld hl,err_in set 2,(hl) ld hl,d_rdy set 6,(hl) df_3 ;--------------------------------------------------- ; Bestimmung 'Anzahl Bloecke pro Zylinder' ; und 'Anzahl Bloecke pro Laufwerk' ;--------------------------------------------------- ld hl,0 ld a,(hds) ;Anzahl Koepfe ld b,a ld d,0 ld a,(secs) ;Blockanzahl pro Spur ld e,a ld a,0 blz0 add hl,de jr nc,blz1 inc a blz1 djnz blz0 ld (bl_zyl),hl ld (bl_zyh),a ld hl,0 ld (bl_dr0),hl ld (bl_dr1),hl ld d,0 ld a,(secs) ;Blockanzahl pro Spur ld e,a ld hl,(cyls) ;Zylinderanzahl pro Laufwerk dec hl blz4 push hl ld a,(hds) ;Spuranzahl pro Zylinder ld b,a blz2 ld hl,(bl_dr0) add hl,de ld (bl_dr0),hl jr nc,blz3 xor a ld hl,(bl_dr1) inc hl ld (bl_dr1),hl blz3 djnz blz2 pop hl dec hl ld a,h or l jp nz,blz4 ld hl,bl_dr0 ;Lowest ld b,4 d_bl dec (hl) ld a,(hl) cp 0ffh jr nz,d_bn inc hl djnz d_bl d_bn jp begin ;--- pos_t0 ------------------------------------ ; Schrittweises Zurueckfahren der Koepfe auf Zyl 0 ; Rueckkehr: Z ok. ; NZ Fehler ;------------------------------------------------- pos_t0 ld hl,3000 ;mehr als Max von Zylindern wt_see ld bc,400 ;max. 400 ms warten auf SEEKC wt_se1 in a,(ST_PRT) ;Lesen des Statusports bit 3,a ;'SEEKC=aktiv' ? jr z,rd_stp ;Sprung, wenn 'SEEKC=aktiv' ld de,1 call time1 ;ca. 1 ms dec bc ld a,b or c jr nz,wt_se1 inc a ;Rueckkehr mit Fehler (nz) ret ;Rueckkehr mit Fehler rd_stp in a,(ST_PRT) ;Lesen des Statusports bit 6,a ;'T0=aktiv' ? ret z ;Rueckkehr ok. ld a,(dsk_c1) set 0,a ;'ST=aktiv' out (DSKC1),a res 0,a ;'ST=inaktiv' out (DSKC1),a dec hl ld a,h or l jr nz,wt_see inc a ret ;Rueckkehr mit Fehler (nz) ;---------------------------- ; Ausfuehrung eines Schrittes ; HL: Schrittanzahl ;---------------------------- ramp ld a,(dsk_c1) ;Ausgabebyte fuer DSKC1 xor 1 ;Step-Impuls ein out (DSKC1),a xor 1 ;Step-Impuls aus out (DSKC1),a dec hl ld a,h or l jr nz,ramp ret si_step ld a,(dsk_c1) ;Ausgabebyte fuer DSKC1 xor 1 ;Step-Impuls ein out (DSKC1),a xor 1 ;Step-Impuls aus out (DSKC1),a dec hl ld a,h or l ret z ld de,150 call time jr si_step ;--- cy_pos --------------------------------------------- ; Bestimmung der Position in 'cy_tab' ; IN : A = Laufwerk ; OUT: HL= Adresse der Eintragung in der Zylindertabelle ;---------------------------------------------------------- cy_pos add a,a ld c,a ld b,0 ld hl,cy_tab ;Positionstabelle add hl,bc ret ;--- rd_dfk ---------------------------------------------- ; Lesen des Sektors der Parameter- und der Defektspurtabelle ;----------------------------------------------------------- rd_dfk ld de,ident ld hl,id_df ld bc,5 ldir ld de,c_zt ld hl,fe_n ld bc,7 ldir ;Setzen der Fehlerzaehler ld hl,200h ld (cmd_br-2),hl ;Laenge festlegen ld (dt_len),hl ld a,0 ld (rd_mod),a ;Lesen von Kenn- und Datenfeld call rd_id ret ;--- t_par ----------------------------------------------------- ; Ueberpruefung der Parametertabelle ; Daten muessen im RAM-Bereich fuer den ersten Sektor stehen ;--------------------------------------------------------------- ; Test auf 'PARMTR' t_par ld hl,(dt_br) ld bc,269 add hl,bc ;erstes Byte der Parametertabelle res 4,h ld de,txt_pm ;Kenntext der Parametertabelle ld b,6 sl_pm ld a,(de) cp (hl) jp nz,t_pare inc hl inc de djnz sl_pm ; Test auf ASCII-Zeichen in der Laufwerksbezeichnung ld b,12 sl_asc ld a,(hl) cp 20h ;unterste Grenze jp c,t_pare ;Fehler cp 7bh ;oberste Grenze + 1 jp nc,t_pare ;Fehler inc hl djnz sl_asc inc hl ; Test der Zylindernummer inc hl inc hl ld a,(hl) ;Zylinder Low inc hl ld h,(hl) ;Zylinder High ld l,a push hl pop de ;Zylinderanzahl push hl ld bc,100 ;mind. 100 Zylinder xor a sbc hl,bc pop hl ;Zylinder jp c,t_pare ld bc,3000 ;max. 3000 Zylinder xor a sbc hl,bc jp nc,t_pare ; Test der Kopfanzahl ld hl,(dt_br) ld bc,292 add hl,bc res 4,h ;HL zeigt Kopfanzahl ld a,(hl) cp 2 ;mind. 2 Koepfe jp c,t_pare cp 17 ;max. 16 Koepfe jp nc,t_pare ; Test der Sektoranzahl inc hl ld a,(hl) ;Sektoranzahl cp 17 jp c,t_pare cp 19 jp nc,t_pare ; Test der Praekompensationseinschaltung inc hl ld a,(hl) inc hl ld h,(hl) ld l,a push hl ;Zylindernummer der Praek. ld bc,0 xor a sbc hl,bc pop hl jp c,t_pare xor a ex de,hl sbc hl,de ;HL enthaelt Zylinderanzahl jp c,t_pare ; Test von 'rp_mod' ld hl,(dt_br) ld bc,296 add hl,bc res 4,h ld a,(hl) cp 1 jp c,t_pare cp 22 jp nc,t_pare ; Test der Zeitkonstanten ld hl,(dt_br) ld bc,303 add hl,bc res 4,h ld a,(hl) ;Zeitkonstante 40 MHz cp 0b0h ;untere Grenze jp c,t_pare inc hl cp (hl) ;Zeitkonstante 41,4 MHz jp nc,t_pare cp 0f1h ;obere Grenze + 1 jp nc,t_pare ; Test der Grenzwerte fuer 40MHz/41,4MHz-Umschaltung inc hl ld b,(hl) ;'zmn_40' inc hl ld a,(hl) ;'zmx_40' cp b jp c,t_pare inc hl ld c,(hl) ;'zmn_41' inc hl ld a,(hl) ;'zmx_41' cp c jp c,t_pare ld a,c ;'zmn_41' sub b ;'zmn_40' jp nc,t_pare xor a ret ;Rueckkehr ok t_pare ld a,1 cp 0 ret ;Fehlerrueckkehr ;--- parram --------------------------------------------------- ; Vergleich der im RAM (3000) eingetragenen Parameter mit den ; von 0/0/1 gelesenen Werten ;-------------------------------------------------------------- parram ld hl,(dt_br) ld bc,275 add hl,bc res 4,h ;Beginn der Inf. im Sektorbereich ld de,p_blk ;Beginn der Inf. im RAM-Bereich ld b,12 prr1 ld a,(de) cp (hl) ret nz inc de inc hl djnz prr1 inc de inc de inc de inc hl inc hl inc hl ld b,19 prr2 ld a,(de) cp (hl) ret nz inc de inc hl djnz prr2 xor a ret ;--- v_par ---------------------------------------------------- ; Umladen der Parametertabelle aus dem Sektorbereich in den ; PAR-RAM-Bereich ;-------------------------------------------------------------- v_par ld hl,(dt_br) ld bc,275 add hl,bc res 4,h ld bc,12 ld de,p_blk ldir inc hl inc hl inc hl xor a inc de ld (de),a inc de ld (de),a inc de ld (de),a ld bc,19 ldir ret ;--- par_v --------------------------------------------------------------- ; Umladen von PAR aus dem 3000-Bereich in den Datenbereich des 1. Sektors ;------------------------------------------------------------------------- par_v ld hl,(dt_br) ld bc,275 add hl,bc res 4,h ex de,hl ld bc,34 ld hl,p_blk ldir ret ;--- btt_cl ---------------------------------------------------------- ; Loeschen der BTT im 3000-RAM ;--------------------------------------------------------------------- btt_cl ld hl,(df_end) ld (hl),0 inc hl ld (hl),0 ld hl,(df_tab) ld b,40*3+3 xor a btt_c1 ld (hl),a inc hl djnz btt_c1 ld hl,(df_tab) ld (hl),0ffh inc hl ld (hl),0ffh inc hl ld (hl),0ffh ret ;--- t_btt -------------------------------------------------------- ; Ueberpruefung der Defektspurtabelle ; Daten muessen im RAM-Bereich fuer den ersten Sektor stehen ;------------------------------------------------------------------ ; Test auf 'DEFEKT' t_btt ld hl,(dt_br) ld bc,13 add hl,bc ;erstes Datenbyte res 4,h ld de,txt_df ;Text der BTT ld b,6 sl_df ld a,(de) cp (hl) jp nz,t_btte inc hl inc de djnz sl_df ; Test, ob Zaehler Vielfaches von 3 t_btt1 ld e,(hl) inc hl ld d,(hl) ;DE: Anzahl der Eintragungen df_dek bit 7,d jp nz,t_btte ld a,d or d jr nz,df_dk1 ld a,e or e jr z,df_ok df_dk1 dec de dec de dec de jr df_dek ; Test auf Maximalwert des Zaehlers df_ok inc hl push hl ;Beginn der BTT-Eintragungen dec hl dec hl ;Anzahl der Eintragungen ld e,(hl) inc hl ld d,(hl) ;DE: Anzahl der belegten Plaetze in der BTT ld hl,40*3 ;Maximum von Eintragungen xor a sbc hl,de pop hl ;Beginn der Eintragungen jp c,t_btte ;Fehler, da Zaehler zu gross ; Test auf richtige Anordnung der Defektspuren push hl add hl,de ;HL: zeigt auf Endekennzeichen push hl push de exx pop de pop hl exx pop hl ;Beginn der Eintragungen ld a,d or e jr z,er_df5 ;keine Eintragungen er_df3 ld d,(hl) ;Zyl high inc hl ld e,(hl) ;Zyl low push de ;Zylinder inc hl inc hl ld b,(hl) ;Zyl high inc hl ld c,(hl) ;Zyl low dec hl dec hl dec hl ;HL zeigt auf Zyl low ex de,hl pop hl ;Zylinder xor a sbc hl,bc ;Zyl - Zyl_nex jr c,er_df4 ;Zyl_nex groesser jp nz,t_btte ;Fehler: Reihenfolge falsch ex de,hl inc hl ld a,(hl) ;Kopf inc hl inc hl inc hl ld b,(hl) ;Kopf_nex sub b ;Kopf - Kopf_nex jp nc,t_btte ;Fehler: Zyl gleich, Kopfreihenfolge falsch dec hl dec hl dec hl dec hl ;HL zeigt auf Zyl low ex de,hl ; Test auf Maximalwert fuer Zylinder er_df4 ex de,hl ;HL zeigt auf Zyl low ld e,(hl) dec hl ld d,(hl) ex de,hl ;HL: Zyl, DE: zeigt auf Zyl high ld bc,(cyls) xor a sbc hl,bc jp nc,t_btte ;Fehler: Zylinder zu gross ; Test auf Maximalwert fuer Kopf ex de,hl inc hl inc hl ld a,(hds) ld b,a ld a,(hl) ;Kopf sub b jp nc,t_btte inc hl ;HL zeigt auf Zyl high exx dec de ;Endetest dec de dec de ld a,d or e exx jp nz,er_df3 ; Test auf Endekennzeichen er_df5 exx push hl exx pop hl ;HL: zeigt auf Endekennzeichen ld a,(hl) cp 0ffh jr nz,t_btte ;Fehler, da kein exaktes Endekennzeichen inc hl cp (hl) jr nz,t_btte ;Fehler, da kein exaktes Endekennzeichen inc hl cp (hl) jr nz,t_btte ;Fehler, da kein exaktes Endekennzeichen xor a ret ;Ruecksprung ok t_btte ld a,1 cp 0 ret ;Fehler-Ruecksprung ;--- v_btt ----------------------------------------------------------- ; Umladen der BTT aus dem Datenbereich des 1. Sektors in den 3000-RAM ;--------------------------------------------------------------------- v_btt ld hl,(dt_br) ld bc,19 add hl,bc res 4,h ld bc,40*3+2+3 ld de,(df_end) ldir ret ;--- btt_v ----------------------------------------------------------- ; Umladen der BTT aus 3000-RAM in den Datenbereich des 1. Sektors ;--------------------------------------------------------------------- btt_v ld hl,(dt_br) ld bc,19 add hl,bc res 4,h ex de,hl ld hl,(df_end) ld bc,40*3+2+3 ldir ret ;--- def_ad --------------------------------------------- ; Bestimmung der aktuellen Adressen der Defektspurtabelle ; cmd_br-7 : Laufwerk ;-------------------------------------------------------- def_ad ld a,(cmd_br-7) ;Laufwerk ld hl,dfend0 ld (df_end),hl ld hl,dfend1 ld de,dfend2 cp 1 jr c,d_adr jr z,d_ad1 ld (df_end),de jr d_adr d_ad1 ld (df_end),hl d_adr ld hl,(df_end) ;Adresse von 'dfendx' inc hl inc hl ld (df_tab),hl ;Adresse des Beginns der aktuellen BTT ret ;--- par_s --------------------------------------------------- ; UP Setzen des PAR-Bits in 's_rdy' fuer das Laufwerk ;------------------------------------------------------------- par_s ld a,(cmd_br-7) ;Laufwerk aus Kommando ld b,a inc b xor a scf par_s1 rla djnz par_s1 ld hl,s_rdy or (hl) ld (s_rdy),a ret ;--- btt_s --------------------------------------------------- ; UP Setzen des BTT-Bits in 's_rdy' fuer das Laufwerk ;------------------------------------------------------------- btt_s ld a,(cmd_br-7) ;Laufwerk aus Kommando ld b,a inc b xor a scf rla rla rla btt_s1 rla djnz btt_s1 ld hl,s_rdy or (hl) ld (s_rdy),a ret ;--- par_r --------------------------------------------------- ; UP Ruecksetzen des PAR-Bits in 's_rdy' fuer das Laufwerk ;------------------------------------------------------------- par_r ld a,(cmd_br-7) ;Laufwerk aus Kommando ld b,a inc b xor a scf par_r1 rla djnz par_r1 cpl ld hl,s_rdy and (hl) ld (s_rdy),a ret ;--- btt_r --------------------------------------------------- ; UP Ruecksetzen des BTT-Bits in 's_rdy' fuer das Laufwerk ;------------------------------------------------------------- btt_r ld a,(cmd_br-7) ;Laufwerk aus Kommando ld b,a inc b xor a scf rla rla rla btt_r1 rla djnz btt_r1 cpl ld hl,s_rdy and (hl) ld (s_rdy),a ret eject begin ;----------------------------------------------------------------------- ; Host-Schnittstelle auf die Eingabe eines Kommandos (9 Byte) einstellen ;----------------------------------------------------------------------- ld bc,9 ;Eingabelaenge ld hl,cmd_br ;Ende des Kommandobereich ld a,1 ;Status '1' call p_h_wc ;Programmierung der Host-Schnittstelle ;--------------------------------------- ; Auswertung des eingelaufenen Kommandos ;--------------------------------------- ; Inkrement Zugriffszaehler ld b,10 ld hl,z_cnt zc_inc inc (hl) jr nz,zc_ok inc hl djnz zc_inc ; Fehler in der Initialisierung ? zc_ok ld hl,d_rdy bit 7,(hl) ;INIT-Bit jr z,not_in ;nicht erste Abfrage nach Initialisierung res 7,(hl) ;INIT-Bit ruecksetzen bit 6,(hl) ;ERR_IN-Bit jr z,not_in ;kein Fehler in der Initialisierung ld a,(hl) and 3fh ;ZY0- und RDY-Bits jr nz,nt_27 ;kein LW "ready" ld a,27h ;kein LW "ready" ld (err_cd),a jp error nt_27 ld a,(hl) and 38h ;ZY0-Bits jr z,inerr ;kein ZY0-Fehler srl a srl a srl a ;Laufwerkscodierung or 28h ;CYL0-Fehler ld (err_cd),a jp error inerr ld hl,err_in ld a,(hl) and 7 ;0/0/1 nicht lesbar jr z,nt_30 or 30h ld (err_cd),a jp error nt_30 ld a,(hl) and 38h ;PAR&BTT-Fehler srl a srl a srl a or 38h ld (err_cd),a jp error ; Loeschen Inkrementierungszaehler not_in xor a ld (l_inc),a ; Warten, bis HS-Treiber frei wt_hst ld hl,hst_by bit 7,(hl) jr nz,wt_hst ; Auswertung des Kommando-Codes ld a,(cmd_br-8) ;Kommandocode cp 21h ;Block lesen ? jr z,t_com cp 22h ;Block schreiben ? jr z,t_com1 ld hl,com_tb ;Tabelle aller Kommandos com_ts cp (hl) jr z,com_ok cp 0ffh ;Endekennzeichen inc hl jr nz,com_ts jp err_1 ;Fehler 1 : falscher Kommandocode com_ok bit 3,a ;WDC-RAM-Kommandos ? jp nz,mv_ok bit 1,a ;HD-Schreiben ? jp z,t_com cp 0c2h ;HD-Schreiben Defektspurtabelle ? jr z,t_com ; Uebernahme der zu schreibenden Daten vom Host t_com1 ld hl,dt ld bc,13 add hl,bc res 4,h ld bc,(cmd_br-2) ;Laenge add hl,bc dec hl ;Endadresse Daten ld a,2 ;Status 2 call p_h_wc ; Datenlaenge umspeichern t_com ld hl,(cmd_br-2) ;Datenlaenge aus Kommando ld (dt_len),hl ; Bestimmung der aktuellen BTT call def_ad ; Einfuegen der Select-Bits in die Steuerbytes der DSS ld a,(cmd_br-7) ;angefordertes Laufwerk and 3 inc a rlca rlca rlca rlca ld c,a ld hl,cl_crc ;Beginn der Steuerbytes ld b,9 einf_d ld a,(hl) and 0fh ;Loeschen der Select-Bits or c ld (hl),a inc hl djnz einf_d ; Laufwerkstest ld a,(d_rdy) ;Ready-Byte ld b,a ld a,(cmd_br-7) ;Laufwerk cp 3 jp nc,err_3 ;max. drei LW moeglich cp 0 jp nz,lt_1 bit 0,b jp z,err_3 jr lt_ok lt_1 cp 1 jr nz,lt_2 bit 1,b jp z,err_3 ;gefordertes LW nicht 'ready' jr lt_ok lt_2 bit 2,b jp z,err_3 ;gefordertes LW nicht 'ready' lt_ok ; weitere Auswertung des Kommandocodes ld a,(cmd_br-8) ;Kommandocode bit 2,a ;Formatier-Kommandos ? jp nz,t_cd3 bit 0,a ;Lese-Kommandos ? jp nz,t_cd bit 1,a ;Schreib-Kommandos ? jp z,mv_ok t_cd bit 5,a ;Blocknummern ? jr z,t_cd1 ; Test der Blocknummer ld hl,cmd_br-3 ;hoechstwertiges Byte im Kommando ld de,bl_dr1+1 ;hoechstwertiges Byte in Blockanzahl ld b,4 t_bn ld a,(de) cp (hl) jr c,bn_err jr nz,bn_ok dec hl dec de djnz t_bn ;------------------------------------------------------------ ; Bestimmung der physischen Sektoradresse aus der Blocknummer ; Blocknummer in cmd_br-6,...,cmd_br-3 (low..high) ; Sektoradresse in ident+1,...,ident+4 ; Blocknummer 0: Zyl 1, Hd 0, Sc 1 ;------------------------------------------------------------ bn_ok ld de,(bl_zyl) ;Anzahl der Bloecke pro Zylinder ; Bloecke auf Zylinder ld bc,(cmd_br-6) ld hl,(cmd_br-4) ld a,17 or a bl2 sbc hl,de jr nc,bl4 add hl,de bl4 ccf rl c rl b adc hl,hl dec a jr nz,bl2 rr h rr l inc bc ld (ident+1),bc ; Bestimmung der Kopfnummer ex de,hl ld hl,ident+3 ;zeigt auf Kopfnummer ld a,(secs) ld c,a ld b,0 ;Sektoranzahl pro Spur ld (hl),-1 ;Loeschen der Kopfnummer bl5 inc (hl) ex de,hl xor a sbc hl,bc ex de,hl jr nc,bl5 ex de,hl ; Bloecke auf Sektoren add hl,bc ;restliche Bloecke ld a,l inc a ld (ident+4),a ld a,0feh ld (ident),a ; ENDE der Blocknummernumrechnung --------------------------------- call sc_def jp hd_mov bn_err ld a,5 ;Fehlercode 5: Blocknummer zu gross ld (err_cd),a jp error t_cd1 bit 4,a ;Defektspurberuecksichtigung ? jr z,t_cd2 ld hl,cmd_br-6 call id_ein call sc_def jp hd_mov t_cd2 bit 6,a ;Defektspurtabelle ? jr z,t_cd3 ld de,ident ld hl,id_df ld bc,5 ldir jp hd_mov t_cd3 ld hl,cmd_br-6 call id_ein jp hd_mov eject ;-------------------------------------------------------------------- ; Routine zur Bewegung der Schreib-Lese-Koepfe (Kamm) ;-------------------------------------------------------------------- hd_mov ; Test der Zylindernummer im Kommando ld hl,(ident+1) ;Zylinder ld bc,(cyls) ;Anzahl der Zylinder xor a sbc hl,bc jp nc,err_4 ;Zylindernummer im Kommando zu gross ; Laufwerk selektieren ld a,(st_ina) out (DSKC2),a ; Bestimmung der aktuellen Kopfposition ld a,(cmd_br-7) ;Laufwerk add a,a ld c,a ld b,0 ld hl,cy_tab ;Tabelle der Kopfpositionen add hl,bc ;Zeiger auf Kopfposition ld c,(hl) ;Low-Teil inc hl ld b,(hl) ;High-Teil inc bc ;ffff-Test ld a,b or c jp z,err_6 dec bc ld hl,(ident+1) ;angeforderter Zylinder xor a sbc hl,bc ;Positionsdifferenz jp z,mv3 ;Position ok. jp c,st_out ;Kopfbewegung nach aussen ; Kopfbewegung nach innen ld a,(dsk_c1) set 3,a ;SD nach innen ld (dsk_c1),a out (DSKC1),a jr mv0 ; Kopfbewegung nach aussen st_out ld a,(dsk_c1) res 3,a ;SD nach aussen ld (dsk_c1),a out (DSKC1),a push hl pop bc ld hl,0 xor a sbc hl,bc ; Bestimmung der Art der Schrittbewegung mv0 push hl ;Step-Anzahl ld a,(rp_mod) ld c,a ld b,0 sbc hl,bc pop hl jr c,sngl call ramp ;Stepausfuehrung im Ramp-Mode jr mv1 sngl call si_step ;Stepausfuehrung im Single-Step-Mode mv1 in a,(ST_PRT) ;Lesen des Status-Ports bit 3,a ;'SEEKC=aktiv' ? jr nz,mv1 ld hl,(ident+1) ;angeforderter Zylinder ld a,h or l ;Track0 angefordert ? jr nz,mv2 in a,(ST_PRT) bit 6,a ;'Track0=aktiv' ? jr z,mv2 ld a,7 ;Fehlercode fuer 'Track0 nicht erreicht' ld (err_cd),a jp error ; Eintragen der neuen Kopfposition mv2 ld a,(cmd_br-7) ;Laufwerk call cy_pos ld bc,(ident+1) ;geforderte Position ld (hl),c inc hl ld (hl),b ;------------ ; Kopfauswahl ;------------ mv3 ld a,(hds) ld b,a ld a,(ident+3) ;Kopfnummer cp b jp nc,err_2 ;Kopfnummer zu gross rrca rrca rrca rrca ld b,a ld a,(dsk_c1) and 0fh ;Loeschen der HS-Bits or b ;Einfuegen der neuen HS-Bits ld (dsk_c1),a out (DSKC1),a ;----------------------------- ; Auswertung des Kommandocodes ;----------------------------- mv_ok ld a,(cmd_br-8) ;Kommandocode cp 21h ;Blocklesen ? jp z,read1 cp 22h ;Blockschreiben ? jp z,write cp 0a1h ;Block-Kopieren ? jp z,read1 cp 81h ;Testlesen ? jp z,read5 cp 11h ;Lesen mit BTT-Test ? jp z,read1 cp 1 ;Sektorlesen ohne BTT-Test ? jp z,read1 cp 0 ;Ready-Test ? jp z,rdy_ts bit 1,a ;Schreib-Kommandos ? jp nz,write bit 2,a ;Formatier-Kommandos ? jp nz,format bit 3,a ;WDC-RAM-Transfers ? jp nz,ram_tr jp err_1 ;------------------------- ; Ready-Test des Laufwerks ;------------------------- rdy_ts jp begin eject ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Lesen eines Sektors, der durch seine Sektoradresse angegeben ist ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ read1 ; Setzen der Fehlerzaehler ld de,c_zt ld hl,fe_n ld bc,7 ldir ; Lesen von Hard-Disk ld a,0 ld (rd_mod),a ;Lesen von Kenn- und Datenfeld call rd_id jp nz,error ; Test auf Block-Kopieren ld a,(cmd_br-8) cp 0a1h jr nz,read11 ld a,22h ld (cmd_br-8),a ;Block-Schreiben ld a,0 ld (cmd_br-7),a ;Schreiben auf Laufwerk 0 jp t_com ; Uebergabe der gelesenen Daten an den Host read11 ld hl,dt ld bc,13 add hl,bc ;Anfangsadresse der gelesenen Daten res 4,h ;eventuelles Bit 12 ruecksetzen ld bc,(cmd_br-2) ;Datenlaenge add hl,bc dec hl ;Endadresse der gelesenen Daten ld a,3 ;Status '3' call p_wc_h ;Programmierung der Host-Schnittstelle jp begin eject read5 ;+++++++++++++++++++++++++++++++++++++++++++ ; Testlesen eines Sektors ;+++++++++++++++++++++++++++++++++++++++++++ ; Datenlaenge fuer einen Sektor einstellen ld hl,200h ld (dt_len),hl ; Loeschen der RAM-Zellen fuer Auswertung beim Testlesen ld hl,t_cnt ld b,8 clr_fm ld (hl),0 inc hl djnz clr_fm ; Setzen der Fehlerzaehler rd5_sl ld de,c_zt ld hl,fe_t ld bc,7 ldir ; Lesen von Hard-Disk ld a,0 ld (rd_mod),a ;Lesen von Kenn- und Datenfeld call rd_id ; Auswertung der Leseversuche im Testmodus jr nz,t_err ld hl,t_kf ;Anzahl der richtigen Leseversuche (Test) inc (hl) jp t_end ; Fehlerauswertung im Test-Modus t_err ld a,(err_cd) ;Fehlercode cp 0fh ;CRC-Fehler im Datenfeld ? jp z,asw_f ld hl,f_ande inc (hl) jp t_end ; Auswertung der CRC-Fehler im Datenfeld asw_f ld hl,f_0f inc (hl) ld hl,(dt_br) ;Beginn des Datenfeldes ld bc,13 add hl,bc res 4,h ld bc,200h ;Laenge des Datenfeldes sl_t1 ld a,(hl) cp 0e5h ;Wert ok. ? jr nz,diff1 inc hl dec bc ld a,c or b jr nz,sl_t1 ld a,(f_eb) cp 1 jp z,t_end ld hl,f_unkl inc (hl) jp t_end diff1 ld d,a ;Wert retten inc hl dec bc ld a,b or c jr nz,sl_t2 ld hl,f_eb ld (hl),1 jp t_end sl_t2 ld a,(hl) ;naechster Wert cp 0e5h ;Wert ok. ? jr nz,ausras push hl ld hl,f_eb ld (hl),1 pop hl jp sl_t1 ausras ld hl,f_ausr inc (hl) ;Fehler: ausgerastet jp t_end ; Endebehandlung des Testmodus t_end ld a,(f_eb) cp 1 ;Einzelbit-Fehler ? jr nz,k_eb ld hl,f_ebit inc (hl) k_eb ld a,(t_cnt) inc a ld (t_cnt),a cp 0ffh jp z,t_ueb xor a ld (f_eb),a jp rd5_sl ; Uebergabe der Testwerte an den Host t_ueb ld bc,(cmd_br-2) ld hl,t_cnt add hl,bc dec hl ld a,3 call p_wc_h xor a ld (err_cd),a jp begin eject ;************************************************************************** ; UP rd_id ; Lesen eines Kennfeldes (und des Datenfeldes) von Hard-Disk ; 'ident' : Kennfeld, 'rd_mod' : 0=Lesen des Kennfeldes und des Datenfeldes ; 1=Lesen des Kennfeldes ;************************************************************************** rd_id ; Initialisierung von 'dt_br' ld hl,dt ld (dt_br),hl ; Test auf Abschluss eventueller Host-Datentransfers rd_id1 ld a,(hst_by) bit 7,a jr nz,rd_id1 ; Loeschen bzw. Umladen der Zaehler xor a ld (err_cd),a ld (k_flg),a ld a,(c_zt) ld (ct_zt),a ;Zaehler fuer Zeitueberwachung ld a,(c_cd) ld (ct_cd),a ;Zaehler fuer CRC-Fehler im Datenfeld ld a,(c_sc) ld (ct_sc),a ;Zaehler fuer 'kein richtiges Kennfeld' nx_sc ld a,40 ld (sc_cnt),a ;Sektorzaehler nx_sc1 ; Ausschaltimpuls fuer DSS ld a,(st_ina) out (DSKC2),a out (IMPAUS),a ; Ausgabe der Bitmuster der Marken fuer Takt und Daten ld a,0a1h ;Datenbits out (BM_D),a ld a,0ah ;Taktbits out (BM_T),a ; Berechnung des Disk-Adresszaehlers fuer das Datenfeld ld hl,(dt_br) ld bc,11 add hl,bc res 4,h call b_daz ld (dsk_az),hl ; Vorbereiten der '-Register exx ld a,(st_ina) ld b,a ld a,(st_akt) ld c,a ld a,0f0h ;DEND zur Steuerungsumschaltung ld e,a exx ;-------------------------------- ; Schleife zum Suchen des Sektors ;-------------------------------- nx_sec ; Loeschen eventuellen CRC-Fehler in a,(ST_PRT) ; Richtung des Transfers ausgeben ld a,(cnt_st) ;Ausgabebyte res 7,a ;DR/W: Disk-->RAM set 6,a ;DA12=1 ld (cnt_st),a out (CNTST),a ; Vorbereiten der Ausgabewerte fuer die ISR exx ld hl,(dsk_az) ;HL: Adresse des Datenfeld exx ; ISR-Adresse fuer Markenerkennung beim Kennfeld ld hl,isr_m9 ld a,(rd_mod) cp 1 jr z,is_ok ld hl,isr_m1 is_ok ld (isr_mk),hl ; Laden des Disk-Adresszaehlers ld hl,(dsk_ad) ld (hl),a ; Laden der Disk-Endadresse fuer den CRC-Test des Kennfeldes ; Angabe der Anzahl der zu erkennenden Marken in den unteren drei Bits ld hl,(kf_br) ld bc,7 add hl,bc ;HL: Kennfeldadresse fuer CRC-Test & CM ld a,l out (DSKEA),a ; Vorbereiten der Register ld a,(st_min) ;'MEN=inaktiv' ld b,a ; CTC/0 fuer Markenerkennung programmieren ld a,0c7h ;EI & Counter & High-Low-Flanke out (CTC),a ld a,1 out (CTC),a ; Beginn des CRC-Loeschens ld a,(cl_crc) out (DSKC2),a ;Loeschen des CRC-Gen./Checkers auf 'ff' ; Einschalten der Zeitueberwachung ld a,0a7h ;Timer & VT256 out (CTC+3),a ld a,30h ;(20h) ca. 2,0 ms out (CTC+3),a ; Eintragen der ISR-Adresse fuer die Zeitueberwachung ld hl,isr_zt ld (isr_ix),hl ; Aktivieren der Schnittstelle zur Markenerkennung ld a,(st_akt) out (DSKC2),a ;alles aktiv zur Markenerkennung ld a,b ;Vorbereitung fuer ISR halt ;Warten auf das Erkennen der Marke A1 ; ------- Warten auf drei Marken A1 vor dem Kennfeld ---------- halt ;Warten auf Marke ; ------- Warten auf Marke A1 vor dem Datenfeld --------- ; Loeschen der Zeitueberwachung und der Markenerkennung hlt_2 di ld a,3 out (CTC),a out (CTC+3),a ei ;----------------------------------- ; Auswertung der eingelaufenen Daten ;----------------------------------- ; Test des Identifiers ld b,5 ld hl,(kf_br) inc hl ;Beginn des eingelaufenen Idents ld de,ident ;Beginn des geforderten Idents tst_id ld a,(de) cp (hl) jp nz,id_e inc hl inc de djnz tst_id ; CRC-Test des Identifiers in a,(ST_PRT) bit 7,a jp z,id_e ; geforderter Sektor ist gefunden ld a,(rd_mod) ;Nur Kennfeld ? cp 1 ret z ;Rueckkehr ok. ;----------------------------------------- ; Kennfeld gefunden, Lesen des Datenfeldes ;----------------------------------------- ; Test auf Datenfeldkennzeichen ld hl,(dt_br) ld bc,12 add hl,bc res 4,h ld a,0fbh ;HL auf Datenfeldkennzeichen cp (hl) jp nz,tdc_er ; Zurueckschreiben des durch FB ueberschriebenen Wertes ld a,(sav_fb) ;gerettetes Byte ld (hl),a ; Programmierung der Disk-Schnittstelle fuer exakte Datenfelduebertragung ld a,(st_dak) out (DSKC2),a ;'DEN=aktiv' & 'MEN=inaktiv' & 'CRCEN=inaktiv' ld hl,(dt_br) ld bc,90h ;neue DEND-Adresse zur Steuerungsumschaltung add hl,bc ld a,l out (DSKEA),a ; CTC/1 fuer DEND-Erkennung programmieren ld a,0d7h ;EI & Counter & Low-High-Flanke out (CTC+1),a ld a,2 ;Zaehler out (CTC+1),a halt ;Warten auf das 2. DEND ; ------- Warten auf DEND vor dem CRC-Test ------- ; Berechnung der Adresse fuer den CRC-Test ld hl,(dt_br) ld bc,526 add hl,bc ld a,l out (DSKEA),a ; Umprogrammierung der Schnittstelle auf CRC-Test ld a,(st_min) out (DSKC2),a ;'DEN=aktiv' & 'MEN=inaktiv' & 'CRCEN=aktiv' ; Vorbereitung fuer das Abschalten der Disk-Schnittstelle ld a,(st_ina) ;alles inaktiv ld c,a ld a,0d7h out (CTC+1),a ld a,1 out (CTC+1),a halt ; ------- Warten auf das DEND zum CRC-Test ------- ; Programmierung fuer das Abschalten der Schnittstelle ld a,c out (DSKC2),a ;alles inaktiv out (IMPAUS),a ;Schnittstelle aus ld a,3 out (CTC+1),a ;Loeschen der Interrupts fuer DEND out (CTC),a ;Loeschen der Interrupts fuer MAERK ;---------------------------------------- ; Auswertung des eingelesenen Datenfeldes ;---------------------------------------- ; Test auf CRC-Fehler in a,(ST_PRT) bit 7,a ;CRC-Fehler ? jp z,tdc_er ; Retten des Anfangs des ersten Datenfeldes ld hl,k_flg ;Steuerbyte bit 7,(hl) jr nz,no_sav set 7,(hl) ;Anfang ist gerettet ld hl,(dt_br) ld bc,13 add hl,bc res 4,h ld de,sav_20 ld b,20h call ldir23 no_sav ; Retten des letzten Datenbytes des Datenfeldes ld hl,(dt_br) ld bc,524 add hl,bc res 4,h ld a,(hl) ld (sav_fb),a ; naechsten Sektor lesen ? ld hl,(dt_len) ;aktuelle Datenlaenge ld bc,200h xor a sbc hl,bc ld (dt_len),hl jr z,um_20 jp nc,n_sec ; Zurueckschreiben des Anfangs des ersten Datenfeldes um_20 ld hl,dt ld bc,13 add hl,bc ex de,hl res 4,d ld hl,sav_20 ld b,20h call ldir32 ld hl,k_flg res 7,(hl) ;Flag ruecksetzen xor a ;Flags loeschen ret ;Rueckkehr, wenn Lesen ok. n_sec ; Bestimmung des naechsten Bereichs im WDC-RAM ld hl,(dt_br) ld bc,200h add hl,bc res 4,h ld (dt_br),hl ; Berechnung des Disk-Adresszaehlers fuer das Datenfeld ld hl,(dt_br) ld bc,11 add hl,bc res 4,h call b_daz ld (dsk_az),hl ; Setzen der Fehlerzaehler fuer den neuen Sektor ld a,10 ld (sc_cnt),a ld a,(c_zt) ld (ct_zt),a ;Zaehler fuer Zeitueberwachung ld a,(c_cd) ld (ct_cd),a ;Zaehler fuer Fehler im Datenfeld ; Bestimmung des naechsten Sektors ld a,(secs) ld b,a inc b ld hl,ident+4 ;HL zeigt auf Sektor inc (hl) ld a,(hl) ;Sektornummer cp b ;max. Sektor + 1 jp c,nx_sec ld (hl),1 ;naechste Spur, Beginn mit Sektor 1 dec hl ;HL zeigt auf Kopf ld a,(l_inc) ;Inkrementierungszaehler ld b,a inc b nx_s1 push bc ;Zaehler retten ld a,(hds) ld b,a ld hl,ident+3 inc (hl) ;Kopfnummer inkr. ld a,(hl) ;Kopfnummer cp b ;Max. Kopf + 1 jr nc,nx_cy ;Sprung, wenn Zylinderwechsel noetig nx_s2 pop bc djnz nx_s1 ld a,(ident+3) call hd_sl ;Kopfselektierung jp nx_sc ; Zylinderwechsel waehrend eines Tranfers nx_cy ld (hl),0 ;naechster Zyl, Beginn mit Kopf 0 dec hl ;Zyl high ld d,(hl) dec hl ;HL zeigt auf Zyl low ld e,(hl) inc de ;naechster Zylinder push hl ld hl,(cyls) xor a sbc hl,de pop hl jp p,nxs ;Sprung, wenn Zyl ok pop bc ld a,04h ;Fehlercode: Zyl zu gross ld (err_cd),a cp 0 ret nxs ld (hl),e inc hl ld (hl),d call step1 jr nx_s2 ;-------------------------------------------------------------------- ; Fehlerbehandlung fuer Fehler waehrend des Lesevorgangs ;-------------------------------------------------------------------- ; es wird nicht der richtige Sektor gefunden id_e ld a,(st_ina) ;alles inaktiv out (DSKC2),a out (IMPAUS),a ;Ausschaltimpuls ld hl,sc_cnt ;Sektorzaehler dec (hl) jp nz,nx_sec ld hl,sum_sc ld a,0ah ;Fehlercode 0A call d_err jp nz,nx_sc ;sofort weitersuchen jp err_rt ;Fehlerabbruch ; keine Marke waehrend der Zeit der Zeitueberwachung err_mk ld hl,sum_zt ld a,0bh ;Fehlercode 0B call d_err jp nz,nx_sec ;sofort weitersuchen jp err_rt ;Fehlerabbruch ; Fehler im Datenfeld tdc_er ld hl,sum_cd ld a,0ch ;Fehlercode 0C call d_err jp z,err_rt call dis_1 ;fast eine Umdrehung abwarten ld a,10 ld (sc_cnt),a jp nx_sc ; Rueckkehr mit Fehler err_rt ld (err_cd),a ;Fehlercode cp 0 ;Flags setzen ret ;--- isr_m1 ------------------------------------------------- ; ISR fuer den Interrupt bei der Markenerkennung des Kennfeldes ; (fuer Kennfeldlesen mit anschliessendem Datenfeldlesen ; CTC-Kanal 0 ;-------------------------------------------------------------- isr_m1 out (DSKC2),a ;'MEN=inaktiv' exx ld a,b out (DSKC2),a ;alles inaktiv out (IMPAUS),a ;Abschaltimpuls ; Vorbereitung fuer das Lesen des Datenfeldes ld (hl),a ;Laden Diskadresszaehler ld hl,isr_m7 ;ISR-Adresse fuer Int. vor Datenfeld ld (isr_mk),hl ;Umladen der ISR-Adresse ld a,e out (DSKEA),a ;DEND-Adresse fuer Markenanzahl ld a,(cnt_st) res 6,a ;DA12 = 0 ld (cnt_st),a out (CNTST),a ;Umschaltung des RAM-Bereichs ld a,c out (DSKC2),a ;alles aktiv zur Markenerkennung exx ;--- isr_al ------------------------------------------------ ; ISR fuer allgemeine Verwendung ; alle CTC-Kanaele ;------------------------------------------------------------ isr_al ei reti ;--- isr_m9 ------------------------------------------------ ; ISR fuer Interrupt bei Markenerkennung des Kennfeldes ; (nur Kennfeldlesen) ; CTC-Kanal 0 ;------------------------------------------------------------- isr_m9 out (DSKC2),a ;'MEN=inaktiv' nop ld a,(st_ina) out (DSKC2),a ;alles inaktiv out (IMPAUS),a ;Abschaltimpuls ld a,3 out (CTC),a ;Reset Markenerkennung pop hl ;Verwerfen der Returnadresse ld hl,hlt_2 ;neue Returnadresse push hl ei reti ;--- isr_m7 ------------------------------------------------- ; ISR fuer Interrupt bei Markenerkennung des Datenfeldes ; CTC-Kanal 0 ;-------------------------------------------------------------- isr_m7 ld a,3 out (CTC),a ;Reset Markenerkennung ei reti ;--- isr_zt -------------------------------- ; ISR fuer das Ansprechen der Zeitueberwachung ; (CTC-Kanal 3) ;--------------------------------------------- isr_zt ld a,3 out (CTC),a out (CTC+3),a ;Reset pop hl ;Verwerfen der Returnadresse ld hl,err_mk push hl ;neue Returnadresse ei reti ;--- ct_um ------------------------------------ ; Umladen bzw. Loeschen der Maximalfehlerzellen ; hl: Adresse des Momentanwerts 'mx_xx' ; hl+1: Adresse des Maximalwerts 'max_xx' ;------------------------------------------------ ct_um ld a,(hl) ;'mx_xx' inc hl ;'max_xx' cp (hl) jr c,ct_um1 ld (hl),a ;neuen Maxwert eintragen ct_um1 xor a dec hl ld (hl),a ;Loeschen Momentanwert 'mx_xx' ret ;--- d_err ------------------------------------------------------------- ; Ausschalten der Diskschnittstelle nach Fehler und Behandlung der Zaehler ; hl: Adresse des Beginns der speziellen Zaehlerzellen ; a: Fehlercode ;------------------------------------------------------------------------- d_err ld b,a ld a,(st_ina) ;alles inaktiv out (DSKC2),a ;Steuerbits inaktiv out (IMPAUS),a ;Ausschaltimpuls inc (hl) ;Low-Teil 'sum_xx' push af inc hl ;Zeiger auf High-Teil 'sum_xx' pop af jr nz,sm_ok inc (hl) ;Inc High-Teil 'sum_xx' sm_ok inc hl ;Zeiger auf 'mx_xx' ; inc (hl) ;Inc 'mx_xx' inc hl ;'max_xx' uebergehen inc hl ;Zeiger auf 'ct_xx' dec (hl) ;Dec 'ct_xx' ret nz ;Return fuer Wiederholung xor a ld a,b ;Fehlercode ret ;Return im Fehlerfall ;--- dis_1 ------------------------------------------------- ; Programmierung Zeitinterrupt fuer fast eine Plattenumdrehung ;------------------------------------------------------------- dis_1 push af ld a,0a7h out (CTC+1),a ld a,230 out (CTC+1),a halt ld a,3 out (CTC+1),a pop af ret eject ;--- id_ein ----------------------- ; Eintragen des Kennfeldes ; hl: Zeiger auf 'Cy-L, Cy-H, Hd, Sc' ;------------------------------------ id_ein ld de,ident ld a,0feh ld (de),a inc de ld bc,4 ldir ret ;--- step1 -------------------------------------------------------- ; Verschiebung der Koepfe um einen Zylinder nach innen ;------------------------------------------------------------------- step1 ld a,(dsk_c1) ;Ausgabebyte fuer DSKC1 set 3,a ;SD nach innen out (DSKC1),a xor 1 ;ST ein out (DSKC1),a xor 1 ;ST aus out (DSKC1),a step11 in a,(ST_PRT) bit 3,a jr nz,step11 ld a,(cmd_br-7) ;Laufwerk add a,a ld c,a ld b,0 ld hl,cy_tab ;Positionstabelle add hl,bc ld e,(hl) ;Low-Teil inc hl ld d,(hl) ;High-Teil inc de ;Inc Zylinder ld (hl),d dec hl ld (hl),e ret ;ok. ;--- hd_sl ------------------------------------------------------ ; Kopfselektierung ; A: Kopfnummer 0...max, Test auf Richtigkeit muss vorher erfolgen ;------------------------------------------------------------------ hd_sl rrca rrca rrca rrca ld b,a ld a,(dsk_c1) and 0fh ;Loeschen der HS-Bits or b ;neue HS-Bits ld (dsk_c1),a out (DSKC1),a ret ;--- sc_def ------------------------------------------------ ; Berechnung der Sektoradresse mit Defektspurberuecksichtigung ; Sektoradresse vorher und nachher in 'ident' ;------------------------------------------------------------- ; l_inc: Anzahl der Spurinkrementierungen, um bei Mehrblock- ; transfers auf die richtige Spuradresse zu kommen ;------------------------------------------------------------- sc_def xor a ld (l_inc),a ;Loeschen Spurinkrementierungen ld de,(df_end) ;Adresse ld a,(de) ld l,a inc de ld a,(de) or l ret z ;keine Adressinkr. noetig ex af,af' xor a ;Loeschen Inkrements ex af,af' ld de,(df_tab) ;Adresse der Tabelle der Defektspuren dec de ; naechste Spur aus der BTT sc2 inc de ;Zeiger auf Zylinder High ld a,(de) ;Zyl High ld h,a inc de ld a,(de) ;Zyl Low ld l,a inc de ;Zeiger auf Kopfnummer ; Endekennzeichen ? push hl ld bc,0ffffh ;Endekennzeichen xor a sbc hl,bc pop hl jp z,sc4 ;Sprung, wenn Ende der Defektspuren ; Spur_def <= geforderte Spur ? ld bc,(ident+1) ;Zyl-gef xor a sbc hl,bc jp c,sc3 jp nz,sc4 ; Cyl-gef = Cyl-def, Test der Kopfnummer ld a,(de) ;Kopf defekt ld b,a ld a,(ident+3) ;Kopf sub b ;Kopf - Kopf-def jp c,sc4 ; Zaehler erhoehen sc3 ex af,af' inc a ex af,af' jp sc2 ; Erhoehung der Spuradresse sc4 dec de ;Zeiger auf vorhergehenden BTT-Eintrag dec de dec de ex af,af' ld b,a xor a ;Zaehler loeschen ex af,af' ld a,b cp 0 jr z,sc7 ld b,a ;Anzahl der Inkrementierungen sc5 ld a,(hds) ld c,a ld a,(ident+3) ;Kopf inc a ld (ident+3),a cp c jr nz,sc6 xor a ld (ident+3),a ld hl,(ident+1) ;Zylinder inc hl ld (ident+1),hl sc6 djnz sc5 jp sc2 ;Test auf weitere BTT-Eintragungen ; Test, ob naechste Spur defekt ist (fuer Mehrblocktransfer) sc7 ld hl,(dt_len) ld bc,201h xor a sbc hl,bc ret c ;Return, wenn nur ein Block ld hl,(ident+1) ;Zyl_akt ld a,(ident+3) ;Hd_akt ld b,a sc9 inc de ;DE: Zeiger auf Zyl_btt_high inc b ;naechster Kopf ld a,(hds) ;Kopfanzahl ld c,a ld a,b cp c jr c,sc8 ld b,0 ;naechster Kopf ist 0 inc hl ;naechster Zyl sc8 ld a,(de) ;Zyl_btt_high cp h ;Zyl_akt_high ret nz ;naechste Spur ist keine BTT-Spur inc de ld a,(de) ;Zyl_btt_low cp l ;Zyl_akt_low ret nz ;naechste Spur ist keine BTT-Spur inc de ld a,(de) ;Hd_btt cp b ;Hd_akt ret nz ;naechste Spur ist keine BTT-Spur ld a,(l_inc) ;Zaehler inkrementieren inc a ld (l_inc),a jr sc9 ;naechste Spur auch BTT-Spur ? eject ;*********************************************************** ; Schreiben auf Hard-Disk ;*********************************************************** write ; Setzen der Fehlerzaehler ld de,c_zt ld hl,fe_n ld bc,7 ldir ; Auswertung des Kommandocodes ld a,(cmd_br-8) ;Kommandocode cp 0c2h ;Schreiben 'PAR&BTT' ? jp z,wr_df call wr_dt ;Schreiben des Datenfeldes jp nz,error jp begin ;---------------------------------------------------------------------- ; Schreiben 'PAR&BTT' auf den Sektor 0/0/1 ;---------------------------------------------------------------------- wr_df ld hl,200h ld (cmd_br-2),hl ld (dt_len),hl ; Eintragen 'DEFEKT' ld hl,dt ld (dt_br),hl ld bc,13 add hl,bc res 4,h push hl ex de,hl ld hl,txt_df ld bc,6 ldir ; Umladen der Defektspurtabelle ld hl,(df_end) ld bc,40*3+3+2 ldir ; Eintragen 'PARMTR' pop hl ld bc,256 add hl,bc res 4,h ex de,hl ld hl,txt_pm ld bc,6 ldir ; Umladen der Parametertabelle call par_v ; Untersuchung der umgeladenen Tabellen call t_par ;Test der Parameter jp nz,err_17 ;Fehler, kein Schreiben call t_btt ;Test der Defektspurtabelle jr nz,wr_df1 ;Sprung, wenn fehlerhafte BTT call btt_s ;Setzen des BTT-Bits jr wr_df2 ; Loeschen des BTT-Bereichs wr_df1 call btt_cl ;Loeschen der BTT im 3000-RAM call btt_v ;Umladen in den Datenbereich des 1. Sektors call btt_r ;Ruecksetzen des BTT-Bits wr_df2 call wr_dt ;Aufruf des Schreibprogramms jr nz,wr_df7 call par_s ;Setzen des PAR-Bits jp entry wr_df7 call par_r ;Ruecksetzen des PAR-Bits call btt_r ;Ruecksetzen des BTT-Bits jp error ;--- wr_dt ----------------------------------------------------------- ; UP Aufruf des Schreibprogramms ;--------------------------------------------------------------------- wr_dt ld a,4 ld (ct_ra),a ;Zaehler fuer Schreibwiederholungen wr_dt1 call wrt_dt ;Schreiben des Datenfeldes ret nz ;Schreibfehler ld a,(cmd_br-8) ;Kommandocode bit 7,a ;'Read after Write' ? ret z ; Setzen der Fehlerzaehler fuer das Lesen ld de,c_zt ld hl,fe_n ld bc,7 ldir ; Lesen von Hard-Disk ld a,0 ld (rd_mod),a call rd_id ret ;Ruecksprung bei 'Read after Write' ; Fehler, Fehlerzaehlerbehandlung ld hl,(sum_ra) inc hl ld (sum_ra),hl ld hl,mx_ra ; inc (hl) ld hl,ct_ra dec (hl) jp nz,wr_dt1 ld a,11h ;Fehlercode 11h ld (err_cd),a cp 0 ret ;Fehlerruecksprung bei 'Read after Write' eject ;*************************************************************************** ; UP wrt_dt ; Schreiben des Datenfeldes eines Sektors ;*************************************************************************** wrt_dt ; Initialisierung von 'dt_br' ld hl,dt ld (dt_br),hl ; Setzen der Fehlerzaehler fuer das Schreiben ld a,3 ld (ct_fw),a ;Zaehler fuer Fault-Write-Fehler ld a,3 ld (ct_wi),a ;Zaehler fuer Identfehler vor dem Schreiben ; Umspeichern des aktuellen Sektors, ; da in 'ident' fuer das Lesen geaendert wird ld a,(ident+4) ;geforderte Sektornummer ld (sc_akt),a ;retten des aktuellen Sektors ; Bestimmung der vorhergehenden Sektornummer (fuer das Schreiben) suche ld a,(sc_akt) ;aktuelle Sektornummer ld hl,sc_tab ;Tabelle des Sektorversatz vs_sl cp (hl) jr z,vs_ok inc hl jr vs_sl vs_ok dec hl ;HL zeigt auf Vorgaenger ld a,(hl) cp 0ffh ;vor Sektor 1 jr nz,vs_ok1 ld a,(secs) ld c,a ld b,0 ld hl,sc_tab-1 add hl,bc ld a,(hl) ;letzter Sektor vor Sektor 1 vs_ok1 ld (ident+4),a ;vorhergehende Sektornummer ; Test auf Abschluss eventueller Host-Datentransfers wr_sl1 ld a,(hst_by) bit 7,a jr nz,wr_sl1 ; Retten des Praeambelbereichs des Sektors ld hl,(dt_br) ;Beginn der Praeambel ld de,s_prae ;Rettungsbereich ld b,13 call ldir23 ;Umladen ; Lesen des vorhergehenden Sektorkennfeldes ld a,1 ;Kennfeldlesen ld (rd_mod),a call rd_id1 ;Kennfeldlesen ohne Bereichsweiterschaltung ret nz ;Fehler im Kennfeld ; Retten des Postambel-Bereichs nx_wrt ld hl,(dt_br) ld bc,525 add hl,bc ;Beginn der Postambel res 4,h ld de,s_post ;Rettungsbereich fuer Postambel ld bc,12 ;Laenge der Postambel ldir ; Eintragen der Praeambel und der Postambel ld de,(dt_br) ;Beginn der Praeambel ld hl,prae ;Praeambel ld bc,11 ;Laenge der Praeambel ldir res 4,d ld bc,2 ldir ld hl,(dt_br) ld bc,525 add hl,bc res 4,h ex de,hl ;Beginn der Postambel ld hl,post ;Postambel ld bc,12 ;Laenge der Postambel ldir ; Setzen des Sektor-Index-Zaehlers ld a,4 ld (c_s_ix),a ; Vorbereitung des Schreibens nx_wr1 ld a,(cnt_st) res 7,a ;DR/W: Disk-->RAM (Lesen) set 6,a ;DA12=1 ld (cnt_st),a out (CNTST),a ld hl,(kf_br) dec hl ld a,l out (DSKEA),a ;DEND-Adresse bereinigen ld a,0a1h out (BM_D),a ;Datenbits der Marke ld hl,(kf_br) call b_daz ld (hl),a ;Diskadresszaehler fuer das Kennfeld ld hl,isr_m2 ;Eintragen der neuen ISR ld (isr_mk),hl ld hl,(dt_br) ;Anfangsadresse der Daten call b_daz ;Berechnung des Disk-Adresszaehlers push hl exx ex af,af' ld hl,(dt_br) ;DEND-Adresse fuer Markeneinblenden ld bc,11 add hl,bc ld e,l pop hl ;Disk-Adresszaehler ld a,(st_wa) ld c,a ;'WG=aktiv' res 3,a ;'WG=inaktiv' ld b,a ld a,4 ;PRAEOFF & MFM & eine Marke ld d,a push hl push bc ld a,(cmd_br-7) ;akt. Laufwerk call cy_pos ld b,(hl) ;Low-Teil Zylinderposition inc hl ld h,(hl) ;High-Teil Zylinderposition ld l,b ld bc,(pre_cy) ;Praekompensationsbeginn xor a sbc hl,bc pop bc pop hl jr c,pre_ok ld a,0ch ;PRAEON & MFM & eine Marke ld d,a pre_ok ld a,(cnt_st) set 7,a ;DR/W: RAM-->Disk res 6,a ;DA12=0 ld (cnt_st),a ex af,af' exx ; Programmierung CTC/0 auf MAERK ld a,0c7h out (CTC),a ld a,1 out (CTC),a ; Einschalten der DSS zur Erkennung des Kennfeldes des zu schreibenden S. ld hl,(kf_br) ld bc,5 add hl,bc ;zeigt auf Sektornummer im Kennfeld ld a,(sc_akt) ;aktuelle Sektornummer ld b,a ld a,(st_min) ;Schnittstelle aktiv mit 'MEN=inaktiv' out (DSKC2),a ld a,(st_vb) ;'DEN=inaktiv' als Vorbereitung zum Abschalten out (DSKC2),a ld a,3 ;Vorbereitung fuer CTC-Reset halt ; ------ Warten auf drei A1 des Kennfeldes vor dem Schreiben ------ ; ------ Interruptserviceroutine 'isr_m2' ------------------------- ld hl,(kf_br) ld bc,5 add hl,bc ld a,(sc_akt) ld b,a ld a,(hl) cp b ;Sektornummer richtig ? jp nz,wr_err ld hl,(dt_br) ld bc,93 add hl,bc ld a,l out (DSKEA),a ;DEND-Adresse fuer das Umschalten ld a,0d5h out (CTC+1),a ld a,2 ;Interrupt nach zwei DEND out (CTC+1),a ; Rueckschreiben des Praeambelbereichs des Sektors ld hl,(dt_br) ex de,hl ld hl,s_prae ld bc,11 ldir res 4,d ld bc,2 ldir halt ;Warten auf das 2. DEND ; ---- Warten auf Zwischeninterrupt ------------------- ld hl,(dt_br) ld bc,525 ;DEND-Adresse zum CRC-Einblenden add hl,bc ld a,l out (DSKEA),a ld a,(st_wc) ;Steuerbits zum CRC-Einblenden out (DSKC2),a ld a,0d7h out (CTC+1),a ld a,1 out (CTC+1),a ;Interrupt beim CRC-Einblenden ; Vorbereitung der nachfolgenden Operationen ld a,(st_ina) ;alles inaktiv halt ;Warten auf den CRC-Interrupt ; --- Warten ------------------- out (DSKC2),a out (IMPAUS),a ;Disk-Schnittstelle aus ld a,3 out (CTC+1),a ;CTC/1-Reset (DEND) in a,(ST_PRT) bit 5,a ;'Fault write=aktiv ?' jp z,wr_fw ; naechsten Sektor schreiben ? ld hl,(dt_len) ;aktuelle Datenlaenge ld bc,200h xor a sbc hl,bc ld (dt_len),hl ret z ;Schreiben ok. ret c ;Schreiben ok. ; Berichtigung des Postambelbereichs ld hl,(dt_br) ld bc,525 add hl,bc res 4,h ex de,hl ;Postambel ld hl,s_post ;Rettungsbereich fuer Postambel ld bc,12 ldir ; Bestimmung der RAM-Adressen fuer den naechsten Sektor ld hl,(dt_br) ld bc,200h add hl,bc res 4,h ld (dt_br),hl ; Loeschen des Zylinderwechsel-Flag ld hl,ch_cyl ld (hl),0 ; Bestimmung des naechsten Sektors ld a,(secs) ld b,a inc b ld hl,sc_akt ;aktueller Sektor inc (hl) ld a,(hl) ;Sektornummer cp b ;max. Sektor + 1 jp c,nx_wrt ; Kopfwechsel waehrend eines Zugriffs ld a,1 ld (sc_akt),a ld hl,ident+4 ;zeigt auf Sektornummer ld (hl),a ;naechster Sektor, Beginn mit Sektor 1 dec hl ;HL zeigt auf Kopf ld a,(l_inc) ;Inkrementierungszaehler ld b,a inc b n_cy1 push bc ld a,(hds) ld c,a ld hl,ident+3 ;Kopfnummer inc (hl) ;Kopfnummer inkr. ld a,(hl) ;Kopfnummer cp c ;Max. Kopf + 1 jr nc,n_cy ;Sprung, wenn Zylinderwechsel n_cy2 pop bc djnz n_cy1 ld a,(ident+3) call hd_sl ;Kopfselektierung ld a,(ch_cyl) cp 0 jp z,nx_wrt ;Schreiben des Sektors jp suche ;Orientieren auf der Spur ; Zylinderwechsel waehrend eines Zugriffs n_cy ld (hl),0 ;naechster Zyl, Beginn mit Kopf 0 dec hl ;Zyl high ld d,(hl) dec hl ;HL zeigt auf Zyl low ld e,(hl) inc de ;naechster Zylinder push hl ld hl,(cyls) ;max. Zylinder + 1 xor a sbc hl,de pop hl jp p,nxd ;Sprung, wenn Zyl ok. pop bc ld a,04h ;Fehlercode: Zyl zu gross ld (err_cd),a cp 0 ret ;Fehlerrueckkehr ; Kopfauswahl bzw. Zylinderauswahl nxd ld (hl),e inc hl ld (hl),d call step1 ld hl,ch_cyl ld (hl),1 jr n_cy2 ; Fehler vor dem Schreiben (falsche Sektornummer) wr_err ld hl,c_s_ix ;erlaubte falsche Sektornummern dec (hl) jp nz,nx_wr1 ;sofort den naechsten Sektor schreiben ld hl,sum_wi ld a,12h ;Fehlercode 12 call d_err jr nz,wr_er2 ld (err_cd),a cp 0 ret wr_er2 call r_post ;Berichtigung des Postambelbereichs ld hl,(dt_br) ex de,hl ld hl,s_prae ld bc,11 ldir res 4,d ld bc,2 ldir jp suche ;neu orientieren auf der Spur ; Fehler beim Schreiben wr_fw ld a,(st_ina) set 7,a ;'FR=aktiv' out (DSKC2),a out (IMPAUS),a ;Schnittstelle aus res 7,a ;FR ruecksetzen out (DSKC2),a ld hl,sum_fw ld a,10h ;Fehlercode 10h call d_err jr nz,wr_fw1 ld (err_cd),a cp 0 ret wr_fw1 call r_post ;Berichtigung des Postambelbereichs jp suche ;--- isr_m2 --------------------------------------------------------- ; ISR fuer den Interrupt nach Erkennung von drei A1 vor dem Kennfeld ; beim Schreiben ;-------------------------------------------------------------------- isr_m2 out (CTC),a ;Reset CTC/0 (MAERK) out (IMPAUS),a ;Schnittstelle aus ld a,(hl) cp b jr nz,isr_m3 exx ex af,af' out (CNTST),a ;Richtungsumsteuerung der Schnittstelle ld (hl),a ;neuer Disk-Adresszaehler ld a,e ;DEND-Adresse zum Markeneinblenden holen out (DSKEA),a ld a,d out (BM_D),a ;MFM ld a,b out (DSKC2),a ;alles aktiv zum Schreiben ld a,c ;'WG=aktiv' out (DSKC2),a ex af,af' exx nop nop nop nop nop nop nop nop ld a,(st_wm) out (DSKC2),a ;'MEN=inaktiv' & 'CRCEN=inaktiv' isr_m3 ei reti ;-- r_post -------------------------------------------------- ; Rueckschreiben Postambelbereich ;-------------------------------------------------------------- r_post ld hl,(dt_br) ld bc,525 add hl,bc res 4,h ex de,hl ;Postambel ld hl,s_post ;Rettungsbereich fuer Postambel ld bc,12 ldir ret ;--- ldir23 ------------------------------------------------ ; Umladen von RAM-Bereich 2000...2fff nach RAM-Bereich 3000, ; wobei die Adresse im 2000-Bereich "rund" laeuft ; HL: Quelle (2000...2fff), DE: Ziel (3000), B: Anzahl ;------------------------------------------------------------- ldir23 ld a,(hl) ld (de),a ;Umladen inc hl res 4,h inc de djnz ldir23 ret ;--- ldir32 ------------------------------------------------ ; Umladen von RAM-Bereich 3000 nach RAM-Bereich 2000...2fff, ; wobei die Adresse im 2000-Bereich "rund" laeuft ; HL: Quelle (3000), DE: Ziel (2000...2fff), B: Anzahl ;------------------------------------------------------------- ldir32 ld a,(hl) ld (de),a ;Umladen inc hl inc de res 4,d djnz ldir32 ret eject ;********************************** ; Formatierprogramme fuer Hard-Disk ;********************************** format ld hl,200h ld (cmd_br-2),hl ;Laenge setzen ld (dt_len),hl ; Zeitkonstante schon bestimmt ? ld a,(ztk) and a jp nz,ztk_ok ld a,(cmd_br-8) cp 84h ;Spurloeschen ? jp z,ztk_ok ;----------------------------------------------------------- ; Bestimmung der Zeitkonstanten fuer das Formatieren ;----------------------------------------------------------- ; Laufwerk mit 17 Sektoren ? ld a,(ztk_41) ld (ztk),a ;Voreinstellen ztk ld a,(secs) cp 17 jp z,ztk_ok ld hl,isr_al ld (isr_ix),hl ;ISR-Adresse ld hl,ztk_f ;HL zeigt auf Hilfsfeld ld b,8 ;8 Durchlaeufe ztk_1 ld a,0d5h ;Counter, EI out (CTC+3),a ld a,1 out (CTC+3),a halt ;---- Warten auf den naechsten IX-Impuls ---- ;---- ISR 'isr_al' -------------------------- ld a,027h ;Timer ohne Interrupt out (CTC+1),a ld a,0 out (CTC+1),a halt ;---- Warten auf den naechsten IX-Impuls ---- ;---- ISR 'isr_al' -------------------------- ld a,3 ;RESET out (CTC+3),a in a,(CTC+1) ;Lesen Zaehlerstand ld (hl),a ;sichern ld a,3 ;RESET out (CTC+1),a inc hl djnz ztk_1 ; Summieren des Hilfsfeldes ld b,8 ld hl,0 ld de,ztk_f ztk_2 push bc ld b,0 ld a,(de) ld c,a add hl,bc inc de pop bc djnz ztk_2 ; Division durch 8 ld b,3 ztk_3 srl l srl h jr nc,ztk_4 set 7,l ztk_4 djnz ztk_3 ld a,l ; 'ztk' im 41,4-MHz-Bereich ? ld hl,zmn_41 ;Zeiger auf Grenzwerte cp (hl) jr c,ztk_6 ;Sprung, wenn kleiner inc hl ;Zeiger auf 'zmx_41' ld b,(hl) inc b cp b jr nc,ztk_5 ;Sprung, wenn groesser ld a,(ztk_41) ;Zeitkonstante fuer 41,4 MHz ld (ztk),a jr ztk_ok ; 'ztk' im 40,0-MHz-Bereich ? ztk_5 dec hl dec hl dec hl ;Zeiger auf 'zmn_40' cp (hl) jr c,ztk_6 ;Sprung, wenn kleiner inc hl ;Zeiger auf 'zmx_40' ld b,(hl) cp b jr nc,ztk_6 ;Sprung, wenn groesser ld a,(ztk_40) ;Zeitkonstante fuer 40,0 MHz ld (ztk),a jr ztk_ok ; Fehler waehrend der Zeitkonstantenbestimmung ztk_6 xor a ld (ztk),a jp err_15 ; Ende der Zeitkonstantenbestimmung ztk_ok ld a,(cmd_br-8) cp 04h jp z,frmt1 cp 14h jp z,frmt2 cp 24h jp z,frmt3 cp 44h jp z,frmt4 cp 84h jr z,frmt1 jp err_1 ;--------------------------------- ; Einfaches Formatieren einer Spur ;--------------------------------- frmt1 call ft_trk jp nz,error jp begin ;--------------------------------------------- ; Formatieren einer Spur mit Test der Sektoren ;--------------------------------------------- frmt2 ; Formatieren der Spur call ft_trk jp nz,error ; Ruecklesen der Einzelsektoren frmt4 ld de,c_zt ld hl,fe_n ld bc,7 ldir ld a,1 ld (ident+4),a ;Sektor ld hl,2400h ;18 Sektoren ld a,(secs) cp 18 jr z,frmt41 ld hl,2200h ;17 Sektoren frmt41 ld (dt_len),hl ld a,0 ld (rd_mod),a call rd_id jp nz,error jp begin ;------------------------------------------------------------- ; Formatieren einer Spur mit Defektfeststellung und Eintragung ; in die Defektspurtabelle ;------------------------------------------------------------- frmt3 ld de,c_zt ld hl,fe_f1 ld bc,7 ldir ld a,3 ld (dl_f),a ;Anfangswert f301 ld hl,dl_f dec (hl) jp z,f_def call ft_trk ;Formatieren einer Spur jp nz,f301 ; Ruecklesen der Einzelsektoren ld a,2 ld (dl_r),a ;Anfangswert f302 ld hl,dl_r dec (hl) jp z,begin ;Formatierung ok. ld a,1 ld (ident+4),a ;Sektor ld hl,2400h ;18 Sektoren ld a,(secs) cp 18 jr z,f303 ld hl,2200h ;17 Sektoren f303 ld (dt_len),hl ld a,0 ld (rd_mod),a call rd_id jp nz,f301 jp f302 ; Eintragen der Adresse der Defektspur in die Defektspurtabelle ; df_tab : Anfangsadresse der Defektspurtabelle ; df_end : Adresse des Beginns der Eintragung des Endekennzeichens f_def xor a ld (err_cd),a ;Loeschen Fehlercode ld hl,(df_end) ld c,(hl) inc hl ld b,(hl) ;BC: Anzahl schon eingetragener Spuren ld hl,39*3 ;Maximum = 120 ( -3) xor a sbc hl,bc jp c,err_16 ;Fehler 16: BTT voll ld hl,(df_tab) ;Beginn der aktuellen BTT f350 ld a,(ident+2) ;High-Teil Zylinder ld b,a ld a,(hl) cp b jp c,f351 jp nz,f358 inc hl ld a,(ident+1) ;Low-Teil Zylinder ld b,a ld a,(hl) cp b jp c,f352 jp nz,f357 inc hl ld a,(ident+3) ;Kopf ld b,a ld a,(hl) cp b jp c,f353 jp z,begin ;Eintragung schon vorhanden ; Verschieben der Resttabelle nach hinten dec hl f357 dec hl f358 ex de,hl ;DE: unterste Adresse zum Umladen push de ld hl,(df_end) ;Adresse des Endwertes push de ld e,(hl) inc hl ld d,(hl) ex de,hl pop de ld bc,(df_tab) add hl,bc inc hl inc hl inc hl push hl ;HL: erster freier Platz nach Endek. xor a sbc hl,de push hl pop bc ;BC: Anzahl der umzuladenden Bytes pop hl dec hl ;Quelle: oberstes Byte push hl pop de inc de inc de inc de ;Ziel: oberstes Byte lddr ;Verschieben der Resttabelle pop de ex de,hl ; Eintragen der defekten Spuradresse ld a,(ident+2) ;High-Teil Zylinder ld (hl),a inc hl ld a,(ident+1) ;Low-Teil Zylinder ld (hl),a inc hl ld a,(ident+3) ;Kopf ld (hl),a ld de,(df_end) ld a,(de) ld l,a inc de ld a,(de) ld h,a ld bc,3 add hl,bc dec de ld a,l ld (de),a inc de ld a,h ld (de),a ; Ausgabe der Adresse des defekten Sektors an den Host ld bc,3 ld hl,ident+3 ld a,3 ;Status 3 call p_wc_h jp begin ; naechste Eintragung f351 inc hl f352 inc hl f353 inc hl ; Ende-Test ld a,(hl) cp 0ffh jp nz,f350 jp f358 eject ;************************************************* ; Formatieren der aktuellen Spur ;************************************************* ft_trk ld a,(st_ina) out (DSKC2),a ;alles inaktiv out (IMPAUS),a ; Loeschen des RAM von 2000 bis 2fff ld hl,ram ;Anfangsadresse ld bc,0fffh ;Laenge ld de,ram+1 ld (hl),0 ;Loeschbyte ldir ; Programmierung der Transfer-Richtung ld a,(cnt_st) set 7,a ;RAM-->Disk res 6,a ;DA12=0 ld (cnt_st),a out (CNTST),a ; Laden des Diskadresszaehlers ld hl,2000h call b_daz ld (hl),a ; Einschalten der Disk-Schnittstelle ld a,(st_wm) ;'WG=aktiv' & 'DEN=aktiv' ld b,a res 3,a out (DSKC2),a ;Schnittstelle in Betrieb ld a,b out (DSKC2),a ; Warten auf den 2.Index ld hl,isr_al ld (isr_ix),hl ;Eintragen der ISR-Adresse ld a,0d5h ;Counter & L-H-Flanke out (CTC+3),a ld a,2 out (CTC+3),a halt ;Warten auf Interrupt nach zwei Impulsen ; --- warten -------------------- ; Ausschalten der Schnittstelle nach dem Spurloeschen ld a,(st_ina) out (DSKC2),a ;alles inaktiv out (IMPAUS),a ;Disk_Schnittstelle aus ld a,3 out (CTC+3),a ;CTC/3-Reset ; Ende, wenn "Spurloeschen" ld a,(cmd_br-8) cp 84h ret z ; Sektoraufbau ld hl,kf_top ;Beginn der Praeambel ld b,18 id1 ld (hl),0ffh inc hl djnz id1 ld b,3 id2 ld (hl),0a1h ;Vorbytes inc hl djnz id2 ld (hl),0feh ;Identmarke inc hl ex de,hl ld bc,3 ld hl,ident+1 ldir ;Cylinder & Head ex de,hl ld (hl),1 ;Beginn mit Sektornummer 1 inc hl ld b,12 id3 ld (hl),0ffh ;2 Byte CRC und 10 Byte Luecke inc hl djnz id3 ;--------------------------------------------------- ; Vorbereiten der Disk-Schnittstelle zum Formatieren ;--------------------------------------------------- ; Bestimmung Disk-Adresszaehler ld hl,3600h call b_daz ld (dsk_az),hl ld (hl),a ;Laden des Zaehlers ; Markenaufbau ld a,4 ;MFM & PRAEOFF ld d,a ld a,(cmd_br-7) ;akt. Laufwerk call cy_pos ld b,(hl) ;Low-Teil Zylinderposition inc hl ld h,(hl) ;High-Teil Zylinderposition ld l,b ld bc,(pre_cy) ;Praekompensationsbeginn xor a sbc hl,bc jr c,pr_ok ld a,0ch ;MFM & PRAEON ld d,a pr_ok ld a,d out (BM_D),a ld a,0ah ;Taktbits der Marken out (BM_T),a ; Einstellen des RAM-Bereichs ld a,(cnt_st) set 6,a ;RAM12 = 1 ld (cnt_st),a out (CNTST),a ; Eintragen der ISR-Adressen ld hl,isr_al ld (isr_ix),hl ;ISR-Adresse ; DEND-Adresse festlegen ld a,0ffh out (DSKEA),a ; Bereitstellung der Sektorreihenfolge in 'fs_tab' ld hl,fs_tab ;RAM-Tabelle ld a,(ident+3) ;Kopfnummer ld b,0 ld c,a add hl,bc ;Beginn der Sektornummern fuer akt. Kopf ex de,hl ;DE: Position der Sektornummer 1 ld b,a ;Kopfnummer ld a,(secs) ;Anzahl der Sektoren sub b ;Anzahl der umzuladenden Sektoren ld b,0 ld c,a ;BC: Anzahl ld hl,sc_tab ;Reihenfolge fuer Kopf 0 ldir ld a,(ident+3) ;Kopfnummer cp 0 jr z,fs_ta1 ;kein weiteres Umladen ld c,a ld b,0 ld de,fs_tab ;Beginn der RAM-Tabelle ldir ;Umladen des Rests ; Sektornummer initialisieren fs_ta1 ld hl,fs_tab ;Beginn der Sektortabelle ld a,(hl) ex de,hl ld hl,kf_top+19h ;Speicherplatz der Sektornummer ld (hl),a ld a,(secs) ld b,a ;Sektorenzaehler ;----------------------------------------------------------------- ; Formatieren einer Spur (Schreiben der Kennfelder) ;----------------------------------------------------------------- ; CTC-Programmierung fuer Indexerkennung vor dem Formatieren ld a,0d5h ;Counter out (CTC+3),a ld a,1 out (CTC+3),a halt ;Warten auf den naechsten Index ; --- warten --- warten --- warten --- warten --- warten f_nsec ld a,3 out (CTC+3),a ;Reset IX-Interrupt ld a,(st_wa) ;alles aktiv ld c,a res 3,a ;'WG=inaktiv' out (DSKC2),a ;Schnittstelle an (ohne WG) ld a,c out (DSKC2),a ;Schnittstelle an (mit WG=aktiv) ld a,12h out (DSKEA),a ;DEND zum Markeneinblenden und -anzahl nop nop nop nop nop nop nop nop nop nop nop ld a,(st_wc) out (DSKC2),a ;CRC-Einblenden ld a,1ah out (DSKEA),a ;DEND zum CRC-Einblenden nop nop nop nop nop ld a,(st_ina) out (DSKC2),a ;Schnittstelle aus out (IMPAUS),a ld hl,(dsk_az) ld (hl),a ;Diskadresszaehler neu laden ld a,87h ;Timer & VT16 out (CTC+3),a ld a,(ztk) ;berechnete Zeitkonstante out (CTC+3),a inc de ;Tabelle der Reihenfolge der Sektoren ld a,(de) ;Sektornummer ld hl,kf_top+19h ;Adresse der Sektornummer ld (hl),a dec b jp z,ft_end halt ;Warten auf Zeitinterrupt ;--- Warten ----- jp f_nsec ft_end ld a,3 out (CTC+3),a ;Reset CTC/3 xor a ;----------------------------------------------------- ; Initialisieren der Datenfelder ;----------------------------------------------------- ld hl,ram ld de,ram+1 ld bc,0fffh ld (hl),0e5h ldir ;---------------------------------------------------- ; Schreiben der Datenfelder ;---------------------------------------------------- ; Setzen der Fehlerzaehler fuer das Lesen der Kennfelder ld de,c_zt ld hl,fe_n ld bc,7 ldir ; Schreiben der Datenfelder der Sektoren ld a,4 ld (ct_ra),a ;Zaehler fuer Schreibwiederholungen ld a,1 ;Beginn mit Sektor 1 ld (ident+4),a ld hl,2400h ;18 Sektoren ld a,(secs) cp 18 jr z,wrt_d1 ld hl,2200h ;17 Sektoren wrt_d1 ld (dt_len),hl call wrt_dt ;Schreiben der Datenfelder ret ;Schreibfehler eject ;*********************************************************************** ; Datentransfer zwischen Host und WDC-RAM ;*********************************************************************** ram_tr ld hl,cmd_br-7 ;RAM-Anfangsadresse ld a,(hl) ld e,a inc hl ld a,(hl) ld d,a ;(DE): Anfangsadresse ld hl,cmd_br-2 ;Laenge ld a,(hl) ld c,a inc hl ld a,(hl) ld b,a ;(BC): Laenge ex de,hl add hl,bc dec hl ld a,(cmd_br-8) ;Kommandocode cp 08h ;Lesen WDC-RAM ? jp z,rd_ram cp 18h ;Schreiben WDC-RAM ? jp z,wt_ram cp 28h ;Lesen WDC-Parameterblock ? jp z,rd_pb cp 78h ;Schreiben WDC-Parameterblock ? jp z,wr_pb cp 38h ;Lesen WDC-Fehlerstatistik ? jp z,rd_fs cp 58h ;Lesen WDC-RAM-BTT (auf den Host-RAM) ? jp z,rd_def cp 68h ;Schreiben WDC-RAM-BTT (aus Host-RAM) ? jp z,wr_def cp 48h ;Loeschen BTT im WC-RAM ? jp nz,err_1 ;----------------------------------------------------- ; Loeschen Defektspurtabelle ;----------------------------------------------------- call def_ad call btt_cl jp begin ;----------------------------------------------------- ; Lesen der BTT aus dem WDC-RAM in den Host-RAM ;----------------------------------------------------- rd_def call def_ad ld hl,(df_end) push bc call t_btt1 pop bc jp nz,err_18 ld hl,(df_end) add hl,bc dec hl ld a,3 call p_wc_h jp begin ;----------------------------------------------------- ; Schreiben der BTT im WDC-RAM aus dem Host-RAM ;----------------------------------------------------- wr_def call def_ad ld hl,(df_end) add hl,bc dec hl ld a,2 call p_h_wc jp begin ;----------------------------------------------------- ; Lesen WDC-RAM ;----------------------------------------------------- rd_ram ld a,3 call p_wc_h jp begin ;----------------------------------------------------- ; Schreiben WDC-RAM ;----------------------------------------------------- wt_ram ld a,2 call p_h_wc jp begin ;----------------------------------------------------- ; Schreiben WDC-Parameterblock ;----------------------------------------------------- wr_pb ld hl,p_blk add hl,bc dec hl ld a,2 call p_h_wc jp begin ;----------------------------------------------------- ; Lesen WDC-Parameterblock ;----------------------------------------------------- rd_pb ; Eintragen der Parameter push bc ld hl,string ;Zeichenkette zur Identifizierung ld de,p_str ld bc,7 ldir ; Umladen der Anzahl der Bloecke ld hl,bl_dr0 ld de,zmx_41 inc de ld bc,4 ldir ; Umladen 'd_rdy', s_rdy, 'err_in', Anzahl Laufwerke ld a,(d_rdy) ld (de),a inc de ld a,(s_rdy) ld (de),a inc de ld a,(err_in) ld (de),a inc de ld a,(d_rdy) ld b,3 ld c,0 dr_t0 rrc a jr nc,dr_t1 inc c dr_t1 djnz dr_t0 ;Anzahl der angeschlossenen Laufwerke ld a,c ld (de),a ; Ausgabe der Parameter pop bc ld hl,p_str add hl,bc dec hl ld a,3 call p_wc_h jp begin ;----------------------------------------------------- ; Lesen WDC-Fehlerstatistik ;----------------------------------------------------- rd_fs ld hl,sum_zt add hl,bc dec hl ld a,3 call p_wc_h jp begin eject ;--------------------------------------------------------------- ; PROGRAMMIERUNG DER HOST-SCHNITTSTELLE ;--------------------------------------------------------------- ; A: Status des WDC ; BC: Laenge der Ausgabe ; HL: Endadresse des Ausgabebereichs ;--------------------------------------------------------------- p_wc_h ;WDC-RAM --> Host ; bei 'WDC-->Host' muss ein Byte mehr uebertragen werden ; (wird vom Host nicht abgeholt, nur zur Ready-Abschaltung PIO) push af p_sl1 ld a,(hst_by) ;Besetzt-Anzeiger bit 7,a jr nz,p_sl1 ;Warten in Schleife, wenn Treiber besetzt set 7,a ;Treiber besetzt ld (hst_by),a inc hl inc bc ld a,(cnt_st) set 5,a ;WDC-RAM --> Host ld (cnt_st),a pop af jr p_h_1 ;------------------------------------------------------------ p_h_wc ;Host --> WDC-RAM push af p_sl2 ld a,(hst_by) ;Besetzt-Anzeiger bit 7,a jr nz,p_sl2 ;Warten in Schleife, wenn Treiber besetzt set 7,a ;Treiber besetzt ld (hst_by),a ld a,(cnt_st) res 5,a ;WDC-RAM <-- Host ld (cnt_st),a pop af ;------------------------------------------------------------ p_h_1 push hl ;Endadresse retten push bc ;Laenge retten push af ;Status retten ; Wert des Adresszaehlers berechnen xor a sbc hl,bc inc hl ;Beginn des E/A-Bereiches pop af push hl ;Beginn retten push af res 5,h ;Kennzeichnung RAM ruecksetzen (Bit 13) ; Ausgabebyte fuer CNTST aktualisieren ld a,(cnt_st) ;Programmierbyte res 4,a ;HA12 = 0 bit 4,h ;Adressbit 12 gesetzt ? jr z,hrt1 set 4,a ;HA12 = 1 hrt1 ld (cnt_st),a pop af push af ld b,a ld a,(cnt_st) set 3,a ;HEN ein or b ;Status einfuegen ld (cnt_st),a ;Ausgabebyte ; Host-Adresszaehler-Kennzeichnung einfuegen ld a,h and 0ch ;Bit 11,10 der Adresse rlca rlca rlca rlca ;Bit 15,14 ld b,a ld a,h and 03h ;Bit 9,8 der Adresse or b ;Bit 15,14,9,8 or 038h ;Kennzeichnung einfuegen ld h,a ;Host-Adresszaehler fertig pop af pop de ;Beginn des Bereichs pop bc ;Laenge des Bereichs ; Host-Adresszaehler laden ld (hl),a ; Bestimmung der Schaltflanke fuer den CTC-Kanal pop hl ;Endadresse des E/A-Bereiches ld a,0c7h ;Uebergang '1...0' bit 0,l ;gerade oder ungerade jr nz,hrt11 ld a,0d7h ;Uebergang '0...1' hrt11 ld (ctc_st),a ; Bestimmung der CTC-Clocks inc bc xor a rr b rr c ;Laenge/2 ld hl,100h xor a sbc hl,bc jr c,gr_100 ; CTC-Clocks kleiner/gleich 100h hrt17 ld a,(ctc_st) ;CTC-Steuerwort out (CTC+2),a ld a,c ;Anzahl der Impulse out (CTC+2),a ld hl,cnt_st ld a,(hl) res 3,(hl) ;'HEN=inaktiv' out (CNTST),a ;Ansteuerung aktiv ld a,(hl) out (CNTST),a ;Vorbereitung von 'Schnittstelle inaktiv' ret ; CTC-Clocks groesser 100h gr_100 xor a cp c ;C = 0 ? jr nz,gr_101 dec b gr_101 ld a,b ld (hst_bl),a ;Anzahl der Bloecke auf der HS ld hl,isr_h1 ;ISR-Adresse ld (isr_hs),hl ld a,(ctc_st) ;CTC-Steuerwort out (CTC+2),a ld a,c out (CTC+2),a ld a,(ctc_st) ;CTC-Steuerwort res 1,a ;kein Reset out (CTC+2),a ld a,0 out (CTC+2),a ;256 Impulse ld a,(cnt_st) out (CNTST),a ret ;--------------------------------------------------------------- ; Interruptroutinen fuer den Host-Adresszaehler ;--------------------------------------------------------------- ; ISR fuer Zwischeninterrupts bei langen Uebertragungen isr_h1 push af push hl ld hl,hst_bl ;Zaehler fuer HS-Bloecke dec (hl) jr nz,isr_h2 ;Sprung, wenn Zaehler nicht abgelaufen ld hl,isr_h0 ;ISR fuer letzen Interrupt ld (isr_hs),hl ld a,(cnt_st) res 3,a ;'HEN=inaktiv' ld (cnt_st),a out (CNTST),a isr_h2 pop hl pop af ei reti ; ISR fuer letzten Interrupt waehrend eines Transfers isr_h0 push af ld a,(cnt_st) and 0d0h ;'TR=inaktiv' & 'HEN=inaktiv' & Status=0 ld (cnt_st),a out (CNTST),a ld a,3 out (CTC+2),a ld a,(hst_by) res 7,a ;Treiber frei ld (hst_by),a pop af ei reti eject ;--------------------------------------------------------------------- ; Fehlerauswertung und Uebergabe an den Host ;--------------------------------------------------------------------- err_1 ld a,1 jr error1 err_2 ld a,2 jr error1 err_3 ld a,3 jr error1 err_4 ld a,4 jr error1 err_5 ld a,5 jr error1 err_6 ld a,6 jr error1 err_7 ld a,7 jr error1 err_15 ld a,15h jr error1 err_16 ld a,16h jr error1 err_17 ld a,17h jr error1 err_18 ld a,18h jr error1 error1 ld (err_cd),a ; Programmierung der Host-Schnittstelle error ld a,(err_cd) ld (err_br),a ld bc,1 ;Ausgabelaenge ld hl,err_br ;auszugebendes Byte ld a,7 ;Status '7' call p_wc_h ;Programmierung der Host-Schnittstelle xor a ld (err_cd),a ;Loeschen des Fehlercodes jp begin ;--- b_daz --------------------------------------------- ; Berechnung des Disk-Adresszaehlers ; in : HL Adresse ; out: HL Disk-Adresszaehler ;--------------------------------------------------------- b_daz res 5,h ;Kennzeichnung RAM ruecksetzen ld a,h and 0ch ;Bit 11,10 der Adresse rlca rlca rlca rlca ld b,a ld a,h and 03h ;Bit 9,8 der Adresse or b ;Bit 15,14,9,8 des Disk-Adresszaehlers or 03ch ;Kennzeichnung einfuegen ld h,a ;Adresszaehler fertig ret ;--- time -------------------------------------- ; ca. 0,01 ms pro Durchlauf, 4MHz-CPU, Wait-Zyklen ; DE: Zaehlwert ;------------------------------------------------- time ld a,1 ld a,1 dec de bit 7,d jr z,time ret ;--- time1 ---------------------------------- ; ca. 1 ms pro Durchlauf, 4MHz-CPU, Wait-Zyklen ; DE: Zaehlwert ;---------------------------------------------- time1 push de ld de,130 time10 dec de bit 7,d jr z,time10 pop de dec de ld a,d or e jr nz,time1 ret ;--- time2 ----------------------------------- ; ca. 10 ms pro Durchlauf, 4MHz-CPU, Wait-Zyklen ; DE: Zaehlwert ;----------------------------------------------- time2 push de ld de,1288 time20 dec de bit 7,d jr z,time20 pop de dec de ld a,d or e jr nz,time2 ret ;--- crc_br ----------------------------------- ; CRC-Berechnung ;------------------------------------------------ crc_br ld de,-1 crc1 ld a,(hl) xor d ld d,a rrca rrca rrca rrca and 0fh xor d ld d,a rrca rrca rrca push af and 1fh xor e ld e,a pop af push af rrca and 0f0h xor e ld e,a pop af and 0e0h xor d ld d,e ld e,a inc hl dec bc ld a,b or c jr nz,crc1 ret ;---------------- PROGRAMMTEXT-ENDE --------------------------------------- begin 1 ; Tabelle der Kommandocodes com_tb db 021h ;HD-Lesen von einer Blocknummer db 022h ;HD-Schreiben auf eine Blocknummer db 001h ;HD-Lesen von einer Sektoradresse db 081h ;HD-Testlesen von einer Sektoradresse db 011h ;HD-Lesen von einer Sektoradresse mit BTT-Berueck. db 002h ;HD-Schreiben auf eine Sektoradresse db 082h ;HD-Schreiben auf eine Sektoradresse mit Ruecklesen db 012h ;HD-Schreiben auf eine Sektoradresse mit BTT-Berue. db 092h ;HD-Schreiben auf eine Sektoradresse mit BTT- ;Beruecksichtigung und Ruecklesen db 0a1h ;HD-Kopieren von einer Blocknummer des LW 1 auf LW 0 db 0a2h ;HD-Schreiben auf eine Blocknummer mit Ruecklesen db 0c2h ;HD-Schreiben von PAR und BTT auf das Laufwerk db 004h ;HD-Formatieren einer Spur db 014h ;HD-Formatieren einer Spur mit Ruecklesen db 024h ;HD-Formatieren einer Spur mit Defektspurfeststellung db 044h ;HD-Ruecklesen einer Spur (Verify) db 084h ;HD-Loeschen einer Spur db 008h ;Lesen WDC-RAM db 018h ;Schreiben WDC-RAM db 028h ;Lesen des WDC-Parameterblocks db 038h ;Lesen der WDC-Fehlerstatistik db 048h ;Loeschen der BTT im WDC-RAM db 058h ;Lesen der BTT aus dem WDC-RAM in den Host-RAM db 068h ;Schreiben der BTT aus dem Host-RAM in den WDC-RAM db 078h ;Schriben des WDC-Parameterblocks db 0ffh ;Endekennzeichen ; Praeambel beim Schreiben eines Datenfeldes (13 Byte) prae db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0a1h db 0fbh ; Postambel beim Schreiben eines Datenfeldes (12 Byte) post db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh db 0ffh ; Kennfeld der Defektspurtabelle id_df db 0feh db 00h db 00h db 00h db 01h ; Kennung der Parametertabelle txt_pm text 'PARMTR' ; Kennung der Defektspurtabelle txt_df text 'DEFEKT' ; Fehlerzaehler fuer normales Lesen fe_n db 4 db 8 db 4 db 4 db 4 db 4 db 4 ; Fehlerzaehler fuer das Formatieren fe_f1 db 2 db 2 db 2 db 2 db 2 db 2 db 2 ; Fehlerzaehler fuer das Testlesen fe_t db 1 db 1 db 1 db 1 db 1 db 1 db 1 ; Tabelle des Sektorversatz db 0ffh sc_tab db 1 db 10 db 2 db 11 db 3 db 12 db 4 db 13 db 5 db 14 db 6 db 15 db 7 db 16 db 8 db 17 db 9 db 18 db 0ffh end