[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: linux kernel error reading end of cd/dvd



On Tue 14 October 2003 12:30, Andy Polyakov wrote:
> Meet the players in the field:
>
> - block buffer which provides for read-ahead, I/O requests'
> slicing and coalescing;
> - value returned by READ CAPACITY command, hereafter simply READ
> CAPACITY;
> - actual lead-out position;
>
> Rules of the game (please note that I'm not claiming that I know
> all the rules in detail:-):
>
> - block buffer rearranges I/O depending on *momentary*
> availability of spare memory, e.g. even if you ask for bs=2k, it
> may coalesce them to e.g. 126KB chunks, or it may break larger
> requests to a number of 4KB ones;
> - no requests are posed beyond the READ CAPACITY;
> - READ CAPACITY coincides with lead-out position most of the
> time, *but not always*;
> - CD lead-out position is documented to be inaccurate [with 75
> blocks inaccuracy?], DVD lead-out position is believed to be
> accurate; - CD lead-out is preceded by few unaccesible blocks
> (unless disk is recorded in DAO mode?), lead-out itself is
> unaccesible;

Thanks for the explanation! That sheds some more light on the case. 
I've dug up the ECMA-130 spec (== Yellow Book for all practical 
purposes) from www.ecma-international.org and after a bit of 
searching I found this (from section 22.3.4.2):

"If set to (A2) the P-MIN, P-SEC and P-FRAC fields specify the 
beginning of the Lead-out Track, thus the address of the first 
Section of the Lead-out Track."

The TOC basically consists of a list of records, each of which 
specifies a track number and a start address in min:sec:frac format 
(with a fraction being 1/75th of a second). The last element in the 
list describes the start of the Lead-out, as quoted above.

Now the interesting bit is that this is actually section-accurate, 
and that each section holds one block (ie 2k) of data. Also note 
that the last readable block before the Lead-out is at 
address_of_lead_out - 1. At any rate, unless I missed something, 
the amount of readable blocks is actually stored on the CD, and the 
number is accurate.

Okay, so that's how the information is stored on the disc 
physically. A bit of Googling got me to 
http://www.t10.org/ftp/t10/document.01/01-246r0.pdf, which states 
that the READ CAPACITY SCSI bus command returns a logical block 
address (LBA) and a block length in bytes. The LBA is the address 
of the last logical block on the disc, so the number of blocks in 
total before the Lead-out is actually LBA + 1.

From /usr/src/linux-2.4.21/drivers/ide/ide-cd.c, 
cdrom_read_capacity:

        pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
        pc.buffer = (char *)&capbuf;
        pc.buflen = sizeof(capbuf);

        stat = cdrom_queue_packet_command(drive, &pc);
        if (stat == 0)
                *capacity = 1 + be32_to_cpu(capbuf.lba);

        return stat;

So it seems that as long as the drive gives the correct LBA number 
(should be P-MIN * 60 * 75 + P-SEC * 75 + P-FRAC - 1 with values as 
above), ide-cd will report the correct media size.

Readcd from cdrecord uses the exact same way to get the capacity 
from the drive, and displays the amount of blocks correctly. 
According to it, my Nero CD has 169825 blocks.

Unfortunately the -fulltoc option of readcd isn't implemented, so I 
can't verify that this matches the information on the disc. Does 
anyone know of another way to get to the raw TOC data on a CD?

Now, as I said ide-cd.c reads the amount of blocks the same way, so 
it will get the same value. I'm not sure what happens with this 
value though, presumably it ends up with the block driver as Andy 
described, but I haven't found out how yet.

Looking at the Linux SCSI stuff, I found this in drivers/scsi/sr.c:

/*
* The SCSI specification allows for the value returned
* by READ CAPACITY to be up to 75 2K sectors past the
* last readable block.  Therefore, if we hit a medium
* error within the last 75 2K sectors, we decrease the
* saved size value.
*/
if ((error_sector >> 1) < sr_sizes[device_nr] &&
    scsi_CDs[device_nr].capacity - error_sector < 4 *75)
        sr_sizes[device_nr] = error_sector >> 1;

So it seems that you were correct about that.

<snip>
>
> Relevant question is when READ CAPACITY is not equal to lead-out
> offset? I don't know about CD, but in DVD case most units would
> report full media capacity for READ CAPACITY under following
> circumstances:

Well, it looks like that's up to the drive's firmware. READ CAPACITY 
is pretty much useless, since it's allowed to give wrong 
information.

<snip>
>
> case. One can wonder if the common block buffer could do better
> job spotting the last addressible sector? Well, yes, but do keep
> in mind that it's a *common* block buffer, which is not aware of
> CD technicalities... So that I'd say that it's perfectly
> legitimate to advice as following. If you really have to checksum
> the whole image, then make sure to bypass the block buffer *and*
> provide sane block count value. A.

Well, it seems to me that the block driver gets the capacity from 
the underlying device driver. So if that driver gives the correct 
capacity to the block layer, things should actually work fine. The 
question is how to get the device driver to give the correct 
capacity, if READ CAPACITY doesn't work well enough.

I can see two options:

1) Modify ide-cd.c and sr.c to use READ CAPACITY, and then try to 
read the 75 2k sectors before that. Catch the IO error, and adjust 
the capacity based on the number of succesfully read sectors.

2) Modify ide-cd.c and sr.c to read the TOC and get the capacity 
directly from the disc, thus completely circumventing the READ 
CAPACITY command.

Comments?

Lourens
-- 
GPG public key: http://home.student.utwente.nl/l.e.veen/lourens.key



Reply to: