flat assembler
Message board for the users of flat assembler.

Index > OS Construction > what's the fastest way to read from CD?

Author
Thread Post new topic Reply to topic
zhak



Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 20 Jan 2008, 23:49
Hi guys! I need to read a lot of sectors from cd-rom to memory above 1MB in real mode. Actually, I want to map cd-rom image to memory. I've thought of the following implementation:
1. enter unreal mode (for one segment register, for example, FS)
2. read 64Kb of data from cd-rom to buffer below 1MB
3. copy 64Kb of data from buffer to memory above 1MB using unreal mode
4. goto 2

I think this will be very slow. Is there more elegant way of doing this?
But, from the other side, 1x speed rating for CDs is 150 Kb/s... on x40 drive - it's about 6Mb/sec. Maybe mem to mem copying won't affect the overal speed at all at this rate?
what do you think of it?
Post 20 Jan 2008, 23:49
View user's profile Send private message Reply with quote
edfed



Joined: 20 Feb 2006
Posts: 4330
Location: Now
edfed 21 Jan 2008, 01:47
what about using UDMA?
if i well understand, UDMA covers the first 16 Mb of memory.

and about mem to mem copy, dma is able to do that.
Post 21 Jan 2008, 01:47
View user's profile Send private message Visit poster's website Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 789
Location: Adelaide
sinsi 21 Jan 2008, 05:54
Is this from your own OS, from DOS or from a dosbox in windows (or linux, or what...)?
Post 21 Jan 2008, 05:54
View user's profile Send private message Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 21 Jan 2008, 07:52
it's from my own boot loader. I want to make live distributive, so I use boot from cd, no-emulation mode. at first, i loaded all necessary stuff (kernel, drivers, etc.) from cd. but i decided to map system disk in the memory to make cd-rom drive fully available for user.

i've thought about using dma, but 16MB limit is actually a problem. what if more than 16MB should be loaded in future??? one more thing, i'm not familiar with dma. I've read some articles about using dma with floppy drive controller, but nothing about using it with cd-rom. for example, what channel should be used, and all the rest...

i'll appreciate any help from your side Smile
Post 21 Jan 2008, 07:52
View user's profile Send private message Reply with quote
sinsi



Joined: 10 Aug 2007
Posts: 789
Location: Adelaide
sinsi 21 Jan 2008, 07:58
So are you using PIO to read the CD? in real mode?
Post 21 Jan 2008, 07:58
View user's profile Send private message Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 21 Jan 2008, 08:53
It seems so. I use INT 13h Fn 42h.
I didn't want to access cd-rom via i/o ports to keep boot loader as compact as possible.
Hmm, I though right now, that one can use SATA cd-rom instead of IDE. In that case using i/o ports becomes even more complicated... maybe using direct access to cd-rom in boot loader is not a good idea? This code is executed only once, so it's better not to make it overcomplicated.
Post 21 Jan 2008, 08:53
View user's profile Send private message Reply with quote
Octavio



Joined: 21 Jun 2003
Posts: 366
Location: Spain
Octavio 21 Jan 2008, 09:39
edfed wrote:
what about using UDMA?
if i well understand, UDMA covers the first 16 Mb of memory.

and about mem to mem copy, dma is able to do that.

this limit is for old dma chips (floppy,sb) a modern pci bus master controler can acces all memory.
Post 21 Jan 2008, 09:39
View user's profile Send private message Visit poster's website Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 21 Jan 2008, 11:57
maybe you've got some samples or links to good articles on programming udma?
Post 21 Jan 2008, 11:57
View user's profile Send private message Reply with quote
tom tobias



Joined: 09 Sep 2003
Posts: 1320
Location: usa
tom tobias 21 Jan 2008, 12:15
http://board.flatassembler.net/topic.php?t=6299
http://board.flatassembler.net/topic.php?t=1386
(see the post by anton on 30 June 2004, links seem still active!)
Post 21 Jan 2008, 12:15
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 21 Jan 2008, 12:15
Any storage device is so slow (seek as well as transfer) that you shouldn't worry about memory copying in any way. Even the fastest harddrives can't do 100MB/s yet except for bursts, and 100MB/s speed was much less than memory bandwidth even many years ago.

You do need to use DMA though, and UDMA if the drive supports it (not all optical drives do). Not because of memory speed, but because PIO access mode can bring even a quadcore system to it's knees Smile

So... even if you had 16mb low memory DMA limit, it wouldn't be a problem DMA'ing there and moving to the real target location.
Post 21 Jan 2008, 12:15
View user's profile Send private message Visit poster's website Reply with quote
Japheth



Joined: 26 Oct 2004
Posts: 151
Japheth 21 Jan 2008, 21:19
for UDMA access you can look the UDMA XCDROM32 source in jemm569s.zip at

http://www.japheth.de/Jemm.html

UDMA has no 16 MB limit and it's faster than PIO. Accessing SATA devices is not that different - it is still ATA/ATAPI.
Post 21 Jan 2008, 21:19
View user's profile Send private message Reply with quote
Mihail_b



Joined: 01 May 2011
Posts: 1
Location: Bucharest
Mihail_b 01 May 2011, 21:25
Just in case you need this ...
It's how you can read or send any SCSI packet to a cd/dvd drive
Code:
#Define atapi_Read10 &h28

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

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)+((i-1) shl 11))
next i
End Function

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    
edit by revolution: added code tags
Post 01 May 2011, 21:25
View user's profile Send private message Send e-mail Visit poster's website Reply with quote
tom tobias



Joined: 09 Sep 2003
Posts: 1320
Location: usa
tom tobias 06 May 2011, 09:13
Thank you, well written.
Post 06 May 2011, 09:13
View user's profile Send private message Reply with quote
neville



Joined: 13 Jul 2008
Posts: 507
Location: New Zealand
neville 07 May 2011, 10:25
I was reading the posts in this thread and thinking somebody's gotta tell zhak that mem-to-mem copies are definitely not slow compared to rotating storage media - even buffered 64K at a time.
Then I saw this post:
f0dder wrote:
Any storage device is so slow (seek as well as transfer) that you shouldn't worry about memory copying in any way. Even the fastest harddrives can't do 100MB/s yet except for bursts, and 100MB/s speed was much less than memory bandwidth even many years ago.
Well said, fodder Very Happy

_________________
FAMOS - the first memory operating system
Post 07 May 2011, 10:25
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.