;;;;INIT: Place the proper ORG directives here!
;;;;INIT: Place the proper ORG directives here!
;;;;INIT: Place the proper ORG directives here!

org 100h

jmp short START
align 16
db "   TMP.COM START"
START:

;;;;END:  Place the proper ORG directives here!
;;;;END:  Place the proper ORG directives here!
;;;;END:  Place the proper ORG directives here!
bits 16






call atadiskdetect



;;;;INIT: Remove this instruction if not called from DOS
;;;;INIT: Remove this instruction if not called from DOS
;;;;INIT: Remove this instruction if not called from DOS
int 20h

;;;;END:  Place the proper ORG directives here!



































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "            ata_atapi__determine_active_contacts";;;;;;;;;;;
ata_atapi__determine_active_contacts:
 pushad









 call ata_atapi__master
 call ata_atapi__readregs
     or byte[read_pri_sec_master_slave],00000000b



    call contacts_2
    jc .nocountmaster2
     or byte[read_pri_sec_master_slave],00000001b
     jmp .mastercounted
   .nocountmaster2:


   call check_valid_ata_regs
   jc .nocountmaster                ;If carry set, the contents are stalled
;inc byte[gs:160*22]
     or byte[read_pri_sec_master_slave],00000001b
     jmp .mastercounted
   .nocountmaster:



   .mastercounted:













 call ata_atapi__slave
 call ata_atapi__readregs


    call contacts_2
    jc .nocountslave2
     or byte[read_pri_sec_master_slave],00000010b
     jmp .slavecounted
   .nocountslave2:



   call check_valid_ata_regs
   jc .nocountslave                ;If carry set, the contents are stalled
;inc byte[gs:160*22]
     or byte[read_pri_sec_master_slave],00000010b
     jmp .slavecounted

   .nocountslave:

   .slavecounted:


  call ata_atapi__readregs
  call ata_atapi_showregs

 popad
ret























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "            ata_atapi__id_drives";;;;;;;;;;;;;;;;;;;;
ata_atapi__id_drives:
 pushad

 call ata_atapi__master
 call ata_atapi__readregs


 pushad
 mov esi,[ata_atapi_toidentstring__ptrs]
 mov eax,[ata_atapi_highlight_detect]
 mov [gs:esi],eax
 mov eax,[ata_atapi_highlight_detect+4]
 mov [gs:esi+4],eax
 popad


  test byte[read_pri_sec_master_slave],00000001b   ;See if we must watch master
  jz .nowatchmaster
    call scan_for_identify_ata_atapi_command
    jc .errmaster
     call ata_atapi_toidentstring
 pushf
; sub dword[ata_atapi_toidentstring__ptrs],160
 popf
inc byte[gs:160*22]
     jmp .goslave

    .errmaster:
  .nowatchmaster:
;call bios_kbwait



 pushad
 mov esi,[ata_atapi_toidentstring__ptrs]
 mov eax,[ata_atapi_none]
 mov [gs:esi],eax
 mov eax,[ata_atapi_none+4]
 mov [gs:esi+4],eax
 popad
 pushf
 add dword[ata_atapi_toidentstring__ptrs],160
 popf




.goslave





 pushad
 mov esi,[ata_atapi_toidentstring__ptrs]
 mov eax,[ata_atapi_highlight_detect]
 mov [gs:esi],eax
 mov eax,[ata_atapi_highlight_detect+4]
 mov [gs:esi+4],eax
 popad



 call ata_atapi__slave
 call ata_atapi__readregs

  test byte[read_pri_sec_master_slave],00000010b   ;See if we must watch slave
  jz .nowatchslave
    call scan_for_identify_ata_atapi_command
    jc .errslave
     call ata_atapi_toidentstring
 pushf
; sub dword[ata_atapi_toidentstring__ptrs],160
 popf
inc byte[gs:160*22]
     jmp .end

  .nowatchslave:


    .errslave:
;call bios_kbwait



 pushad
 mov esi,[ata_atapi_toidentstring__ptrs]
 mov eax,[ata_atapi_none]
 mov [gs:esi],eax
 mov eax,[ata_atapi_none+4]
 mov [gs:esi+4],eax
 popad
 pushf
 add dword[ata_atapi_toidentstring__ptrs],160
 popf



.end:



 popad
ret










screendump_start:
incbin  "screendump.txt"
screendump_end:




screendump_sz equ screendump_end-screendump_start




















align(16)
db "      contacts_2"
contacts_2:
pushad




;//0015 -- Write AAh to "Cylinder Low" Register (as for ATA-3)
;//also known as "LBA Mid" Register (as for ATA-6, ATA-7)
;;;
 .gotoStep0015:
   add dx,4     ;Point to the register
    mov al,0xAA
    out dx,al
   sub dx,4


;//0016 -- Write 55h to "Cylinder High" Register (as for ATA-3)
;//also known as "LBA High" Register (as for ATA-6, ATA-7)
;;;
 .gotoStep0016:
   add dx,5    ;Point to the register
    mov al,0x55
    out dx,al
   sub dx,5


;//0017 -- Write FFh to "Sector Count" Register:
;;;
 .gotoStep0017:
   add dx,2      ;Point to the register
    mov al,0xFF
    out dx,al
   sub dx,2


;//0018 -- Read "Cylinder Low" Register (as for ATA-3)
;//also known as "LBA Mid" Register (as for ATA-6, ATA-7)
;;;
 .gotoStep0018:
   add dx,4        ;Point to the register
    in al,dx
   sub dx,4


;//0019 -- Value==AAh?
;;;
 .gotoStep0019:
  cmp al,0xAA
  je .gotoStep0005  ;If yes, go to the EXECUTE DEVICE DIAGNOSTIC tests



;//0020 -- Value==FFh?
;;;
 .gotoStep0020:
  cmp al,0xFF
  je .gotoStep0006   ;If yes, the channel seems to be empty


 ;If not, let's .gotoStep0021



;//0021 -- Read Cylinder High Register
;;;
 .gotoStep0021:
  add dx,5
  in al,dx
  sub dx,5


;//0022 -- Value==55h?
;;;
 .gotoStep0022:
  cmp al,0x55
  je  .gotoStep0005  ;If yes, go to the EXECUTE DEVICE DIAGNOSTIC tests




  jmp .gotoStep0006  ;If not, goto "Yes, bus is floating"



.end:

popad
ret


.gotoStep0005
clc
jmp .end


.gotoStep0006
stc
jmp .end



align(16)
db " contacts_2__END"











atadiskdetect:
pushad
pushf
push ds
push es
push fs
push gs

call clearscreen



push ds
pop es

push word 0xB800
pop gs


push es
push gs
pop es

mov esi,screendump_start
mov edi,0
mov ecx,(80*25)*2
call memcpy0
pop es





mov byte[gs:160*22],"0"








.llllllllll:
mov esi,[EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr]  ;get value in the pointer
mov byte[read_pri_sec_master_slave],00000000b


;Get the information of our first channel:
;;;
 call ATA_ATAPI__getNextChannel

  call ata_atapi__determine_active_contacts


  call ata_atapi__id_drives


  mov ax,[ATA_ATAPI__channelCount]
  inc word[ATA_ATAPI__currentChannel]
  cmp word[ATA_ATAPI__currentChannel],ax
  ja .endllllllllll

jmp .llllllllll


.endllllllllll:


pop gs
pop fs
pop es
pop ds
popf
popad
ret



























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "       ATA_ATAPI__getNextChannel";;;;;;;;;;;;;;;

;//DS must be properly configured
;//by a function outside of it before
;//it gets called for being able to
;//find the tables.
;;;
ATA_ATAPI__getNextChannel:
 pushf
 push eax
 push ebx
   ;//Take the value of this "offseting"
   ;//variable:
   ;;;
     movzx eax,word[ATA_ATAPI__currentChannel]

   ;//Multiply it by 4 to get the WORD offset in the
   ;//ports addresses table:
   ;;;
     shl eax,2

   ;//Get the address from the
   ;//ports addresses table
   ;//and put it in DX:
   ;;;
     mov ebx,[ATA_ATAPI__addr_table]   ;The start of the table (this is a
                                       ;variable far apart from the table
                                       ;itself). This variable contains
                                       ;a value that points to the start of
                                       ;the I/O port table we built
   ;//Get the base I/O value in DX:
   ;;;
     mov edx,[eax+ebx]

 pop ebx
 pop eax
 popf
ret


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "  ATA_ATAPI__getNextChannel__END";;;;;;;;;;;;;;;































;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "              ata_atapi_printdev";;;;;;;;;;;;;;


;//This routine requires that DS:ESI points to the
;//512-byte detection buffer before calling this
;//function:
;;;
ata_atapi_printdev:
pushf
pushad
push ds
push es

mov ax,0xB880
mov es,ax  ;ES==0xB8800

;push word 0
;pop ds



mov cx,512  ;512 bytes

xor edi,edi



.loo:
 a32 lodsb
 a32 stosb
  inc edi

dec cx
jcxz .endloo
jmp .loo
.endloo:



pop es
pop ds
popad
popf
ret






;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "         ata_atapi_printdev__END";;;;;;;;;;;;;;



























align 16
db "         ata_atapi_toidentstring"

ata_atapi_toidentstring__ptrs dd 0x21E

ata_atapi_toidentstring:
pushad
pushf
push es

push word 0xB800
pop es
mov edi,[ata_atapi_toidentstring__ptrs]


mov esi,[ata_atapi_ident_buff_ptr]
add esi,54

mov ecx,20   ;20 words

 push bx
.l:
 a32 lodsw
 mov bl,0x1A
 shl ebx,8
 mov bl,al
 shl ebx,8
 mov bl,0x1A
 shl ebx,8
 mov bl,ah
 mov eax,ebx
 a32 stosd

dec ecx
jnz .l
 pop bx


add edi,2



cmp bh,0xEC
jne .noec
push esi
mov esi,ata_string
mov ecx,10
call memcpy0
pop esi
.noec:


cmp bh,0xA1
jne .noa1
push esi
mov esi,atapi_string
mov ecx,14
call memcpy0
pop esi
.noa1:




add dword[ata_atapi_toidentstring__ptrs],160

pop es
popf
popad
ret


align 16
db "    ata_atapi_toidentstring__END"
































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "         bin2hex";;;;;;;;;;;;;;;;;;;;;




;//Takes in AL 1 value between 0 & 255 (0-FF)
;//and puts the "hex" as an "ASCII hex" in EAX
;//plus the attribute bytes for video "Mode 3"
;//(Little Endian order).
;;;
bin2hex:
pushf
 push ebx
  and eax,11111111b

  ;//Take a copy of our value into AH
  ;//to have it in AL and also in AH
  ;;;
    mov ah,al


  shr al,4       ;Take the higher 4 bits
  cmp al,0x09
  ja .noner1     ;See if this value is higher than 9
   add al,0x30   ;if(AL>=0 && AL<=9) add 0x30 (char '0') to convert to ASCII
   jmp .noner1_1  ;Go to the next step

  .noner1:
   add al,0x37   ;if(AL>9) add 0x37 (char 'A') to convert to ASCII 'A'--'F'

  .noner1_1:



  ;//Now it's the time to use our
  ;//backup value in AH (convenient
  ;//to avoid using the stack, etc...)
  ;;;
    and ah,00001111b   ;Now, take the lower 4 bits
    cmp ah,0x09
    ja .noner2         ;See if this value is higher than 9
     add ah,0x30       ;if(AH>=0 && AH<=9) add 0x30 (char '0') to convert to ASCII
     jmp .noner2_2     ;Go to the next step

    .noner2:
     add ah,0x37  ;if(AH>9) add 0x37 (char 'A') to convert to ASCII 'A'--'F'

    .noner2_2:



  ;//Let's prepare the lower hex digit
  ;//(remember that we must start with it
  ;//since we are working in Little Endian):
  ;;;
  ;;;;
  mov bl,00111111b   ;white char with lightblue background for first hex digit

  shl ebx,8    ;Store this attribute (take it away from BL)
  mov bl,ah    ;Take the lower hex digit

  shl ebx,8        ;Store lower digit with its attribute color
                   ;(take it away from BL)


  ;;;;;;;;;;;
  ;;;;;;;;;;;
  ;;;;;;;;;;;
  ;;;;;;;;;;;
  ;;;;;;;;;;;



  ;//Let's prepare the higher hex digit:
  ;;;
  ;;;;
  mov bl,00111111b   ;white char with lightblue background for 2nd hex digit

  shl ebx,8    ;Store this attribute (take it away from BL)
  mov bl,al    ;Take the higher hex digit



  ;//We're done. Put the final value that was just built in EBX
  ;//into EAX (2 bytes per digit -- the value with its onscreen colors)
  ;;;
    mov eax,ebx


 pop ebx
