-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Sun, 3 Sep 2000, Mohammad A. Haque wrote:

> Ok, looking better. I havent been able to forcibly corrupt my mailboxes
> like I did before. Yet anyways. I left my machine for about 10 mins and
> came back and noticed this...
> 
> Sep  3 16:46:29 viper kernel: attempt to access beyond end of device 
> Sep  3 16:46:29 viper kernel: 21:01: rw=0, want=1070936764,
> limit=30015184 
> Sep  3 16:46:29 viper kernel: attempt to access beyond end of device 
> Sep  3 16:46:29 viper kernel: 21:01: rw=0, want=1422438616,
> limit=30015184 
> ........



Talk to Jens Axboe regarding this. He gave me a patch when I experienced
the same problems with a DVD the other day.

Attached is the patch if you would like to try. It is against test8-pre1



/Richard
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.2 (GNU/Linux)
Comment: Made with pgp4pine 1.75

iD8DBQE5sr5MUSLExYo23RsRAqqLAJ9UF+dav+R3jkIL5ykzTXDRidPtPgCgvFt/
ggV9L3Vh5yeddF36QfUrMzU=
=1MFr
-----END PGP SIGNATURE-----

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:     [EMAIL PROTECTED]
+M:     [EMAIL PROTECTED]
 L:     [EMAIL PROTECTED]
 W:     http://www.kernel.dk
 S:     Maintained
@@ -986,7 +986,7 @@
 
 SCSI CDROM DRIVER
 P:     Jens Axboe
-M:     [EMAIL PROTECTED]
+M:     [EMAIL PROTECTED]
 L:     [EMAIL PROTECTED]
 W:     http://www.kernel.dk
 S:     Maintained
@@ -1174,7 +1174,7 @@
 
 UNIFORM CDROM DRIVER
 P:     Jens Axboe
-M:     [EMAIL PROTECTED]
+M:     [EMAIL PROTECTED]
 L:     [EMAIL PROTECTED]
 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 <[EMAIL PROTECTED]>"
+#define VERSION "v4.63 Andrew J. Kroll <[EMAIL PROTECTED]> Wed Jul 26 
+04:24:10 EDT 2000"
 
 /*   Copyright (C) 1993, 1994, 1995  Eberhard Moenkeberg <[EMAIL PROTECTED]>
  *
@@ -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 <[EMAIL PROTECTED]>
  *
+ *  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 <[EMAIL PROTECTED]> 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 ([EMAIL PROTECTED]) 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 <[EMAIL PROTECTED]> - support DVD-RAM
  *      transparently and loose the GHOST hack
  *
+ *      Modified by Arnaldo Carvalho de Melo <[EMAIL PROTECTED]>
+ *      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);

Reply via email to