diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/MAINTAINERS linux/MAINTAINERS
--- /opt/kernel/linux-2.4.0-test8-pre1/MAINTAINERS	Thu Aug 24 05:12:54 2000
+++ linux/MAINTAINERS	Thu Aug 31 01:04:34 2000
@@ -540,7 +540,7 @@
 
 IDE/ATAPI CDROM DRIVER
 P:	Jens Axboe
-M:	axboe@image.dk
+M:	axboe@suse.de
 L:	linux-kernel@vger.kernel.org
 W:	http://www.kernel.dk
 S:	Maintained
@@ -986,7 +986,7 @@
 
 SCSI CDROM DRIVER
 P:	Jens Axboe
-M:	axboe@image.dk
+M:	axboe@suse.de
 L:	linux-scsi@vger.kernel.org
 W:	http://www.kernel.dk
 S:	Maintained
@@ -1174,7 +1174,7 @@
 
 UNIFORM CDROM DRIVER
 P:	Jens Axboe
-M:	axboe@image.dk
+M:	axboe@suse.de
 L:	linux-kernel@vger.kernel.org
 W:	http://www.kernel.dk
 S:	Maintained
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/cdrom.c	Fri Jun 30 03:25:50 2000
+++ linux/drivers/cdrom/cdrom.c	Sun Aug 27 03:26:40 2000
@@ -784,6 +784,8 @@
 	if (!CDROM_CAN(CDC_SELECT_DISC))
 		return -EDRIVE_CANT_DO_THIS;
 
+	(void) cdi->ops->media_changed(cdi, slot);
+
 	if (slot == CDSL_NONE) {
 		/* set media changed bits, on both queues */
 		cdi->mc_flags = 0x3;
@@ -851,8 +853,8 @@
 	if (cdi == NULL || cdi->ops->media_changed == NULL)
 		return 0;
 	if (!CDROM_CAN(CDC_MEDIA_CHANGED))
-	    return 0;
-	return (media_changed(cdi, 0));
+		return 0;
+	return media_changed(cdi, 0);
 }
 
 /* badly broken, I know. Is due for a fixup anytime. */
@@ -872,8 +874,7 @@
                 return;
         }        
 	/* Grab the TOC header so we can see how many tracks there are */
-	ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
-	if (ret) {
+	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
 		if (ret == -ENOMEDIUM)
 			tracks->error = CDS_NO_DISC;
 		else
@@ -1516,12 +1517,13 @@
 		cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); 
 		if (!CDROM_CAN(CDC_MEDIA_CHANGED))
 			return -ENOSYS;
+
+		/* cannot select disc or select current disc */
 		if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
-			/* cannot select disc or select current disc */
 			return media_changed(cdi, 1);
-		if ((unsigned int)arg >= cdi->capacity) {
+
+		if ((unsigned int)arg >= cdi->capacity)
 			return -EINVAL;
-		}
 
 		if ((ret = cdrom_read_mech_status(cdi, &info)))
 			return ret;
@@ -1570,10 +1572,10 @@
 		if (!CDROM_CAN(CDC_SELECT_DISC))
 			return -ENOSYS;
 
-                if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) {
-		    if ((int)arg >= cdi->capacity)
-			return -EINVAL;
-		}
+                if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE))
+			if ((int)arg >= cdi->capacity)
+				return -EINVAL;
+
 		/* cdo->select_disc is a hook to allow a driver-specific
 		 * way of seleting disc.  However, since there is no
 		 * equiv hook for cdrom_slot_status this may not 
@@ -1834,7 +1836,6 @@
 	struct cdrom_device_ops *cdo = cdi->ops;
 	struct cdrom_generic_command cgc;
 	struct modesel_head mh;
-	int ret;
 
 	memset(&mh, 0, sizeof(mh));
 	mh.block_desc_length = 0x08;
@@ -1852,14 +1853,7 @@
 	mh.block_length_med = (size >> 8) & 0xff;
 	mh.block_length_lo = size & 0xff;
 
-	ret = cdo->generic_packet(cdi, &cgc);
-	if (ret) {
-		printk("switch_blocksize failed, ret %x ", ret);
-		if (cgc.sense)
-			printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq);
-		printk("\n");
-	}
-	return ret;
+	return cdo->generic_packet(cdi, &cgc);
 }
 
 static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
@@ -1916,16 +1910,10 @@
 			}
 			cgc.sense = NULL;
 			ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1);
-			if (ret) {
-				printk("read_cd failed, ret %x ", ret);
-				if (cgc.sense)
-					printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq);
-			printk("\n");
-			}
 			ret |= cdrom_switch_blocksize(cdi, blocksize);
 		}
 		if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize))
-				ret = -EFAULT;
+			ret = -EFAULT;
 		kfree(cgc.buffer);
 		return ret;
 		}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/sbpcd.c	Thu Aug  3 23:41:01 2000
+++ linux/drivers/cdrom/sbpcd.c	Thu Aug 10 02:39:56 2000
@@ -1,3 +1,5 @@
+
+
 /*
  *  sbpcd.c   CD-ROM device driver for the whole family of traditional,
  *            non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
@@ -13,7 +15,7 @@
  *             labelled E2550UA or MK4015 or 2800F).
  */
 