popf
ret




align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "    bin2hex__END";;;;;;;;;;;;;;;;;;;;;


























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "     bios_kbwait";;;;;;;;;;;;;;;;;;;;;
bios_kbwait:
 pushad
 pushf
  xor ah,ah
  int 16h
 popf
 popad
ret





























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "            check_valid_ata_regs";;;;;;;;;;;;
;EDX==Bus addresses
;AL==DEV bit value
;
;This function requires that the DS:ESI registers be properly
;set to point to a storage buffer before calling it:
;;;
  check_valid_ata_regs:
    pushad

    mov esi,[EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr]  ;take pointer value

     mov ecx,6

     a32 lodsb
     mov bl,al


      .loop:
          a32 lodsb
          cmp al,bl
          jne .endloop
      a32 loop .loop
       .endloop:

      cmp cl,0                  ;See if we read all 6 registers...
      jne .notequal_and_valid   ;If not, flag that the registers have content
        stc                     ;If yes, state that all registers are equal
        jmp .end                ;(maybe floating)
      .notequal_and_valid:
      clc


       a32 lodsb   ;read the Alternate Status value
       cmp al,bl   ;compare with the first register's value
       jne .notequal_and_valid_2
         stc
         jmp .end
       .notequal_and_valid_2:
       clc




    .end:
    popad
  ret



align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "       check_valid_ata_regs__END";;;;;;;;;;;;



























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "     clearscreen";;;;;;;;;;;;;;
clearscreen:
 pushf
 pusha
  ;//Try to clear the screen:
  ;;;
    mov ah,6       ;//VIDEO - SCROLL UP WINDOW
    mov al,0       ;//number of lines by which to scroll up
                   ;//(00h = clear entire window)
    mov bh,0x7     ;//attribute used to write blank lines
                   ;//at bottom of window
    xor cx,cx      ;//row,column of window's upper left corner
    mov dx,0x1950  ;//80x25 ;DH,DL row,column of window's
                   ;//lower right corner
     int 10h

  ;//Set position of cursor at top of screen:
  ;;;
    mov ah,2   ;//VIDEO - SET CURSOR POSITION
    mov bh,0   ;//page number
               ;//   0-3 in modes 2&3
               ;//   0-7 in modes 0&1
               ;//   0 in graphics modes
    xor dx,dx  ;//DH,DL row (00h is top), column (00h is left)
      int 10h
 popa
 popf
ret


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "clearscreen__END";;;;;;;;;;;;;;





























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "       identify_ata_atapi_device";;;;;;;;;;;;








;//BL==Must be set originally to 0 to indicate the possibility to
;//    return an alternative command code here. If it's not 0, no other
;//    command will be suggested.
;//    If another command must be used (i.e., ATAPI 0xA1 instead of ATA 0xEC),
;//    the command code will be returned here. If no other command is
;//    suggested (i.e., because a proper signature was not found as the
;//    answer to the command), it will still be 0.
;//BH==ECh for IDENTIFY DEVICE command
;//    A1h for IDENTIFY PACKET DEVICE command
;//EDX,ES:EDI must be properly set by some other functions
;;;
identify_ata_atapi_device:
 push eax
 push ecx
 push esi
 push edi
  mov esi,[EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr]  ;get value in the pointer


  ;//Send the requested command:
  ;;;
   add dx,7
     mov al,bh  ;Take the command that was put in BH
     out dx,al
   sub dx,7


   mov ecx,0xFFFF
   .waitdrq:
     call ata_atapi__readregs
      mov al,[esi+7]
      test al,00001000b    ;DRQ
      jnz .waitdrq_end

   loop .waitdrq
   .waitdrq_end:


 ;Write the DEVICE REGISTER
 ;;;
  push ax
  add dx,6
  in al,dx           ;Read DEVICE REGISTER
  or al,10000001b    ;Preserve all bits including DEV bit
                     ;and...
                       ;Set BSY and ERR/CHK
                       ;This is for some weird buses
  out dx,al            ;that are half-floating and that also
                       ;change all of their floating registers to
  sub dx,6             ;the same last value written (to the device register).
  pop ax               ;If that's the case, it will cause the bits 0 and 7
                       ;to be set to 1, even for the Status Register, which
                       ;correspond to the ERR/CHK and the BSY bits,
                       ;respectively.
                       ;
                       ;At the same time, those bits correspond to bits that
                       ;are not used for the IDENTIFY DEVICE or
                       ;IDENTIFY PACKET DEVICE commands, and correspond to
                       ;the obsolete, ATA-3 HS0 (bit 0) and a 1 (bit 7).


  call ata_atapi__readregs


;                                                                               ;   mov al,[esi]
;                                                                               ;   test al,00000100b    ;ABRT
;                                                                               ;   jnz .nocount
   mov al,[esi+7]
   test al,00000001b    ;ERR/CHK
   jnz .nocount

   test al,00001000b    ;DRQ
   jz .nocount


   test al,10000000b    ;BSY
   jnz .nocount
    clc
    jmp .end



 .nocount:
   stc


  .end:
   pushf
   mov esi,ata_atapi_ident_buff
   mov edi,esi
   call ata_atapi__r512
   call ata_atapi__pr512
   call ata_atapi__readregs
   popf


 pop edi
 pop esi
 pop ecx
 pop eax
ret





align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "  identify_ata_atapi_device__END";;;;;;;;;;;;





























align 16
db "         memcpy0"
memcpy0:
 pushad
 pushf
  .lo:
  a32 lodsb
  a32 stosb
  dec ecx
  jnz .lo

 popf
 popad
ret


align 16
db "    memcpy0__END"






























align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "             scan_for_identify_ata_atapi_command";;;;;;;;;;;;


;//This routine sets the CF to 1 if there was
;//an error (nothing found) and clears it if
;//it was successful.
;//
;//The BH register will contain the command that
;//was executed so that external functions can
;//know immediately if the device was ATA or ATAPI
;//
;//If the CARRY FLAG (CF) is set to 1, the value
;//in BH is not valid for determinining a device type,
;//neither ATA nor ATAPI.
;;;
scan_for_identify_ata_atapi_command:
 push eax
 push ecx
; pushad


 ;Zero-out our special-case variables:
 ;;;
   mov ax,0x0000
   mov cx,ax

 ;Zero-out the relevant ATA registers to leave
 ;no chance of malfunction by spurious values:
 ;;;
   add dx,2
   out dx,al   ;Write sector count
   inc dx
   out dx,al   ;Write LBA Low
   inc dx
   out dx,al   ;Write LBA Mid
   inc dx
   out dx,al   ;Write LBA High
   sub dx,5


 mov bh,0xEC  ;IDENTIFY DEVICE command
 call identify_ata_atapi_device
 jnc .allok__ATAonly


  call ata_atapi__readregs
  mov eax,[EXECUTE_DEVICE_DIAGNOSTIC_signatures+1]
  mov ecx,0xEB140000
  and eax,ecx
  cmp eax,ecx
  jne .deviceisnotatapi
    mov cl,0x32   ;flag this as "special ATAPI"
    jmp .tryatapi
  .deviceisnotatapi:

 
  xor cx,cx


 .tryatapi:
  cmp cl,0x32
  jne .nospecialatapi
    mov ch,0x64  ;flag a "special ATAPI" to not discard it by error

  .nospecialatapi:


 ;//If the CARRY FLAG in the EFLAGS register is set,
 ;//we will need to execute the IDENTIFY PACKET DEVICE command
 ;;;
  mov bh,0xA1  ;IDENTIFY PACKET DEVICE command
  call identify_ata_atapi_device
  jnc .allok__specials_ATAPI

  .errors:
 ;//If the CARRY FLAG (CF) was set after that, then there is
 ;//no valid ATA-ATAPI drive for this bus and master/slave socket:
 ;;;
  stc  ;ERROR
  jmp .end


 .allok__specials_ATAPI:
;  cmp ch,0x64
;  jne .errors

;  cmp cl,0x32
;  jne .errors

  .wasspecialatapi__not_an_error:
  .allok__ATAonly:
  clc   ;All OK


 .end:
  call ata_atapi_showregs

; popad
 pop ecx
 pop eax
ret


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "        scan_for_identify_ata_atapi_command__END";;;;;;;;;;;;



































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db 0x0D,0x0A,"           INIT: variables.txt",0x0D,0x0A;;;;;;;;
db "           INIT: variables.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;
db "           INIT: variables.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;
align 16
db "                "








align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "           ATA_ATAPI__addr_table";;;;;;
ATA_ATAPI__addr_table dd ata_atapi_common_buses



align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "          ata_atapi_common_buses";;;;;
ata_atapi_startiobuses:
   ata_atapi_common_buses:  dw 0x1F0  ;Primary
                            dw 0x3F6  ;Primary Alternate Status
                            dw 0x170  ;Secondary
                            dw 0x376  ;Secondary Alternate Status
                            dw 0x1E8  ;Tertiary
                            dw 0x3E6  ;Tertiary Alternate Status
                            dw 0x168  ;Quaternary
                            dw 0x366  ;Quaternary Alternate Status
ata_atapi_endiobuses:



;This is an index, NOT a port number:
;;
;;;
 align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 db "       ATA_ATAPI__currentChannel";;;;;;;
 ATA_ATAPI__currentChannel dw 0



;Number of channels, number is in address mode:
;;
;;;
 align 16
 db "         ATA_ATAPI__channelCount"
 ATA_ATAPI__channelCount   dw ((ata_atapi_endiobuses-ata_atapi_startiobuses)/4)-1



align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "        iddrives";;;;;;;;;;;;;;;;;;;;;;;
iddrives db 0






;//To know if we can read either Master, Slave or both:
;;;
  align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  db "       read_pri_sec_master_slave";;;;;;;;;;;;;
  read_pri_sec_master_slave   db 0


;//This will help us determine if we are using a special
;//shortcut version of the floating bus detection in effect:
;;;
  align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  db "     ata_atapi_found_immediately";;;;;;;;;;;;;
  ata_atapi_found_immediately db 0















align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db 0x0D,0x0A,"           END:  variables.txt",0x0D,0x0A;;;;;;;;
db "           END:  variables.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;
db "           END:  variables.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;
align 16
db "                "




































ata_string   db "(",0x1E,"A",0x1E,"T",0x1E,"A",0x1E,")",0x1E
atapi_string db "(",0x1E,"A",0x1E,"T",0x1E,"A",0x1E,"P",0x1E,"I",0x1E,")",0x1E

ata_atapi_highlight_detect db "W",0x9A,"a",0x9A,"i",0x9A,"t",0x9A

ata_atapi_none db "N",0x1E,"o",0x1E,"n",0x1E,"e",0x1E




































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "               ata_atapi__master";;;;;;;;;;;;;;;;;;;;
ata_atapi__master:
 pushf
 push ax
  add dx,6
   mov al,00000000b   ;Set DEV bit to 0 (Master)
   out dx,al
  sub dx,6

 pop ax
 popf
ret


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "          ata_atapi__master__END";;;;;;;;;;;;;;;;;;;;
































;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "ata_atapi__pr512";;;;;;;;;;;;;;;;;;;;



ata_atapi__pr512:
 pushf
 push esi

  mov esi,[ata_atapi_ident_buff_ptr]
  call ata_atapi_printdev


 pop esi
 popf
ret


;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "           ata_atapi__pr512__END";;;;;;;;;;

































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db 0x0D,0x0A," INIT: r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;
db " INIT: r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db " INIT: r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "                ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;







align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "            ata_atapi_ident_buff";;;;;;;;;;;;;;;;;;

;//The temporal buffer for storing the IDENTIFY xxxxx results:
;;;
  ata_atapi_ident_buff times 128 dd 0x11121314


  ata_atapi_ident_buff_ptr dd ata_atapi_ident_buff


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db " ata_atapi__r512";;;;;;;;;;;;;;;;;;;;;;;;
ata_atapi__r512:
 pushf
 push edi

   mov ecx,512/2
   a32 rep insw

 pop edi
 popf
ret








align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db 0x0D,0x0A," END:  r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;
db " END:  r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db " END:  r512.txt",0x0D,0x0A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "                ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;






























align 16
db 0x0D,0x0A,"              INIT: readregs.txt",0x0D,0x0A
db "              INIT: readregs.txt",0x0D,0x0A
db "              INIT: readregs.txt",0x0D,0x0A
align 16
db "                "






align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;DEBUG
db "            EXECUTE_DEVICE_DIAGNOSTIC_signatures";;;DEBUG... rc src.c -dbgobj
EXECUTE_DEVICE_DIAGNOSTIC_signatures:
                                     times 8 db 0   ;For Master
                                     times 8 db 0   ;For Slave


;If we want to change some time the destination of the buffer,
;we must change it here. This allows us to use the very same utility
;function in a more portable way. But we must investigate up to which
;point it is reliable and stable.
;
;THE CALLER SHOULD SAVE THE ORIGINAL POINTER VALUE AND RESTORE IT, BUT
;IT WILL NEED LOCKING FOR THE VARIABLE AND A SEMAPHORE COUNTER TO RESTORE
;IT WHEN IT'S OUR TURN.
;;
EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr dd EXECUTE_DEVICE_DIAGNOSTIC_signatures


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "             ata_atapi__readregs";;;;;;;;;;;;;;;;
ata_atapi__readregs:
 pushf
 push ecx
 push edi

 mov ecx,7
 mov edi,[EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr]  ;get value in the pointer


  push dx
  .loop
   inc dx
   a32 insb

  loop .loop
  pop dx

  ror edx,16
  a32 insb
  ror edx,16


 pop edi
 pop ecx
 popf
ret


align 16
db 0x0D,0x0A,"              END:  readregs.txt",0x0D,0x0A
db "              END:  readregs.txt",0x0D,0x0A
db "              END:  readregs.txt",0x0D,0x0A
align 16
db "                "





































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "              ata_atapi_showregs";;;;;;;;;


;//DS:ESI must point to the location where the
;//signatures for this bus are stored:
;
ata_atapi_showregs:
 pushf
 push eax
 push esi
 push ds
 push gs

 push word 0xB800
 pop gs

  mov esi,[EXECUTE_DEVICE_DIAGNOSTIC_signatures_ptr]  ;get value in the pointer

  mov al,[esi]
  call bin2hex
  mov dword[gs:0+4000-160],eax

  mov al,[esi+1]
  call bin2hex
  mov dword[gs:6+4000-160],eax

  mov al,[esi+2]
  call bin2hex
  mov dword[gs:12+4000-160],eax

  mov al,[esi+3]
  call bin2hex
  mov dword[gs:18+4000-160],eax

  mov al,[esi+4]
  call bin2hex
  mov dword[gs:24+4000-160],eax

  mov al,[esi+5]
  call bin2hex
  mov dword[gs:30+4000-160],eax

  mov al,[esi+6]
  call bin2hex
  mov dword[gs:36+4000-160],eax

  mov al,[esi+7]
  call bin2hex
  mov dword[gs:42+4000-160],eax


  mov al,dh
   call bin2hex
    mov dword[gs:50+4000-160],eax

  mov al,dl
   call bin2hex
    mov dword[gs:54+4000-160],eax


 pop gs
 pop ds
 pop esi
 pop eax
 popf
ret




align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "         ata_atapi_showregs__END";;;;;;;;;

































align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "ata_atapi__slave";;;;;;;;;;;;;;;;;;;;;;;;;
ata_atapi__slave:
 pushf
 push ax
  add dx,6
   mov al,00010000b   ;Set DEV bit to 0 (Master)
   out dx,al
  sub dx,6

 pop ax
 popf
ret


align 16;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
db "           ata_atapi__slave__END";;;;;;;;;;;;;;;;;;;;;;;;;
