Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S263607AbUA0NNh (ORCPT ); Tue, 27 Jan 2004 08:13:37 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S263609AbUA0NNh (ORCPT ); Tue, 27 Jan 2004 08:13:37 -0500 Received: from mail1-106.ewetel.de ([212.6.122.106]:65525 "EHLO mail1.ewetel.de") by vger.kernel.org with ESMTP id S263607AbUA0NN2 (ORCPT ); Tue, 27 Jan 2004 08:13:28 -0500 Date: Tue, 27 Jan 2004 14:13:20 +0100 (CET) From: Pascal Schmidt To: Jens Axboe cc: linux-kernel@vger.kernel.org Subject: Re: MO: opening for write in cdrom.c In-Reply-To: <20040127110713.GR11683@suse.de> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-CheckCompat: OK Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9474 Lines: 267 On Tue, 27 Jan 2004, Jens Axboe wrote: > Sounds pretty shaky... This drive is a bit strange, yeah. > Hmm, looks a bit strange. You want write protect to be set _if_ > detection works, not otherwise. If it fails, just assume that you can > write to the drive and let the normal drive rejection work fail those > (maybe even catch them and write protect then). Before I had this worked out, I accidentally tried fscking a write-protected disc. Yes, it errored out at the end of the fsck, but the error messages are quite unintuitive. Lot's of I/O error in the kernel log and an error=0x70 from the drive. I sure didn't realize at first what the problem really was. > Seeing as the method is > unreliable, we cannot solely rely on that. I've not seen all three variants fail, yet. I was following sd.c's example, that also sets write protect by default if it cannot get info from the drive. It's fine with me either way. Do you want me to resend with the default fallback changed? Oh, BTW, while I have your attention ;), have you looked at my latest variable blocksize support patch for ide-cd? I've tried to incorporate yours and Bart's suggestions. Here it is again in case you missed it in the thread. --- linux-2.6.2-rc1/drivers/ide/ide-cd.c.orig Sat Jan 24 01:24:03 2004 +++ linux-2.6.2-rc1/drivers/ide/ide-cd.c Sat Jan 24 01:39:40 2004 @@ -294,10 +294,12 @@ * 4.60 Dec 17, 2003 - Add mt rainier support * - Bump timeout for packet commands, matches sr * - Odd stuff + * 4.61 Jan 22, 2004 - support hardware sector sizes other than 2kB, + * Pascal Schmidt * *************************************************************************/ -#define IDECD_VERSION "4.60" +#define IDECD_VERSION "4.61" #include #include @@ -1211,6 +1213,7 @@ static int cdrom_read_from_buffer (ide_d { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; + unsigned short sectors_per_frame = drive->queue->hardsect_size >> 9; /* Can't do anything if there's no buffer. */ if (info->buffer == NULL) return 0; @@ -1249,7 +1252,7 @@ static int cdrom_read_from_buffer (ide_d will fail. I think that this will never happen, but let's be paranoid and check. */ if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) && - (rq->sector % SECTORS_PER_FRAME) != 0) { + (rq->sector % sectors_per_frame) != 0) { printk("%s: cdrom_read_from_buffer: buffer botch (%ld)\n", drive->name, (long)rq->sector); cdrom_end_request(drive, 0); @@ -1268,13 +1271,8 @@ static int cdrom_read_from_buffer (ide_d static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - int nsect, sector, nframes, frame, nskip; - - /* Number of sectors to transfer. */ - nsect = rq->nr_sectors; - - /* Starting sector. */ - sector = rq->sector; + unsigned short sectors_per_frame = drive->queue->hardsect_size >> 9; + int nskip; /* If the requested sector doesn't start on a cdrom block boundary, we must adjust the start of the transfer so that it does, @@ -1283,31 +1281,19 @@ static ide_startstop_t cdrom_start_read_ of the buffer, it will mean that we're to skip a number of sectors equal to the amount by which CURRENT_NR_SECTORS is larger than the buffer size. */ - nskip = (sector % SECTORS_PER_FRAME); + nskip = (rq->sector % sectors_per_frame); if (nskip > 0) { /* Sanity check... */ if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) && - (rq->sector % CD_FRAMESIZE != 0)) { + (rq->sector % sectors_per_frame != 0)) { printk ("%s: cdrom_start_read_continuation: buffer botch (%u)\n", drive->name, rq->current_nr_sectors); cdrom_end_request(drive, 0); return ide_stopped; } - sector -= nskip; - nsect += nskip; rq->current_nr_sectors += nskip; } - /* Convert from sectors to cdrom blocks, rounding up the transfer - length if needed. */ - nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME; - frame = sector / SECTORS_PER_FRAME; - - /* Largest number of frames was can transfer at once is 64k-1. For - some drives we need to limit this even more. */ - nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ? - (65534 / CD_FRAMESIZE) : 65535); - /* Set up the command */ rq->timeout = ATAPI_WAIT_PC; @@ -1346,13 +1332,10 @@ static ide_startstop_t cdrom_seek_intr ( static ide_startstop_t cdrom_start_seek_continuation (ide_drive_t *drive) { struct request *rq = HWGROUP(drive)->rq; - int sector, frame, nskip; + unsigned short sectors_per_frame = drive->queue->hardsect_size >> 9; + int frame; - sector = rq->sector; - nskip = (sector % SECTORS_PER_FRAME); - if (nskip > 0) - sector -= nskip; - frame = sector / SECTORS_PER_FRAME; + frame = rq->sector / sectors_per_frame; memset(rq->cmd, 0, sizeof(rq->cmd)); rq->cmd[0] = GPCMD_SEEK; @@ -1396,6 +1379,7 @@ static ide_startstop_t cdrom_start_read { struct cdrom_info *info = drive->driver_data; struct request *rq = HWGROUP(drive)->rq; + unsigned short sectors_per_frame = drive->queue->hardsect_size >> 9; /* We may be retrying this request after an error. Fix up any weirdness which might be present in the request packet. */ @@ -1411,8 +1395,8 @@ static ide_startstop_t cdrom_start_read info->nsectors_buffered = 0; /* use dma, if possible. */ - if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && - (rq->nr_sectors % SECTORS_PER_FRAME == 0)) + if (drive->using_dma && (rq->sector % sectors_per_frame == 0) && + (rq->nr_sectors % sectors_per_frame == 0)) info->dma = 1; else info->dma = 0; @@ -1950,11 +1934,13 @@ static ide_startstop_t cdrom_start_write static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) { struct cdrom_info *info = drive->driver_data; + unsigned short sectors_per_frame = drive->queue->hardsect_size >> 9; /* - * writes *must* be 2kB frame aligned + * writes *must* be hardware frame aligned */ - if ((rq->nr_sectors & 3) || (rq->sector & 3)) { + if ((rq->nr_sectors & (sectors_per_frame - 1)) || + (rq->sector & (sectors_per_frame - 1))) { cdrom_end_request(drive, 0); return ide_stopped; } @@ -1969,12 +1955,12 @@ static ide_startstop_t cdrom_start_write info->nsectors_buffered = 0; - /* use dma, if possible. we don't need to check more, since we - * know that the transfer is always (at least!) 2KB aligned */ + /* use dma, if possible. we don't need to check more, since we + * know that the transfer is always (at least!) frame aligned */ info->dma = drive->using_dma ? 1 : 0; info->cmd = WRITE; - /* Start sending the read request to the drive. */ + /* Start sending the write request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); } @@ -2209,6 +2195,7 @@ static int cdrom_eject(ide_drive_t *driv } static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, + unsigned long *sectors_per_frame, struct request_sense *sense) { struct { @@ -2227,8 +2214,10 @@ static int cdrom_read_capacity(ide_drive req.data_len = sizeof(capbuf); stat = cdrom_queue_packet_command(drive, &req); - if (stat == 0) + if (stat == 0) { *capacity = 1 + be32_to_cpu(capbuf.lba); + *sectors_per_frame = be32_to_cpu(capbuf.blocklen) >> 9; + } return stat; } @@ -2270,6 +2259,7 @@ static int cdrom_read_toc(ide_drive_t *d struct atapi_toc_entry ent; } ms_tmp; long last_written; + unsigned long sectors_per_frame = SECTORS_PER_FRAME; if (toc == NULL) { /* Try to allocate space. */ @@ -2289,12 +2279,14 @@ static int cdrom_read_toc(ide_drive_t *d if (CDROM_STATE_FLAGS(drive)->toc_valid) return 0; - /* Try to get the total cdrom capacity. */ - stat = cdrom_read_capacity(drive, &toc->capacity, sense); + /* Try to get the total cdrom capacity and sector size. */ + stat = cdrom_read_capacity(drive, &toc->capacity, §ors_per_frame, + sense); if (stat) toc->capacity = 0x1fffff; - set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME); + set_capacity(drive->disk, toc->capacity * sectors_per_frame); + blk_queue_hardsect_size(drive->queue, sectors_per_frame << 9); /* First read just the header, so we know how long the TOC is. */ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, @@ -2406,7 +2398,7 @@ static int cdrom_read_toc(ide_drive_t *d stat = cdrom_get_last_written(cdi, &last_written); if (!stat && last_written) { toc->capacity = last_written; - set_capacity(drive->disk, toc->capacity * SECTORS_PER_FRAME); + set_capacity(drive->disk, toc->capacity * sectors_per_frame); } /* Remember that we've read this stuff. */ @@ -3306,12 +3298,12 @@ int ide_cdrom_setup (ide_drive_t *drive) static sector_t ide_cdrom_capacity (ide_drive_t *drive) { - unsigned long capacity; + unsigned long capacity, sectors_per_frame; - if (cdrom_read_capacity(drive, &capacity, NULL)) + if (cdrom_read_capacity(drive, &capacity, §ors_per_frame, NULL)) return 0; - return capacity * SECTORS_PER_FRAME; + return capacity * sectors_per_frame; } static -- Ciao, Pascal - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/