IDE ATA Ports for {Primary/Secundary , Master/Slave} ATAPI Packet For CD/DVD devices - reading/writeing sector

The function to send SCSI(ATAPI) Packet and (if the case) to receive data from device (after painfull tries, without no tutorial for this specific func .... LOT OF PAIN 'till I camed to this !)
Function pioreadideatapi(ide As UByte, typ As UByte,packet As Any Ptr,sector As UlongInt, counts As Uinteger,where As Any ptr)As UInteger
If where=0 Then Exit function
if packet=0 then exit function
if ide >1 or typ>1 then exit function
Dim As Uinteger c_ide
Dim As Uinteger c_typ,s_reg
dim as uinteger stat,did,marked

Select Case ide
Case 0
c_ide=&h1f0
s_reg=&h3f6
Case 1
c_ide=&h170
s_reg=&h376
End Select
typ And=&h01
typ Shl= 4 'select which cannel ... Master(0) / Slave(1)

Asm
pushad

mov edx,0

mov dx,[c_ide]
add dx,7
LOOP1:
IN AL, DX 'sets AL to status register (which is 8 bits)

'If the first bit of the status register (BUSY) isn't 0, the device is busy,
'so keep looping until it isn't.

AND AL, &b10000000
JNE LOOP1

'----------------------------------------------------------------------------

'Clear interrupts so something doesn't interrupt the drive or controller
'while this program is working.
CLI

'----------------------------------------------------------------------------

mov dx,[c_ide]
add dx,7
LOOP2:
IN AL, DX 'sets AL to status register again

'If the second bit of the status register (DRDY) isn't 1, the device isn't
'ready, so keep looping until it is.

AND AL, &B01000000
JE LOOP2

'----------------------------------------------------------------------------

mov dx,[c_ide]
add dx,6

MOV AL, &ha0 '0 selects device 0 (master). 10h would select device 1 (slave).
Or al, [typ]
OUT DX, AL 'selects master device

'IMPORTANT: Set nIEN before you send the PACKET command!
'Let's set nIEN to 1 so we can skip the INTRQ_Wait state.

MOV DX, [s_reg] 'Device Control register
MOV AL, &b00001010 'nIEN is the second bit from the right here
OUT DX, AL 'nIEN is now one!

mov dx,[c_ide]
add dx, 1 'Point to ATAPI - Features
mov al,0
out dx,al 'if bit 0 is = 0 PIO transfer else DMA transfer

mov dx,[c_ide]
add dx, 3 'Point to byte count registers.
mov ax,[counts] 'Output data-transfer length.
out dx,al
inc dx
mov al,ah
out dx,al

mov dx,[c_ide]
add dx,7
MOV AL, &h0A0 'PACKET command
OUT DX, AL 'sends the command!

'After sending the PACKET command, the host is to wait 400 nanoseconds before
'doing anything else.
MOV ECX,&h0FFFF
WAITLOOP:
LOOPNZ WAITLOOP

'----------------------------------------------------------------------------

mov dx,[c_ide]
add dx,7
LOOP3:
IN AL, DX 'sets AL to status register again

'Poll until BUSY bit is clear.

AND AL, &b10000000
JNE LOOP3

'Also, poll until DRQ is one.
mov dx,[c_ide]
add dx,7
LOOP4:
IN AL, DX
AND AL, &b00001000
JE LOOP4

'----------------------------------------------------------------------------
'NOW WE START SENDING THE COMMAND PACKET!!!

MOV ECX, 6 'do this 6 times because it's 6 word writes (a word is 2 bytes)
MOV ESI, [packet]
'DS:SI now points to the buffer which contains our ATAPI command packet
CLD 'clear direction flag so SI gets incremented, not decremented

COMPACKLOOP: 'command packet sending loop
mov dx,[c_ide]

'Because we're going to need to write a word (2 bytes), we can't just use an
'8-bit register like AL. For this operation, we'll need to use the full width
'of the 16-bit accumulator AX. We'll use the LODSW opcode, which loads AX
'with whatever DS:SI points to. Not only this, but if the direction flag is
'cleared (which we did a few lines above with the CLD instruction), LODSW
'also auto-increments SI.
LODSW
OUT DX, AX 'send the current word of the command packet!!!

MOV DX, [s_reg] 'Alternate Status Register
IN AL, DX 'wait one I/O cycle

LOOPNZ COMPACKLOOP

'----------------------------------------------------------------------------

'Once again, let's read the Alternate Status Register and ignore the result,
'since the spec says so.

MOV DX, [s_reg]
IN AL, DX
'pushad
'end asm
'print "complete sending PACKET ! ";
'asm
'popad

'Okay... That's done.
'Time to poll the status register until BUSY is 0 again.

mov dx,[c_ide]
add dx,7
LOOP5:
IN AL, DX
And AL, &b10000000
JNE LOOP5

'BUSY is zero here.
mov dx,[c_ide]
add dx,7
'LOOP23:
IN AL, DX
And AL, &B00001000
'JE LOOP23 'We're also supposed to check DRQ
JE cont1_02 'if drq=0 no DATA (because command is done )!

continue_to_get:
MOV DX, [s_reg]
in AL,dx 'delay for a while

mov dx,[c_ide] 'Get controller-buffer byte count.
add dx,5
in al,dx
mov ah,al
dec dx
in al,dx

mov [marked],ax
mov dx,[c_ide]
mov ecx,[counts]
cmp ax,cx
je eq1111
movzx ecx,ax
mov [stat],ecx
sub [counts],ecx
'pushad
'end asm
'print "[well stat=";stat;" while counts=";counts;" did=";did;"]"
'asm
'popad
eq1111:
shr ecx,1
mov edi,[where]
add edi,[did]
cld
rep insw
movzx ecx,word ptr [marked]
add [did],ecx
'pushad
'end asm
'print "Veve !"
'asm
'popad
MOV DX, [s_reg] 'Device Control register
in al,dx

mov dx,[c_ide]
add dx,7
'in al,dx
'in al,dx
mov ecx,100
LOOP51:
dec ecx
jcxz cont1_01
IN AL, DX
And AL, &b10000000
JNE LOOP51
cont1_01:

mov dx,[c_ide]
add dx,7
IN AL, DX
And AL, &B01000
'bt ax,3:jnc short continue_to_get
jne short continue_to_get

cont1_02:
MOV DX, [s_reg] 'Device Control register
'in al,dx
MOV AL, &b00001000 'nIEN is the second bit from the right here
OUT DX, AL 'nIEN is now on!
STI
popad
End Asm
'movsb1(the_where,where,counts)
Function=1
End Function

Helpfull function to read sectors from IDE CD/DVD... (send PACKET and recives DATA !)
Function pioreadideatapi10(ide As UByte, typ As UByte,sector As UInteger, counts As Ushort,where As Any ptr)As UInteger
If where=0 Then Exit function
Dim As atapi_packet_READ10 aprd
dim as ulongint ssee
dim as ushort cou
dim as uinteger sect
dim as ushort i
for i=1 to counts
sect=sector+(i-1)
asm
push eax
mov ax,1
xchg al,ah
mov [cou],ax
mov eax,[sect]
xchg al,ah
rol eax,16
xchg al,ah
mov [sect],eax
pop eax
end asm
aprd.cmd=atapi_Read10
aprd.lba=sect
aprd.transfer_len=cou
function=pioreadideatapi(ide,typ,@aprd,ssee,2048,cptr(ubyte ptr,where)+2048*(i-1))
next i
End Function

ATAPI interface commands (this are "SCUZY" - SCSI - commnads in fact ) for CD/DVD

'this are onely for a CD[-RW]... But the new DVD[-RW] might include some new facilities ... And not to forget BlueRay .....
#Define atapi_INQUIRE &H12
#Define atapi_loadunloadcd &hA6
#Define atapi_mechanismstatus &HBD
#Define atapi_modeselect &h55
#Define atapi_modesense &h5a
#Define atapi_PauseResume &h4B
#Define atapi_PlayAudio &h45
#Define atapi_PlayAudio2 &hA5
#Define atapi_PlayAudioMSF &h47
#Define atapi_PlayCD &hBC
#Define atapi_PreventAllowMediaRemoval &h1E
#Define atapi_Read10 &h28
#Define atapi_Read12 &hA8
#Define atapi_ReadCDROMCapacity8 &h25
#Define atapi_ReadCD &hBE
#Define atapi_ReadCDMSF &hB9
#Define atapi_ReadHeader &h44
#Define atapi_ReadSubChannel &h42
#Define atapi_ReadTOC &h43
#Define atapi_RequestSense &h03
#Define atapi_RezeroUnit9 &h01
#Define atapi_Scan &hBA
#Define atapi_Seek &h2B
#Define atapi_ServiceCommands_First &hF0
#Define atapi_ServiceCommands_Last &hff
#Define atapi_SetCDSpeed &hBB
#Define atapi_StartStopUnit &h1B
#Define atapi_StopPlayScan &h4E
#Define atapi_TestUnitReady &h0
#Define atapi_Verify &hAF
'cd writer commands MMC CD-R/W COMMANDS (MMC - MultiMediaCommand set)
#Define MMC_CDRW_BLANKCommand &hA1
#Define MMC_CDRW_CloseTRACKSESSION &h5B
#Define MMC_CDRW_FormatUNIT &h04
#Define MMC_CDRW_ReadBUFFERCAPACITY &h5C
#Define MMC_CDRW_READDISCINFORMATION &h51
#Define MMC_CDRW_ReadMASTERCUE &h59
#Define MMC_CDRW_ReadTRACKINFORMATION &h52
#Define MMC_CDRW_REPAIRPACKETTRACK12 &h58
#Define MMC_CDRW_RESERVETRACK &h53
#Define MMC_CDRW_sendCUESHEET &h5D
#Define MMC_CDRW_SENDOPCINFORMATION &h54
#Define MMC_CDRW_SYNCHRONIZECACHE &h35
#Define MMC_CDRW_WRITE &h2A

'STANDARD ATAPI COMMAND PACKET FORMAT
Type atapi_packet Field=1
As UByte cmd,params(2 To 12)
End Type
'INQUIRY DATA FORMAT
#Define inquiry_allocation_length 56 'bytes
Type atapi_packet_INQUIRY Field=1
As UByte cmd
As UByte reserved1(1 To 3)
As UByte allocation_len
As UByte reserved2(1 To 7)
End Type
#Define inquiry_peripheralDeviceType_CD &h05
Type atapi_INQUIRY Field=1
As UByte peripheralDeviceType, RMB, ISO_ECMA_ANSIver, ATAPIVer_RESPONSEDATAFORMAT
As UByte AdditionalLength,reserved1,reserved2,reserved3
As UByte VendorId(1 To 15-8+1), ProductId(1 To 31-16+1), ProductlRevisonLevel(1 To 35-32+1)
As UByte SerialNumber(1 To 51-36+1),ServoRevisionNum(1 To 55-52+1)
End Type
'MECHANISM status
Type atapi_packet_MECHANISMSTATUS Field=1
As UByte cmd
As UByte reserved1(1 To 7)
As UShort allocation_len
As UByte reserved2(1 To 2)
End Type
Type atapi_MECHANISMSTATUS_return Field=1
As UByte fault_changestatus_currentslot
As UByte cdmechanismstate_res
As UByte current_LBA(1 To 3)
As UByte num_slots_avail
As UShort Len_slot_tables
End Type
'MODE Select
'read TOC
Type atapi_packet_READTOC Field=1
As UByte cmd
As UByte MSFbit2
As UByte format4bits
As UByte reserved1(1 To 3)
As UByte trackSesNum
As UShort allocation_len
As UByte reserver2(1 To 3)
End Type
#Define readtoc_formatTOC 0
#Define readtoc_formatSESSIONINFO 1
#Define readtoc_formatFullTOC 2
Type atapi_READTOC_return Field=1
As UShort toc_data_len
As UByte first_track,last_track
End Type
Type atapi_READTOC_returnTOC Field=1
As UByte reserved
As UByte address_control
As UByte track_num
As UByte reserved2
As UInteger lba
End Type
Type atapi_READTOC_returnTOC2 Field=1
As UByte session_num, _
address_control, _
tno, _
point_, _
min_, _
sec_, _
frame, _
zero, _
pmin, _
psec, _
pframe
End Type
' '''endreadtoc
'atapi read
Type atapi_packet_READ10 Field=1
As UByte cmd, reserved1
As UInteger lba
As UByte reserved2
As UShort transfer_len
As UByte resrved3(1 To 3)
End Type
Type atapi_packet_SETCDSPEED field=1
As UByte cmd1,reserved
As UShort readspeed
As UShort writespeed
As UByte reserved2(1 To 6)
End Type
#Define cd_max_speed &hffff