Page 1 of 1

How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 9:58 am
by ~
What is the maximum possible CHS value?
Without this detail, I could implement a limited or unnecessarily adjusted READ_SECTORS_CHS function.

Cylinders is a 16-bit value, but if Heads or Sectors is greater than 255, how can this command be called?

Is it similar to READ SECTORS for LBA48, where we need to write registers several times to reach 48 instead of 28 bits?

Or the maximum CHS would ever be 65535-15-255.

I will achieve maximum compatibility by always reading the MBR in CHS mode, although I've read that even the ATA 1 standard (the very first version?) supports LBA.

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 11:01 am
by iansjack
CHS addressing is obsolete. Let it RIP.

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 11:14 am
by Octocontrabass
~ wrote:What is the maximum possible CHS value?
Without this detail, I could implement a limited or unnecessarily adjusted READ_SECTORS_CHS function.
In ATA, the maximum possible CHS address is 65535/15/255.

In INT 0x13 AH=0x02, the maximum possible CHS address is 1023/255/63 (but most BIOSes are limited to 1023/254/63).
~ wrote:I will achieve maximum compatibility by always reading the MBR in CHS mode,
If you are using ATA commands, you must support LBA. CHS may not work on ATA-6 or newer disks, and CHS may not work on disks bigger than 7.8 GiB.
~ wrote:although I've read that even the ATA 1 standard (the very first version?) supports LBA.
LBA is standardized by ATA-1, but not required, so some ATA-1 disks do not support it.

ATA-1 is extended from the IBM PC/AT Fixed Disk and Diskette Drive Adapter, with some features taken from other compatible drive controllers. (For example, the IDENTIFY DRIVE command comes from ESDI drive controllers.)

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 11:15 am
by ~
It's just like LBA if you put them together.

The only difference is that you need to clamp every value to the device maximums, and Sector starts at 1 (the first joined CHS would be 0x00000001), with a wrapper function that takes care of that for manipulating them separately (or from a total count), with manual bit fields; then it's the same than LBA.

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 12:18 pm
by Schol-R-LEA
First off, ~, why are you answering your own question? If you are intending this to explain what you found, please say so, and maybe add it to the wiki if you really think anyone else could benefit from it. Though to be honest, what you just said is already there, so...

Or by checking Wikipedia's entry on the topic. Seriously.

Second, where do you expect to even find working drives that old, which haven't been ruined by stiction or head crashes more than a decade ago? CHS was really only valid for drives prior to the late 1990s, and was officially deprecated in 2002 for future ATA drives. Most of the drives which it could be used with - and almost all of the drives it was necessary to use it with - are long dead and irrecoverable.

Also, you have to consider that this was still during the period when the number of computer units sold were doubling alongside Moore's Law. Just based on production numbers, there have been far more drives made which don't support CHS addressing than do, as the number of drives sold between 2003 and 2010 was more than double the total for all hard drive sales before 2003.

As an aside, it is my understanding that this is one of the things which comes up a lot with retro-computing; the electromechanical parts tend to fail with time far more often than the solid-state ones, and while floppy drives are usually easy enough to fix (the disks themselves are another matter), older hard drives have usually failed by the time a collector gets to them. The drives for workstations tend to be more solidly built than those for home computers, which is why you are more likely to be able to revive, say, an Iris, rather than an Amiga 2000, an Archimedes, or a 486 PC, but even if the machine has been kept in pristine condition, the chances are pretty low that the disk is still going to be usable. Oddly enough, I've heard that machines which have been run at least from time to time tend to do a little better, since some of the older drives tend to get problems if left unused.

There are some notable exceptions, with some interesting finds made on old drives which were recovered, but according to those doing it, the drives fail more than half the time when they try to start it (note that the Amiga 4000 recovered in that Perifractic video was a workstation-class system, more comparable to a Sun or Iris than to other Amiga models, and the drive in question very likely was a high-end 3rd party device anyway). The add-on devices used to connect SD or flash drives to older systems are more than just a convenience.

I can appreciate the interest in older technology, and I do think that knowing how it worked can give insights into how it's successors work, but I don't see how supporting CHS today, even on older hardware, could possibly help. Do you have a specific need for this? I can only think that you are trying to read existing FAT16 and FAT32 drives, but as I said, there are only so many of those which are still in working condition.