-#define VERSION "v4.61 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
 
 /*   Copyright (C) 1993, 1994, 1995  Eberhard Moenkeberg <emoenke@gwdg.de>
  *
@@ -46,7 +48,7 @@
  *
  *  0.1  initial release, April/May 93, after mcd.c (Martin Harriss)
  *
- *  0.2  the "repeat:"-loop in do_sbpcd_request did not check for
+ *  0.2  thek "repeat:"-loop in do_sbpcd_request did not check for
  *       end-of-request_queue (resulting in kernel panic).
  *       Flow control seems stable, but throughput is not better.  
  *
@@ -312,9 +314,20 @@
  *	             module_init & module_exit.
  *	             Torben Mathiasen <tmm@image.dk>
  *
+ *  4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
+ *		Annoying things fixed:
+ *		TOC reread on automated disk changes
+ *		TOC reread on manual cd changes
+ *		Play IOCTL tries to play CD before it's actually ready... sometimes.
+ *		CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
+ *		Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
+ *
  *
  *  TODO
  *     implement "read all subchannel data" (96 bytes per frame)
+ *     remove alot of the virtual status bits and deal with hardware status
+ *     move the change of cd for audio to a better place
+ *     add debug levels to insmod parameters (trivial)
  *
  *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
  *     elaborated speed-up experiments (and the fabulous results!), for
@@ -637,9 +650,9 @@
 static u_int maxtim_data= 3000;
 #endif LONG_TIMING
 #if DISTRIBUTION
-static int n_retries=3;
+static int n_retries=6;
 #else
-static int n_retries=1;
+static int n_retries=6;
 #endif
 /*==========================================================================*/
 
@@ -2046,7 +2059,9 @@
 	do
 	{
 		i=GetStatus();
-		if ((i<0)&&(i!=-ERR_DISKCHANGE)) return (-2); /* from sta2err */
+		if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
+			return (-2); /* from sta2err */
+		}
 		if (!st_caddy_in) break;
 		sbp_sleep(1);
 	}
@@ -2343,16 +2358,21 @@
 
 static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
 {
-  int i;
-  i = MINOR(cdi->dev);
-
-  switch_drive(i);
-  if (position == 1) {
-    cc_SpinDown();
-  } else {
-    return cc_CloseTray();
-  }
-  return 0;
+	int i;
+	int retval=0;
+	i = MINOR(cdi->dev);
+	switch_drive(i);
+	/* DUH! --AJK */
+	if(D_S[d].CD_changed != 0xFF) {
+		D_S[d].CD_changed=0xFF;
+		D_S[d].diskstate_flags &= ~cd_size_bit;
+	}
+	if (position == 1) {
+		cc_SpinDown();
+	} else {
+		retval=cc_CloseTray();
+	}
+  return retval;
 }
 
 /*==========================================================================*/
@@ -4023,6 +4043,7 @@
 	msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
 	msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
 	msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
+
 #if 0
   if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
   if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
@@ -4031,8 +4052,11 @@
   return CDS_NO_DISC;
 #else
   if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
-  return CDS_TRAY_OPEN;
+/*  return CDS_TRAY_OPEN; */
+  return CDS_NO_DISC;
+  
 #endif
+
 }
 
 
@@ -4500,7 +4524,7 @@
 static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
 		       void * arg)
 {
-	int i, st;
+	int i, st, j;
 	
 	msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n",
 	    MINOR(cdi->dev), cmd, arg);
@@ -4696,19 +4720,68 @@
 
 	case CDROMSUBCHNL:   /* Get subchannel info */
 		msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
