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
|
|