Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Apr 1999 00:25:12 +0200
From:      Jeremy Lea <reg@shale.csir.co.za>
To:        ports@freebsd.org
Cc:        sos@freebsd.org
Subject:   [PATCH] cdda2wav using FreeBSD ioctl for IDE CDs.
Message-ID:  <19990402002512.K12489@shale.csir.co.za>

next in thread | raw e-mail | index | archive | help
Hi,

I'm posting the attached patch, which implements 'cooked_ioctl' support
for FreeBSD in cdda2wav, so that it works with ATAPI/IDE CD drives. 
I've not send-pr'd it since it needs a little more testing, before it
can become part of the port, and I can submit it back to the author.

It works for me...  I get the same .WAV files as from my Windows
machine, with a speed of about 660KB/sec.  CD Drive:

wdc1 at 0x170-0x177 irq 15 flags 0xa0ffa0ff on isa
wdc1: unit 0 (atapi): <ASUS CD-S340/V1.71>, removable, accel, dma, iordy
wcd0: drive speed 0 - 5843KB/sec, 128KB cache
wcd0: supported read types: CD-R, CD-RW, CD-DA
, packet track
wcd0: Audio: play, 255 volume levels
wcd0: Mechanism: ejectable tray
wcd0: Medium: no/blank disc inside, unlocked

Please could people look and comment.

Regards,
 -Jeremy

Soren:  I've cc'd you, as author of atapi-cd.c (both versions), for
two reasons: 1. The driver reads in only 8 sector blocks?  Is this
optimal, or could it go higher?  Would it make any difference?  2. The
driver returns LBA addresses in network byte order, but takes them in
host byte order...  This confused me for a while, and I would call it a
bug.  Question is if it is to late to fix?  It would be nice if it
always worked in host byte order, so that slow people like me don't
spend hours wondering why the numbers look so funny ;)

-- 
  |    What will people think when they hear that I'm a Jesus freak?
--+--  What will people do when they find that it's true?
  |    I don't really care if they label me a Jesus Freak,
  |    There ain't no disguising the truth.  - d c Talk

--- cdda2wav/interface.c.orig	Thu Apr  1 23:25:54 1999
+++ cdda2wav/interface.c	Thu Apr  1 23:32:57 1999
@@ -44,33 +44,8 @@
 #include <sys/stat.h>
 #include <statdefs.h>
 
-
 #include "mycdrom.h"
 #include "lowlevel.h"
-/* some include file locations have changed with newer kernels */
-#if defined (__linux__)
-# if LINUX_VERSION_CODE > 0x10300 + 97
-#  if LINUX_VERSION_CODE < 0x200ff
-#   include <linux/sbpcd.h>
-#   include <linux/ucdrom.h>
-#  endif
-#  if !defined(CDROM_SELECT_SPEED)
-#   include <linux/ucdrom.h>
-#  endif
-# endif
-
-/* Hack hack hack hack hack... makes the code clean, though. Zygo was here */
-# ifndef SG_BIG_BUFF
-#  define SG_BIG_BUFF 4096	/* FIXME: should be the size of page */
-# endif
-/* HACK! the kernel header files were misdesigned for
- *  user applications.
- * #include <linux/blkdev.h> did not work
- */
-struct request {		/* this is and may not used */
-  int dummy;
-};
-#endif
 
 #include "byteorder.h"
 #include "interface.h"
@@ -316,18 +291,17 @@
     }
 }
 
-#if defined (__linux__)
+#if defined (__FreeBSD__)
 /*******************************************************************
  *
  *	cooked ioctl section
  *
  */
-static struct cdrom_tochdr hdr;
-static struct cdrom_tocentry entry[100];
-static struct cdrom_read_audio arg;
+static struct ioc_toc_header hdr;
+static struct ioc_read_toc_single_entry entry;
+static struct ioc_read_audio arg;
 static int err;
 
-static subq_chnl *ReadSubQ_cooked __PR(( SCSI *x, unsigned char sq_format, unsigned char track ));
 static unsigned ReadToc_cooked __PR(( SCSI *x, TOC *toc ));
 
 /* read the table of contents (toc) via the ioctl interface */
@@ -341,7 +315,7 @@
     PRETEND_TO_USE(x);
 
 #if 0
-    err = ioctl( global.cooked_fd, CDROMSTOP, NULL );
+    err = ioctl( global.cooked_fd, CDIOCSTOP, NULL );
     if ( err != 0 ) {
        /* error handling */
        if (err == -1) {
@@ -355,7 +329,7 @@
        }
     }
 
-    err = ioctl( global.cooked_fd, CDROMSTART, NULL );
+    err = ioctl( global.cooked_fd, CDIOCSTART, NULL );
     if ( err != 0 ) {
        /* error handling */
        if (err == -1) {
@@ -370,7 +344,7 @@
     }
 #endif
     /* get TocHeader to find out how many entries there are */
-    err = ioctl( global.cooked_fd, CDROMREADTOCHDR, &hdr );
+    err = ioctl( global.cooked_fd, CDIOREADTOCHEADER, &hdr );
     if ( err != 0 ) {
 	/* error handling */
 	if (err == -1) {
@@ -384,59 +358,67 @@
 	}
     }
     /* get all TocEntries */
-    for ( i = 0; i < hdr.cdth_trk1; i++ ) {
-	entry[i].cdte_track = 1+i;
+    tracks = hdr.ending_track - hdr.starting_track + 1;
+    for ( i = 0; i < tracks; i++ ) {
+	entry.track = hdr.starting_track+i;
 #if 0
-	entry[i].cdte_format = CDROM_LBA;
-	err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+	entry.address_format = CD_LBA_FORMAT;
+	err = ioctl( global.cooked_fd, CDIOREADTOCENTRY, &entry );
 	if ( err != 0 ) {
 	    /* error handling */
 	    fprintf( stderr, "can't get TocEntry #%d (error %d).\n", i+1, err );
 	    exit( -1 );
 	}
-    }
-    entry[i].cdte_track = CDROM_LEADOUT;
-    entry[i].cdte_format = CDROM_LBA;
-    err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+	toc[i].bFlags = (entry.entry.addr_type << 4) | 
+			    (entry.entry.control & 0x0f);
+	toc[i].bTrack = entry.entry.track;
+	toc[i].dwStartSector = ntohl(entry.entry.addr.lba);
+    }
+    entry.track = CDROM_LEADOUT;
+    entry.address_format = CD_LBA_FORMAT;
+    err = ioctl( global.cooked_fd, CDIOREADTOCENTRY, &entry );
     if ( err != 0 ) {
 	/* error handling */
 	fprintf( stderr, "can't get TocEntry LEADOUT (error %d).\n", err );
 	exit( -1 );
     }
-    tracks = hdr.cdth_trk1+1;
-    for (i = 0; i < tracks; i++) {
-        toc[i].bFlags = (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f);
-        toc[i].bTrack = entry[i].cdte_track;
-        toc[i].dwStartSector = entry[i].cdte_addr.lba;
+    toc[i].bFlags = (entry.entry.addr_type << 4) | 
+			(entry.entry.control & 0x0f);
+    toc[i].bTrack = entry.entry.track;
+    toc[i].dwStartSector = ntohl(entry.entry.addr.lba);
 #else
-	entry[i].cdte_format = CDROM_MSF;
-	err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+	entry.address_format = CD_MSF_FORMAT;
+	err = ioctl( global.cooked_fd, CDIOREADTOCENTRY, &entry );
 	if ( err != 0 ) {
 	    /* error handling */
 	    fprintf( stderr, "can't get TocEntry #%d (error %d).\n", i+1, err );
 	    exit( -1 );
 	}
-    }
-    entry[i].cdte_track = CDROM_LEADOUT;
-    entry[i].cdte_format = CDROM_MSF;
-    err = ioctl( global.cooked_fd, CDROMREADTOCENTRY, &entry[i] );
+	toc[i].bFlags = (entry.entry.addr_type << 4) | 
+			    (entry.entry.control & 0x0f);
+	toc[i].bTrack = entry.entry.track;
+	toc[i].dwStartSector = -150 + 75*60*entry.entry.addr.msf.minute+
+				      75*   entry.entry.addr.msf.second+
+				            entry.entry.addr.msf.frame;
+    }
+    entry.track = CDROM_LEADOUT;
+    entry.address_format = CD_MSF_FORMAT;
+    err = ioctl( global.cooked_fd, CDIOREADTOCENTRY, &entry );
     if ( err != 0 ) {
 	/* error handling */
 	fprintf( stderr, "can't get TocEntry LEADOUT (error %d).\n", err );
 	exit( -1 );
     }