+		/* Bogus, I can do better than this! --AJK
 		if ((st_spinning)||(!subq_valid)) {
 			i=cc_ReadSubQ();
 			if (i<0) RETURN_UP(-EIO);
 		}
+		*/
+		i=cc_ReadSubQ();
+		if (i<0) {
+			j=cc_ReadError(); /* clear out error status from drive */
+			D_S[d].audio_state=CDROM_AUDIO_NO_STATUS;
+			/* get and set the disk state here, 
+			probably not the right place, but who cares!
+			It makes it work properly! --AJK */
+			if (D_S[d].CD_changed==0xFF) {
+				msg(DBG_000,"Disk changed detect\n");
+				D_S[d].diskstate_flags &= ~cd_size_bit;
+			}
+			RETURN_UP(-EIO);
+		}
+		if (D_S[d].CD_changed==0xFF) {
+			/* reread the TOC because the disk has changed! --AJK */
+			msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
+			i=DiskInfo();
+			if(i==0) {
+				D_S[d].CD_changed=0x00; /* cd has changed, procede, */
+				RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
+			} else {
+				RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
+			}
+		}
 		memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
+		/* 
+			This virtual crap is very bogus! 
+			It doesn't detect when the cd is done playing audio!
+			Lets do this right with proper hardware register reading!
+		*/
+		cc_ReadStatus();
+		i=ResponseStatus();
+		msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
+		msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
+		msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
+		msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
+		msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
+		msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
+		/* st_busy indicates if it's _ACTUALLY_ playing audio */
 		switch (D_S[d].audio_state)
 		{
 		case audio_playing:
-			SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+			if(st_busy==0) {
+				/* CD has stopped playing audio --AJK */
+				D_S[d].audio_state=audio_completed;
+				SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
+			} else {
+				SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+			}
 			break;
 		case audio_pausing:
 			SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
 			break;
+		case audio_completed:
+			SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
+			break;
 		default:
 			SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
 			break;
@@ -5883,6 +5956,14 @@
         {
                 D_S[i].CD_changed=0;
                 msg(DBG_CHK,"medium changed (drive %d)\n", i);
+		/* BUG! Should invalidate buffers! --AJK */
+		invalidate_buffers(full_dev);
+		D_S[d].diskstate_flags &= ~toc_bit;
+		D_S[d].diskstate_flags &= ~cd_size_bit;
+#if SAFE_MIXED
+		D_S[d].has_data=0;
+#endif SAFE_MIXED
+
                 return (1);
         }
         else
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/sbpcd.h linux/drivers/cdrom/sbpcd.h
--- /opt/kernel/linux-2.4.0-test8-pre1/drivers/cdrom/sbpcd.h	Mon Jan  5 09:06:26 1998
+++ linux/drivers/cdrom/sbpcd.h	Thu Aug 10 02:39:56 2000
@@ -412,6 +412,7 @@
 /*
  * audio states:
  */
+#define audio_completed	3 /* Forgot this one! --AJK */
 #define audio_playing	2
 #define audio_pausing	1
 
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- /opt/kernel/linux-2.4.0-test8-pre1/drivers/ide/ide-cd.c	Thu Aug  3 23:41:01 2000
+++ linux/drivers/ide/ide-cd.c	Tue Aug 15 04:21:16 2000
@@ -285,9 +285,13 @@
  * 4.58  May 1, 2000	- Clean up ACER50 stuff.
  *			- Fix small problem with ide_cdrom_capacity
  *
+ * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
+ *			  correctly sensing a disc change.
+ *			- Rearranged some code
+ *
  *************************************************************************/
  
-#define IDECD_VERSION "4.58"
+#define IDECD_VERSION "4.59"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -542,11 +546,11 @@
 
 /* Returns 0 if the request should be continued.
    Returns 1 if the request was ended. */
-static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive, int good_stat,
-				int *stat_ret)
+static int cdrom_decode_status (ide_startstop_t *startstop, ide_drive_t *drive,
+				int good_stat, int *stat_ret)
 {
 	struct request *rq = HWGROUP(drive)->rq;
-	int stat, cmd, err, sense_key;
+	int stat, err, sense_key;
 	struct packet_command *pc;
 	
 	/* Check for errors. */
@@ -560,103 +564,99 @@
 	err = GET_ERR();
 	sense_key = err >> 4;
 
-	if (rq == NULL)
-		printk ("%s: missing request in cdrom_decode_status\n",
-			drive->name);
-	else {
-		cmd = rq->cmd;
-
-		if (cmd == REQUEST_SENSE_COMMAND) {
-			/* We got an error trying to get sense info
-			   from the drive (probably while trying
-			   to recover from a former error).  Just give up. */
-
-			pc = (struct packet_command *) rq->buffer;
-			pc->stat = 1;
-			cdrom_end_request (1, drive);
-			*startstop = ide_error (drive, "request sense failure", stat);
-			return 1;
-
-		} else if (cmd == PACKET_COMMAND) {
-			/* All other functions, except for READ. */
+	if (rq == NULL) {
+		printk("%s: missing rq in cdrom_decode_status\n", drive->name);
+		*startstop = ide_stopped;
+		return 1;
+	}
 
-			struct semaphore *sem = NULL;
-			pc = (struct packet_command *) rq->buffer;
+	if (rq->cmd == REQUEST_SENSE_COMMAND) {
+		/* We got an error trying to get sense info
+		   from the drive (probably while trying
+		   to recover from a former error).  Just give up. */
 
-			/* Check for tray open. */
-			if (sense_key == NOT_READY) {
-				cdrom_saw_media_change (drive);
-			} else if (sense_key == UNIT_ATTENTION) {
-				/* Check for media change. */
-				cdrom_saw_media_change (drive);
-				/*printk("%s: media changed\n",drive->name);*/
-				return 0;
-			} else {
-				/* Otherwise, print an error. */
-				ide_dump_status (drive, "packet command error",
-						 stat);
-			}
-			
-			/* Set the error flag and complete the request.
-			   Then, if we have a CHECK CONDITION status,
-			   queue a request sense command.  We must be careful,
-			   though: we don't want the thread in
-			   cdrom_queue_packet_command to wake up until
-			   the request sense has completed.  We do this
-			   by transferring the semaphore from the packet
-			   command request to the request sense request. */
-
-			if ((stat & ERR_STAT) != 0) {
-				sem = rq->sem;
-				rq->sem = NULL;
-			}
-
-			pc->stat = 1;
-			cdrom_end_request (1, drive);
+		pc = (struct packet_command *) rq->buffer;
+		pc->stat = 1;
+		cdrom_end_request (1, drive);
+		*startstop = ide_error (drive, "request sense failure", stat);
+		return 1;
 
-			if ((stat & ERR_STAT) != 0)
-				cdrom_queue_request_sense(drive, sem, pc->sense,
-							  pc);
+	} else if (rq->cmd == PACKET_COMMAND) {
+		/* All other functions, except for READ. */
+		struct semaphore *sem = NULL;
+		pc = (struct packet_command *) rq->buffer;
+
+		/* Check for tray open. */
+		if (sense_key == NOT_READY) {
+			cdrom_saw_media_change (drive);
+		} else if (sense_key == UNIT_ATTENTION) {
+			/* Check for media change. */
+			cdrom_saw_media_change (drive);
+			/*printk("%s: media changed\n",drive->name);*/
+			return 0;
 		} else {
-			/* Handle errors from READ requests. */
+			/* Otherwise, print an error. */
+			ide_dump_status(drive, "packet command error", stat);
+		}
+		
+		/* Set the error flag and complete the request.
+		   Then, if we have a CHECK CONDITION status,
+		   queue a request sense command.  We must be careful,
+		   though: we don't want the thread in
+		   cdrom_queue_packet_command to wake up until
+		   the request sense has completed.  We do this
+		   by transferring the semaphore from the packet
+		   command request to the request sense request. */
+
+		if ((stat & ERR_STAT) != 0) {
+			sem = rq->sem;
+			rq->sem = NULL;
+		}
 
-			if (sense_key == NOT_READY) {
-				/* Tray open. */
-				cdrom_saw_media_change (drive);
+		pc->stat = 1;
+		cdrom_end_request (1, drive);
 
-				/* Fail the request. */
-				printk ("%s: tray open\n", drive->name);
-				cdrom_end_request (0, drive);
-			} else if (sense_key == UNIT_ATTENTION) {
-				/* Media change. */
-				cdrom_saw_media_change (drive);
+		if ((stat & ERR_STAT) != 0)
+			cdrom_queue_request_sense(drive, sem, pc->sense, pc);
+	} else {
+		/* Handle errors from READ requests. */
 
-				/* Arrange to retry the request.
-				   But be sure to give up if we've retried
-				   too many times. */
-				if (++rq->errors > ERROR_MAX)
-					cdrom_end_request (0, drive);
-			} else if (sense_key == ILLEGAL_REQUEST ||
-				   sense_key == DATA_PROTECT) {
-				/* No point in retrying after an illegal
-				   request or data protect error.*/
-				ide_dump_status (drive, "command error", stat);
-				cdrom_end_request (0, drive);
-			} else if ((err & ~ABRT_ERR) != 0) {
-				/* Go to the default handler
-				   for other errors. */
-				*startstop = ide_error (drive, "cdrom_decode_status", stat);
-				return 1;
-			} else if ((++rq->errors > ERROR_MAX)) {
-				/* We've racked up too many retries.  Abort. */
-				cdrom_end_request (0, drive);
-			}
+		if (sense_key == NOT_READY) {
+			/* Tray open. */
+			cdrom_saw_media_change (drive);
 
-			/* If we got a CHECK_CONDITION status,
-			   queue a request sense command. */
-			if ((stat & ERR_STAT) != 0)
-				cdrom_queue_request_sense(drive, NULL, NULL, NULL);
+			/* Fail the request. */
+			printk ("%s: tray open\n", drive->name);
+			cdrom_end_request (0, drive);
+		} else if (sense_key == UNIT_ATTENTION) {
+			/* Media change. */
+			cdrom_saw_media_change (drive);
+
+			/* Arrange to retry the request.
+			   But be sure to give up if we've retried
+			   too many times. */
+			if (++rq->errors > ERROR_MAX)
+				cdrom_end_request (0, drive);
+		} else if (sense_key == ILLEGAL_REQUEST ||
+			   sense_key == DATA_PROTECT) {
+			/* No point in retrying after an illegal
+			   request or data protect error.*/
+			ide_dump_status (drive, "command error", stat);
+			cdrom_end_request (0, drive);
+		} else if ((err & ~ABRT_ERR) != 0) {
+			/* Go to the default handler
+			   for other errors. */
+			*startstop = ide_error (drive, "cdrom_decode_status", stat);
+			return 1;
+		} else if ((++rq->errors > ERROR_MAX)) {
+			/* We've racked up too many retries.  Abort. */
+			cdrom_end_request (0, drive);
 		}
+
+		/* If we got a CHECK_CONDITION status,
+		   queue a request sense command. */
+		if ((stat & ERR_STAT) != 0)
+			cdrom_queue_request_sense(drive, NULL, NULL, NULL);
 	}
 
 	/* Retry, or handle the next request. */
@@ -686,8 +686,9 @@
    called when the interrupt from the drive arrives.  Otherwise, HANDLER
    will be called immediately after the drive is prepared for the transfer. */
 
-static ide_startstop_t cdrom_start_packet_command (ide_drive_t *drive, int xferlen,
-				       ide_handler_t *handler)
+static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+						  int xferlen,
+						  ide_handler_t *handler)
 {
 	ide_startstop_t startstop;
 	struct cdrom_info *info = drive->driver_data;
@@ -783,7 +784,7 @@
 
 	/* If we couldn't get a buffer, don't try to buffer anything... */
 	if (info->buffer == NULL)
-			sectors_to_buffer = 0;
+		sectors_to_buffer = 0;
 
 	/* If this is the first sector in the buffer, remember its number. */
 	if (info->nsectors_buffered == 0)
@@ -1657,10 +1658,10 @@
 
 	/* Check to see if the existing data is still valid.
 	   If it is, just return. */
-	if (CDROM_STATE_FLAGS (drive)->toc_valid)
-		(void) cdrom_check_status(drive, sense);
+	(void) cdrom_check_status(drive, sense);
 
-	if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
+	if (CDROM_STATE_FLAGS(drive)->toc_valid)
+		return 0;
 
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
@@ -1717,10 +1718,10 @@
 			toc->hdr.first_track = CDROM_LEADOUT;
 			toc->hdr.last_track = CDROM_LEADOUT;
 		}
-	} else if (stat) {
-		return stat;
 	}
-	if (stat) return stat;
+
+	if (stat)
+		return stat;
 
 	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
 
@@ -1843,6 +1844,12 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct atapi_toc *toc = info->toc;
 	int ntracks;
+
+	/*
+	 * don't serve cached data, if the toc isn't valid
+	 */
+	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
+		return -EINVAL;
 
 	/* Check validity of requested track number. */
 	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test8-pre1/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- /opt/kernel/linux-2.4.0-test8-pre1/drivers/scsi/sr.c	Thu Aug  3 23:41:01 2000
+++ linux/drivers/scsi/sr.c	Tue Aug 29 00:06:26 2000
@@ -28,6 +28,9 @@
  *       Modified by Jens Axboe <axboe@suse.de> - support DVD-RAM
  *	 transparently and loose the GHOST hack
  *
+ *	 Modified by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *	 check resource allocation in sr_init and some cleanups
+ *
  */
 
 #include <linux/module.h>
@@ -82,11 +85,11 @@
 	init_command:sr_init_command
 };
 
-Scsi_CD *scsi_CDs = NULL;
-static int *sr_sizes = NULL;
+Scsi_CD *scsi_CDs;
+static int *sr_sizes;
 
-static int *sr_blocksizes = NULL;
-static int *sr_hardsizes = NULL;
+static int *sr_blocksizes;
+static int *sr_hardsizes;
 
 static int sr_open(struct cdrom_device_info *, int);
 void get_sectorsize(int);
@@ -710,30 +713,45 @@
 	}
 	if (scsi_CDs)
 		return 0;
-	sr_template.dev_max =
-	    sr_template.dev_noticed + SR_EXTRA_DEVS;
-	scsi_CDs = (Scsi_CD *) kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
+
+	sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS;
+	scsi_CDs = kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
+	if (!scsi_CDs)
+		goto cleanup_devfs;
 	memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));
 
-	sr_sizes = (int *) kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
+	sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
+	if (!sr_sizes)
+		goto cleanup_cds;
 	memset(sr_sizes, 0, sr_template.dev_max * sizeof(int));
 
-	sr_blocksizes = (int *) kmalloc(sr_template.dev_max *
-					sizeof(int), GFP_ATOMIC);
-
-	sr_hardsizes = (int *) kmalloc(sr_template.dev_max *
-				       sizeof(int), GFP_ATOMIC);
+	sr_blocksizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
+	if (!sr_blocksizes)
+		goto cleanup_sizes;
+
+	sr_hardsizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
+	if (!sr_hardsizes)
+		goto cleanup_blocksizes;
 	/*
 	 * These are good guesses for the time being.
 	 */