(Second aside: Solar and some of the other old hands may want to watch Perifractic's follow-up video on the system the drive was removed from. especially since it discusses replacement parts for Amigas - included entire new motherboards which someone is manufacturing - which fans of the platform may find interesting. You may want to watch the other one first, as the title of that video contains a spoiler for the previous one.)

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 2:03 pm
by Octocontrabass
Schol-R-LEA wrote:Second, where do you expect to even find working drives that old, which haven't been ruined by stiction or head crashes more than a decade ago?
Compared to ~'s usual nonsense, it's actually pretty reasonable to have some still-working retro hardware and the desire to write code for it.

Re: How to send READ SECTORS for CHS?

Posted: Sat Mar 07, 2020 7:05 pm
by Schol-R-LEA
Octocontrabass wrote:
Schol-R-LEA wrote:Second, where do you expect to even find working drives that old, which haven't been ruined by stiction or head crashes more than a decade ago?
Compared to ~'s usual nonsense, it's actually pretty reasonable to have some still-working retro hardware and the desire to write code for it.
I'll grant you that, yes.

Re: How to send READ SECTORS for CHS?

Posted: Sun Mar 08, 2020 5:47 am
by Octacone
iansjack wrote:CHS addressing is obsolete. Let it RIP.
This is one of the best advises given on this forum in a while!
Seriously, stop using stupid CHS, it is more dead than the dinosaurs.

Re: How to send READ SECTORS for CHS?

Posted: Sun Mar 08, 2020 5:04 pm
by ~
This is a simple version that I've tried to optimize to read sectors in CHS mode.

Is the out dx,ax instruction OK to try to write Cylinder Low/Cylinder High (registers 4 and 5) in Little Endian order to the device?

CHS and DEV bit in a 32-bit DWORD

Code: Select all

     16-31           H (8-11)        0-7
----------------       ----       --------
0000000000000000   00000000       00000000
----------------      -           --------
  C (16-bit)        DEV (bit 12)     S (8-bit)

Code: Select all

push wideword widedi                      ;Buffer
push wideword 1                           ;Sector Count
push wideword 1|(.ATA_CHS_DEV_Master<<8)  ;CHS/DEV bit
push wideword 0x1F0                       ;Base address

call OPCODE__ATA__READ_SECTORS_CHS
add widesp,wideword_sz*4

Code: Select all

%xdefine .ATA_CHS_DEV_Master 00000000b
%xdefine .ATA_CHS_DEV_Slave  00010000b


;Parameters (push order):
;
;.ATA_destbuff
;.SectCount
;.CHS|.ATA_CHS_DEV_Bit
;.ATA_base
;
;
;;

align wideword_sz
OPCODE__ATA__READ_SECTORS_CHS:
 push widebp
 pushfwide
 mov widebp,widesp
 add widebp,wideword_sz*3   ;Skip flags, BP and return


 ;Parameters (only defined with %xdefine, not with EQU):
 ;;
  %xdefine .ATA_base     word[widebp]
  %xdefine .CHS_DEV      dword[widebp+wideword_sz*2]
  %xdefine .SectCount    byte[widebp+wideword_sz*3]
  %xdefine .ATA_destbuff wideword[widebp+wideword_sz*4]


 ;Set base address:
 ;;
  mov dx,.ATA_base



 ;Write Sector Count:
 ;;
  inc dx
  inc dx
  mov al,.SectCount
  out dx,al   ;Reg. 2



 ;Get CHS/DEV value:
 ;;
  mov eax,.CHS_DEV


 ;Write S:
 ;;
  inc dx
  out dx,al   ;Bits 0-7, Reg. 3

 ;Write C:
 ;;
  ror eax,16 ;Point to 16-bit Cylinder
  inc dx     ;Cylinder Low, Reg. 4 (Bits 16-23)
  out dx,ax  ;Write Cylinder Low, then Cylinder High in a single operation

  ;ror eax,16 ;Point to 16-bit Cylinder
  ;inc dx     ;Cylinder Low, Reg. 4 (Bits 16-23)
  ;out dx,al
  ;ror eax,8
  ;inc dx    ;Cylinder High, Reg. 5 (contiguous regs/rotations optimization original from here) (Bits 24-31)
  ;out dx,al

 ;Write H/DEV:
 ;;
  rol eax,8
  inc dx
  out dx,al   ;Bits 8-15, Reg. 6

 ;Write command (READ SECTORS, 0x20):
 ;;
  inc dx
  mov al,0x20
  out dx,al   ;Reg. 7

 ;Wait DRQ before reading each sector:
 ;;
  sub dx,7  ;Point to Data Register (WORD-sized, 16-bit)
            ;but DWORD-readable, maybe WIDEWORD readable.
  mov widedi,.ATA_destbuff


 


  cld
  push widedi
  push widecx
  align wideword_sz
  .readSects:
   dec .SectCount       ;Intention is to read up to 256 sectors (0 is 256)
   call wait_DRQ


    mov widecx,128      ;No flags affected
    align wideword_sz
    rep insd            ;No flags affected


  jnz .readSects   ;Zero Flag from dec .SectCount
  pop widecx
  pop widedi


 popfwide
 pop widebp
retwide


Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 7:34 am
by Octocontrabass
~ wrote:Is the out dx,ax instruction OK to try to write Cylinder Low/Cylinder High (registers 4 and 5) in Little Endian order to the device?
No. You must use the correct size to access each register. The data register accepts only 16-bit accesses (unless you've detected and configured the device for 8-bit accesses), and all other registers accept only 8-bit accesses.

Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 10:57 am
by ~
Octocontrabass wrote:
~ wrote:Is the out dx,ax instruction OK to try to write Cylinder Low/Cylinder High (registers 4 and 5) in Little Endian order to the device?
No. You must use the correct size to access each register. The data register accepts only 16-bit accesses (unless you've detected and configured the device for 8-bit accesses), and all other registers accept only 8-bit accesses.
How would you detect that a disk is 8-bit or 16-bit? I can only think trying to read it in both ways, and if the result differs between 8 and 16-bit, it's an 8-bit disk. If it's the same, it's a 16-bit disk.

I've seen that 16/32-bit BIOSes don't check for 8-bit disks (for example, an ATA-3 era laptop disk with an ATA-7 era motherboard always has its identification data read by half by the BIOS).

Also, I always read/write the data register with a REP INSD or REP OUTSD with 128 DWORDs, so I know that it can be used as a 32-bit data register.

I suspect there's a chance that the other registers can be accessed simultaneously in some cases, so it could be detected.

What makes me suspect the most is that the 4 CHS/LBA registers are contiguous (3-6) as a DWORD, so it suggests that they could even be written by an OUT DX,EAX.

Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 12:00 pm
by Octocontrabass
~ wrote:How would you detect that a disk is 8-bit or 16-bit?
All disks are 16-bit.

CF cards and some ancient IDE drives can be switched to 8-bit for compatibility with 8-bit computers using the SET FEATURES command. This might come in handy if you're designing your own hardware, but you really don't need it otherwise.

The obsolete READ LONG and WRITE LONG commands use a mix of 16-bit and 8-bit transfers. As far as I know, these are completely useless.
~ wrote:Also, I always read/write the data register with a REP INSD or REP OUTSD with 128 DWORDs, so I know that it can be used as a 32-bit data register.
You can't rely on that behavior. It won't work on every PC.

Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 1:32 pm
by BenLunt
I agree with Octocontrabass here.

The 8-bit data transfers are for the CF compatibility mode only, and are for early implementations only.

As for the DATA register, a size of 16-bit word access has been used throughout most of the ATA hardware's life. A size of 32-bit word access is common, but not expected to work on all hardware. The hardware won't even specify if 32-bit reads are accepted. You have to actually try it to see if it works. My code tries to use the Identify Device command with 32-bit reads and compares the block returned with a same call but using 16-bit reads. If the returned block is identical, then 32-bit reads are assumed accepted. The big word here is 'assumed'. I have used this exact test on one of my test machines, and some of the words have come back a different endian format, specifically the high 16-bit of the 32-bit read.

Most of the physical hardware I have tried--that have been on the PCI bus--have allowed 32-bit reads/writes. Last time I checked, QEMU does not allow 32-bit access to the data register. Bochs and VirtualBox do. Again, to be 100% accurate, you need to stick with 16-bit reads and writes of the DATA register.

Another thing you have to remember is that if the drive is on the ISA bus, not the PCI bus, 32-bit reads will not work since the ISA is 16-bit only.

As for the other registers, each must be read and written as single byte only access. It is completely undefined behavior if accessed with 16-bit or 32-bit reads/writes. i.e. you must not write two consecutively addressed registers at once, especially the SELECT register. Imagine writing a 16-bit word to offset 0x06 to select a drive and writing to the COMMAND register at the same time with a 16-bit write. Does the hardware switch to the other drive before the write to the command register or after? Not an option. You must use byte access only.

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 1:55 pm
by Schol-R-LEA
Hopefully - though it is unlikely - Tilde will actually read and (try to) understand what Ben just explained. I fear, however, that at this point Tilde isn't going to pay attention to anything anyone says which doesn't support his preconceptions (or perhaps 'delusions' is a better way to put it).

Re: How to send READ SECTORS for CHS?

Posted: Mon Mar 09, 2020 4:20 pm
by eekee
Schol-R-LEA wrote:I fear, however, that at this point Tilde isn't going to pay attention to anything anyone says which doesn't support his preconceptions (or perhaps 'delusions' is a better way to put it).
I think it's more lkely just confusion + overexertion. Trying too hard makes the brain skip stuff whether it's important or not. The appearance of bias arises because the harder something is to recognize, the more likely it is to be skipped.

I may even be wrong about the overexertion part. I was drugged when I was a child, including at least one overdose, and now my brain just skips stuff sometimes. The skipping is certainly much worse on some days, which I assume follows mental exertion, but it's proving very hard to determine what exactly constitutes mental exertion. Even too much daylight seems to contribute.