HDD - driver for working with HDD.

After repairing the computer, I started testing the HDD driver, which
I dashed off under is-dos. Connected a clean HDD with SLAV and installed
driver in is-dos. I haven’t created any partitions on the disk yet, but
In the driver I registered the beginning of the partitions on the zero sector of the HDD SLAVE.
I ran CREATE and created an IS disk with a size of 24576 blocks. For tes─
After testing the work, I decided to copy the system disk one-to-one.
He started the copier and leaned back in his chair. However, what already
After a few seconds the copier fell out with an error, which meant─
It appears that the directory was not found. In the root directory of the disk there was already
two directories with subdirectories. I couldn’t get into some of them─
tee. It is difficult to look for such an error when “here I write correctly, but here
how will it turn out."
You need to think about how to find an error without using shadow debugging -
Still, the DOS ports are open and the shadow guy is clearly sick of it.
For now I decided to just test the reading speed in LBA mode.
I launched the BAD.com program, which reads one sector at a time, and
It is in this mode that the superiority should be especially noticeable
LBA from CHS, because with LBA it is not necessary for every requested
sector, calculate its offset from the beginning of the section and expand
offset to absolute CHS coordinates. Those. a lot of division/multiplication─
They are simply excluded from the program.
I measured the time spent by the CHS driver and the LBA driver on the computer─
a certain amount of information. Here's what I haveit turned out:
LBA 234.03 kb/sec
CHS 227.56 kb/s
I couldn’t believe my eyes and the calculator. Such a meager increase?!

The next day I started looking for driver failures. For
First you need to determine in which sector the failure is occurring. For
So I created a text file with the following content:
SECTOR01......................
...............................
...............................
(total 8 lines of 31 characters + at the end of each line #0D. Total
256 bytes)
SECTOR02.........
...........................
(same thing)

That is file length 64 sectors. I wrote this file to an empty partition
new RHDDSMUC driver and then visually checked where something was
violated. The failure was in a new location each time, depending on
partition size. So with a size of 3200 blocks and the length of the root
directory block 4, the failure was as follows: after sector 51 there was a sector
64, then garbage, then 55,56,57,58,59,60,61,62,63, then garbage.
By sectors here I'm talking about lines in a text file.
Physically, the failure occurred on the 58th block from the beginning of the section,
(29th physical sector of HDD). The section itself started from zero
HDD sector LBA.

Two ideas emerged:
1. when remaking the original driver, I overlooked something and
made a mistake;
2. I had two versions of the original driver. They were different
quite significant.  One had the line Complete 100%, and
another, later edition did not contain such a line. But in this
versionsThere were comments and it seemed more logical to me. By─
That's why I took it upon myself to remake it. Perhaps she initially
was not completed or tested.

I decided to start with the second idea. I took the previous version and updated it─
I installed it under LBA mode. Installed it and started testing. Result
turned out to be the same.

This means I probably made a mistake when modifying the driver. To make sure
in the functionality of the original version of the driver, I just took it and compiled it─
sawed the original, installed and tested. The errors remain.
It turns out that there were errors in the original version and it is not clear
how it worked for Oleg Grigoriev, the author of the driver.
The only difference from the original is the full port addressing
#1ffd.  In the original version, access to the port went through the command─
special addressing.  This trick doesn't work on GMX either.
while the driver was running, the color of the border changed, so I did
full address.

I gathered all my thoughts into a heap and wrote a letter to Grigoriev. Bye
there was no answer.


Here is the driver source. Maybe someone can defeat him:

;RHDDLBA.BLK
;HDD DRIVER FOR SMUC WITH OPEN PORTS
;LBA-28 MODE ONLY
;MASTER/SLAVE HDD SUPPORT
;BASED ON RHDDSMUC BY RUINER AKA #0R
;(C) AMOSOV NIKOLAY AKA AMONIK
;VERSION 0.0
;COMPLETE 100%
;CREATING DATE: 24-09-2006
;LAST EDIT: 09/26/2006
;**********************************************************************

        ORG #8000

        DEFW INST;     mailing addressinstallations
        DEFW READ;     reading address
        DEFW WRIT;     post address address
        DEFW INIT;     initialization address
        DEFB #E0;      status register
        DEFB #04;      status register
        DEFW#0000;    Do not install IM2 at the output
        DEFW#0101;    TRDOS type and number of read attempts
        DEFW #ADDE;    Driver Label
;----------------------------------------------------------------
;Disk partition information format:
;In the first word the low part of the sector address is LBA bits 0...15
;In the second word, the high part of the LBA sector address bits 16...27
;bits 29...31 always =1, and bit 28 selects 0=MASTER/1=SLAVE
;Exxx=MASTER/Fxxx=SLAVE
CDEV DEFW #0000;    LBA bits 0..15
        DEFW #F000;    Drive/bits 16..27

;Coordinates of the beginning of the partition for 8 disks
DEVS DEFW #0000;    LBA 0..15
        DEFW #F000;    drive/bits 16..27

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

        DEFW #0000
        DEFW #F000

INT DEFB #00;      Interrupt status

;----------------------------------------------------------------
;Driver installation and initialization routine
INST
INIT CP #08;      No more than 8 discs
        RET NC

;Copy the coordinatesselected section to coordinate area
;current disk
        ADD A,A
        ADD A,A
        LD C,A
        LD B,0
        LD HL,DEVS
        ADD HL,BC
        LD DE,CDEV
        LD C,4;      only 4 bytes
        LDIR
        RET