-	for (i = 0; i < sr_template.dev_max; i++)
-        {
+	for (i = 0; i < sr_template.dev_max; i++) {
 		sr_blocksizes[i] = 2048;
 		sr_hardsizes[i] = 2048;
         }
 	blksize_size[MAJOR_NR] = sr_blocksizes;
         hardsect_size[MAJOR_NR] = sr_hardsizes;
 	return 0;
+cleanup_blocksizes:
+	kfree(sr_blocksizes);
+cleanup_sizes:
+	kfree(sr_sizes);
+cleanup_cds:
+	kfree(scsi_CDs);
+cleanup_devfs:
+	devfs_unregister_blkdev(MAJOR_NR, "sr");
+	sr_registered--;
+	return 1;
 }
 
 void sr_finish()
@@ -830,29 +848,26 @@
 	return;
 }
 
-
-#ifdef MODULE
-
-int init_module(void)
+int init_sr(void)
 {
 	sr_template.module = &__this_module;
 	return scsi_register_module(MODULE_SCSI_DEV, &sr_template);
 }
 
-void cleanup_module(void)
+void exit_sr(void)
 {
 	scsi_unregister_module(MODULE_SCSI_DEV, &sr_template);
 	devfs_unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
 	if (scsi_CDs != NULL) {
-		kfree((char *) scsi_CDs);
+		kfree(scsi_CDs);
 
-		kfree((char *) sr_sizes);
+		kfree(sr_sizes);
 		sr_sizes = NULL;
 
-		kfree((char *) sr_blocksizes);
+		kfree(sr_blocksizes);
 		sr_blocksizes = NULL;
-		kfree((char *) sr_hardsizes);
+		kfree(sr_hardsizes);
 		sr_hardsizes = NULL;
 	}
 	blksize_size[MAJOR_NR] = NULL;
@@ -863,23 +878,5 @@
 	sr_template.dev_max = 0;
 }
 
-#endif				/* MODULE */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
+module_init(init_sr);
+module_exit(exit_sr);
