From: Ana Bobillo <[email protected]> atapi_inquiry() takes the block size from the READ CAPACITY reply of an ATAPI device as it is, while atapi_read() asks the device for, and moves the buffer on by, ATAPI_READ_BLOCK_SIZE (2048) bytes for every block. With any other block size the callers' buffers, which are sized by blksz, do not match what atapi_read() writes into them: a 512-byte block size makes a read of several blocks write past the end of the buffer.
Some CD drives report another block size although they read 2048-byte blocks: 2340 (HP 4020i CD-Recorder), 2352 (Philips CD-Writers) or 0. Take these as ATAPI_READ_BLOCK_SIZE, as Linux does in get_sectorsize(), so that a drive reporting 0, which ide_probe() skipped until now, is read with 2048-byte blocks too. Refuse any other value: a device reporting one is left with a zero block size, which ide_probe() skips, as for a drive without a medium. This refuses drives with 512-byte blocks, such as ZIP drives, whose reads of more than one block already overran the buffer; supporting them needs atapi_read() to use the block size of the device. Signed-off-by: Ana Bobillo <[email protected]> Reviewed-by: Simon Glass <[email protected]> --- (no changes since v2) Changes in v2: - Take 0, 2340 and 2352 as 2048, as Linux get_sectorsize() does (Simon) - Say what is skipped in the message (Simon) drivers/block/ide.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 44ce054bdf5..56e55bc8bc1 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -450,6 +450,7 @@ static void atapi_inquiry(struct blk_desc *desc) { u8 ccb[12]; /* Command descriptor block */ u8 iobuf[64]; /* temp buf */ + ulong blksz; u8 c; int device; @@ -514,10 +515,28 @@ static void atapi_inquiry(struct blk_desc *desc) iobuf[0], iobuf[1], iobuf[2], iobuf[3], iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + blksz = (ulong)iobuf[4] << 24 | (ulong)iobuf[5] << 16 | + (ulong)iobuf[6] << 8 | (ulong)iobuf[7]; + /* + * atapi_read() transfers ATAPI_READ_BLOCK_SIZE bytes per block. Some + * CD drives report another size although they read 2048-byte blocks, + * which Linux takes as 2048 in get_sectorsize(): do the same. + */ + switch (blksz) { + case 0: + case 2340: /* HP 4020i CD-Recorder */ + case 2352: /* Philips CD-Writers */ + blksz = ATAPI_READ_BLOCK_SIZE; + break; + case ATAPI_READ_BLOCK_SIZE: + break; + default: + printf("ATAPI block size %lu not supported, skipping\n", blksz); + return; + } desc->lba = (ulong)iobuf[0] << 24 | (ulong)iobuf[1] << 16 | (ulong)iobuf[2] << 8 | (ulong)iobuf[3]; - desc->blksz = (ulong)iobuf[4] << 24 | (ulong)iobuf[5] << 16 | - (ulong)iobuf[6] << 8 | (ulong)iobuf[7]; + desc->blksz = blksz; desc->log2blksz = LOG2(desc->blksz); /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */
