diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/MAINTAINERS linux/MAINTAINERS
--- linux-2.3.25-clean/MAINTAINERS	Wed Nov  3 21:01:37 1999
+++ linux/MAINTAINERS	Tue Nov  2 01:05:01 1999
@@ -764,7 +764,7 @@
 SCSI CDROM DRIVER
 P:	Jens Axboe
 M:	axboe@image.dk
-L:	linux-kernel@vger.rutgers.edu
+L:	linux-scsi@vger.rutgers.edu
 W:	http://www.kernel.dk
 S:	Maintained
 
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- linux-2.3.25-clean/drivers/block/ide-cd.c	Wed Nov  3 21:01:37 1999
+++ linux/drivers/block/ide-cd.c	Mon Nov  1 21:46:45 1999
@@ -24,11 +24,6 @@
  *
  * ----------------------------------
  * TO DO LIST:
- * -Implement Microsoft Media Status Notification per the spec at
- *   http://www.microsoft.com/hwdev/respec/storspec.htm
- *   This will allow us to get automagically notified when the media changes
- *   on ATAPI drives (something the stock ATAPI spec is lacking).  Looks
- *   very cool.  I discovered its existance the other day at work...
  * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
  *   boot
  *
@@ -537,6 +532,7 @@
 	}
 	if (rq->cmd == READ && !rq->current_nr_sectors)
 		uptodate = 1;
+
 	ide_end_request (uptodate, HWGROUP(drive));
 }
 
@@ -769,17 +765,9 @@
 
 	char *dest;
 
-	/* 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->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->buffer == NULL)
+	/* If we couldn't get a buffer, don't try to buffer anything... */
+	if (info->buffer == NULL)
 			sectors_to_buffer = 0;
-	}
 
 	/* If this is the first sector in the buffer, remember its number. */
 	if (info->nsectors_buffered == 0)
@@ -866,13 +854,14 @@
 		return;
  
 	if (dma) {
-		if (!dma_error) {
-			for (i = rq->nr_sectors; i > 0;) {
-				i -= rq->current_nr_sectors;
-				ide_end_request(1, HWGROUP(drive));
-			}
-		} else
+		if (dma_error) {
 			ide_error (drive, "dma error", stat);
+			return;
+		}
+		for (i = rq->nr_sectors; i > 0;) {
+			i -= rq->current_nr_sectors;
+			ide_end_request(1, HWGROUP(drive));
+		}
 		return;
 	}
 
@@ -1789,7 +1778,7 @@
 
 	/* Now try to get the total cdrom capacity. */
 #if 0
-	stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major, minor,
+	stat = cdrom_get_last_written(MKDEV(HWIF(drive)->major, minor),
 				     (long *)&toc->capacity);
 	if (stat)
 #endif
@@ -1797,6 +1786,7 @@
 	if (stat) toc->capacity = 0x1fffff;
 
 	/* for general /dev/cdrom like mounting, one big disc */
+	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
 	HWIF(drive)->gd->sizes[minor] = (toc->capacity * SECTORS_PER_FRAME) >>
 					(BLOCK_SIZE_BITS - 9);
 
@@ -1812,11 +1802,11 @@
 	i = toc->hdr.first_track;
 	while ((i <= ntracks) && ((minor & CD_PART_MASK) < CD_PART_MAX)) {
 		drive->part[minor & PARTN_MASK].start_sect = 0;
- 		drive->part[minor & PARTN_MASK].nr_sects = (toc->ent[i].addr.lba *
+ 		drive->part[minor & PARTN_MASK].nr_sects =
+			(toc->ent[i].addr.lba *
 			SECTORS_PER_FRAME) << (BLOCK_SIZE_BITS - 9);
 		HWIF(drive)->gd->sizes[minor] = (toc->ent[i].addr.lba *
 			SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
-		blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE;
 		i++;
 		minor++;
 	}
@@ -2273,8 +2263,11 @@
 		struct atapi_capabilities_page cap;
 	} buf;
 
-	if (CDROM_CONFIG_FLAGS (drive)->nec260)
+	if (CDROM_CONFIG_FLAGS (drive)->nec260) {
+		CDROM_CONFIG_FLAGS (drive)->no_eject = 0;                       
+		CDROM_CONFIG_FLAGS (drive)->audio_play = 1;       
 		return nslots;
+	}
 
 	init_cdrom_command(&cgc, &buf, sizeof(buf));
 	/* we have to cheat a little here. the packet will eventually
@@ -2342,9 +2335,12 @@
 			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
 	}
 
-	printk ("%s: ATAPI %dX %s", 
-        	drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
-		(CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
+	/* don't print speed if the drive reported 0.
+	 */
+	printk("%s: ATAPI", drive->name);
+	if (CDROM_CONFIG_FLAGS(drive)->max_speed)
+		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
+	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
 
 	if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_ram)
         	printk (" DVD%s%s", 
@@ -2398,7 +2394,7 @@
 	int nslots;
 
 	set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
-	blksize_size[HWIF(drive)->major][minor] = CD_FRAMESIZE;
+	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
 
 	drive->special.all	= 0;
 	drive->ready_stat	= 0;
@@ -2534,9 +2530,12 @@
 static
 int ide_cdrom_open (struct inode *ip, struct file *fp, ide_drive_t *drive)
 {
+	struct cdrom_info *info = drive->driver_data;
 	int rc;
 
 	MOD_INC_USE_COUNT;
+	if (info->buffer == NULL)
+		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
 	rc = cdrom_fops.open (ip, fp);
 	if (rc) {
 		drive->usage--;
@@ -2617,12 +2616,7 @@
 MODULE_PARM(ignore, "s");
 MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
 
-int init_module (void)
-{
-	return ide_cdrom_init();
-}
-
-void cleanup_module(void)
+void __exit ide_cdrom_exit(void)
 {
 	ide_drive_t *drive;
 	int failed = 0;
@@ -2636,7 +2630,7 @@
 }
 #endif /* MODULE */
  
-int ide_cdrom_init (void)
+int __init ide_cdrom_init (void)
 {
 	ide_drive_t *drive;
 	struct cdrom_info *info;
@@ -2677,3 +2671,6 @@
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
+
+module_init(ide_cdrom_init);
+module_exit(ide_cdrom_exit);
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- linux-2.3.25-clean/drivers/cdrom/cdrom.c	Wed Nov  3 21:01:37 1999
+++ linux/drivers/cdrom/cdrom.c	Wed Nov  3 01:37:42 1999
@@ -178,14 +178,19 @@
   -- Export cdrom_mode_sense and cdrom_mode_select.
   -- init_cdrom_command() for setting up a cgc command.
   
-  3.05 Sep 23, 1999 - Jens Axboe <axboe@image.dk>
+  3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk>
   -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually
   impossible to send the drive data in a sensible way.
+  -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and
+  dvd_read_manufact.
+  -- Added setup of write mode for packet writing.
+  -- Fixed CDDA ripping with cdda2wav - accept much larger requests of
+  number of frames and split the reads in blocks of 8.
   
 -------------------------------------------------------------------------*/
 
 #define REVISION "Revision: 3.05"
-#define VERSION "Id: cdrom.c 3.05 1999/09/23"
+#define VERSION "Id: cdrom.c 3.05 1999/10/24"
 
 /* I use an error-log mask to give fine grain control over the type of
    messages dumped to the system logs.  The available masks include: */
@@ -205,7 +210,6 @@
 /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
 /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
 
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -311,7 +315,7 @@
 int register_cdrom(struct cdrom_device_info *cdi)
 {
 	static char banner_printed = 0;
-	int major = MAJOR (cdi->dev);
+	int major = MAJOR(cdi->dev);
         struct cdrom_device_ops *cdo = cdi->ops;
         int *change_capability = (int *)&cdo->capability; /* hack */
 
@@ -362,7 +366,7 @@
 int unregister_cdrom(struct cdrom_device_info *unreg)
 {
 	struct cdrom_device_info *cdi, *prev;
-	int major = MAJOR (unreg->dev);
+	int major = MAJOR(unreg->dev);
 
 	cdinfo(CD_OPEN, "entering unregister_cdrom\n"); 
 
@@ -388,7 +392,7 @@
 }
 
 static
-struct cdrom_device_info *cdrom_find_device (kdev_t dev)
+struct cdrom_device_info *cdrom_find_device(kdev_t dev)
 {
 	struct cdrom_device_info *cdi;
 
@@ -736,7 +740,7 @@
 	return cdi->ops->generic_packet(cdi, &cgc);
 }
 
-int cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
+int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
 {
 	struct cdrom_changer_info info;
 	int curslot;
@@ -908,7 +912,8 @@
 void init_cdrom_command(struct cdrom_generic_command *cgc,
 			void *buffer, int len)
 {
-	memset(cgc, 0, sizeof(*cgc));
+	memset(cgc, 0, sizeof(struct cdrom_generic_command));
+	memset(buffer, 0, len);
 	cgc->buffer = (char *) buffer;
 	cgc->buflen = len;
 }
@@ -918,19 +923,49 @@
 #define copy_key(dest,src)	memcpy((dest), (src), sizeof(dvd_key))
 #define copy_chal(dest,src)	memcpy((dest), (src), sizeof(dvd_challenge))
 
-static void setup_report_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
+static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
 {
 	cgc->cmd[0] = GPCMD_REPORT_KEY;
 	cgc->cmd[10] = type | (agid << 6);
+	switch (type) {
+		case 0: case 8: case 5: {
+			cgc->buflen = 8;
+			break;
+		}
+		case 1: {
+			cgc->buflen = 16;
+			break;
+		}
+		case 2: case 4: {
+			cgc->buflen = 12;
+			break;
+		}
+	}
+	cgc->cmd[9] = cgc->buflen;
 }
 
-static void setup_send_key (struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
+static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
 {
 	cgc->cmd[0] = GPCMD_SEND_KEY;
 	cgc->cmd[10] = type | (agid << 6);
+	switch (type) {
+		case 1: {
+			cgc->buflen = 16;
+			break;
+		}
+		case 3: {
+			cgc->buflen = 12;
+			break;
+		}
+		case 6: {
+			cgc->buflen = 8;
+			break;
+		}
+	}
+	cgc->cmd[9] = cgc->buflen;
 }
 
-static int dvd_do_auth (struct cdrom_device_info *cdi, dvd_authinfo *ai)
+static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
 {
 	int ret;
 	u_char buf[20];
@@ -943,8 +978,7 @@
 	/* LU data send */
 	case DVD_LU_SEND_AGID:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n"); 
-		setup_report_key (&cgc, 0, 0);
-		cgc.buflen = cgc.cmd[9] = 8;
+		setup_report_key(&cgc, ai->lsa.agid, 0);
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -955,8 +989,7 @@
 
 	case DVD_LU_SEND_KEY1:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n"); 
-		setup_report_key (&cgc, ai->lsk.agid, 2);
-		cgc.buflen = cgc.cmd[9] = 12;
+		setup_report_key(&cgc, ai->lsk.agid, 2);
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -967,8 +1000,7 @@
 
 	case DVD_LU_SEND_CHALLENGE:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n"); 
-		setup_report_key (&cgc, ai->lsc.agid, 1);
-		cgc.buflen = cgc.cmd[9] = 16;
+		setup_report_key(&cgc, ai->lsc.agid, 1);
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -980,12 +1012,11 @@
 	/* Post-auth key */
 	case DVD_LU_SEND_TITLE_KEY:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n"); 
-		setup_report_key (&cgc, ai->lstk.agid, 4);
+		setup_report_key(&cgc, ai->lstk.agid, 4);
 		cgc.cmd[5] = ai->lstk.lba;
 		cgc.cmd[4] = ai->lstk.lba >> 8;
 		cgc.cmd[3] = ai->lstk.lba >> 16;
 		cgc.cmd[2] = ai->lstk.lba >> 24;
-		cgc.buflen = cgc.cmd[9] = 12;
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -993,14 +1024,13 @@
 		ai->lstk.cpm = (buf[4] >> 7) & 1;
 		ai->lstk.cp_sec = (buf[4] >> 6) & 1;
 		ai->lstk.cgms = (buf[4] >> 4) & 3;
-		copy_key (ai->lstk.title_key, &buf[5]);
+		copy_key(ai->lstk.title_key, &buf[5]);
 		/* Returning data, let host change state */
 		break;
 
 	case DVD_LU_SEND_ASF:
 		cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n"); 
-		setup_report_key (&cgc, ai->lsasf.asf, 5);
-		cgc.buflen = cgc.cmd[9] = 8;
+		setup_report_key(&cgc, ai->lsasf.asf, 5);
 		
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -1011,10 +1041,9 @@
 	/* LU data receive (LU changes state) */
 	case DVD_HOST_SEND_CHALLENGE:
 		cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n"); 
-		setup_send_key (&cgc, ai->hsc.agid, 1);
-		cgc.buflen = cgc.cmd[9] = 16;
-		buf[1] = 14;
-		copy_chal (&buf[4], ai->hsc.chal);
+		setup_send_key(&cgc, ai->hsc.agid, 1);
+		buf[1] = 0xe;
+		copy_chal(&buf[4], ai->hsc.chal);
 
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
@@ -1024,13 +1053,11 @@
 
 	case DVD_HOST_SEND_KEY2:
 		cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n"); 
-		setup_send_key (&cgc, ai->hsk.agid, 3);
-		cgc.buflen = cgc.cmd[9] = 12;
-		buf[1] = 10;
-		copy_key (&buf[4], ai->hsk.key);
+		setup_send_key(&cgc, ai->hsk.agid, 3);
+		buf[1] = 0xa;
+		copy_key(&buf[4], ai->hsk.key);
 
-		ret = cdo->generic_packet(cdi, &cgc);
-		if (ret) {
+		if ((ret = cdo->generic_packet(cdi, &cgc))) {
 			ai->type = DVD_AUTH_FAILURE;
 			return ret;
 		}
@@ -1040,7 +1067,7 @@
 	/* Misc */
 	case DVD_INVALIDATE_AGID:
 		cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n"); 
-		setup_report_key (&cgc, ai->lsa.agid, 0x3f);
+		setup_report_key(&cgc, ai->lsa.agid, 0x3f);
 		if ((ret = cdo->generic_packet(cdi, &cgc)))
 			return ret;
 		break;
@@ -1053,7 +1080,7 @@
 	return 0;
 }
 
-static int dvd_read_physical (struct cdrom_device_info *cdi, dvd_struct *s)
+static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
 {
 	int ret, i;
 	u_char buf[4 + 4 * 20], *base;
@@ -1061,7 +1088,6 @@
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
 
-	memset(buf, 0, sizeof(buf));
 	init_cdrom_command(&cgc, buf, sizeof(buf));
 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[6] = s->physical.layer_num;
@@ -1077,7 +1103,7 @@
 	/* place the data... really ugly, but at least we won't have to
 	   worry about endianess in userspace or here. */
 	for (i = 0; i < 4; ++i, base += 20, ++layer) {
-		memset (layer, 0, sizeof (*layer));
+		memset(layer, 0, sizeof(*layer));
 		layer->book_version = base[0] & 0xf;
 		layer->book_type = base[0] >> 4;
 		layer->min_rate = base[1] & 0xf;
@@ -1103,7 +1129,6 @@
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
 
-	memset(buf, 0, sizeof(buf));
 	init_cdrom_command(&cgc, buf, sizeof(buf));
 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[6] = s->copyright.layer_num;
@@ -1120,27 +1145,30 @@
 	return 0;
 }
 
-static int dvd_read_disckey (struct cdrom_device_info *cdi, dvd_struct *s)
+static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int ret;
-	u_char buf[4 + 2048];
+	int ret, size;
+	u_char *buf;
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
 
-	memset(buf, 0, sizeof (buf));
-	init_cdrom_command(&cgc, buf, sizeof(buf));
+	size = sizeof(s->disckey.value) + 4;
+
+	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	init_cdrom_command(&cgc, buf, size);
 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
-	cgc.cmd[8] = sizeof(buf) >> 8;
-	cgc.cmd[9] = cgc.buflen & 0xff;
+	cgc.cmd[8] = size >> 8;
+	cgc.cmd[9] = size & 0xff;
 	cgc.cmd[10] = s->disckey.agid << 6;
 
-	if ((ret = cdo->generic_packet(cdi, &cgc)))
-		return ret;
-
-	memcpy(s->disckey.value, &buf[4], 2048);
+	if (!(ret = cdo->generic_packet(cdi, &cgc)))
+		memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
 
-	return 0;
+	kfree(buf);
+	return ret;
 }
 
 static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -1150,7 +1178,6 @@
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
 
-	memset(buf, 0, sizeof (buf));
 	init_cdrom_command(&cgc, buf, sizeof(buf));
 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
@@ -1171,30 +1198,38 @@
 
 static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
 {
-	int ret;
-	u_char buf[4 + 2048];
+	int ret = 0, size;
+	u_char *buf;
 	struct cdrom_generic_command cgc;
 	struct cdrom_device_ops *cdo = cdi->ops;
 
-	memset(buf, 0, sizeof(buf));
-	init_cdrom_command(&cgc, buf, sizeof(buf));
+	size = sizeof(s->manufact.value) + 4;
+
+	if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	init_cdrom_command(&cgc, buf, size);
 	cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
 	cgc.cmd[7] = s->type;
-	cgc.buflen = sizeof(buf);
-	cgc.cmd[8] = sizeof(buf) >> 8;
-	cgc.cmd[9] = cgc.buflen & 0xff;
+	cgc.cmd[8] = size >> 8;
+	cgc.cmd[9] = size & 0xff;
 
-	if ((ret = cdo->generic_packet(cdi, &cgc)))
+	if ((ret = cdo->generic_packet(cdi, &cgc))) {
+		kfree(buf);
 		return ret;
+	}
 
 	s->manufact.len = buf[0] << 8 | buf[1];
 	if (s->manufact.len < 0 || s->manufact.len > 2048) {
-		cdinfo(CD_WARNING, "Recieved invalid manufacture info length (%d)\n", s->bca.len);
-		return -EIO;
+		cdinfo(CD_WARNING, "Received invalid manufacture info length"
+				   " (%d)\n", s->bca.len);
+		ret = -EIO;
+	} else {
+		memcpy(s->manufact.value, &buf[4], s->manufact.len);
 	}
-	memcpy(s->manufact.value, &buf[4], s->manufact.len);
 
-	return 0;
+	kfree(buf);
+	return ret;
 }
 
 static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s)
@@ -1709,7 +1744,7 @@
 }
 
 static inline
-int msf_to_lba (char m, char s, char f)
+int msf_to_lba(char m, char s, char f)
 {
 	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
 }
@@ -1763,7 +1798,7 @@
 		}
 	case CDROMREADAUDIO: {
 		struct cdrom_read_audio ra;
-		int lba;
+		int lba, frames;
 
 		IOCTL_IN(arg, struct cdrom_read_audio, ra);
 
@@ -1780,12 +1815,10 @@
 		if (lba < 0)
 			return -EINVAL;
 
-		/* do between 1 and 8 frames at the time */
-		if (ra.nframes > 8 || ra.nframes < 1)
-			return -EINVAL;
+		/* do max 8 frames at the time */
+		frames = ra.nframes > 8 ? 8 : ra.nframes;
 
-		/* just a nice round figure */
-		if ((cgc.buffer = (char *) kmalloc(CD_FRAMESIZE_RAW*ra.nframes,
+		if ((cgc.buffer = (char *) kmalloc(CD_FRAMESIZE_RAW * frames,
 						   GFP_KERNEL)) == NULL)
 			return -ENOMEM;
 
@@ -1795,14 +1828,14 @@
 		}
 
 		while (ra.nframes > 0) {
-			ret = cdrom_read_block(cdi, &cgc, lba, ra.nframes, 1,
+			ret = cdrom_read_block(cdi, &cgc, lba, frames, 1,
 					       CD_FRAMESIZE_RAW);
 			if (ret) break;
 			__copy_to_user(ra.buf, cgc.buffer,
-				       CD_FRAMESIZE_RAW*ra.nframes);
-			ra.buf += (CD_FRAMESIZE_RAW * ra.nframes);
-			ra.nframes -= ra.nframes;
-			lba += ra.nframes;
+				       CD_FRAMESIZE_RAW * frames);
+			ra.buf += (CD_FRAMESIZE_RAW * frames);
+			ra.nframes -= frames;
+			lba += frames;
 		}
 		kfree(cgc.buffer);
 		return ret;
@@ -1950,17 +1983,27 @@
 		cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
 		return cdo->generic_packet(cdi, &cgc);
 		}
-	
+
 	case DVD_READ_STRUCT: {
-		dvd_struct s;
+		dvd_struct *s;
+		int size = sizeof(dvd_struct);
 		if (!CDROM_CAN(CDC_DVD))
 			return -ENOSYS;
+		if ((s = (dvd_struct *) kmalloc(size, GFP_KERNEL)) == NULL)
+			return -ENOMEM;
 		cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); 
-		IOCTL_IN(arg, dvd_struct, s);
-		if ((ret = dvd_read_struct(cdi, &s)))
+		if (copy_from_user(s, (dvd_struct *)arg, size)) {
+			kfree(s);
+			return -EFAULT;
+		}
+		if ((ret = dvd_read_struct(cdi, s))) {
+			kfree(s);
 			return ret;
-		IOCTL_OUT(arg, dvd_struct, s);
-		return 0;
+		}
+		if (copy_to_user((dvd_struct *)arg, s, size))
+			ret = -EFAULT;
+		kfree(s);
+		return ret;
 		}
 
 	case DVD_AUTH: {
@@ -2069,7 +2112,6 @@
 
 	/* set up command and get the disc info */
 	init_cdrom_command(&cgc, di, sizeof(*di));
-	memset(di, 0, sizeof(disc_information));
 	cgc.cmd[0] = GPCMD_READ_DISC_INFO;
 	cgc.cmd[8] = cgc.buflen;
 
@@ -2207,7 +2249,6 @@
 
 	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)))
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- linux-2.3.25-clean/drivers/scsi/sr.c	Wed Nov  3 21:01:37 1999
+++ linux/drivers/scsi/sr.c	Sun Oct 31 12:43:59 1999
@@ -862,8 +862,10 @@
 	int the_result, retries;
 	Scsi_Cmnd *SCpnt;
 
+	spin_lock_irq(&io_request_lock);
 	buffer = (unsigned char *) scsi_malloc(512);
 	SCpnt = scsi_allocate_device(NULL, scsi_CDs[i].device, 1);
+	spin_unlock_irq(&io_request_lock);
 
 	retries = 3;
 	do {
@@ -957,7 +959,9 @@
 		""
 	};
 
+	spin_lock_irq(&io_request_lock);
 	buffer = (unsigned char *) scsi_malloc(512);
+	spin_unlock_irq(&io_request_lock);
 	cmd[0] = MODE_SENSE;
 	cmd[1] = (scsi_CDs[i].device->lun << 5) & 0xe0;
 	cmd[2] = 0x2a;
@@ -1030,6 +1034,8 @@
 {
 	Scsi_Cmnd *SCpnt;
 	Scsi_Device *device = scsi_CDs[MINOR(cdi->dev)].device;
+	unsigned char *buffer = cgc->buffer;
+	int buflen;
 	int stat;
 
 	/* get the device */
@@ -1037,6 +1043,20 @@
 	if (SCpnt == NULL)
 		return -ENODEV;	/* this just doesn't seem right /axboe */
 
+	/* use buffer for ISA DMA */
+	buflen = (cgc->buflen + 511) & ~511;
+	if (cgc->buffer && SCpnt->host->unchecked_isa_dma &&
+    	   (virt_to_phys(cgc->buffer) + cgc->buflen - 1 > ISA_DMA_THRESHOLD)) {
+		spin_lock_irq(&io_request_lock);
+		buffer = scsi_malloc(buflen);
+		spin_unlock_irq(&io_request_lock);
+		if (buffer == NULL) {
+			printk("sr: SCSI DMA pool exhausted.");
+			return -ENOMEM;
+		}
+		memcpy(buffer, cgc->buffer, cgc->buflen);
+	}
+
 	/* set the LUN */
 	cgc->cmd[1] |= device->lun << 5;
 
@@ -1044,8 +1064,8 @@
 	SCpnt->request.rq_dev = cdi->dev;
 	/* scsi_do_cmd sets the command length */
 	SCpnt->cmd_len = 0;
-	
-	scsi_wait_cmd (SCpnt, (void *)cgc->cmd, (void *)cgc->buffer, cgc->buflen,
+
+	scsi_wait_cmd (SCpnt, (void *)cgc->cmd, (void *)buffer, cgc->buflen,
 		sr_init_done, SR_TIMEOUT, MAX_RETRIES);
 
 	stat = SCpnt->result;
@@ -1054,6 +1074,12 @@
 	SCpnt->request.rq_dev = MKDEV(0, 0);
 	scsi_release_command(SCpnt);
 	SCpnt = NULL;
+
+	/* write DMA buffer back if used */
+	if (buffer && (buffer != cgc->buffer)) {
+		memcpy(cgc->buffer, buffer, cgc->buflen);
+		scsi_free(buffer, buflen);
+	}
 
 	return stat;
 }
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- linux-2.3.25-clean/drivers/scsi/sr_ioctl.c	Wed Nov  3 21:01:37 1999
+++ linux/drivers/scsi/sr_ioctl.c	Sun Oct 31 12:43:59 1999
@@ -36,6 +36,12 @@
     
     req = &SCpnt->request;
     req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
+
+    if (SCpnt->buffer && req->buffer && SCpnt->buffer != req->buffer) {
+	memcpy(req->buffer, SCpnt->buffer, SCpnt->bufflen);
+	scsi_free(SCpnt->buffer, (SCpnt->bufflen + 511) & ~511);
+	SCpnt->buffer = req->buffer;
+    } 
     
     if (req->sem != NULL) {
 	up(req->sem);
@@ -52,27 +58,33 @@
     Scsi_Device * SDev;
     int result, err = 0, retries = 0;
     unsigned long flags;
+    char * bounce_buffer;
 
     spin_lock_irqsave(&io_request_lock, flags);
     SDev  = scsi_CDs[target].device;
     SCpnt = scsi_allocate_device(NULL, scsi_CDs[target].device, 1);
     spin_unlock_irqrestore(&io_request_lock, flags);
 
+    /* use ISA DMA buffer if necessary */
+    SCpnt->request.buffer=buffer;
+    if (buffer && SCpnt->host->unchecked_isa_dma &&
+       (virt_to_phys(buffer) + buflength - 1 > ISA_DMA_THRESHOLD)) {
+	bounce_buffer = (char *)scsi_malloc((buflength + 511) & ~511);
+	if (bounce_buffer == NULL) {
+		printk("SCSI DMA pool exhausted.");
+		return -ENOMEM;
+	}
+	memcpy(bounce_buffer, (char *)buffer, buflength);
+	buffer = bounce_buffer;
+    }
+
 retry:
     if( !scsi_block_when_processing_errors(SDev) )
         return -ENODEV;
-    {
-	DECLARE_MUTEX_LOCKED(sem);
-	SCpnt->request.sem = &sem;
-	spin_lock_irqsave(&io_request_lock, flags);
-	scsi_do_cmd(SCpnt,
-		    (void *) sr_cmd, buffer, buflength, sr_ioctl_done, 
-		    IOCTL_TIMEOUT, IOCTL_RETRIES);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-	down(&sem);
-        SCpnt->request.sem = NULL;
-    }
-    
+
+    scsi_wait_cmd(SCpnt, (void *)sr_cmd, (void *)buffer, buflength,
+		  sr_ioctl_done, IOCTL_TIMEOUT, IOCTL_RETRIES);
+
     result = SCpnt->result;
     
     /* Minimal error checking.  Ignore cases we know about, and report the rest. */
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/drivers/scsi/sr_vendor.c linux/drivers/scsi/sr_vendor.c
--- linux-2.3.25-clean/drivers/scsi/sr_vendor.c	Wed Nov  3 21:01:37 1999
+++ linux/drivers/scsi/sr_vendor.c	Sun Oct 31 12:43:59 1999
@@ -158,7 +158,9 @@
 	if (scsi_CDs[minor].cdi.mask & CDC_MULTI_SESSION)
 		return 0;
 	
+	spin_lock_irq(&io_request_lock);
 	buffer = (unsigned char *) scsi_malloc(512);
+	spin_unlock_irq(&io_request_lock);
 	if(!buffer) return -ENOMEM;
 	
 	sector   = 0;         /* the multisession sector offset goes here  */
diff -ur --exclude-from /home/axboe/cdrom/exclude-from linux-2.3.25-clean/include/linux/cdrom.h linux/include/linux/cdrom.h
--- linux-2.3.25-clean/include/linux/cdrom.h	Wed Nov  3 21:01:37 1999
+++ linux/include/linux/cdrom.h	Sun Oct 31 12:43:59 1999
@@ -482,17 +482,17 @@
 
 
 /* Mode page codes for mode sense/set */
-#define GPMODE_R_W_ERROR_PAGE	    0x1
-#define GPMODE_WRITE_PARMS_PAGE	    0x5
-#define GPMODE_AUDIO_CTL_PAGE	    0xe
-#define GPMODE_POWER_PAGE	    0x1a
-#define GPMODE_FAULT_FAIL_PAGE	    0x1c
-#define GPMODE_TO_PROTECT_PAGE	    0x1d
-#define GPMODE_CAPABILITIES_PAGE    0x2a
-#define GPMODE_ALL_PAGES	    0x3f
+#define GPMODE_R_W_ERROR_PAGE		0x01
+#define GPMODE_WRITE_PARMS_PAGE		0x05
+#define GPMODE_AUDIO_CTL_PAGE		0x0e
+#define GPMODE_POWER_PAGE		0x1a
+#define GPMODE_FAULT_FAIL_PAGE		0x1c
+#define GPMODE_TO_PROTECT_PAGE		0x1d
+#define GPMODE_CAPABILITIES_PAGE	0x2a
+#define GPMODE_ALL_PAGES		0x3f
 /* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
  * of MODE_SENSE_POWER_PAGE */
-#define GPMODE_CDROM_PAGE              0x0d
+#define GPMODE_CDROM_PAGE		0x0d
 
 
 
@@ -505,18 +505,18 @@
 
 struct dvd_layer {
 	__u8 book_version	: 4;
-	__u8 book_type	: 4;
+	__u8 book_type		: 4;
 	__u8 min_rate		: 4;
-	__u8 disc_size	: 4;
-	__u8 layer_type	: 4;
-	__u8 track_path	: 1;
+	__u8 disc_size		: 4;
+	__u8 layer_type		: 4;
+	__u8 track_path		: 1;
 	__u8 nlayers		: 2;
 	__u8 track_density	: 4;
 	__u8 linear_density	: 4;
 	__u8 bca		: 1;
-	__u8 start_sector;
-	__u8 end_sector;
-	__u8 end_sector_l0;
+	__u32 start_sector;
+	__u32 end_sector;
+	__u32 end_sector_l0;
 };
 
 struct dvd_physical {
@@ -536,7 +536,7 @@
 struct dvd_disckey {
 	__u8 type;
 
-	unsigned agid			: 2;
+	unsigned agid		: 2;
 	__u8 value[2048];
 };
 