-    tracks = hdr.cdth_trk1+1;
-    for (i = 0; i < tracks; i++) {
-        toc[i].bFlags = (entry[i].cdte_adr << 4) | (entry[i].cdte_ctrl & 0x0f);
-        toc[i].bTrack = entry[i].cdte_track;
-        toc[i].dwStartSector = -150 + 75*60*entry[i].cdte_addr.msf.minute+
-				      75*   entry[i].cdte_addr.msf.second+
-				            entry[i].cdte_addr.msf.frame;
+    toc[i].bFlags = (entry.entry.addr_type << 4) | 
+			(entry.entry.control & 0x0f);
+    toc[i].bTrack = entry.entry.track;
+    toc[i].dwStartSector = -150 + 75*60*entry.entry.addr.msf.minute+
+				  75*   entry.entry.addr.msf.second+
+				        entry.entry.addr.msf.frame;
 #endif
-    }
     bufferTOC[0] = '\0';
     bufferTOC[1] = '\0';
-    return --tracks;           /* without lead-out */
+    return tracks;           /* without lead-out */
 }
 
 static void trash_cache_cooked __PR((UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
@@ -447,13 +429,13 @@
 	unsigned SectorBurstVal;
 {
       /* trash the cache */
-      static struct cdrom_read_audio arg2;
+      static struct ioc_read_audio arg2;
 
-      arg2.addr.lba = find_an_off_sector(lSector, SectorBurstVal);
-      arg2.addr_format = CDROM_LBA;
+      arg2.address.lba = find_an_off_sector(lSector, SectorBurstVal);
+      arg2.address_format = CD_LBA_FORMAT;
       arg2.nframes = 3;
-      arg2.buf = (unsigned char *) &p[0];
-      ioctl(global.cooked_fd, CDROMREADAUDIO, &arg2);
+      arg2.buffer = (unsigned char *) &p[0];
+      ioctl(global.cooked_fd, CDIOCREADAUDIO, &arg2);
 }
 
 static void ReadCdRom_cooked __PR(( SCSI *x, UINT4 *p, unsigned lSector, unsigned SectorBurstVal));
@@ -472,13 +454,13 @@
   PRETEND_TO_USE(x);
 
 /* read 2352 bytes audio data */
-  arg.addr.lba = lSector;
-  arg.addr_format = CDROM_LBA;
+  arg.address.lba = lSector;
+  arg.address_format = CD_LBA_FORMAT;
   arg.nframes = SectorBurstVal;
-  arg.buf = (unsigned char *) &p[0];
+  arg.buffer = (unsigned char *) &p[0];
 
   do {
-    err = ioctl(global.cooked_fd, CDROMREADAUDIO, &arg);
+    err = ioctl(global.cooked_fd, CDIOCREADAUDIO, &arg);
     retry_count++;
 
     if (err) { 
@@ -495,7 +477,7 @@
           fprintf(stderr, " sector %u + %u, buffer %p, %p + %x\n", lSector, SectorBurstVal, p, fill_buffer, global.shmsize);
       } else {
 	  fprintf(stderr, "can't read frame #%d (error %d).\n", 
-		  arg.addr.lba, err);
+		  arg.address.lba, err);
       }
   } else {
     nothing_read = 0;
@@ -508,7 +490,7 @@
 {
 	PRETEND_TO_USE(x);
 
-	return ioctl( global.cooked_fd, CDROMSTOP, 0 ) ? 0 : -1; 
+	return ioctl( global.cooked_fd, CDIOCSTOP, 0 ) ? 0 : -1; 
 }
 
 static int Play_at_cooked __PR(( SCSI *x, unsigned int from_sector, unsigned int sectors));
@@ -517,40 +499,47 @@
 	unsigned int from_sector;
 	unsigned int sectors;
 {
-	struct cdrom_msf cmsf;
+	struct ioc_play_msf cmsf;
 
 	PRETEND_TO_USE(x);
 
-	cmsf.cdmsf_min0 = (from_sector + 150) / (60*75);
-	cmsf.cdmsf_sec0 = ((from_sector + 150) / 75) % 60;
-	cmsf.cdmsf_frame0 = (from_sector + 150) % 75;
-	cmsf.cdmsf_min1 = (from_sector + 150 + sectors) / (60*75);
-	cmsf.cdmsf_sec1 = ((from_sector + 150 + sectors) / 75) % 60;
-	cmsf.cdmsf_frame1 = (from_sector + 150 + sectors) % 75;
+	cmsf.start_m = (from_sector + 150) / (60*75);
+	cmsf.start_s = ((from_sector + 150) / 75) % 60;
+	cmsf.start_f = (from_sector + 150) % 75;
+	cmsf.end_m = (from_sector + 150 + sectors) / (60*75);
+	cmsf.end_s = ((from_sector + 150 + sectors) / 75) % 60;
+	cmsf.end_f = (from_sector + 150 + sectors) % 75;
 
-	ioctl( global.cooked_fd, CDROMSTART, 0 );
-	return ioctl( global.cooked_fd, CDROMPLAYMSF, &cmsf ) ? 0 : -1; 
+	ioctl( global.cooked_fd, CDIOCSTART, 0 );
+	return ioctl( global.cooked_fd, CDIOCPLAYMSF, &cmsf ) ? 0 : -1; 
 }
 
 /* request sub-q-channel information. This function may cause confusion
  * for a drive, when called in the sampling process.
  */
+static subq_chnl *ReadSubQ_cooked __PR(( SCSI *x, unsigned char sq_format, unsigned char track ));
 static subq_chnl *ReadSubQ_cooked ( x, sq_format, track )
 	SCSI *x;
 	unsigned char sq_format;
 	unsigned char track;
 {
-    struct cdrom_subchnl sub_ch;
+    struct ioc_read_subchannel sub_ch;
+    struct cd_sub_channel_info sub_ch_info;
 
     PRETEND_TO_USE(x);
 
+    sub_ch.address_format = CD_MSF_FORMAT;
+    sub_ch.track = track;
+    sub_ch.data_len = sizeof(struct cd_sub_channel_info);
+    sub_ch.data = &sub_ch_info;
     switch (sq_format) {
       case GET_CATALOGNUMBER:
-      if (!(err = ioctl(global.cooked_fd, CDROM_GET_MCN, (struct cdrom_mcn *) SubQbuffer))) {
+      sub_ch.data_format = CD_MEDIA_CATALOG;
+      if (!(err = ioctl(global.cooked_fd, CDIOCREADSUBCHANNEL, &sub_ch))) {
           subq_chnl *SQp = (subq_chnl *) SubQbuffer;
 	  subq_catalog *SQPp = (subq_catalog *) &SQp->data;
 
-          movebytes(SQp, SQPp->media_catalog_number, sizeof (SQPp->media_catalog_number));
+          movebytes(sub_ch_info.what.media_catalog.mc_number, SQPp->media_catalog_number, sizeof (SQPp->media_catalog_number));
           SQPp->zero = 0;
           SQPp->mc_valid = 0x80;
       } else {
@@ -558,21 +547,22 @@
       }
       break;
       case GET_POSITIONDATA:
-      if (!(err = ioctl(global.cooked_fd, CDROMSUBCHNL, &sub_ch))) {
+      sub_ch.data_format = CD_CURRENT_POSITION;
+      if (!(err = ioctl(global.cooked_fd, CDIOCREADSUBCHANNEL, &sub_ch))) {
 	  /* copy to SubQbuffer */
 	  subq_chnl *SQp = (subq_chnl *) (SubQbuffer);
 	  subq_position *SQPp = (subq_position *) &SQp->data;
-	  SQp->audio_status 	= sub_ch.cdsc_audiostatus;
-	  SQp->format 		= sub_ch.cdsc_format;
-	  SQp->control_adr	= (sub_ch.cdsc_adr << 4) | (sub_ch.cdsc_ctrl & 0x0f);
-	  SQp->track 		= sub_ch.cdsc_trk;
-	  SQp->index 		= sub_ch.cdsc_ind;
-	  SQPp->abs_min 	= sub_ch.cdsc_absaddr.msf.minute;
-	  SQPp->abs_sec 	= sub_ch.cdsc_absaddr.msf.second;
-	  SQPp->abs_frame 	= sub_ch.cdsc_absaddr.msf.frame;
-	  SQPp->trel_min 	= sub_ch.cdsc_reladdr.msf.minute;
-	  SQPp->trel_sec 	= sub_ch.cdsc_reladdr.msf.second;
-	  SQPp->trel_frame 	= sub_ch.cdsc_reladdr.msf.frame;
+	  SQp->audio_status 	= sub_ch_info.header.audio_status;
+	  SQp->format 		= sub_ch_info.what.position.data_format;
+	  SQp->control_adr	= (sub_ch_info.what.position.addr_type << 4) | (sub_ch_info.what.position.control & 0x0f);
+	  SQp->track 		= sub_ch_info.what.position.track_number;
+	  SQp->index 		= sub_ch_info.what.position.index_number;
+	  SQPp->abs_min 	= sub_ch_info.what.position.absaddr.msf.minute;
+	  SQPp->abs_sec 	= sub_ch_info.what.position.absaddr.msf.second;
+	  SQPp->abs_frame 	= sub_ch_info.what.position.absaddr.msf.frame;
+	  SQPp->trel_min 	= sub_ch_info.what.position.reladdr.msf.minute;
+	  SQPp->trel_sec 	= sub_ch_info.what.position.reladdr.msf.second;
+	  SQPp->trel_frame 	= sub_ch_info.what.position.reladdr.msf.frame;
       } else {
 	  if (err == -1) {
 	      if (errno == EPERM)
@@ -624,41 +614,6 @@
 static void SetupCookedIoctl( pdev_name )
 	char *pdev_name;
 {
-#if (HAVE_ST_RDEV == 1)
-    struct stat statstruct;
-
-    if (fstat(global.cooked_fd, &statstruct)) {
-      fprintf(stderr, "cannot stat cd %d (%s)\n",global.cooked_fd, pdev_name);
-      exit(1);
-    }
-    switch ((int)(statstruct.st_rdev >> 8L)) {
-    case CDU31A_CDROM_MAJOR:	/* sony cdu-31a/33a */
-        global.nsectors = 13;
-        if (global.nsectors >= 14) {
-	  global.overlap = 10;
-	}
-        break;
-    case MATSUSHITA_CDROM_MAJOR:	/* sbpcd 1 */
-    case MATSUSHITA_CDROM2_MAJOR:	/* sbpcd 2 */
-    case MATSUSHITA_CDROM3_MAJOR:	/* sbpcd 3 */
-    case MATSUSHITA_CDROM4_MAJOR:	/* sbpcd 4 */
-        /* some are more compatible than others */
-        global.nsectors = 13;
-	break;
-	default:
-    }
-    err = ioctl(global.cooked_fd, CDROMAUDIOBUFSIZ, global.nsectors);
-
-    switch ((int)(statstruct.st_rdev >> 8L)) {
-    case MATSUSHITA_CDROM_MAJOR:	/* sbpcd 1 */
-    case MATSUSHITA_CDROM2_MAJOR:	/* sbpcd 2 */
-    case MATSUSHITA_CDROM3_MAJOR:	/* sbpcd 3 */
-    case MATSUSHITA_CDROM4_MAJOR:	/* sbpcd 4 */
-      if (err == -1) {
-        perror("ioctl(CDROMAUDIOBUFSIZ)");
-      }
-    }
-#endif
     EnableCdda = (void (*)(SCSI *, int))Dummy;
     ReadCdRom = ReadCdRom_cooked;
     ReadCdRomData = (void (*)(SCSI *, unsigned char *, unsigned, unsigned )) ReadCdRom_cooked;
@@ -672,6 +627,7 @@
 }
 #endif
 
+
 /********************** General setup *******************************/
 
 /* As the name implies, interfaces and devices are checked.  We also
@@ -699,9 +655,6 @@
     switch ((int) (statstruct->st_rdev >> 8L)) {
 #if defined (__linux__)
     case SCSI_GENERIC_MAJOR:	/* generic */
-#else
-    default:			/* ??? what is the proper value here */
-#endif
 #if !defined (STAT_MACROS_BROKEN) || (STAT_MACROS_BROKEN != 1)
        if (!S_ISCHR(statstruct->st_mode)) {
 	 fprintf(stderr, "%s is not a char device\n",pdev_name);
@@ -717,8 +670,6 @@
 	 interface = GENERIC_SCSI;
        }
 #endif
-       break;
-#if defined (__linux__)
     case SCSI_CDROM_MAJOR:     /* scsi cd */
     default:
 	if (!S_ISBLK(statstruct->st_mode)) {
@@ -731,6 +682,15 @@
 	    interface = COOKED_IOCTL;
 	}
 	break;
+#else
+    default:			/* ??? what is the proper value here */
+#if !defined (STAT_MACROS_BROKEN) || (STAT_MACROS_BROKEN != 1)
+       if (!S_ISCHR(statstruct->st_mode)) {
+	 fprintf(stderr, "%s is not a char device\n",pdev_name);
+	 exit(1);
+       }
+#endif
+       break;
 #endif
     }
 #endif
@@ -751,7 +711,6 @@
       b. an SCSI device specified with bus,target,lun numbers,
       c. a non-SCSI device such as ATAPI or proprietary CDROM devices.
    */
-#ifdef __linux__
   have_named_device = strchr(pdev_name, ':') == NULL
 			 && memcmp(pdev_name, "/dev/", 5) == 0;
 
@@ -763,7 +722,6 @@
       Check_interface_for_device( &statstruct, pdev_name );
     }
   }
-#endif
 
   if (interface == GENERIC_SCSI) {
       needroot(0);
@@ -1113,7 +1071,7 @@
 
 	/* set cache to zero */
 
-#if defined (__linux__)
+#if defined (__linux__) || defined (__FreeBSD__)
     } else {
 	SetupCookedIoctl( global.dev_name );
 #endif
--- cdda2wav/mycdrom.h.orig	Tue Oct 20 18:29:24 1998
+++ cdda2wav/mycdrom.h	Thu Apr  1 22:26:44 1999
@@ -1,5 +1,46 @@
+#if defined (__linux__)
 
-#if !defined(__linux__)
+#include <linux/cdrom.h>
+
+/* some include file locations have changed with newer kernels */
+#if defined (__linux__)
+# if LINUX_VERSION_CODE > 0x10300 + 97
+#  if LINUX_VERSION_CODE < 0x200ff
+#   include <linux/sbpcd.h>
+#   include <linux/ucdrom.h>
+#  endif
+#  if !defined(CDROM_SELECT_SPEED)
+#   include <linux/ucdrom.h>
+#  endif
+# endif
+
+/* Hack hack hack hack hack... makes the code clean, though. Zygo was here */
+# ifndef SG_BIG_BUFF
+#  define SG_BIG_BUFF 4096	/* FIXME: should be the size of page */
+# endif
+/* HACK! the kernel header files were misdesigned for
+ *  user applications.
+ * #include <linux/blkdev.h> did not work
+ */
+struct request {		/* this is and may not used */
+  int dummy;
+};
+#endif
+
+#elif defined (__FreeBSD__)
+
+#include <sys/cdio.h>
+/*
+ * bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl)
+ */
+#define	CDROM_DATA_TRACK	0x04
+
+/*
+ * The leadout track is always 0xAA, regardless of # of tracks on disc
+ */
+#define	CDROM_LEADOUT	0xAA
+
+#else
 
 /*
  * -- <linux/cdrom.h>
@@ -215,6 +256,4 @@
 
 
 #endif
-#else
-#include <linux/cdrom.h>
 #endif


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-ports" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990402002512.K12489>