; ********************** ; *** EMS-HD20.Z80 *** ; ********************** hd_strt .PHASE 8A00H ; ; ------ >>> Teste ob HARDDISK vorhanden <<< ------ ; test_hd LD A,(hd_flag) ;X-DDOS HD-Flag -> 'A' INC A ;Harddisk aktiv ? lD A,00H ;00h => keine Harddisk JR NZ,xtesthd ;Abbruch wenn HD not ready ; LD HL,dph_d ;Zeiger auf DPH Drive D LD (2E35H),HL ; in die Drive Table LD HL,dph_e ;Zeiger auf DPH Drive E LD (2E37H),HL ; in die Drive Table LD HL,dph_f ;Zeiger auf DPH Drive F LD (2E39H),HL ; in die Drive Table LD HL,dph_g ;Zeiger auf DPH Drive G LD (2E3BH),HL ; in die Drive Table LD HL,dpb_hd LD BC,7FC1H ;Common-Bank ab 0C000h OUT (C),C ; einblenden LD DE,dpb_d ;DPB in die Common Bank LD BC,0011H ; kopieren LDIR LD BC,7FC0H ;Die 1. 64K wieder OUT (C),C ; komplett einschalten LD A,20H ;Msg#20 ', HD20 hard disc' ; xtesthd LD (0BE3DH),A ;CP/M+ Harddisk-Flag setzen RET ; ; ------ >>> Write HARDDISK-Sector <<< ------ ; hd_wrte LD HL,hdwrsec ;Adr Befehls-Block -> 'HL' LD DE,sendata ;Adr WRITE-Routine -> 'DE' JR hd_rdwr ; ; ------ >>> Read HARDDISK-Sector <<< ------ ; hd_read LD HL,hdrdsec ;Adr Befehls-Block -> 'HL' LD DE,rcvdata ;Adr READ-Routine -> 'DE' ; ; ------ >>> Read/Write HARDDISK-Sector <<< ------ ; ; Das RAM ist beim Einsprung wie folgt belegt: ; ; = Drive-Nr. ( 3..6 ) ; = Log.Track-Nr. ( 0..203 ) ; = Log.Sector-Nr. ( 0..50 ) ; = Zeiger auf 512 Byte Sector-Buffer ; = Sector-Buffer Bank ; hd_rdwr PUSH HL ;Adr Befehls-Block merken PUSH DE ;Adr RD/WR-Routine merken CALL hd_prep ;Kommando senden BIT 2,A ;STATUS State ? JR NZ,badrdwr ;Ja, dann Fehler POP HL PUSH HL ;Adr RD/WR-Routine -> 'HL' LD DE,0FFE0H ;Zieladr. in COMMON-Page LD BC,21 ;L{nge der RD/WR-Routine LDIR LD DE,512 ;512 Byte Sectorl{nge LD HL,(dmaadr) ;Buffer-Adr. -> 'HL' LD A,(dmabnk) ;Buffer-Bank -> 'A' ADD 0C1H LD C,A LD B,7FH ;7FC1H - 7FC3H -> 'BC' CALL 0FFE0H ;Sector lesen/schreiben LD BC,hdstat ;HDSTAT -> 'BC' CALL wtctrl badrdwr CALL errchck ;Fehler aufgetreten ? CALL NC,ric_err ;Evtl. Meldung ausgeben POP DE ;Adr RD/WR-Routine -> 'DE' POP HL ;Adr Befehls-Block -> 'HL' LD A,00H ;00h => Alles OK RET C ;RET wenn alles OK JR NZ,hd_rdwr ;Nochmal bei RETRY INC A ;01h => Fehler RET ;Abbruch bei CANCEL ; ; ------ >>> Retry Ignore Cancel Fehler <<< ------ ; ric_err LD A,(scb+4BH) ;Message-Flag -> 'A' INC A ;Fehlermeldungen erlaubt ? RET Z ;Nein, dann Abbruch ; LD A,(track) LD D,A ;Track -> 'D' LD A,(sector) LD E,A ;Sector -> 'E' LD A,(phydrv) LD C,A ;Drive -> 'C' LD B,03H ;= Fehler-Nr. 'data error' JP xbios41 ;R-I-C Fehler ausf}hren ; ; ------ >>> SEND DATA <<< ------ ; sendata DI OUT (C),C ;Die DMA-Bank im Bereich LD BC,hddata ; 0000H - 0BFFFH einblenden ; sndloop INC B ;'BC' f}r OUTI korrigieren OUTI ;Daten-Byte schreiben DEC DE ;Z{hler = Z{hler - 1 LD A,D ;Sind schon alle OR E ; Bytes geschrieben ? JR NZ,sndloop ;Nein, dann weiter ; LD BC,7FC1H ;SYSTEM- & COMMON-Bank OUT (C),C ; wieder einschalten EI RET ; ; ------ >>> RECEIVE DATA <<< ------ ; rcvdata DI OUT (C),C ;Die DMA-Bank im Bereich LD BC,hddata ; 0000h - 0BFFFh einblenden ; rcvloop INI ;Daten-Byte lesen INC B ;'BC' nach INI korrigieren DEC DE ;Z{hler = Z{hler - 1 LD A,D ;Sind schon alle OR E ; Bytes gelesen ? JR NZ,rcvloop ;Nein, dann weiter ; LD BC,7FC1H ;SYSTEM- & COMMON-Bank OUT (C),C ; wieder einschalten EI RET ; ; ------ >>> HARDDISK Login/Init <<< ------ ; hd_logn EX DE,HL justret RET ; ; ------ >>> Read/Write vorbereiten <<< ------ ; ; Einsprung: ; ; 'HL' = Zeiger auf Command-Block ; ; Cylinder, Head & Sector berechnen, ; im Command-Block eintragen und senden ; hd_prep PUSH HL LD A,(sector) ;Sector-Nr. -> 'A' LD HL,(track) ;Log.Track -> 'HL' LD C,L LD B,H ;Log.Track -> 'BC' ADD HL,HL ADD HL,BC ;Log.Track * 3 -> 'HL' LD C,-17 ;Division durch 17 DEC HL ;Phys.Track - 1 inctrk INC HL ;Phys.Track erh|hen ADD A,C ;Log.Sector - 17 -> 'A' JR C,inctrk SUB C ;Rest = Phys.Sector LD C,A ;Phys.Sector-Nr. -> 'C' LD A,L AND 00000011B LD B,A ;Head -> 'B' SRL H RR L SRL H ;DIV 4 = Cylinder RR L ;Cylinder -> 'HL' LD A,(phydrv) ;Drive -> 'A' LD DE,153*0 ;= Startcyl. Drive D SUB 03H ;Drive D ? JR Z,add_cyl ;Ja, dann springe LD DE,153*1 ;= Startcyl. Drive E DEC A ;Drive E ? JR Z,add_cyl ;Ja, dann springe LD DE,153*2 ;= Startcyl. Drive F DEC A ;Drive F ? JR Z,add_cyl ;Ja, dann springe LD DE,153*3 ;= Startcyl. Drive G add_cyl ADD HL,DE ;Startcyl. addieren EX DE,HL ;Cylinder -> 'DE' ; POP HL INC HL LD (HL),B ;Head -> Datenblock+1 INC HL INC HL ;Adr.Datenblock+3 (Cyl.) LD (HL),E ;LSB Cyl. -> Datenblock+3 SRL D RR E SRL D RR E ;DIV 4 LD A,E AND 11000000B ADD A,C ;MSB Cyl. + Sector -> 'A' DEC HL ;Adr.Datenblk+2 (Cyl./Sec) LD (HL),A ;MSB Cyl./Sec-> Datenblk+2 DEC HL DEC HL ;Adr. Datenblock -> 'HL' ; ; ------ >>> SEND COMMAND <<< ------ ; sendcmd LD BC,hdslct OUT (C),A ;Select Controller DEC C DEC C ;HDDATA -> 'BC' cmdloop INC C ;HDSTAT -> 'BC' CALL wtctrl ;Wait Controller Ready CP 00001101B ;COMMAND State ? RET NZ ;Nein, dann RET DEC C ;HDDATA -> 'BC' LD A,(HL) ;Command-Byte -> 'A' OUT (C),A ;Zum Controller senden INC HL JR cmdloop ; ; ------ >>> WAIT_CONTROLLER_READY <<< ------ ; wtctrl IN A,(C) ;Controller Status -> 'A' AND 00001111B ;Mask significant Bits BIT 0,A ;Controller Ready ? RET NZ ;Ja, dann RET BIT 3,A ;Controller selected ? JR NZ,wtctrl ;Ja, dann warten RET ; ; ------ >>> ERROR CHECKING <<< ------ ; ; RET mit CARRY = 1 und ZERO = 1 => Kein Fehler ; RET mit CARRY = 0 und ZERO = 0 => Fehler ; errchck CP 00001111B ;STATUS State ? JR NZ,hderror ;Nein, dann springe DEC C ;HDDATA -> 'BC' IN A,(C) ;Result-Phase -> 'A' BIT 1,A ;Fehler aufgetreten ? SCF ;Nein, dann RET mit RET Z ; Carry & Zero = 1 ; hderror LD A,0FFH AND A ;RET mit Carry & Zero = 0 RET ; wenn Fehler aufgetreten ; ; ------ >>> Daten-Bl|cke <<< ------ ; hdrdsec DEFB 08H,00H,00H,00H,01H,02H ;Read Sector hdwrsec DEFB 0AH,00H,00H,00H,01H,01H ;Write Sector ; ; ------ >>> Daten- und Systemvariablen <<< ------ ; DEFW hd_wrte ;Sector schreiben DEFW hd_read ;Sector lesen DEFW hd_logn ;Login Drive DEFW justret ;No Init DEFB 03H ;03h => Drive D DEFB 00H ;Not used dph_d DEFW 0000H ;No XLT DEFS 10,00H ;DPH Drive D (Harddisk) DEFW 0FF98H ;Adr. DPB DEFW 0000h ;No DIR-Check DEFW alv_d DEFW 0BEFBH ;DIR Buffer Control Block DEFW 0BEFDH ;DATA Buffer Control Block DEFW 5080h ;HASH Drive D DEFB 02H ;HBANK ; DEFW hd_wrte ;Sector schreiben DEFW hd_read ;Sector lesen DEFW hd_logn ;Login Drive DEFW justret ;No Init DEFB 04H ;04h => Drive E DEFB 00H ;Not used dph_e DEFW 0000H ;No XLT DEFS 10,00H ;DPH Drive E (Harddisk) DEFW 0FF98H ;Adr. DPB DEFW 0000H ;No DIR-Check DEFW alv_e DEFW 0BEFBH ;DIR Buffer Control Block DEFW 0BEFDH ;DATA Buffer Control Block DEFW 5880H ;HASH Drive E DEFB 02H ;HBANK ; DEFW hd_wrte ;Sector schreiben DEFW hd_read ;Sector lesen DEFW hd_logn ;Login Drive DEFW justret ;No Init DEFB 05H ;05h => Drive F DEFB 00H ;Not used dph_f DEFW 0000H ;No XLT DEFS 10,00H ;DPH Drive F (Harddisk) DEFW 0FF98H ;Adr. DPB DEFW 0000H ;No DIR-Check DEFW alv_f DEFW 0BEFBH ;DIR Buffer Control Block DEFW 0BEFDH ;DATA Buffer Control Block DEFW 6080H ;HASH Drive F DEFB 02H ;HBANK ; DEFW hd_wrte ;Sector schreiben DEFW hd_read ;Sector lesen DEFW hd_logn ;Login Drive DEFW justret ;No Init DEFB 06H ;06h => Drive G DEFB 00H ;Not used dph_g DEFW 0000H ;No XLT DEFS 10,00H ;DPH Drive G (Harddisk) DEFW 0FF98H ;Adr. DPB DEFW 0000H ;No DIR-Check DEFW alv_g DEFW 0BEFBH ;DIR Buffer Control Block DEFW 0BEFDH ;DATA Buffer Control Block DEFW 6880H ;HASH Drive G DEFB 02H ;HBANK ; ; ------ >>> Disk Parameter Block Harddisk <<< ------ ; ; Aufteilung der Harddisk: ; ; 153 Cylinder / Partition ; 4 phys. Tracks / Cylinder ; ; 1 log. Track = 3 phys. Tracks = 3/4 Cylinder ; ; => 204 log. Tracks / Partition ; 204 Records / log. Track ; 1294 Bl|cke / Partition => 2*162 Byte ALV ; dpb_hd DEFW 00CCH ;128 Byte-Records / log.Tr DEFB 05H ;Block Shift DEFB 00011111B ;Block Maske DEFB 00000001B ;Extend Maske DEFW 050DH ;Maximale Blocknummer DEFW 01FFH ;Directory Eintr{ge-1 DEFW 00F0H ;4 Bl|cke Verzeichnisgr|~e DEFW 8000H ;Zu pr}fende Eintr{ge / 4 DEFW 0001H ;Anzahl der log.System-Tr. DEFB 02H ;PSH DEFB 03H ;PHM ; ; ------ >>> Allocation Vectoren Harddisk <<< ------ ; alv_d EQU 0*2*162+$ ;ALV Drive D (Harddisk) alv_e EQU 1*2*162+$ ;ALV Drive E (Harddisk) alv_f EQU 2*2*162+$ ;ALV Drive F (Harddisk) alv_g EQU 3*2*162+$ ;ALV Drive G (Harddisk) .DEPHASE