;----------------------------------------------------------------
;Detecting interrupt status
;Litters on the stack and spoils HL,BC
SETDI LD HL,SETEI;      Exit through it
        EX (SP),HL
        LD (ERROR+#01),SP
        PUSH HL
        LD HL,SETDIO;     Implicit call
        PUSH HL
        LD IX,INT
        XOR A
        LD(IX),A
        LD A,R;           INT check
        RET PE
        LD A,R
        RET PE
        INC(IX)
        RET

;Opening DOS ports
SETDIO DI
        LD A,#04;    for IS-DOS CLASSIC
;       LD A,#14;    for IS-DOS CHIC
        LD BC,#1FFD
        OUT(C),A
;       LD BC,#FFBE; Status register
;       IN A,(C);    We are waiting for the device to be released,
;       RLCA;          those. reset BUSY
;       JR C,$-#03

;Enable reading prediction mode
;       LD A,(CDEV+#03)
;       DEC B;        Accumulator register
;       OUT(C),A;    Selected disk
;       LD DE,#AAEF
;       LD B,#F9;    Additional Features Register
;       OUT(C),D;    Command Options
;       LD B,#FF;    Command register
;       OUT(C),E;    Issued a command

;Waiting for releasedevices
WBSY LD BC,#FFBE; Status register
        IN A,(C);    We are waiting for the device to be released,
        RLCA;          those. reset BUSY
        JR C,$-#03;  Still busy
        RET

SETEI PUSH AF
        XOR A;        for IS-DOS CLASSIC
;       LD A,#10;    for IS-DOS CHIC
        LD BC,#1FFD
        OUT(C),A;    Closing DOS ports
        POP AF;       Restoring interrupt mode
        BIT 0,(IX)
        RET NZ
        EI
        RET

;----------------------------------------------------------------
;Subroutine for reading sector(s)
READ LD C,#7C;    Reading
        DEFB #3A;      command LD A,(NN)
WRIT LD C,#7D;    Record

        PUSH BC
        LD C,#09;    Pressure test
        RST#10;      any key
        POP B.C.
        JR Z,RW00;   Not pressed
        CP#16;      is this BREAK?
        JR NZ,RW00;  No
        LD C,#07;    Cleaning the key buffer
        RST #10
        LD A,#14;    We leave with a message
        SCF;           BREAK
        RET

;At the entrance:
;B number of blocks
;DE first block number
;HL memory address
RW00 PUSH DE;       Remember the number
        EXX;           block and others
        POP DE
        CALL SETDI;    Enabled ports
        SRL D;        divide the block number
        RR E;        by two
        EX AF,AF';   retained flag C

;Calculate the offset from the beginning of the section using the block numberLD HL,(CDEV);low part of the LBA sector address 0..15
        ADD HL,DE;    added with block number
        EX DE,HL;    remembered in DE
        LD HL,(CDEV+#02);high part of the sector address
        JR NC,$+#03; If there was no overflow of the low part
        INC HL;       Added to the senior part of the sector address
        CALL PCOORDL;  Writing to HDD registers

        EXX;
        EX AF,AF';
;Returned:
;HL memory address
;DE block number
;B number of blocks
;C operation type
;CF offset in the first sector

        LD D,B
        JR NC,$+#03; If from the middle, then reduce the amount
        DEC D;        blocks
        RLA;           We remember the offset.
        SRL D;        Number of sectors.
        RLA;           We remember the remainder and
        LD E,A;      make a copy in E.

        BIT 1,E;      If from the middle, then
        JR Z,$+#03;  increasing the quantity
        INC D;        sectors.

        SCF;           Implicitly modifying register C
        RR C;        and get the port address in it
        JR C, HDDW;   in CF type of operation.

;----------------------------------------------------------------
HDDR EX AF,AF'
        LD A,#20;    READ SECTORS Team
        EX AF,AF'
        AND #01;      Add a tail.
        ADD A,D
        CALL WKSEC0;   Issuing a command

        BIT 1,E;      Do you have a head?
        JR Z,HDDR01; no
        CALL SKIP;Skipping the first half of the sector
        LD A,#10;    Reading your head
HDDR00 CALL RDHALF+#02;Buffer pump
        DEC D
HDDR01 INC D;        Are there entire sectors?
        DEC D
        JR Z,HDDR02; No.
        CALL WAIT;     We are waiting for readiness
        LD A,#20;    Reading the whole sector
        JR HDDR00

HDDR02 BIT 0,E;      Got a tail?
        RET Z;        No
        CALL WAIT;     We are waiting for readiness
        CALL RDHALF;   Reading the tail

;----------------------------------------------------------------
;Skip half a sector at 6.875 clocks per byte
SKIP LD A,#10;    Number of repetitions
        LD B,#F8;    High byte data port address
SKIP0 DEFB #ED,#70;  command IN F,(C)
        DEFB #ED,#70
        DEFB #ED,#70
        DEFB #ED,#70
        DEFB #ED,#70
        DEFB #ED,#70
        DEFB #ED,#70
        DEFB #ED,#70
        DEC A
        JR NZ,SKIP0; One more time?
        OR A
        RET

;----------------------------------------------------------------
HDDW INC D;        There is no head, no
        DEC D;        bodies?
        JR Z,HDDW21; Yes.
        BIT 1,E;      Do you have a head?
        JR Z,HDDWFF; No
        CALL WKSECR;   Read sector
        CALL RDHLFH;   Reading 1st half into internal buffer
        CALL SKIP;     Skip 2nd half

HDDWFF LD A,#30;    Write a sector
        EX AF,AF'
        LD A,D;Number of whole sectors
        CALL WKSEC0;   They gave the command
        BIT 1,E;      Do you have a head?
        JR Z,HDDW00; No.
        PUSH HL
        CALL WRHLFH;   Writing from the buffer
        POP HL
        LD A,#10;    Writing the head
LOOP CALL WRHALF+#02
        CALL WBSY;     We are waiting for completion
        DEC D;        Reduced the number of entire sectors
HDDW00 INC D;        Do you have a body?
        DEC D
        JR Z,LOOP1;  No.
HDDW10 CALL WBSY;     We are waiting for readiness
        CALL WDRQ;     Waiting for DRQ
        LD A,#20;    We are writing a whole sector
        JR LOOP

LOOP1 BIT 0,E;      Got a tail?
        RET Z;        No.
        LD A,#20
        EX AF,AF'
        LD A,#02
        CALL WKSEC0
        LD A,#20
        CALL SKIP+#02
        CALL WAIT
        JR HDDW22

HDDW21 CALL WKSECR;   Read sector
HDDW22 CALL SKIP;     Skip half
        CALL RDHLFH;   Read to buffer
        LD A,#30;    Write a sector
        CALL WKSEC
        CALL WRHALF;   We write the tail.
        CALL WRHLFH;   We write from the buffer.
        CALL WBSY;     We are waiting for completion.
        XOR A
        RET

;----------------------------------------------------------------
;Write LBA sector address to HDD registers
;H= drive+LBA 27...24
;L= LBA 23...16
;D= LBA 8...15
;E= LBA 0...7
PCOORD LD BC,#FEBE
        OUT (C),H
        DEC B
        OUT(C),L
        DEC B
        OUT(C),D
        DECB
        OUT(C),E
        RET

;----------------------------------------------------------------
RDHLFH PUSH HL;       Reading half the sector
        LD HL,TMPBUF;to internal buffer
        CALL RDHALF
        POP HL
        RET

WKSECR LD A,#20;    Single sector read entry point
WKSEC EX AF,AF';   Entry point for working with
        LD A,#01;    one sector.
WKSEC0 LD B,#FA;    Entry point for working with
        OUT(C),A;    several sectors
        LD B,#FF;    Reading the register
        IN A,(C);    state
        BIT 6,A;      We are waiting for the installation of DRDY.
        JR Z,$-#04
        EX AF,AF';   Write the command code.
        OUT(C),A
WAIT CALL WBSY;     We are waiting for readiness.
        RRCA;          Error checking
        RET NC;       Exit if ERR=0

        LD A,#07;    Read/Write Error
ERROR LD SP,#0000; sectors
        RET

WDRQ IN A,(C);    We are waiting for the DRQ installation.
        BIT 3,A
        JR Z,$-#04
        RET

;----------------------------------------------------------------
;Recording routine at 21.875 clock cycles per byte
WRHLFH LD HL,TMPBUF;buffer address
WRHALF LD A,#10;    Number of repetitions
        PUSH DE
        LD DE,#D8F8
        LD (WRHLF1+#01),SP
        LDSP,HL
WRHLF0 DEFB #E1,#42,#ED,#61,#43,#ED,#69;  POP HL
        DEFB #E1,#42,#ED,#61,#43,#ED,#69;  LD B,D
        DEFB #E1,#42,#ED,#61,#43,#ED,#69;  OUT(C),H
        DEFB #E1,#42,#ED,#61,#43,#ED,#69;  LD B,E
        DEFB #E1,#42,#ED,#61,#43,#ED,#69;  OUT (C),L
        DEFB #E1,#42,#ED,#61,#43,#ED,#69
        DEFB #E1,#42,#ED,#61,#43,#ED,#69
        DEFB #E1,#42,#ED,#61,#43,#ED,#69
        DEC A
        JR NZ,WRHLF0
        LD H,A
        LD L,A
        ADD HL,SP
WRHLF1 LD SP,#0000
        POP OF
        OR A
        RET

;------------------------------------------------------
;A read subroutine with a speed of 20,875 clocks per byte
RDHALF LD A,#10
        PUSH TO
        LD DE,#D8F8
RDHLF0 DEFB #43,#ED,#A2,#42,#ED,#A2; LD B,E:IN:LD B,D:IN
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEFB #43,#ED,#A2,#42,#ED,#A2
        DEC A
        JR NZ,RDHLF0
        POP OF
        OR A
        RET

;------------------------------------------------------
;Internal buffer on floor of sector
TMPBUF DEFS #0100

Share your thoughts about the article