ATA & ATAPI [ DISK & CD-ROM DRIVE ] ASSEMBLY PROGRAMMING

DIRECT I/O  [ TR-DOS project - CENTRAL.COM - P2002.COM i/o drafts ]
 

 ataid.html  ataid.zip atapinq.html atapinq.zip  iso9660.zip

; *****************************************************************************
;
; READPVDL.ASM [ ATAPI I/O code draft - READ PRIMARY VOLUME DESCRIPTOR ]
; Reads&Shows ISO9660 Primary Volume Descriptor
; at Starting Sector + 16 of the 1st Track in the Last Session of CD-ROM
; Copyright (C) 2002  Erdogan TAN  [ 28/11/2002 ]
;
; *****************************************************************************

; ATA/IDE Command Register Block [ AT Task File ]
IdeCmdReg_R_Data      equ 0  ; Data Register
IdeCmdReg_W_Data      equ 0  ; Data Register
IdeCmdReg_R_Error     equ 1  ; Error Register
IdeCmdReg_W_Feature   equ 1  ; Feature Register
IdeCmdReg_R_SectCount equ 2  ; Sector Count Register
IdeCmdReg_W_SectCount equ 2  ; Sector Count Register
IdeCmdReg_R_Sector    equ 3  ; Sector Number or LBA Bits 0-7
IdeCmdReg_W_Sector    equ 3  ; Sector Number or LBA Bits 0-7
IdeCmdReg_R_Cylinder0 equ 4  ; Cylinder Bits 0-7 or LBA Bits 8-15
IdeCmdReg_W_Cylinder0 equ 4  ; Cylinder Bits 0-7 or LBA Bits 8-15
IdeCmdReg_R_Cylinder1 equ 5  ; Cylinder Bits 8-15 or LBA Bits 16-23
IdeCmdReg_W_Cylinder1 equ 5  ; Cylinder Bits 8-15 or LBA Bits 16-23
IdeCmdReg_R_DriveHead equ 6  ; Drive & Head Bits or LBA Bits 24-27
IdeCmdReg_W_DriveHead equ 6  ; Drive & Head Bits or LBA Bits 24-27
IdeCmdReg_R_Status    equ 7  ; Status Register
IdeCmdReg_W_Command   equ 7  ; Command Register

; IDE Status Register Bits
IdeCmdReg_R_Status_BSY  equ 80h ; Bit 7
IdeCmdReg_R_Status_DRDY equ 40h ; Bit 6
IdeCmdReg_R_Status_DWF  equ 20h ; Bit 5
IdeCmdReg_R_Status_DSC  equ 10h ; Bit 4
IdeCmdReg_R_Status_DRQ  equ 08h ; Bit 3
IdeCmdReg_R_Status_CORR equ 04h ; Bit 2
IdeCmdReg_R_Status_IDX  equ 02h ; Bit 1
IdeCmdReg_R_Status_ERR  equ 01h ; Bit 0

; [ ATA Commands ]

; ATA PACKET INTERFACE Command
ATAPI_PKT_COMMAND equ 0A0h ; Mandatory
; ATAPI_IDENTIFY_DRIVE equ 0A1h ; Mandatory
; ATAPI_SOFT_RESET equ 08h ; Mandatory
; ATAPI_SERVICE equ A2h    ; Optional

; [ ATAPI Pkt Commands - as a parameter of ATA Command A0h ]
ATAPI_READ_TOC equ 43h ; Operation Code
ATAPI_READ equ 28h ; Operation Code

 Present segment Para 'code'

		assume CS:Present, DS:Present, ES:Present, SS:Present

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
;              PROCEDURE proc_start
;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

proc_start      proc    far

                org 100h
start:                                         
                push ds
                pop es

                mov byte ptr [Command], ATAPI_PKT_COMMAND

                call proc_clear_screen

                mov si, offset READ_Table_Header
                call proc_printmsg

                mov word ptr [Port], 1F0h
                mov byte ptr [Drive], 0
                mov word ptr [READ_T_Port], "F1"  ; 1F0h
                mov byte ptr [READ_T_Drive], "0"
                call proc_atapi_read

                jc short pass_1F0_0

                call proc_show_pvd_table

pass_1F0_0:
                mov byte ptr [Drive], 10h ; Drive 1
                mov byte ptr [READ_T_Drive], "1"
                call proc_atapi_read

                jc short pass_1F0_1

                call proc_show_pvd_table
