--- cdparanoia-III-alpha4/interface/low_interface.h	Fri Mar 20 10:50:13 1998
+++ cdparanoia/interface/low_interface.h	Mon Apr  6 00:09:21 1998
@@ -44,6 +44,13 @@
 #include <linux/../../drivers/scsi/scsi.h>
 #endif
 
+#ifndef SG_EMULATED_HOST
+/* old kernel revision */
+#define SG_EMULATED_HOST 0x2203
+#define SG_SET_TRANSFORM 0x2204
+#define SG_GET_TRANSFORM 0x2205
+#endif
+
 #include <linux/cdrom.h>
 #include <linux/major.h>
 
--- cdparanoia-III-alpha4/interface/scsi_interface.c	Fri Mar 27 19:09:45 1998
+++ cdparanoia/interface/scsi_interface.c	Mon Apr  6 00:55:56 1998
@@ -157,14 +157,37 @@
 }
 
 static int check_atapi(cdrom_drive *d){
+  /* list of known ATAPI/SCSI drives for which our drive type guess fails */
+  struct {
+    char *model;
+    int atapi;
+  } *p, known_drives[] = {
+    { "SAMSUNG SCR-830 REV 2.09 2.09 ", 1 },
+    { NULL, 0 }
+  };
+  int atapi = -1;
+  int fd = d->cdda_fd;
+  char msg[200];
+
   cdmessage(d,"\nChecking for SCSI emulation and transport revision...\n");
 
   /* This isn't as strightforward as it should be */
 
   /* first, we try the SG_EMULATED_HOST ioctl; this only exists in new
      kernels though */
-  /* DOES NOT EXIST YET... next ide-scsi revision, wait till then */
 
+  if (ioctl(fd,SG_EMULATED_HOST,&atapi))
+    cdmessage(d,"\tGuessing whether the drive is ATAPI or SCSI\n");
+  else {
+    if (atapi==1){
+      cdmessage(d,"\tDrive is ATAPI, using SCSI host adaptor emulation\n");
+      /* Disable kernel SCSI command translation layer for access through sg */
+      if (ioctl(fd,SG_SET_TRANSFORM,0))
+        cderror(d,"\tCouldn't disable kernel command translation layer\n");
+    } else
+      cdmessage(d,"\tDrive is SCSI\n");
+    cdmessage(d,"\tVerifying whether our guess is correct (for older kernels):\n");
+  }
 
   /* If the ioctl fails, we use an Inquiry request to guess.  Even if
      we know for certain, Inquiry will give us other interesting data,
@@ -250,6 +273,23 @@
       break;
     }
   }
+
+  /* check our list of "known" drives */
+  for (p = known_drives; p->model; p++)
+    if (!strcmp(d->drive_model, p->model) && d->is_atapi != p->atapi){
+      sprintf(msg,"\tKnown drive -- overriding drive type to %s\n",
+              p->atapi ? "ATAPI":"SCSI");
+      cdmessage(d,msg);
+      d->is_atapi = p->atapi;
+    }
+
+  /* on newer kernels which support SG_EMULATED_HOST, verify our guess */
+  if (atapi != -1 && d->is_atapi != atapi){
+    cderror(d,"\tOur ATAPI/SCSI guessing algorithm will detect the drive\n");
+    cderror(d,"\ttype incorrectly on older kernels; please e-mail the\n");
+    cderror(d,"\tdrive model to xiphmont@mit.edu\n");
+    d->is_atapi = atapi;
+  }
   return(d->is_atapi);
 }  
 
@@ -557,6 +597,19 @@
   return(0);
 }
 
+static int i_read_mmc2 (cdrom_drive *d, void *p, long begin, long sectors){
+  memcpy(d->sg_buffer,(char []){0xbe, 4, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12);
+
+  d->sg_buffer[3] = (begin >> 16) & 0xFF;
+  d->sg_buffer[4] = (begin >> 8) & 0xFF;
+  d->sg_buffer[5] = begin & 0xFF;
+  d->sg_buffer[8] = sectors;
+  if(handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW))
+    return(1);
+  if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW);
+  return(0);
+}
+
 static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors,
 			  int (*map)(cdrom_drive *, void *, long, long)){
   int retry_count,err;
@@ -650,6 +703,11 @@
   return(scsi_read_map(d,p,begin,sectors,i_read_mmc));
 }
 
+static long scsi_read_mmc2 (cdrom_drive *d, void *p, long begin, 
+			       long sectors){
+  return(scsi_read_map(d,p,begin,sectors,i_read_mmc2));
+}
+
 /* request vendor brand and model */
 unsigned char *scsi_inquiry(cdrom_drive *d){
   memcpy(d->sg_buffer,(char[]){ 0x12,0,0,0,56,0},6);
@@ -834,6 +892,15 @@
 int scsi_init_drive(cdrom_drive *d){
   unsigned char *p;
   int ret;
+  /* list of known drives which require non-standard read functions */
+  struct {
+    char *model;
+    long (*read_audio)   (struct cdrom_drive *d, void *p, long begin,
+                         long sectors);
+  } *ptr, known_drives[] = {
+    { "SAMSUNG SCR-830 REV 2.09 2.09 ", scsi_read_mmc2 },
+    { NULL, NULL }
+  };
 
   check_atapi(d);
   check_mmc(d);
@@ -925,7 +992,14 @@
 
   d->read_toc = (!memcmp(p+8, "IMS", 3) && !d->is_atapi) ? scsi_read_toc2 : 
     scsi_read_toc;
-  
+
+  /* check our list of "known" drives */
+  for (ptr = known_drives; ptr->model; ptr++)
+    if (!strcmp(d->drive_model, ptr->model) && d->read_audio != ptr->read_audio){
+      cdmessage(d,"\tKnown drive -- overriding read_audio\n");
+      d->read_audio = ptr->read_audio;
+    }
+
   d->enable_cdda(d,0);
 
   if(!d->is_atapi){
