--WIyZ46R2i8wDzkSu
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="oct19.diff"
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- /tmp/linux-2.3.23/drivers/block/ide-cd.c Tue Oct 19 21:36:17 1999
+++ linux/drivers/block/ide-cd.c Tue Oct 19 21:55:38 1999
@@ -339,14 +339,15 @@
failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
return;
}
+
if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
&& ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
(reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
{
/*
* Suppress the following errors:
- * "Medium not present", and "in progress of becoming ready",
- * to keep the noise level down to a dull roar.
+ * "Medium not present", "in progress of becoming ready",
+ * and "writing" to keep the noise level down to a dull roar.
*/
return;
}
@@ -431,6 +432,19 @@
printk ("\"\n");
}
+ /* The SKSV bit specifies validity of the sense_key_specific
+ * in the next two commands. It is bit 7 of the first byte.
+ * In the case of NOT_READY, if SKSV is set the drive can
+ * give us nice ETA readings.
+ */
+ if (reqbuf->sense_key == NOT_READY &&
+ (reqbuf->sense_key_specific[0] & 0x80)) {
+ int progress = (reqbuf->sense_key_specific[1] << 8 |
+ reqbuf->sense_key_specific[2]) * 100;
+ printk(" Command is %02d%% complete\n", progress / 0xffff);
+
+ }
+
if (reqbuf->sense_key == ILLEGAL_REQUEST &&
(reqbuf->sense_key_specific[0] & 0x80) != 0) {
printk (" Error in %s byte %d",
@@ -466,21 +480,6 @@
#endif /* not VERBOSE_IDE_CD_ERRORS */
}
-
-/* Fix up a possibly partially-processed request so that we can
- start it over entirely, or even put it back on the request queue. */
-static void restore_request (struct request *rq)
-{
- if (rq->buffer != rq->bh->b_data) {
- int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE;
- rq->buffer = rq->bh->b_data;
- rq->nr_sectors += n;
- rq->sector -= n;
- }
- rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
-}
-
-
static void cdrom_queue_request_sense (ide_drive_t *drive,
struct semaphore *sem,
struct atapi_request_sense *reqbuf,
@@ -533,10 +532,8 @@
struct packet_command *pc = (struct packet_command *)
rq->buffer;
cdrom_analyze_sense_data (drive,
- (struct atapi_request_sense *)
- (pc->buffer - pc->c[4]),
- (struct packet_command *)
- pc->sense_data);
+ (struct atapi_request_sense *) (pc->buffer - pc->c[4]),
+ (struct packet_command *) pc->sense_data);
}
if (rq->cmd == READ && !rq->current_nr_sectors)
uptodate = 1;
@@ -680,7 +677,7 @@
struct cdrom_info *info = drive->driver_data;
/* Wait for the controller to be idle. */
- if (ide_wait_stat (drive, 0, BUSY_STAT, WAIT_READY)) return 1;
+ if (ide_wait_stat(drive, 0, BUSY_STAT, WAIT_READY)) return 1;
if (info->dma)
info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive);
@@ -719,9 +716,10 @@
unsigned char *cmd_buf, int cmd_len,
ide_handler_t *handler)
{
- /* set timeout to an hour */
+ /* don't timeout for blank and format commands. they may take
+ * a _very_ long time. */
if (cmd_buf[0] == GPCMD_BLANK || cmd_buf[0] == GPCMD_FORMAT_UNIT)
- drive->timeout = 3600*HZ;
+ drive->timeout = 0;
if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
/* Here we should have been called after receiving an interrupt
@@ -774,13 +772,12 @@
/* If we don't yet have a sector buffer, try to allocate one.
If we can't get one atomically, it's not fatal -- we'll just throw
the data away rather than caching it. */
- if (info->sector_buffer == NULL) {
- info->sector_buffer = (char *) kmalloc (SECTOR_BUFFER_SIZE,
- GFP_ATOMIC);
+ if (info->buffer == NULL) {
+ info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_ATOMIC);
/* If we couldn't get a buffer,
don't try to buffer anything... */
- if (info->sector_buffer == NULL)
+ if (info->buffer == NULL)
sectors_to_buffer = 0;
}
@@ -789,7 +786,7 @@
info->sector_buffered = sector;
/* Read the data into the buffer. */
- dest = info->sector_buffer + info->nsectors_buffered * SECTOR_SIZE;
+ dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE;
while (sectors_to_buffer > 0) {
atapi_input_bytes (drive, dest, SECTOR_SIZE);
--sectors_to_buffer;
@@ -806,7 +803,6 @@
}
}
-
/*
* Check the contents of the interrupt reason register from the cdrom
* and attempt to recover if there are problems. Returns 0 if everything's
@@ -921,8 +917,7 @@
/* First, figure out if we need to bit-bucket
any of the leading sectors. */
- nskip = MIN ((int)(rq->current_nr_sectors -
- (rq->bh->b_size >> SECTOR_BITS)),
+ nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)),
sectors_to_transfer);
while (nskip > 0) {
@@ -948,8 +943,7 @@
/* If the buffers are full, cache the rest of the data in our
internal buffer. */
if (rq->current_nr_sectors == 0) {
- cdrom_buffer_sectors (drive,
- rq->sector, sectors_to_transfer);
+ cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
sectors_to_transfer = 0;
} else {
/* Transfer data to the buffers.
@@ -961,8 +955,7 @@
/* Read this_transfer sectors
into the current buffer. */
while (this_transfer > 0) {
- atapi_input_bytes (drive,
- rq->buffer, SECTOR_SIZE);
+ atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
rq->buffer += SECTOR_SIZE;
--rq->nr_sectors;
--rq->current_nr_sectors;
@@ -975,10 +968,9 @@
/* Done moving data!
Wait for another interrupt. */
- ide_set_handler (drive, &cdrom_read_intr);
+ ide_set_handler(drive, &cdrom_read_intr);
}
-
/*
* Try to satisfy some of the current read request from our cached data.
* Returns nonzero if the request has been completed, zero otherwise.
@@ -989,7 +981,7 @@
struct request *rq = HWGROUP(drive)->rq;
/* Can't do anything if there's no buffer. */
- if (info->sector_buffer == NULL) return 0;
+ if (info->buffer == NULL) return 0;
/* Loop while this request needs data and the next block is present
in our cache. */
@@ -1000,7 +992,7 @@
cdrom_end_request (1, drive);
memcpy (rq->buffer,
- info->sector_buffer +
+ info->buffer +
(rq->sector - info->sector_buffered) * SECTOR_SIZE,
SECTOR_SIZE);
rq->buffer += SECTOR_SIZE;
@@ -1063,14 +1055,13 @@
nskip = (sector % SECTORS_PER_FRAME);
if (nskip > 0) {
/* Sanity check... */
- if (rq->current_nr_sectors !=
- (rq->bh->b_size >> SECTOR_BITS)) {
- printk ("%s: cdrom_start_read_continuation: buffer botch (%ld)\n",
+ if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) &&
+ (rq->sector % CD_FRAMESIZE != 0)) {
+ printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n",
drive->name, rq->current_nr_sectors);
cdrom_end_request (0, drive);
return;
}
-
sector -= nskip;
nsect += nskip;
rq->current_nr_sectors += nskip;
@@ -1091,16 +1082,17 @@
pc.c[0] = GPCMD_READ_10;
pc.c[7] = (nframes >> 8);
pc.c[8] = (nframes & 0xff);
- put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
+ put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
/* Send the command to the drive and return. */
(void) cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
&cdrom_read_intr);
}
+
#define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
-#define IDECD_SEEK_TIMER (2 * WAIT_MIN_SLEEP) /* 40 ms */
-#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
+#define IDECD_SEEK_TIMER (5 * WAIT_MIN_SLEEP) /* 100 ms */
+#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */
static void cdrom_seek_intr (ide_drive_t *drive)
{
@@ -1114,7 +1106,7 @@
if (retry && jiffies - info->start_seek > IDECD_SEEK_TIMER) {
if (--retry == 0) {
- printk ("%s: disabled DSC seek overlap\n", drive->name);
+ printk("%s: disabled DSC seek overlap\n", drive->name);
drive->dsc_overlap = 0;
}
}
@@ -1147,6 +1139,19 @@
cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
}
+/* Fix up a possibly partially-processed request so that we can
+ start it over entirely, or even put it back on the request queue. */
+static void restore_request (struct request *rq)
+{
+ if (rq->buffer != rq->bh->b_data) {
+ int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE;
+ rq->buffer = rq->bh->b_data;
+ rq->nr_sectors += n;
+ rq->sector -= n;
+ }
+ rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
+}
+
/*
* Start a read request from the CD-ROM.
*/
@@ -1169,23 +1174,22 @@
restore_request (rq);
/* Satisfy whatever we can of this request from our cached sector. */
- if (cdrom_read_from_buffer (drive))
+ if (cdrom_read_from_buffer(drive))
return;
- /* Clear the local sector buffer. */
info->nsectors_buffered = 0;
- if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) && (rq->nr_sectors % SECTORS_PER_FRAME == 0))
+ /* use dma, if possible. */
+ if (drive->using_dma && (rq->sector % SECTORS_PER_FRAME == 0) &&
+ (rq->nr_sectors % SECTORS_PER_FRAME == 0))
info->dma = 1;
else
info->dma = 0;
/* Start sending the read request to the drive. */
- cdrom_start_packet_command (drive, 32768,
- cdrom_start_read_continuation);
+ cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
}
-
/****************************************************************************
* Execute all other packet commands.
*/
@@ -1362,7 +1366,7 @@
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change (drive);
else if (reqbuf->sense_key == NOT_READY &&
- reqbuf->asc == 4) {
+ reqbuf->asc == 4 && reqbuf->ascq != 4) {
/* The drive is in the process of loading
a disk. Retry, but wait a little to give
the drive time to complete the load. */
@@ -1405,10 +1409,10 @@
static
void ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, unsigned long block)
{
+ struct cdrom_info *info = drive->driver_data;
+
switch (rq->cmd) {
case READ: {
- struct cdrom_info *info = drive->driver_data;
-
if (CDROM_CONFIG_FLAGS(drive)->seeking) {
unsigned long elpased = jiffies - info->start_seek;
int stat = GET_STAT();
@@ -2095,12 +2099,16 @@
if (slot_nr == CDSL_CURRENT) {
- struct atapi_request_sense my_reqbuf;
- int stat = cdrom_check_status (drive, &my_reqbuf);
- if (stat == 0 || my_reqbuf.sense_key == UNIT_ATTENTION)
+ struct atapi_request_sense sense;
+ int stat = cdrom_check_status (drive, &sense);
+ if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
+ return CDS_DISC_OK;
+
+ if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
+ sense.ascq == 0x04)
return CDS_DISC_OK;
- if (my_reqbuf.sense_key == NOT_READY) {
+ if (sense.sense_key == NOT_READY) {
/* ATAPI doesn't have anything that can help
us decide whether the drive is really
emtpy or the tray is just open. irk. */
@@ -2381,7 +2389,6 @@
ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
}
-
static
int ide_cdrom_setup (ide_drive_t *drive)
{
@@ -2496,10 +2503,10 @@
}
#endif /* not STANDARD_ATAPI */
- info->toc = NULL;
- info->sector_buffer = NULL;
- info->sector_buffered = 0;
- info->nsectors_buffered = 0;
+ info->toc = NULL;
+ info->buffer = NULL;
+ info->sector_buffered = 0;
+ info->nsectors_buffered = 0;
info->changer_info = NULL;
info->last_block = 0;
info->start_seek = 0;
@@ -2562,8 +2569,8 @@
if (ide_unregister_subdriver (drive))
return 1;
- if (info->sector_buffer != NULL)
- kfree(info->sector_buffer);
+ if (info->buffer != NULL)
+ kfree(info->buffer);
if (info->toc != NULL)
kfree(info->toc);
if (info->changer_info != NULL)
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
--- /tmp/linux-2.3.23/drivers/block/ide-cd.h Tue Oct 19 21:36:17 1999
+++ linux/drivers/block/ide-cd.h Tue Oct 19 21:49:49 1999
@@ -34,19 +34,13 @@
#define NO_DOOR_LOCKING 0
#endif
-
-/* Size of buffer to allocate, in blocks, for audio reads. */
-
-#ifndef CDROM_NBLOCKS_BUFFER
-#define CDROM_NBLOCKS_BUFFER 8
-#endif
-
-
/************************************************************************/
-#define SECTOR_SIZE 512
-#define SECTOR_BITS 9
-#define SECTORS_PER_FRAME (CD_FRAMESIZE / SECTOR_SIZE)
+#define SECTOR_SIZE 512
+#define SECTOR_BITS 9
+#define SECTORS_PER_FRAME (CD_FRAMESIZE / SECTOR_SIZE)
+#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
+#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE / SECTOR_SIZE)
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -84,7 +78,8 @@
__u8 seeking : 1; /* Seeking in progress */
__u8 audio_play : 1; /* can do audio related commands */
__u8 close_tray : 1; /* can close the tray */
- __u8 reserved : 4;
+ __u8 writing : 1; /* pseudo write in progress */
+ __u8 reserved : 3;
byte max_speed; /* Max speed of the drive */
};
#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
@@ -488,13 +483,11 @@
byte reserved2[3];
};
-
struct atapi_changer_info {
struct atapi_mechstat_header hdr;
struct atapi_slot slots[0];
};
-
/* Extra per-device info for cdrom drives. */
struct cdrom_info {
@@ -503,17 +496,9 @@
struct atapi_toc *toc;
- /* Sector buffer. If a read request wants only the first part
- of a cdrom block, we cache the rest of the block here,
- in the expectation that the data is going to be wanted soon.
- SECTOR_BUFFERED is the number of the first buffered sector,
- and NSECTORS_BUFFERED is the number of sectors in the buffer.
- Before the buffer is allocated, we should have
- SECTOR_BUFFER == NULL and NSECTORS_BUFFERED == 0. */
-
- unsigned long sector_buffered;
- unsigned long nsectors_buffered;
- char *sector_buffer;
+ unsigned long sector_buffered;
+ unsigned long nsectors_buffered;
+ unsigned char *buffer;
/* The result of the last successful request sense command
on this device. */
@@ -534,10 +519,6 @@
struct cdrom_device_info devinfo;
};
-
-#define SECTOR_BUFFER_SIZE CD_FRAMESIZE
-
-
/****************************************************************************
* Descriptions of ATAPI error codes.
*/
@@ -653,6 +634,7 @@
{ 0x000013, "Play operation successfully completed" },
{ 0x000014, "Play operation stopped due to error" },
{ 0x000015, "No current audio status to return" },
+ { 0x010c0a, "Write error - padding blocks added" },
{ 0x011700, "Recovered data with no error correction applied" },
{ 0x011701, "Recovered data with retries" },
{ 0x011702, "Recovered data with positive head offset" },
@@ -669,6 +651,7 @@
{ 0x015d01,
"Failure prediction threshold exceeded - Predicted media failure" },
{ 0x015dff, "Failure prediction threshold exceeded - False" },
+ { 0x017301, "Power calibration area almost full" },
{ 0x020400, "Logical unit not ready - cause not reportable" },
/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
{ 0x020401,
@@ -681,9 +664,35 @@
{ 0x023a00, "Medium not present" },
{ 0x025300, "Media load or eject failed" },
{ 0x025700, "Unable to recover table of contents" },
+ { 0x030300, "Peripheral device write fault" },
+ { 0x030301, "No write current" },
+ { 0x030302, "Excessive write errors" },
+ { 0x030c00, "Write error" },
+ { 0x030c01, "Write error - Recovered with auto reallocation" },
+ { 0x030c02, "Write error - auto reallocation failed" },
+ { 0x030c03, "Write error - recommend reassignment" },
+ { 0x030c04, "Compression check miscompare error" },
+ { 0x030c05, "Data expansion occurred during compress" },
+ { 0x030c06, "Block not compressible" },
+ { 0x030c07, "Write error - recovery needed" },
+ { 0x030c08, "Write error - recovery failed" },
+ { 0x030c09, "Write error - loss of streaming" },
{ 0x031100, "Unrecovered read error" },
{ 0x031106, "CIRC unrecovered error" },
{ 0x033101, "Format command failed" },
+ { 0x033200, "No defect spare location available" },
+ { 0x033201, "Defect list update failure" },
+ { 0x035100, "Erase failure" },
+ { 0x037200, "Session fixation error" },
+ { 0x037201, "Session fixation error writin lead-in" },
+ { 0x037202, "Session fixation error writin lead-out" },
+ { 0x037300, "CD control error" },
+ { 0x037302, "Power calibration area is full" },
+ { 0x037303, "Power calibration area error" },
+ { 0x037304, "Program memory area / RMA update failure" },
+ { 0x037305, "Program memory area / RMA is full" },
+ { 0x037306, "Program memory area / RMA is (almost) full" },
+
{ 0x040200, "No seek complete" },
{ 0x040300, "Write fault" },
{ 0x040900, "Track following error" },
@@ -701,11 +710,15 @@
{ 0x052000, "Invalid command operation code" },
{ 0x052c00, "Command sequence error" },
{ 0x052100, "Logical block address out of range" },
+ { 0x052102, "Invalid address for write" },
{ 0x052400, "Invalid field in command packet" },
{ 0x052600, "Invalid field in parameter list" },
{ 0x052601, "Parameter not supported" },
{ 0x052602, "Parameter value invalid" },
{ 0x052700, "Write protected media" },
+ { 0x052c00, "Command sequence error" },
+ { 0x052c03, "Current program area is not empty" },
+ { 0x052c04, "Current program area is empty" },
{ 0x053001, "Cannot read medium - unknown format" },
{ 0x053002, "Cannot read medium - incompatible format" },
{ 0x053900, "Saving parameters not supported" },
@@ -714,11 +727,15 @@
{ 0x055500, "System resource failure" },
{ 0x056300, "End of user area encountered on this track" },
{ 0x056400, "Illegal mode for this track or incompatible medium" },
- { 0x056f00,
- "Copy protection key exchange failure - Authentication failure" },
+ { 0x056f00, "Copy protection key exchange failure - Authentication failure" },
{ 0x056f01, "Copy protection key exchange failure - Key not present" },
- { 0x056f02,
- "Copy protection key exchange failure - Key not established" },
+ { 0x056f02, "Copy protection key exchange failure - Key not established" },
+ { 0x056f03, "Read of scrambled sector without authentication" },
+ { 0x056f04, "Media region code is mismatched to logical unit" },
+ { 0x056f05, "Drive region must be permanent / region reset count error" },
+ { 0x057203, "Session fixation error - incomplete track in session" },
+ { 0x057204, "Empty or partially written reserved track" },
+ { 0x057205, "No more RZONE reservations are allowed" },
{ 0x05bf00, "Loss of streaming" },
{ 0x062800, "Not ready to ready transition, medium may have changed" },
{ 0x062900, "Power on, reset or hardware reset occurred" },
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/drivers/block/ide.c linux/drivers/block/ide.c
--- /tmp/linux-2.3.23/drivers/block/ide.c Tue Oct 19 21:36:17 1999
+++ linux/drivers/block/ide.c Tue Oct 19 21:42:35 1999
@@ -498,6 +498,18 @@
}
/*
+ * The below two are helpers used when modifying the drive timeout.
+ */
+static inline unsigned long set_timeout(ide_drive_t *drive, unsigned long timeout)
+{
+ unsigned long foo = drive->timeout;
+ drive->timeout = timeout;
+ return foo;
+}
+
+#define restore_timeout(drive, old) (drive->timeout = old)
+
+/*
* This should get invoked any time we exit the driver to
* wait for an interrupt response from a drive. handler() points
* at the appropriate code to handle the next interrupt, and a
@@ -517,8 +529,11 @@
}
#endif
hwgroup->handler = handler;
- hwgroup->timer.expires = jiffies + drive->timeout;
- add_timer(&(hwgroup->timer));
+ /* 0 means don't timeout */
+ if (drive->timeout && !timer_pending(&hwgroup->timer)) {
+ hwgroup->timer.expires = jiffies + drive->timeout;
+ add_timer(&(hwgroup->timer));
+ }
spin_unlock_irqrestore(&hwgroup->spinlock, flags);
}
@@ -575,10 +590,9 @@
printk("%s: ATAPI reset complete\n", drive->name);
} else {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- old_timeout = drive->timeout;
- drive->timeout = HZ / 20;
+ old_timeout = set_timeout(drive, HZ / 20);
ide_set_handler (drive, &atapi_reset_pollfunc);
- drive->timeout = old_timeout;
+ restore_timeout(drive, old_timeout);
return; /* continue polling */
}
hwgroup->poll_timeout = 0; /* end of polling */
@@ -604,10 +618,9 @@
if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
if (0 < (signed long)(hwgroup->poll_timeout - jiffies)) {
- old_timeout = drive->timeout;
- drive->timeout = HZ / 20;
+ old_timeout = set_timeout(drive, HZ / 20);
ide_set_handler (drive, &reset_pollfunc);
- drive->timeout = old_timeout;
+ restore_timeout(drive, old_timeout);
return; /* continue polling */
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
@@ -687,10 +700,9 @@
udelay (20);
OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- old_timeout = drive->timeout;
- drive->timeout = HZ / 20;
+ old_timeout = set_timeout(drive, HZ / 20);
ide_set_handler (drive, &atapi_reset_pollfunc);
- drive->timeout = old_timeout;
+ restore_timeout(drive, old_timeout);
__restore_flags (flags); /* local CPU only */
return;
}
@@ -720,10 +732,9 @@
OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
udelay(10); /* more than enough time */
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- old_timeout = drive->timeout;
- drive->timeout = HZ / 20;
+ old_timeout = set_timeout(drive, HZ / 20);
ide_set_handler (drive, &reset_pollfunc);
- drive->timeout = old_timeout;
+ restore_timeout(drive, old_timeout);
/*
* Some weird controller like resetting themselves to a strange
@@ -923,7 +934,6 @@
*/
void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
{
- drive->timeout = WAIT_CMD;
ide_set_handler (drive, handler);
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
--- /tmp/linux-2.3.23/drivers/block/pdc4030.c Tue Oct 19 21:36:17 1999
+++ linux/drivers/block/pdc4030.c Tue Oct 19 21:42:35 1999
@@ -396,7 +396,6 @@
if (GET_STAT() & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
- drive->timeout = 1;
ide_set_handler(drive, &promise_complete_pollfunc);
return; /* continue polling... */
}
@@ -426,7 +425,6 @@
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
- drive->timeout = 1;
ide_set_handler (drive, &promise_write_pollfunc);
return; /* continue polling... */
}
@@ -441,7 +439,6 @@
*/
ide_multwrite(drive, 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- drive->timeout = 1;
ide_set_handler(drive, &promise_complete_pollfunc);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
@@ -475,7 +472,6 @@
if (rq->nr_sectors > 4) {
ide_multwrite(drive, rq->nr_sectors - 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- drive->timeout = 1;
ide_set_handler (drive, &promise_write_pollfunc);
} else {
/*
@@ -484,7 +480,6 @@
*/
ide_multwrite(drive, rq->nr_sectors);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
- drive->timeout = 1;
ide_set_handler(drive, &promise_complete_pollfunc);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- /tmp/linux-2.3.23/drivers/cdrom/cdrom.c Tue Oct 19 21:36:17 1999
+++ linux/drivers/cdrom/cdrom.c Tue Oct 19 21:57:39 1999
@@ -308,8 +308,6 @@
*/
#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
-static int cdrom_setup_writemode(struct cdrom_device_info *cdi);
-
int register_cdrom(struct cdrom_device_info *cdi)
{
static char banner_printed = 0;
@@ -357,9 +355,6 @@
cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
cdi->next = topCdromPtr;
topCdromPtr = cdi;
- if (CDROM_CAN(CDC_CD_R) || CDROM_CAN(CDC_CD_RW) || CDROM_CAN(CDC_DVD_R))
- (void)cdrom_setup_writemode(cdi);
-
return 0;
}
#undef ENSURE
@@ -415,6 +410,8 @@
return cdi;
}
+static int cdrom_setup_writemode(struct cdrom_device_info *cdi);
+
/* We use the open-option O_NONBLOCK to indicate that the
* purpose of opening is only for subsequent ioctl() calls; no device
* integrity checks are performed.
@@ -426,22 +423,31 @@
static
int cdrom_open(struct inode *ip, struct file *fp)
{
+ struct cdrom_device_info *cdi;
kdev_t dev = ip->i_rdev;
- struct cdrom_device_info *cdi = cdrom_find_device(dev);
- int purpose = !!(fp->f_flags & O_NONBLOCK);
- int ret=0;
+ int ret;
cdinfo(CD_OPEN, "entering cdrom_open\n");
- if (cdi == NULL)
+ if ((cdi = cdrom_find_device(dev)) == NULL)
return -ENODEV;
- if (fp->f_mode & FMODE_WRITE)
- return -EROFS;
- purpose = purpose || !(cdi->options & CDO_USE_FFLAGS);
- if (purpose)
- ret = cdi->ops->open(cdi, purpose);
+
+ /* just CD-RW for now. DVD-RW will come soon, CD-R and DVD-R
+ * need to be handled differently. */
+ if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_CD_RW))
+ return -EROFS;
+
+ /* if this was a O_NONBLOCK open and we should honor the flags,
+ * do a quick open without drive/disc integrity checks. */
+ if ((fp->f_flags & O_NONBLOCK) && (cdi->options & CDO_USE_FFLAGS))
+ ret = cdi->ops->open(cdi, 1);
else
ret = open_for_data(cdi);
+
if (!ret) cdi->use_count++;
+
+ if (fp->f_mode & FMODE_WRITE && !cdi->write.writeable)
+ cdi->write.writeable = !cdrom_setup_writemode(cdi);
+
cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
/* Do this on open. Don't wait for mount, because they might
not be mounting, but opening with O_NONBLOCK */
@@ -536,7 +542,7 @@
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
cdo->lock_door(cdi, 1);
cdinfo(CD_OPEN, "door locked.\n");
- }
+ }
cdinfo(CD_OPEN, "device opened successfully.\n");
return ret;
@@ -627,7 +633,7 @@
if (cdi->use_count > 0) cdi->use_count--;
if (cdi->use_count == 0)
cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
- if (cdi->use_count == 0 && /* last process that closes dev*/
+ if (cdi->use_count == 0 &&
cdo->capability & CDC_LOCK && !keeplocked) {
cdinfo(CD_CLOSE, "Unlocking door!\n");
cdo->lock_door(cdi, 0);
@@ -2168,6 +2174,28 @@
}
}
+/* return the buffer size of writeable drives */
+static int cdrom_read_buffer_capacity(struct cdrom_device_info *cdi)
+{
+ struct cdrom_device_ops *cdo = cdi->ops;
+ struct cdrom_generic_command cgc;
+ struct {
+ unsigned int pad;
+ unsigned int buffer_size;
+ unsigned int buffer_free;
+ } buf;
+ int ret;
+
+ init_cdrom_command(&cgc, &buf, 12);
+ cgc.cmd[0] = 0x5c;
+ cgc.cmd[8] = 12;
+
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+ return ret;
+
+ return be32_to_cpu(buf.buffer_size);
+}
+
/* return 0 if succesful and the disc can be considered writeable. */
static int cdrom_setup_writemode(struct cdrom_device_info *cdi)
{
@@ -2180,6 +2208,7 @@
memset(&di, 0, sizeof(disc_information));
memset(&ti, 0, sizeof(track_information));
memset(&wp, 0, sizeof(write_param_page));
+ memset(&cdi->write, 0, sizeof(struct cdrom_write_settings));
if ((ret = cdrom_get_disc_info(cdi->dev, &di)))
return ret;
@@ -2188,35 +2217,53 @@
if ((ret = cdrom_get_track_info(cdi->dev, last_track, 1, &ti)))
return ret;
+ /* if the media is erasable, then it is either CD-RW or
+ * DVD-RW - use fixed packets for those. non-erasable media
+ * indicated CD-R or DVD-R media, use varible sized packets for
+ * those (where the packet size is a bit less than the buffer
+ * capacity of the drive. */
+ if (di.erasable) {
+ cdi->write.fpacket = 1;
+ /* FIXME: DVD-RW is 16, should get the packet size instead */
+ cdi->write.packet_size = 32;
+ } else {
+ int buf_size;
+ cdi->write.fpacket = 0;
+ buf_size = cdrom_read_buffer_capacity(cdi);
+ buf_size -= 100*1024;
+ cdi->write.packet_size = buf_size / CD_FRAMESIZE;
+ }
+
init_cdrom_command(&cgc, &wp, 0x3c);
if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_WRITE_PARMS_PAGE, 0)))
return ret;
/* sanity checks */
- if ((ti.damage && !ti.nwa_v) || ti.blank)
+ if ((ti.damage && !ti.nwa_v) || ti.blank) {
+ cdinfo(CD_WARNING, "can't write to this disc\n");
return 1;
-
- cdi->packet_size = wp.packet_size = be32_to_cpu(ti.fixed_packet_size);
- cdi->nwa = ti.nwa_v ? be32_to_cpu(ti.next_writable) : 0;
- wp.track_mode = ti.track_mode;
- /* write_type 0 == packet/incremental writing */
- wp.write_type = 0;
-
- /* MODE1 or MODE2 writing */
- switch (ti.data_mode) {
- case 1: wp.data_block_type = 8; break;
- case 2: wp.data_block_type = 13; break;
- default: return 1;
}
+ /* NWA is only for CD-R and DVD-R. -RW media is randomly
+ * writeable once it has been formatted. */
+ cdi->write.nwa = ti.nwa_v ? be32_to_cpu(ti.next_writable) : 0;
+
+ wp.fp = cdi->write.fpacket ? 1 : 0;
+ wp.track_mode = 0;
+ wp.write_type = 0;
+ wp.data_block_type = 8;
+ wp.session_format = 0;
+ wp.multi_session = 3;
+ wp.audio_pause = cpu_to_be16(0x96);
+ wp.packet_size = cdi->write.fpacket ? cpu_to_be32(cdi->write.packet_size) : 0;
+ wp.track_mode = 5; /* should be ok with both CD and DVD */
+
if ((ret = cdrom_mode_select(cdi, &cgc)))
return ret;
- printk("%s: writeable with %s packets of %lu in length", cdi->name,
- wp.fp ? "fixed" : "variable",
- (unsigned long)cdi->packet_size);
- printk(", nwa = %lu\n", (unsigned long)cdi->nwa);
-
+ cdinfo(CD_WARNING, "%s: writeable with %lu block %s packets\n",
+ cdi->name, cdi->write.packet_size,
+ cdi->write.fpacket ? "fixed" : "variable");
return 0;
}
@@ -2479,14 +2526,17 @@
initialized = 1;
}
+#endif /* endif CONFIG_SYSCTL */
+
+#ifdef MODULE
static void cdrom_sysctl_unregister(void)
{
+#ifdef CONFIG_SYSCTL
unregister_sysctl_table(cdrom_sysctl_header);
+#endif
}
-#endif /* endif CONFIG_SYSCTL */
-#ifdef MODULE
int init_module(void)
{
#ifdef CONFIG_SYSCTL
diff -ur --exclude-from /home/axboe/cdrom/exclude-from /tmp/linux-2.3.23/include/linux/cdrom.h linux/include/linux/cdrom.h
--- /tmp/linux-2.3.23/include/linux/cdrom.h Tue Oct 19 21:36:17 1999
+++ linux/include/linux/cdrom.h Mon Oct 18 22:17:20 1999
@@ -273,6 +273,7 @@
unsigned char *buffer;
unsigned int buflen;
int stat;
+ void *reserved[4];
};
@@ -655,6 +656,14 @@
} dvd_authinfo;
#ifdef __KERNEL__
+
+struct cdrom_write_settings {
+ unsigned char fpacket; /* fixed/variable packets */
+ unsigned long packet_size; /* write out this number of packets */
+ unsigned long nwa; /* next writeable address */
+ unsigned char writeable; /* cdrom is writeable */
+};
+
/* Uniform cdrom data structures for cdrom.c */
struct cdrom_device_info {
struct cdrom_device_ops *ops; /* link to device_ops */
@@ -673,8 +682,7 @@
/* per-device flags */
__u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
__u8 reserved : 6; /* not used yet */
- __u32 packet_size; /* write out this number of packets */
- __u32 nwa; /* next writeable address */
+ struct cdrom_write_settings write;
};
struct cdrom_device_ops {
--WIyZ46R2i8wDzkSu--