pass_1F0_1:
                mov word ptr [Port], 170h
                mov byte ptr [Drive], 0
                mov word ptr [READ_T_Port], "71"  ; 170h
                mov byte ptr [READ_T_Drive], "0"
                call proc_atapi_read

                jc short pass_170_0

                call proc_show_pvd_table

pass_170_0:    
                mov byte ptr [Drive], 10h ; Drive 1
                mov byte ptr [READ_T_Drive], "1"
                call proc_atapi_read

                jc short loc_terminate

                call proc_show_pvd_table

loc_terminate:
                int 20h

proc_start      endp

proc_atapi_read proc near

                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]

                mov cx, 0FFFFh
loc_read_status_reg_1:
                in al, dx
                and al, ideCmdReg_R_Status_BSY
                jz short loc_write_ide_command_1
                loop loc_read_status_reg_1

                jmp short loc_device_is_busy

loc_write_ide_command_1:
                mov dx, ideCmdReg_W_DriveHead
                add dx, word ptr [Port]
                mov al, byte ptr [Drive]
                or al, 0EFh ; Select Drive via Bit 4
                out dx, al
                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_2:
                in al, dx
                and al, 80h  ; BSY
                jz short loc_write_ide_command_2
                loop loc_read_status_reg_2

                jmp short loc_device_is_busy

loc_write_ide_command_2:
                mov dx, ideCmdReg_W_Command
                add dx, word ptr [Port]
                mov al, byte ptr [Command]
                out dx, al
                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_3:
                in al, dx
                test al, 80h ; BSY bit
                jnz short pass_drq_err_check_1
                test al, 01h ; ERR bit
                jnz short loc_ata_ide_io_error
                test al, 08h  ; DRQ bit
                jnz short loc_write_command_packet_1
pass_drq_err_check_1:
                loop loc_read_status_reg_3
                jmp short loc_device_is_busy

loc_write_command_packet_1:
                mov dx, ideCmdReg_R_Data
                add dx, word ptr [Port]
                mov si, offset TOC_Command_Packet_Buffer
                mov cx, 6
loc_write_command_packet_1a:
                lodsw
                out dx, ax
                loop loc_write_command_packet_1a

                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_4:
                in al, dx
                test al, 80h ; BSY bit
                jnz short pass_drq_err_check_2
                test al, 01h ; ERR bit
                jnz short loc_ata_ide_io_error
                test al, 08h  ; DRQ bit
                jnz short loc_read_data_reg_1a
pass_drq_err_check_2:
                loop loc_read_status_reg_4
loc_device_is_busy:
              ; mov si, Offset Device_is_busy
              ; call proc_printmsg

                stc

                retn

loc_ata_ide_io_error:
              ; mov si, offset IO_Error
              ; call proc_printmsg

                stc

                retn

loc_read_data_reg_1a:
                mov dx, ideCmdReg_R_Data
                add dx, word ptr [Port]

                mov di, offset TOC_Data_Buffer
loc_Read_Data_reg_1b:
                in ax, dx
                xchg ah,al
                mov cx, ax
                shr cx,1
                stosw
loc_Read_Data_reg_1c:
                in ax, dx
                stosw
                loop loc_Read_Data_reg_1c

                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_8:
                in al, dx
                and al, 80h  ; BSY
                jz short loc_write_ide_command_3
                loop loc_read_status_reg_8

loc_write_ide_command_3:
                mov dx, ideCmdReg_W_DriveHead
                add dx, word ptr [Port]
                mov al, byte ptr [Drive]
                or al, 0EFh ; Select Drive via Bit 4
                out dx, al
                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_5:
                in al, dx
                and al, 80h  ; BSY
                jz short loc_write_ide_command_4
                loop loc_read_status_reg_5

                jmp short loc_device_is_busy

loc_write_ide_command_4:

                 mov al, byte ptr Last_Session_Number
                 call proc_hex
                 mov word ptr [READ_T_Session], ax

                 mov si, offset First_Track_Absolute_Address
                 mov di, offset PVD_LBA
                 lodsw
                 xchg ah,al
                 push ax
                 lodsw
                 xchg ah,al
                 pop dx
                 add ax, 10h
                 adc dx, 0
                 xchg dh,dl
                 xchg ah,al
                 push ax
                 push dx
                 pop ax
                 stosw
                 pop ax
                 stosw

loc_write_ide_command_4a:
                mov dx, ideCmdReg_W_Command
                add dx, word ptr [Port]
                mov al, byte ptr [Command]
                out dx, al
                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_6:
                in al, dx
                test al, 80h ; BSY bit
                jnz short pass_drq_err_check_3
                test al, 01h ; ERR bit
                jnz loc_ata_ide_io_error
                test al, 08h  ; DRQ bit
                jnz short loc_write_command_packet_2
pass_drq_err_check_3:
                loop loc_read_status_reg_6
                jmp loc_device_is_busy

loc_write_command_packet_2:
                mov dx, ideCmdReg_R_Data
                add dx, word ptr [Port]
                mov si, offset PVD_Command_Packet_Buffer
                mov cx, 6
loc_write_command_packet_2a:
                lodsw
                out dx, ax
                loop loc_write_command_packet_2a

                mov cx, 0FFFFh
                mov dx, ideCmdReg_R_Status
                add dx, word ptr [Port]
loc_read_status_reg_7:
                in al, dx
                test al, 80h ; BSY bit
                jnz short pass_drq_err_check_4
                test al, 01h ; ERR bit
                jnz loc_ata_ide_io_error
                test al, 08h  ; DRQ bit
                jnz short loc_read_data_reg_2a
pass_drq_err_check_4:
                loop loc_read_status_reg_7

                jmp loc_device_is_busy

loc_read_data_reg_2a:
                mov dx, ideCmdReg_R_Data
                add dx, word ptr [Port]
                mov cx, 1024
                mov di, offset PVD_Buffer
                push di
loc_Read_Data_reg_2b:
                in ax, dx
                stosw
                loop loc_Read_Data_reg_2b
                pop si

                mov di, offset READ_T_PVD_b0
                lodsb
                call proc_hex ; AL= Input, AX= Output as HEX num characters.
                stosw

                mov di, offset READ_T_PVD_ISO9660_ID
                mov cx, 5
                rep movsb

                mov di, offset READ_T_PVD_b6
                lodsb
                call proc_hex
                stosw

                mov di, offset READ_T_PVD_b7
                lodsb
                call proc_hex
                stosw

                mov di, offset READ_T_PVD_SYSID
                mov cx, 16
                rep movsw

                mov di, offset READ_T_PVD_VOLID
                mov cx, 16
                rep movsw

                mov si, offset PVD_Buffer_TOTALSECS
                mov di, offset READ_T_PVD_TOTALSECS

                ; 32 bit Number as First Little Endian (al,ah,dl,dh)

                lodsw
                push ax  ; Byte 0 will be Byte 3 after "pop ax"
                lodsw

                call proc_hex_double
                xchg dx, ax
                push dx
                stosw   
                pop ax
                stosw

                pop ax
                call proc_hex_double
                xchg ax,dx 
                push dx
                stosw   
                pop ax
                stosw

                mov si, offset PVD_Buffer_SECSIZE
                mov di, offset READ_T_PVD_SECSIZE

                ; 16 bit Number as First Little Endian (al,ah)

                lodsw
                call proc_hex_double
                xchg dx,ax
                push dx
                stosw
                pop ax
                stosw

                clc

                retn

proc_atapi_read  endp

proc_show_pvd_table proc near

                mov si, offset READ_Data_Table

loc_print_PVD_Table:
                mov cx, offset end_of_table
                sub cx, si
loc_print_table_cx:
                lodsb                        ; Load byte at DS:SI to AL
                mov     AH,0Eh
		mov     BX,07h             
                int     10h                  ; BIOS Service func ( ah ) = 0Eh
                                             ; Write char as TTY
                                             ;AL-char BH-page BL-color
                loop    short loc_print_table_cx           

             ;  Above instructions are used for preventing STOP due to al=0.
             ;  Otherwise, 'call proc_printmsg' would be used.

                mov si, offset Msg_PressAnyKey
                call proc_printmsg

                xor ah, ah
                int 16h

                retn

proc_show_pvd_table endp

proc_clear_screen proc near

                mov ah, 0Fh 
                int 10h
                mov ah, 0
                int 10h

                retn

proc_clear_screen endp

proc_printmsg   proc near
loc_print:          
                lodsb                        ; Load byte at DS:SI to AL
		and     AL,AL            
                je      short loc_return     ; If AL = 00h then return
		mov     AH,0Eh                  
		mov     BX,07h             
                int     10h                  ; BIOS Service func ( ah ) = 0Eh
                                             ; Write char as TTY
                                             ;AL-char BH-page BL-color
		jmp     short loc_print           
loc_return:
		retn

proc_printmsg   endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (byte) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AL = byte (binary number) to be converted         ;
; output -> AH = First character of hexadecimal number       ;
; output -> AL = Second character of hexadecimal number      ;
;                                                            ;
; (c) Erdogan TAN  1998 - 1999                               ;
;............................................................;

; 1998

proc_hex        proc    near

		db 0D4h,10h                     ; Undocumented inst. AAM
						; AH = AL / 10h
						; AL = AL MOD 10h
		or AX,'00'                      ; Make it ZERO (ASCII) based

		xchg AH,AL

; 1999
		cmp AL,'9'
                jna short pass_ccl_al
		add AL,7
pass_ccl_al:
		cmp AH,'9'
                jna short pass_ccl_ah
		add AH,7
pass_ccl_ah:

; 1998
		retn

proc_hex        endp

;'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';
; From binary (word) to hexadecimal (character) converter    ;
;                                                            ;
; input -> AX = word (binary number) to be converted         ;
; output -> DX = First 2 characters of hexadecimal number    ;
; output -> AX = Last 2 characters of hexadecimal number     ;
;                                                            ;
; (c) Erdogan Tan  [ 28/1/2002 ]                             ;
;............................................................;

proc_hex_double  proc    near

                 push cx
                 xor dx, dx
                 mov cx, 10h
                 div cx      ; Q in AX, R in DX (DL)
                 xchg dh, dl ; DH= 0, R in DL <- CX= 10h 
                 push dx     ; R in DH, DL= 0
                 xor dh, dh
                 div cx
                 push dx     ; R in DL, DH= 0, AX <= FFh
                 div cl      ; AX <= 0Fh
                             ; R in AH, Q in AL, AL (Q) is 0
                 push ax
                 pop dx      ; High Word Characters is in DX

                 pop cx      ; R in CL
                 pop ax      ; R in AH, AL = 0
                 or al, cl
                 
                 or DX,'00'

                 cmp DL,'9'
                 jna short pass_cc_dl
                 add DL,7
pass_cc_dl:
                 cmp DH,'9'
                 jna short pass_cc_dh
                 add DH,7
pass_cc_dh:
                 or AX, '00'

                 cmp AL,'9'
                 jna short pass_cc_al
                 add AL,7
pass_cc_al:
                 cmp AH,'9'
                 jna short pass_cc_ah
                 add AH,7
pass_cc_ah:
                 pop cx

                 retn

proc_hex_double  endp

Command:        db 0
Port:           dw 0
Drive:          db 0

; ATAPI READ (10) Command Parameters (Input - Command packet)
PVD_Command_Packet_Buffer:
db 28h ; Operation Code
db 0 ; Byte 1- Reserved
PVD_LBA:
dd 10000000h ; Logical Block Address (16= ISO9660 Primary Volume Descriptor)
db 0 ; Byte 6 - Reserved
dw 0100h ; Transfer Lengt (1 sector)
db 3 dup(0) ; Byte 9 to 11 are Reserved

; ATAPI READ TOC Command Parameters (Input - Command packet)
TOC_Command_Packet_Buffer:
db 43h ; Operation Code
MSF_Bit:
db 0 ; Byte 1 - Bit 1 = MSF bit. Other bits are reserved.  0= LBA, 1= MSF
Format_Bits:
db 00h ; Byte 2 - Bit 0,1,2 are Format bits.
;O1b= Multi-Session mode, returns the 1st session number, last session number
;and last session's starting track address (LBA or MSF)
; Other bits are reserved
db 3 dup(0) ; Reserved bytes
Starting_Track:  ; or Starting_Session
db 0 ; Byte 6 - Starting Track / Session Number - Reserved in Format 01b
Allocation_Lenght:
dw 0C00h ; Allocation Lengt (12 bytes) 
db 40h ; Byte 9 - Bit 6,7 are Format bits when Format in Byte 2 is zero.
; Other bits of Byte 9 are reserved.
; Format 00b= Backward Compatible Mode (No Multisession)
; Format 01b= Multi Session Mode
; Format 10b= Returns all Sub-Channel Q data in the lead in (TOC) area.
dw 0 ; Byte 10,11 are reserved.

Msg_PressAnyKey:
                db "Press any key to continue ..."
                db 0Dh, 0Ah, 0

READ_Table_Header:
                db 7
                db 0Dh, 0Ah
                db "ISO9660 Primary Volume Descriptor  [ (c) Erdogan Tan 2002 ]"
                db 0Dh, 0Ah, 0
READ_Data_Table:
                db 0Dh, 0Ah
                db "I/O Port                    : "
READ_T_Port:     db "1F0h"
                db 0Dh, 0Ah
                db "Drive                       : "
READ_T_Drive:    db "0"
                db 0Dh, 0Ah
                db 0Dh, 0Ah
                db "Session                     : "
READ_T_Session:
                db "00h"
                db 0Dh, 0Ah
                db 0Dh, 0Ah
                db "Byte 0                      : "
READ_T_PVD_b0:
                db "00h"
                db 0Dh, 0Ah
                db "ISO9660 Identifier          : "
READ_T_PVD_ISO9660_ID:
                db 6 dup(20h)
                db 0Dh,0Ah
                db "Byte 6                      : "
READ_T_PVD_b6:
                db "00h"
                db 0Dh, 0Ah
                db "Byte 7                      : "
READ_T_PVD_b7:
                db "00h"
                db 0Dh,0Ah
                db "System Identifier           : "
READ_T_PVD_SYSID:
                db 32 dup(20h)
                db 0Dh,0Ah
                db "Volume Identifier           : "
READ_T_PVD_VOLID:
                db 32 dup(20h)
                db 0Dh,0Ah
                db "Total Number of Sectors     : "
READ_T_PVD_TOTALSECS:
                db 8 dup("0")
                db "h"
                db 0dh, 0Ah
                db "Sector Size                 : "
READ_T_PVD_SECSIZE:
                db 4 dup("0")
                dd "h"
                db 0Dh, 0Ah
                db 0Dh, 0Ah
end_of_table:
                db 0Dh, 0Ah,0

; Drive_Is_Not_Ready:
              ; db "Drive is not ready !"
              ; db 0Dh, 0Ah, 0
; Device_Is_Busy:
              ; db "Device is busy !"
              ; db 0Dh, 0Ah, 0
; IO_Error:
              ; db "IO Error !"
              ; db 0Dh, 0Ah,0

; READ TOC Data Buffer
TOC_Data_Buffer:
TOC_DATA_Lenght:
dw 0 
First_Session_Number:
db 0
Last_Session_Number:
db 0
; TOC Track Descriptors
db 0 ; Reserved
ADR_Control:
db 0 ; Bit 0,1,2,3 are Control bits, Bits 4,5,6,7 are ADR bits 
First_Track_LS:
db 0 ; First Track Number in Last Session
db 0 ; Reserved
First_Track_Absolute_Address:  ; in Last Session
dd 0 ; 4 bytes - LBA or MSF format ( LBA returns when MSF bit is 0 ) 
db 792 dup(0) ; 100 sessions * 8 bytes structure + 4 bytes = 804 bytes max.

; ISO9660 Primary Volume Descriptor Buffer
PVD_Buffer:
PVD_Buffer_b0:
db 0
PVD_Buffer_ISO9660_ID:
db 5 dup(20h)
PVD_Buffer_b6:
db 0
PVD_Buffer_b7:
db 0
PVD_Buffer_SYSID:
db 32 dup (20h)
PVD_Buffer_VOLID:
db 32 dup (20h)
db 8 dup(0)
PVD_Buffer_TOTALSECS: ; First Little Endian = al,ah,dl,dh
db 4 dup(0)
; PVD_Buffer_TOTALSECS:  [ First Big Endian  = dh,dl,ah,al ]
db 4 dup (0)
db 32 dup (0)
dd 0
dd 0
PVD_Buffer_SECSIZE: ; First Little Endian
dw 0
; PVD_Buffer_SECSIZE:  [ First Big Endian ]
dw 0
PVD_Buffer_PTAB_L:
db 8 dup(0)
PVD_Buffer_Num_Of_1st_Sector:
dd 0
dd 0
dd 0
dd 0
PVD_Buffer_Root_Dir_Record:
db 34 dup(0)
PVD_Buffer_VolSet_ID:
db 128 dup (20h)
PVD_Buffer_Publisher_ID:
db 128 dup (20h)
PVD_Buffer_Data_Prep_ID:
db 128 dup (20h)
PVD_Buffer_Appl_ID:
db 128 dup (20h)
PVD_Buffer_CopyRight_File_ID:
db 37 dup (20h)
PVD_Buffer_Abstract_File_ID:
db 37 dup (20h)
PVD_Buffer_Biblio_File_ID:
db 37 dup (20h)
PVD_Buffer_Creation_DateTime:
db 17 dup (20h)
PVD_Buffer_LastModif_DateTime:
db 17 dup (20h)
PVD_Buffer_Expire_DateTime:
db 17 dup (20h)
PVD_Buffer_Effective_DateTime:
db 17 dup (20h)
db 1
db 0
db 512 dup (0)
db 653 dup (0)

Present         ends

                end  start

    

    

    

    
 index.html  specs.html  trdos.html

Tarkan - KUZU KUZU