diff --git a/cdparanoia-III-alpha9.8.cflags.patch b/cdparanoia-III-alpha9.8.cflags.patch new file mode 100644 index 0000000..4ba27d1 --- /dev/null +++ b/cdparanoia-III-alpha9.8.cflags.patch @@ -0,0 +1,52 @@ +--- cdparanoia-III-alpha9.8/configure.in.cflags 2000-03-26 02:33:22.000000000 -0500 ++++ cdparanoia-III-alpha9.8/configure.in 2004-03-30 11:59:04.861801016 -0500 +@@ -19,18 +19,18 @@ + case $host in + i?86-*-linux*) + DEBUG="-g -Wall -fsigned-char" +- OPT="-O20 -ffast-math -fsigned-char -finline-functions";; ++ OPT="-ffast-math -fsigned-char -finline-functions";; + *) + DEBUG="-g -Wall -fsigned-char" +- OPT="-O20 -fsigned-char";; ++ OPT="-fsigned-char";; + esac + fi + + AC_HEADER_STDC + +-CFLAGS="" ++# CFLAGS="" + +-TYPESIZES="" ++# TYPESIZES="" + + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(int) +--- cdparanoia-III-alpha9.8/configure.cflags 2000-04-15 11:13:01.000000000 -0400 ++++ cdparanoia-III-alpha9.8/configure 2004-03-30 11:58:52.932614528 -0500 +@@ -892,10 +892,10 @@ + case $host in + i?86-*-linux*) + DEBUG="-g -Wall -fsigned-char" +- OPT="-O20 -ffast-math -fsigned-char -finline-functions";; ++ OPT="-ffast-math -fsigned-char -finline-functions";; + *) + DEBUG="-g -Wall -fsigned-char" +- OPT="-O20 -fsigned-char";; ++ OPT="-fsigned-char";; + esac + fi + +@@ -1084,9 +1084,9 @@ + fi + + +-CFLAGS="" ++# CFLAGS="" + +-TYPESIZES="" ++# TYPESIZES="" + + echo $ac_n "checking size of short""... $ac_c" 1>&6 + echo "configure:1093: checking size of short" >&5 diff --git a/cdparanoia-III-alpha9.8.env.patch b/cdparanoia-III-alpha9.8.env.patch new file mode 100644 index 0000000..04159f2 --- /dev/null +++ b/cdparanoia-III-alpha9.8.env.patch @@ -0,0 +1,46 @@ +--- cdparanoia-III-alpha9.8/interface/scsi_interface.c.env 2004-09-30 11:36:29.495045730 -0400 ++++ cdparanoia-III-alpha9.8/interface/scsi_interface.c 2004-09-30 11:35:52.261283378 -0400 +@@ -177,8 +177,11 @@ + * "allocation, so be more conservative: 32kB max until I test more + * thoroughly". We're not currently honoring that, because we should + * always get -ENOMEM. ++ * ++ * Updated: but we don't always get -ENOMEM. Sometimes USB drives ++ * still fail the wrong way. This needs some kernel-land investigation. + */ +-#if 0 ++#if 1 + cur=(cur>1024*32?1024*32:cur); + #endif + d->nsectors=cur/CD_FRAMESIZE_RAW; +--- cdparanoia-III-alpha9.8/interface/scan_devices.c.env 2004-09-30 11:30:55.422135762 -0400 ++++ cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-09-30 11:34:04.815523677 -0400 +@@ -104,6 +104,7 @@ + cdrom_drive *cdda_identify(const char *device, int messagedest,char **messages){ + struct stat st; + cdrom_drive *d=NULL; ++ char *transport = getenv("CDDA_TRANSPORT"); + idmessage(messagedest,messages,"Checking %s for cdrom...",device); + + if(stat(device,&st)){ +@@ -120,11 +121,15 @@ + #endif + + #ifdef SG_IO +- d=cdda_identify_scsi(device,NULL,messagedest,messages); +- if(!d)d=cdda_identify_cooked(device,messagedest,messages); +-#else +- if(!d)d=cdda_identify_scsi(device,NULL,messagedest,messages); +- d=cdda_identify_cooked(device,messagedest,messages); ++ if (transport && !strcasecmp(transport, "cooked")) { ++#endif ++ d=cdda_identify_cooked(device,messagedest,messages); ++ if(!d)d=cdda_identify_scsi(device,NULL,messagedest,messages); ++#ifdef SG_IO ++ } else { ++ d=cdda_identify_scsi(device,NULL,messagedest,messages); ++ if(!d)d=cdda_identify_cooked(device,messagedest,messages); ++ } + #endif + + #ifdef CDDA_TEST diff --git a/cdparanoia-III-alpha9.8.louder.patch b/cdparanoia-III-alpha9.8.louder.patch new file mode 100644 index 0000000..347cbb4 --- /dev/null +++ b/cdparanoia-III-alpha9.8.louder.patch @@ -0,0 +1,86 @@ +--- cdparanoia-III-alpha9.8/interface/scsi_interface.c.louder 2004-04-23 12:18:20.561275440 -0400 ++++ cdparanoia-III-alpha9.8/interface/scsi_interface.c 2004-04-23 12:24:37.853918240 -0400 +@@ -197,16 +197,41 @@ + memset(hdr->dxferp, sgi->bytefill, sgi->dxferp_buffer_len); + memcpy(hdr->cmdp, cmdp, cmd_len); + +- hdr->cmd_len = cmd_len; ++ sgi->cmd_len = hdr->cmd_len = cmd_len; + + sgi->in_size = in_size; + sgi->out_size = out_size; + } + ++void print_cmd_error(cdrom_drive *d, char *direction, char *cmdp, int cmdlen) { ++ unsigned char ebuf[1024], tmp[2]; ++ int x=0; ++ ++ sprintf(ebuf, "\nError %s command: ", direction); ++ cdmessage(d, ebuf); ++ tmp[1] = 0; ++ while (x < cmdlen) { ++ if (x % 8 == 0) ++ cdmessage(d, " "); ++ if (x % 16 == 0) { ++ cdmessage(d, "\n"); ++ if (x+1 < cmdlen) ++ cdmessage(d, "\t"); ++ } ++ tmp[0] = cmdp[x]; ++ sprintf(ebuf, "%02x ", tmp[0]); ++ cdmessage(d, ebuf); ++ x++; ++ } ++ if (!(x % 16 == 0)) ++ cdmessage(d, "\n"); ++} ++ + static int sgio_handle_scsi_cmd(cdrom_drive *d) { + int status = 0; + struct sg_info *sgi = (struct sg_info *)d->sg; + struct sg_io_hdr *hdr = sgi->hdr; ++ char ebuf[256]; + + if (sgi->in_size) { + hdr->dxfer_len = sgi->in_size; +@@ -217,8 +242,10 @@ + if (status >= 0) + if (hdr->status) + status = check_sbp_error(hdr->sbp); +- if (status < 0) ++ if (status < 0) { ++ print_cmd_error(d, "writing", sgi->cmdp, sgi->cmd_len); + return TR_EWRITE; ++ } + } + if (!sgi->in_size | sgi->out_size) { + hdr->dxfer_len = sgi->out_size; +@@ -226,14 +253,18 @@ + + errno = 0; + status = ioctl(d->cdda_fd, SG_IO, hdr); +- if (status < 0) ++ if (status < 0) { ++ print_cmd_error(d, "reading", hdr->cmdp, hdr->cmd_len); + return TR_EREAD; ++ } + if (status >= 0) + if (hdr->status) + status = check_sbp_error(hdr->sbp); + } +- if (status) ++ if (status) { ++ print_cmd_error(d, "reading", hdr->cmdp, hdr->cmd_len); + return status; ++ } + + errno = 0; + return 0; +@@ -352,6 +383,7 @@ + struct sg_header *hdr = (struct sg_header *)sgi->hdr; + + sgi->cmdp = (char *)hdr + sizeof (struct sg_header); ++ sgi->cmd_len = cmd_len; + memcpy(sgi->cmdp, cmdp, cmd_len); + + sgi->dxferp = sgi->cmdp + cmd_len; diff --git a/cdparanoia-III-alpha9.8.sgio.patch b/cdparanoia-III-alpha9.8.sgio.patch new file mode 100644 index 0000000..292c62d --- /dev/null +++ b/cdparanoia-III-alpha9.8.sgio.patch @@ -0,0 +1,1943 @@ +diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/cdda_interface.h paranoia-III/interface/cdda_interface.h +--- cdparanoia-III-alpha9.8/interface/cdda_interface.h 2004-02-21 13:16:47.000000000 -0500 ++++ cdparanoia-III-alpha9.8/interface/cdda_interface.h 2004-02-25 21:42:15.000000000 -0500 +@@ -99,10 +99,46 @@ + + } cdrom_drive; + ++/* buffers for use with the scsi code. d->sg_buffer is unused, ++ and d->sg points to this struct. We can't really change struct ++ cdrom_drive without breaking binary compatibility, so we do this ++ instead. */ ++struct sg_info { ++#ifdef SG_IO ++ struct sg_io_hdr *hdr; ++#else ++ struct sg_header *hdr; ++#endif ++ ++ char *cmdp; ++ ssize_t cmd_len; ++ ssize_t cmdp_buffer_len; ++ ++ char *dxferp; ++ ssize_t dxferp_buffer_len; ++ ssize_t dxferp_max_buffer_len; ++ ++ unsigned char bytefill; ++ int bytecheck; ++ ++ int in_size; ++ int out_size; ++ ++ int (*handle_scsi_cmd)(struct cdrom_drive *d); ++ void (*setup_scsi_cmd)(struct cdrom_drive *d, ++ char *cmdp, unsigned int cmd_len, ++ unsigned int in_size, unsigned int out_size); ++}; ++ ++ + #define IS_AUDIO(d,i) (!(d->disc_toc[i].bFlags & 0x04)) + + /******** Identification/autosense functions */ + ++#ifdef SG_IO ++extern int check_fd_sgio(int fd); ++#endif ++ + extern cdrom_drive *cdda_find_a_cdrom(int messagedest, char **message); + extern cdrom_drive *cdda_identify(const char *device, int messagedest, + char **message); +diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/interface.c paranoia-III/interface/interface.c +--- cdparanoia-III-alpha9.8/interface/interface.c 2004-02-21 13:16:49.000000000 -0500 ++++ cdparanoia-III-alpha9.8/interface/interface.c 2004-02-25 11:17:37.000000000 -0500 +@@ -30,7 +30,7 @@ + + _clean_messages(d); + if(d->cdda_device_name)free(d->cdda_device_name); +- if(d->ioctl_device_name)free(d->ioctl_device_name); ++ if(d->ioctl_device_name && d->ioctl_device_name!=d->cdda_device_name)free(d->ioctl_device_name); + if(d->drive_model)free(d->drive_model); + if(d->cdda_fd!=-1)close(d->cdda_fd); + if(d->ioctl_fd!=-1 && d->ioctl_fd!=d->cdda_fd)close(d->ioctl_fd); +diff --exclude CVS -u -N -r cdparanoia-III-alpha9.8/interface/scan_devices.c paranoia-III/interface/scan_devices.c +--- cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-02-21 13:16:51.000000000 -0500 ++++ cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-02-26 19:26:15.000000000 -0500 +@@ -14,8 +14,8 @@ + #include + #include + #include +-#include "cdda_interface.h" + #include "low_interface.h" ++#include "cdda_interface.h" + #include "common_interface.h" + #include "utils.h" + +@@ -50,6 +50,8 @@ + "/dev/gscd", + "/dev/optcd",NULL}; + ++extern void sg2_init_sg_info(cdrom_drive *d); ++extern void sgio_init_sg_info(cdrom_drive *d); + /* Functions here look for a cdrom drive; full init of a drive type + happens in interface.c */ + +@@ -117,8 +119,13 @@ + } + #endif + +- d=cdda_identify_cooked(device,messagedest,messages); ++#ifdef SG_IO ++ d=cdda_identify_scsi(device,NULL,messagedest,messages); ++ if(!d)d=cdda_identify_cooked(device,messagedest,messages); ++#else + if(!d)d=cdda_identify_scsi(device,NULL,messagedest,messages); ++ d=cdda_identify_cooked(device,messagedest,messages); ++#endif + + #ifdef CDDA_TEST + if(!d)d=cdda_identify_test(device,messagedest,messages); +@@ -412,17 +419,19 @@ + "\nFound an accessible SCSI CDROM drive." + "\nLooking at revision of the SG interface in use...",""); + +- if(ioctl(d->cdda_fd,SG_GET_VERSION_NUM,&version)){ ++ if((version = ioctl(d->cdda_fd,SG_GET_VERSION_NUM,&major)) < 0){ + /* Up, guess not. */ + idmessage(messagedest,messages, + "\tOOPS! Old 2.0/early 2.1/early 2.2.x (non-ac patch) style " + "SG.\n\tCdparanoia no longer supports the old interface.\n",""); + return(0); + } +- major=version/10000; +- version-=major*10000; +- minor=version/100; +- version-=minor*100; ++ if (!version) ++ version = major; ++ ++ major = (version >> 16) & 0xff; ++ minor = (version >> 8) & 0xff; ++ version &= 0xff; + + sprintf(buffer,"\tSG interface version %d.%d.%d; OK.", + major,minor,version); +@@ -431,6 +440,138 @@ + return(major); + } + ++#ifdef SG_IO ++int get_sgio_fd(const char *device, int messagedest, char **messages) { ++ int fd; ++ ++ if (!device) ++ return -errno; ++ /* we don't really care what type of device it is -- if it can do ++ * SG_IO, then we'll put it through the normal mmc/atapi/etc tests ++ * later, but it's good enough for now. */ ++ fd = open(device, O_RDWR|O_EXCL|O_NONBLOCK); ++ if (fd < 0) ++ return -errno; ++ return check_fd_sgio(fd); ++} ++ ++/* removing generic_device breaks ABI; instead, just test both devices */ ++static cdrom_drive *sgio_cdda_identify_scsi(const char *generic_device, ++ const char *ioctl_device, int messagedest, ++ char **messages){ ++ cdrom_drive *d = NULL; ++ char *device = NULL; ++ int fd = -1, g_fd = -1; ++ char *p; ++ ++ /* with SG_IO in 2.6, we much prefer /dev/hdc and /dev/scd0, so ++ * test ioctl_device before testing generic_device */ ++ ++ /* we need to resolve any symlinks for the lookup code to work */ ++ if (ioctl_device) ++ device = test_resolve_symlink(ioctl_device, messagedest, messages); ++ /* test again, in case symlink resolution failed */ ++ if (device) { ++ fd = get_sgio_fd(ioctl_device, messagedest, messages); ++ if (fd < 0) { ++ /* ioctl_device didn't work, so we don't need to keep the strdup of its ++ * real path around */ ++ free(device); ++ device = NULL; ++ } ++ } ++ if (fd < 0) { ++ if (!generic_device) ++ goto cdda_identify_scsi_fail_free; ++ device = test_resolve_symlink(generic_device, messagedest, messages); ++ /* test again, in case symlink resolution failed */ ++ if (!device) ++ goto cdda_identify_scsi_fail_return; ++ g_fd = get_sgio_fd(device, messagedest, messages); ++ if (g_fd < 0) ++ goto cdda_identify_scsi_fail_free; ++ fd = g_fd; ++ } ++ ++ d=calloc(1,sizeof(cdrom_drive)); ++ ++ d->drive_type=SCSI_CDROM_MAJOR; ++ d->cdda_fd=fd; ++ d->ioctl_fd=fd; ++ d->bigendianp=-1; /* We don't know yet... */ ++ d->nsectors=-1; ++ ++ d->interface=GENERIC_SCSI; ++ ++ /* alloc our big buffer for scsi commands */ ++ d->sg=calloc(1, sizeof (struct sg_info)); ++ ((struct sg_info *)d->sg)->dxferp_max_buffer_len = CD_FRAMESIZE_RAW; ++ if (check_fd_sgio(d->cdda_fd)) ++ sgio_init_sg_info(d); ++ else ++ sg2_init_sg_info(d); ++ ++ /* get the lun -- this used to set 0 on failure, maybe still should */ ++ d->lun = -1; ++ ++ p = scsi_inquiry(d); ++ if (!p) ++ goto cdda_identify_scsi_fail_free_device; ++ ++ /* It would seem some TOSHIBA CDROMs gets things wrong */ ++ ++ if (!strncmp (p + 8, "TOSHIBA", 7) && ++ !strncmp (p + 16, "CD-ROM", 6) && ++ p[0] == TYPE_DISK) { ++ p[0] = TYPE_ROM; ++ p[1] |= 0x80; /* removable */ ++ } ++ ++ if (!p || (*p != TYPE_ROM && *p != TYPE_WORM)) { ++ idmessage(messagedest, messages, ++ "\t\tDrive is neither a CDROM nor a WORM device\n", NULL); ++ goto cdda_identify_scsi_fail_free_device; ++ } ++ ++ memcpy(d->inqbytes, p, 4); ++ d->cdda_device_name = device; ++ d->ioctl_device_name = device; ++ ++ d->drive_model = calloc(1, 36); ++ strscat(d->drive_model, p+8, 8); ++ strscat(d->drive_model, p+16, 16); ++ strscat(d->drive_model, p+32, 4); ++ ++ idmessage(messagedest, messages, "\nCDROM model sensed sensed: %s", d->drive_model); ++ ++ return d; ++ ++cdda_identify_scsi_fail_free_device: ++ if (d) { ++ if (d->drive_model) ++ free(d->drive_model); ++ if (d->sg) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ ++ if (sgi->cmdp_buffer_len) ++ free(sgi->cmdp); ++ if (sgi->dxferp_buffer_len) ++ free(sgi->dxferp); ++ if (sgi->hdr) ++ free(sgi->hdr); ++ free(d->sg); ++ } ++ free(d); ++ } ++ if (fd >= 0) ++ close(fd); ++cdda_identify_scsi_fail_free: ++ if (device) ++ free(device); ++cdda_identify_scsi_fail_return: ++ return NULL; ++} ++#endif + cdrom_drive *cdda_identify_scsi(const char *generic_device, + const char *ioctl_device, int messagedest, + char **messages){ +@@ -444,6 +585,12 @@ + int type; + char *p; + ++#ifdef SG_IO ++ d = sgio_cdda_identify_scsi(generic_device, ioctl_device, messagedest, messages); ++ if (d) ++ return d; ++#endif ++ + if(generic_device) + idmessage(messagedest,messages,"\tTesting %s for SCSI interface", + generic_device); +@@ -580,7 +727,6 @@ + "major number",generic_device); + goto cdda_identify_scsi_fail; + } +- + + d=calloc(1,sizeof(cdrom_drive)); + +@@ -601,8 +747,9 @@ + } + + /* malloc our big buffer for scsi commands */ +- d->sg=malloc(MAX_BIG_BUFF_SIZE); +- d->sg_buffer=d->sg+SG_OFF; ++ d->sg=calloc(1, sizeof (struct sg_info)); ++ ((struct sg_info *)d->sg)->dxferp_max_buffer_len = CD_FRAMESIZE_RAW; ++ sg2_init_sg_info(d); + + { + /* get the lun */ +@@ -614,6 +761,8 @@ + } + + p = scsi_inquiry(d); ++ if (!p) ++ goto cdda_identify_scsi_fail; + + /* It would seem some TOSHIBA CDROMs gets things wrong */ + +@@ -632,12 +781,11 @@ + goto cdda_identify_scsi_fail; + } + +- d->drive_model=calloc(36,1); + memcpy(d->inqbytes,p,4); + d->cdda_device_name=copystring(generic_device); + d->ioctl_device_name=copystring(ioctl_device); + +- d->drive_model=calloc(36,1); ++ d->drive_model=calloc(1, 36); + strscat(d->drive_model,p+8,8); + strscat(d->drive_model,p+16,16); + strscat(d->drive_model,p+32,4); +@@ -647,6 +795,22 @@ + return(d); + + cdda_identify_scsi_fail: ++ if (d) { ++ if (d->drive_model) ++ free(d->drive_model); ++ if (d->sg) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ ++ if (sgi->cmdp_buffer_len) ++ free(sgi->cmdp); ++ if (sgi->dxferp_buffer_len) ++ free(sgi->dxferp); ++ if (sgi->hdr) ++ free(sgi->hdr); ++ free(d->sg); ++ } ++ free(d); ++ } + if(generic_device)free((char *)generic_device); + if(ioctl_device)free((char *)ioctl_device); + if(i_fd!=-1)close(i_fd); +--- cdparanoia-III-alpha9.8/interface/scsi_interface.c.sgio 2001-03-23 20:15:46.000000000 -0500 ++++ cdparanoia-III-alpha9.8/interface/scsi_interface.c 2004-03-30 14:19:29.826011776 -0500 +@@ -3,6 +3,7 @@ + * Original interface.c Copyright (C) 1994-1997 + * Eissfeldt heiko@colossus.escape.de + * Current blenderization Copyright (C) 1998-1999 Monty xiphmont@mit.edu ++ * Copyright 2004 Peter Jones + * + * Generic SCSI interface specific code. + * +@@ -11,6 +12,7 @@ + #include "low_interface.h" + #include "common_interface.h" + #include "utils.h" ++#include "scsi_cmds.h" + + /* hook */ + static int Dummy (cdrom_drive *d,int s){ +@@ -19,7 +21,290 @@ + + #include "drive_exceptions.h" + +-static void tweak_SG_buffer(cdrom_drive *d){ ++static void reset_scsi(cdrom_drive *d){ ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_io_hdr *hdr = sgi->hdr; ++ unsigned char key, ASC, ASCQ; ++ int arg, ret, tries; ++ char cmd[6]; ++ ++ d->enable_cdda(d,0); ++ ++ cdmessage(d,"sending SG SCSI reset... "); ++ if(ioctl(d->cdda_fd,SG_SCSI_RESET,&arg)) ++ cdmessage(d,"FAILED: EBUSY\n"); ++ else ++ cdmessage(d,"OK\n"); ++ ++ tries = 0; ++ while(1) { ++ memcpy(cmd, SCSI_TEST_UNIT_READY_6, 6); ++ sgi->setup_scsi_cmd(d, cmd, 6, 0, 56); ++ ret = sgi->handle_scsi_cmd(d); ++ ++ key = hdr->sbp[2] & 0xf; ++ ASC = hdr->sbp[12]; ++ ASCQ = hdr->sbp[13]; ++ ++ if(key == 2 & ASC == 4 & ASCQ == 1 & tries < 10) { ++ tries++; ++ usleep(10); ++ continue; ++ } ++ break; ++ } ++ ++ d->enable_cdda(d,1); ++} ++ ++static int check_sbp_error(const char *sbp) { ++ char key = sbp[2] & 0xf; ++ char ASC = sbp[12]; ++ char ASCQ = sbp[13]; ++ ++ if (sbp[0]) { ++ switch (key){ ++ case 0: ++ if (errno==0) ++ errno = EIO; ++ return(TR_UNKNOWN); ++ case 1: ++ break; ++ case 2: ++ if (errno==0) ++ errno = EBUSY; ++ return(TR_BUSY); ++ case 3: ++ if ((ASC==0x0C) & (ASCQ==0x09)) { ++ /* loss of streaming */ ++ if (errno==0) ++ errno = EIO; ++ return(TR_STREAMING); ++ } else { ++ if (errno==0) ++ errno = EIO; ++ return(TR_MEDIUM); ++ } ++ case 4: ++ if (errno==0) ++ errno = EIO; ++ return(TR_FAULT); ++ case 5: ++ if (errno==0) ++ errno = EINVAL; ++ return(TR_ILLEGAL); ++ default: ++ if (errno==0) ++ errno = EIO; ++ return(TR_UNKNOWN); ++ } ++ } ++ return 0; ++} ++ ++#ifdef SG_IO ++int check_fd_sgio(int fd) { ++ struct sg_io_hdr hdr; ++ ++ if (fd < 0) ++ return fd; ++ ++ memset(&hdr, 0, sizeof (struct sg_io_hdr)); ++ /* First try with interface_id = 'A'; for all but the sg case, ++ * that'll get us a -EINVAL if it supports SG_IO, and some other ++ * error for all other cases. */ ++ hdr.interface_id = 'A'; ++ if (ioctl(fd, SG_IO, &hdr)) { ++ switch (errno) { ++ /* sr and ata give us EINVAL when SG_IO is supported ++ * but interface_id is bad. */ ++ case EINVAL: ++ /* sg gives us ENOSYS when SG_IO is supported but ++ * interface_id is bad. IMHO, this is wrong and ++ * needs fixing in the kernel. */ ++ case ENOSYS: ++ return fd; ++ /* everything else gives ENOTTY, I think. I'm just ++ * going to be paranoid and reject everything else. */ ++ default: ++ return -errno; ++ } ++ } ++ /* if we get here, something is dreadfuly wrong. ioctl(fd,SG_IO,&hdr) ++ * handled SG_IO, but took hdr.interface_id = 'A' as valid, and an empty ++ * command as good. Don't trust it. */ ++ return -1; ++} ++ ++static void sgio_tweak_SG_buffer(cdrom_drive *d) { ++ int table, reserved, cur, err; ++ char buffer[256]; ++ ++ /* SG_SET_RESERVED_SIZE doesn't actually allocate or reserve anything. ++ * what it _does_ do is give you an error if you ask for a value ++ * larger than q->max_sectors (the length of the device's bio request ++ * queue). So we walk it up from 1 sector until it fails, then get ++ * the value we set it to last. ++ */ ++ /* start with 2 frames, round down to our queue's sector size */ ++ cur = 1; ++ do { ++ cur <<= 1; reserved = cur * (1<<9); ++ err = ioctl(d->cdda_fd, SG_SET_RESERVED_SIZE, &reserved); ++ } while(err >= 0); ++ ioctl(d->cdda_fd, SG_GET_RESERVED_SIZE, &reserved); ++ ++ cur = 0; ++ /* this doesn't currently ever work, but someday somebody might ++ implement working sg lists with SG_IO devices, so who knows... */ ++ table=1; ++ if (ioctl(d->cdda_fd, SG_GET_SG_TABLESIZE, &table) < 0) ++ table=1; ++ ++ sprintf(buffer,"\tDMA scatter/gather table entries: %d\n\t" ++ "table entry size: %d bytes\n\t" ++ "maximum theoretical transfer: %d sectors\n", ++ table, reserved, table*reserved/CD_FRAMESIZE_RAW); ++ cdmessage(d,buffer); ++ ++ cur=table*reserved; ++ ++ ((struct sg_info *)d->sg)->dxferp_max_buffer_len = cur; ++ ++ /* so since we never go above q->max_sectors, we should never get -EIO. ++ * we might still get -ENOMEM, but we back off for that later. Monty ++ * had an old comment: "not too much; new kernels have trouble with DMA ++ * "allocation, so be more conservative: 32kB max until I test more ++ * thoroughly". We're not currently honoring that, because we should ++ * always get -ENOMEM. ++ */ ++#if 0 ++ cur=(cur>1024*32?1024*32:cur); ++#endif ++ d->nsectors=cur/CD_FRAMESIZE_RAW; ++ d->bigbuff=cur; ++ ++ sprintf(buffer,"\tSetting default read size to %d sectors (%d bytes).\n\n", ++ d->nsectors,d->nsectors*CD_FRAMESIZE_RAW); ++ cdmessage(d,buffer); ++} ++ ++static void sgio_setup_scsi_cmd(cdrom_drive *d, ++ char *cmdp, ++ unsigned int cmd_len, ++ unsigned int in_size, ++ unsigned int out_size) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_io_hdr *hdr = sgi->hdr; ++ ++ memset(hdr->cmdp, 0, sgi->cmdp_buffer_len); ++ memset(hdr->dxferp, sgi->bytefill, sgi->dxferp_buffer_len); ++ memcpy(hdr->cmdp, cmdp, cmd_len); ++ ++ hdr->cmd_len = cmd_len; ++ ++ sgi->in_size = in_size; ++ sgi->out_size = out_size; ++} ++ ++static int sgio_handle_scsi_cmd(cdrom_drive *d) { ++ int status = 0; ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_io_hdr *hdr = sgi->hdr; ++ ++ if (sgi->in_size) { ++ hdr->dxfer_len = sgi->in_size; ++ hdr->dxfer_direction = SG_DXFER_TO_DEV; ++ ++ errno = 0; ++ status = ioctl(d->cdda_fd, SG_IO, hdr); ++ if (status >= 0) ++ if (hdr->status) ++ status = check_sbp_error(hdr->sbp); ++ if (status < 0) ++ return TR_EWRITE; ++ } ++ if (!sgi->in_size | sgi->out_size) { ++ hdr->dxfer_len = sgi->out_size; ++ hdr->dxfer_direction = sgi->out_size ? SG_DXFER_FROM_DEV : SG_DXFER_NONE; ++ ++ errno = 0; ++ status = ioctl(d->cdda_fd, SG_IO, hdr); ++ if (status < 0) ++ return TR_EREAD; ++ if (status >= 0) ++ if (hdr->status) ++ status = check_sbp_error(hdr->sbp); ++ } ++ if (status) ++ return status; ++ ++ errno = 0; ++ return 0; ++} ++ ++void sgio_init_sg_info(cdrom_drive *d) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_io_hdr *hdr; ++ ++ hdr = calloc(sizeof (struct sg_io_hdr), 1); ++ ++ sgi->cmdp = hdr->cmdp = calloc(128, 1); ++ sgi->cmdp_buffer_len = 128; ++ ++ hdr->sbp = calloc(SG_MAX_SENSE,1); ++ hdr->mx_sb_len = SG_MAX_SENSE; ++ ++ sgi->bytefill = '\xff'; ++ sgi->bytecheck = 0; ++ ++ hdr->timeout = 5000; ++ hdr->interface_id = 'S'; ++ ++ sgi->hdr = hdr; ++ ++ sgi->setup_scsi_cmd = sgio_setup_scsi_cmd; ++ sgi->handle_scsi_cmd = sgio_handle_scsi_cmd; ++ ++ sgio_tweak_SG_buffer(d); ++ ++ sgi->dxferp = hdr->dxferp = calloc(sgi->dxferp_max_buffer_len, 1); ++ sgi->dxferp_buffer_len = sgi->dxferp_max_buffer_len; ++} ++#endif ++ ++static void sg2_clear_garbage(cdrom_drive *d){ ++ fd_set fdset; ++ struct timeval tv; ++ struct sg_header *sg_hd = (struct sg_header *)((struct sg_info *)d->sg)->hdr; ++ int flag = 0; ++ ++ /* clear out any possibly preexisting garbage */ ++ FD_ZERO(&fdset); ++ FD_SET(d->cdda_fd,&fdset); ++ tv.tv_sec=0; ++ tv.tv_usec=0; ++ ++ /* I like select */ ++ while(select(d->cdda_fd+1,&fdset,NULL,NULL,&tv)==1){ ++ ++ sg_hd->twelve_byte = 0; ++ sg_hd->result = 0; ++ sg_hd->reply_len = SG_OFF; ++ read(d->cdda_fd, sg_hd, 1); ++ ++ /* reset for select */ ++ FD_ZERO(&fdset); ++ FD_SET(d->cdda_fd,&fdset); ++ tv.tv_sec=0; ++ tv.tv_usec=0; ++ if(!flag && d->report_all) ++ cdmessage(d,"Clearing previously returned data from SCSI buffer\n"); ++ flag=1; ++ } ++} ++ ++static void sg2_tweak_SG_buffer(cdrom_drive *d){ + int table,reserved; + char buffer[256]; + +@@ -58,74 +343,47 @@ + if(ioctl(d->cdda_fd,SG_SET_COMMAND_Q,&reserved)){ + cdmessage(d,"\tCouldn't disable command queue! Continuing anyway...\n"); + } +- + } + +-static void reset_scsi(cdrom_drive *d){ +- int arg; +- d->enable_cdda(d,0); +- +- cdmessage(d,"sending SG SCSI reset... "); +- if(ioctl(d->cdda_fd,SG_SCSI_RESET,&arg)) +- cdmessage(d,"FAILED: EBUSY\n"); +- else +- cdmessage(d,"OK\n"); +- +- d->enable_cdda(d,1); +-} ++/* process a complete scsi command. */ + +-static void clear_garbage(cdrom_drive *d){ +- fd_set fdset; +- struct timeval tv; +- struct sg_header *sg_hd=(struct sg_header *)d->sg; +- int flag=0; ++static void sg2_setup_scsi_cmd(cdrom_drive *d, ++ char *cmdp, ++ unsigned int cmd_len, ++ unsigned int in_size, ++ unsigned int out_size) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_header *hdr = (struct sg_header *)sgi->hdr; + +- /* clear out any possibly preexisting garbage */ +- FD_ZERO(&fdset); +- FD_SET(d->cdda_fd,&fdset); +- tv.tv_sec=0; +- tv.tv_usec=0; ++ sgi->cmdp = (char *)hdr + sizeof (struct sg_header); ++ memcpy(sgi->cmdp, cmdp, cmd_len); + +- /* I like select */ +- while(select(d->cdda_fd+1,&fdset,NULL,NULL,&tv)==1){ +- +- sg_hd->twelve_byte = 0; +- sg_hd->result = 0; +- sg_hd->reply_len = SG_OFF; +- read(d->cdda_fd, sg_hd, 1); ++ sgi->dxferp = sgi->cmdp + cmd_len; ++ memset(sgi->dxferp, sgi->bytefill, sgi->dxferp_max_buffer_len - cmd_len); + +- /* reset for select */ +- FD_ZERO(&fdset); +- FD_SET(d->cdda_fd,&fdset); +- tv.tv_sec=0; +- tv.tv_usec=0; +- if(!flag && d->report_all) +- cdmessage(d,"Clearing previously returned data from SCSI buffer\n"); +- flag=1; +- } ++ sgi->in_size = in_size; ++ sgi->out_size = out_size; + } + +-/* process a complete scsi command. */ +-static int handle_scsi_cmd(cdrom_drive *d, +- unsigned int cmd_len, +- unsigned int in_size, +- unsigned int out_size, +- +- unsigned char bytefill, +- int bytecheck){ ++static int sg2_handle_scsi_cmd(cdrom_drive *d) { + int status = 0; +- struct sg_header *sg_hd=(struct sg_header *)d->sg; +- long writebytes=SG_OFF+cmd_len+in_size; ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_header *sg_hd = (struct sg_header *)sgi->hdr; ++ ++ int out_size = sgi->out_size; ++ int in_size = sgi->in_size; ++ ++ long writebytes = (int)(sg_hd) + SG_OFF + sgi->cmd_len + sgi->in_size; + + /* generic scsi device services */ + + /* clear out any possibly preexisting garbage */ +- clear_garbage(d); ++ sg2_clear_garbage(d); + +- memset(sg_hd,0,sizeof(sg_hd)); +- sg_hd->twelve_byte = cmd_len == 12; ++ memset(sg_hd,0, SG_OFF); ++ sg_hd->twelve_byte = sgi->cmd_len == 12; + sg_hd->result = 0; +- sg_hd->reply_len = SG_OFF + out_size; ++ sg_hd->reply_len = SG_OFF + sgi->out_size; + + /* The following is one of the scariest hacks I've ever had to use. + The idea is this: We want to know if a command fails. The +@@ -135,8 +393,8 @@ + length for a command that doesn't take data) such that we can + tell if the command failed. Scared yet? */ + +- if(bytecheck && out_size>in_size){ +- memset(d->sg_buffer+cmd_len+in_size,bytefill,out_size-in_size); ++ if(sgi->bytecheck && out_size>in_size){ ++ /* the memset for this is done in sg2_setup_scsi_cmd() */ + /* the size does not remove cmd_len due to the way the kernel + driver copies buffers */ + writebytes+=(out_size-in_size); +@@ -224,40 +482,10 @@ + if(errno==0)errno=EIO; + return(TR_EREAD); + } +- +- if(sg_hd->sense_buffer[0]){ +- char key=sg_hd->sense_buffer[2]&0xf; +- char ASC=sg_hd->sense_buffer[12]; +- char ASCQ=sg_hd->sense_buffer[13]; +- switch(key){ +- case 0: +- if(errno==0)errno=EIO; +- return(TR_UNKNOWN); +- case 1: +- break; +- case 2: +- if(errno==0)errno=EBUSY; +- return(TR_BUSY); +- case 3: +- if(ASC==0x0C && ASCQ==0x09){ +- /* loss of streaming */ +- if(errno==0)errno=EIO; +- return(TR_STREAMING); +- }else{ +- if(errno==0)errno=EIO; +- return(TR_MEDIUM); +- } +- case 4: +- if(errno==0)errno=EIO; +- return(TR_FAULT); +- case 5: +- if(errno==0)errno=EINVAL; +- return(TR_ILLEGAL); +- default: +- if(errno==0)errno=EIO; +- return(TR_UNKNOWN); +- } +- } ++ ++ status = check_sbp_error(sg_hd->sense_buffer); ++ if (status) ++ return status; + + /* still not foolproof; the following doesn't guarantee that we got + all the data, just that the command was not rejected. */ +@@ -266,10 +494,11 @@ + commands still get through. Perhaps no data comes back even + though the target reports success? */ + +- if(bytecheck && in_size+cmd_lenbytecheck && sgi->in_size+sgi->cmd_lenout_size){ + long i,flag=0; +- for(i=in_size;isg_buffer[i]!=bytefill){ ++ for(i=sgi->in_size; iout_size; i++) ++ /* XXX check this offset */ ++ if((sgi->dxferp[i])!=(sgi->bytefill)){ + flag=1; + break; + } +@@ -284,61 +513,67 @@ + return(0); + } + +-/* Group 1 (10b) command */ ++void sg2_init_sg_info(cdrom_drive *d) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_header *hdr; + +-static int mode_sense_atapi(cdrom_drive *d,int size,int page){ +- memcpy(d->sg_buffer, +- (char []) {0x5A, /* MODE_SENSE */ +- 0x00, /* reserved */ +- 0x00, /* page */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* MSB (0) */ +- 0, /* sizeof(modesense - SG_OFF) */ +- 0}, /* reserved */ +- 10); +- +- d->sg_buffer[1]=d->lun<<5; +- d->sg_buffer[2]=0x3F&page; +- d->sg_buffer[8]=size+4; ++ hdr = calloc(sizeof (struct sg_header)+sgi->dxferp_max_buffer_len, 1); + +- if (handle_scsi_cmd (d, 10, 0, size+4,'\377',1)) return(1); ++ sgi->cmdp = (char *)hdr + sizeof (struct sg_header); ++ sgi->cmdp_buffer_len = 0; + +- { +- char *b=d->sg_buffer; +- if(b[0])return(1); /* Handles only up to 256 bytes */ +- if(b[6])return(1); /* Handles only up to 256 bytes */ +- +- b[0]=b[1]-3; +- b[1]=b[2]; +- b[2]=b[3]; +- b[3]=b[7]; ++ sgi->bytefill = '\xff'; ++ sgi->bytecheck = 1; + +- memmove(b+4,b+8,size); +- } +- return(0); ++ sgi->setup_scsi_cmd = sg2_setup_scsi_cmd; ++ sgi->handle_scsi_cmd = sg2_handle_scsi_cmd; ++ ++ sg2_tweak_SG_buffer(d); ++ ++ // sgi->dxferp = hdr + sizeof (struct sg_header); ++ sgi->dxferp = NULL; ++ sgi->dxferp_buffer_len = 0; ++} ++ ++static int mode_sense_atapi(cdrom_drive *d, int size, int page) { ++ char *buffer; ++ ++ ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SENSE_10(page,size), 10, 0, size); ++ ++ buffer = ((struct sg_info *)d->sg)->dxferp; ++#if 0 ++ buffer[1]=d->lun<<5; ++#endif ++ ++ if (((struct sg_info *)d->sg)->handle_scsi_cmd(d)) ++ return 1; ++ ++ if(buffer[0])return(1); /* Handles only up to 256 bytes */ ++ if(buffer[6])return(1); /* Handles only up to 256 bytes */ ++ ++ buffer[0]=buffer[1]-3; ++ buffer[1]=buffer[2]; ++ buffer[2]=buffer[3]; ++ buffer[3]=buffer[7]; ++ ++ memmove(buffer+4,buffer+8,size); ++ return 0; + } + + /* group 0 (6b) command */ + + static int mode_sense_scsi(cdrom_drive *d,int size,int page){ +- memcpy(d->sg_buffer, +- (char []) {0x1A, /* MODE_SENSE */ +- 0x00, /* return block descriptor/lun */ +- 0x00, /* page */ +- 0, /* reserved */ +- 0, /* sizeof(modesense - SG_OFF) */ +- 0}, /* control */ +- 6); ++ char *buffer; ++ ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SENSE_6(page, size), 6, 0, size); + +- d->sg_buffer[1]=d->lun<<5; +- d->sg_buffer[2]=(0x3F&page); +- d->sg_buffer[4]=size; +- +- if (handle_scsi_cmd (d, 6, 0, size, '\377',1)) return(1); +- return(0); ++ buffer = ((struct sg_info *)d->sg)->dxferp; ++#if 0 ++ buffer[1]=d->lun<<5; ++#endif ++ ++ if (((struct sg_info *)d->sg)->handle_scsi_cmd(d)) ++ return 1; ++ return 0; + } + + static int mode_sense(cdrom_drive *d,int size,int page){ +@@ -347,80 +582,77 @@ + return(mode_sense_scsi(d,size,page)); + } + +-static int mode_select(cdrom_drive *d,int density,int secsize){ +- /* short circut the way Heiko does it; less flexible, but shorter */ +- if(d->is_atapi){ +- unsigned char *mode = d->sg_buffer + 18; ++static int atapi_mode_select(cdrom_drive *d, int density, int secsize) { ++ unsigned char *mode; + +- memcpy(d->sg_buffer, +- (char []) { 0x55, /* MODE_SELECT */ +- 0x10, /* no save page */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 0, /* reserved */ +- 12, /* sizeof(mode) */ +- 0, /* reserved */ +- +- /* mode parameter header */ +- 0, 0, 0, 0, 0, 0, 0, +- 8, /* Block Descriptor Length */ +- +- /* descriptor block */ +- 0, /* Density Code */ +- 0, 0, 0, /* # of Blocks */ +- 0, /* reserved */ +- 0, 0, 0},/* Blocklen */ +- 26); +- +- d->sg_buffer[1]|=d->lun<<5; +- +- /* prepare to read cds in the previous mode */ +- mode [0] = density; +- mode [6] = secsize >> 8; /* block length "msb" */ +- mode [7] = secsize & 0xFF; /* block length lsb */ ++ ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SELECT_10, 10, 16, 0); ++ memcpy(((struct sg_info *)d->sg)->dxferp,(char []) { ++ /* mode parameter header */ ++ 0, 0, 0, 0, 0, 0, 0, ++ 8, /* Block Descriptor Length */ ++ /* descriptor block */ ++ 0, /* Density Code */ ++ 0, 0, 0, /* # of Blocks */ ++ 0, /* reserved */ ++ 0, 0, 0},/* Blocklen */ ++ 16); ++ ++ mode = ((struct sg_info *)d->sg)->dxferp; ++#if 0 ++ mode[1] |= d->lun << 5; ++#endif ++ /* prepare to read cds in the previous mode */ ++ mode[8] = density; ++ mode[14] = secsize >> 8; /* block length "msb" */ ++ mode[15] = secsize & 0xFF; /* block length lsb */ ++ ++ /* do the scsi cmd */ ++ return ((struct sg_info *)d->sg)->handle_scsi_cmd(d); ++} ++ ++static int scsi_mode_select(cdrom_drive *d, int density, int secsize) { ++ unsigned char *mode; ++ ++ ((struct sg_info *)d->sg)->setup_scsi_cmd(d, SCSI_MODE_SELECT_6, 6, 12, 0); ++ memcpy(((struct sg_info *)d->sg)->dxferp,(char []) { ++ /* mode section */ ++ 0, ++ 0, 0, ++ 8, /* Block Descriptor Length */ ++ 0, /* Density Code */ ++ 0, 0, 0, /* # of Blocks */ ++ 0, /* reserved */ ++ 0, 0, 0},/* Blocklen */ ++ 12); ++ ++ /* prepare to read cds in the previous mode */ ++ mode = ((struct sg_info *)d->sg)->dxferp; ++ mode [4] = density; ++ mode [10] = secsize >> 8; /* block length "msb" */ ++ mode [11] = secsize & 0xFF; /* block length lsb */ + + /* do the scsi cmd */ +- return(handle_scsi_cmd (d,10, 16, 0,0,0)); +- +- }else{ +- unsigned char *mode = d->sg_buffer + 10; +- +- memcpy(d->sg_buffer, +- (char []) { 0x15, /* MODE_SELECT */ +- 0x10, /* no save page */ +- 0, /* reserved */ +- 0, /* reserved */ +- 12, /* sizeof(mode) */ +- 0, /* reserved */ +- /* mode section */ +- 0, +- 0, 0, +- 8, /* Block Descriptor Length */ +- 0, /* Density Code */ +- 0, 0, 0, /* # of Blocks */ +- 0, /* reserved */ +- 0, 0, 0},/* Blocklen */ +- 18); +- +- /* prepare to read cds in the previous mode */ +- mode [0] = density; +- mode [6] = secsize >> 8; /* block length "msb" */ +- mode [7] = secsize & 0xFF; /* block length lsb */ ++ return ((struct sg_info *)d->sg)->handle_scsi_cmd(d); ++} + +- /* do the scsi cmd */ +- return(handle_scsi_cmd (d,6, 12, 0,0,0)); +- } ++static int mode_select(cdrom_drive *d, int density, int secsize) { ++ /* short circut the way Heiko does it; less flexible, but shorter */ ++ if (d->is_atapi) ++ return atapi_mode_select(d, density, secsize); ++ return scsi_mode_select(d, density, secsize); + } + + /* get current sector size from SCSI cdrom drive */ + static unsigned int get_orig_sectorsize(cdrom_drive *d){ +- if(mode_sense(d,12,0x01))return(-1); ++ if (mode_sense(d,12,0x01)) ++ return -1; ++ ++ d->orgdens = ((struct sg_info *)d->sg)->dxferp[4]; ++ ++ d->orgsize = (int)(((struct sg_info *)d->sg)->dxferp[10]<<8); ++ d->orgsize += (int)((struct sg_info *)d->sg)->dxferp[11]; + +- d->orgdens = d->sg_buffer[4]; +- return(d->orgsize = ((int)(d->sg_buffer[10])<<8)+d->sg_buffer[11]); ++ return d->orgsize; + } + + /* switch CDROM scsi drives to given sector size */ +@@ -463,23 +695,23 @@ + fails on at least one Kodak drive. */ + + static int scsi_read_toc (cdrom_drive *d){ ++ struct sg_info *sgi = (struct sg_info *)d->sg; + int i,first,last; + unsigned tracks; +- +- /* READTOC, MSF format flag, res, res, res, res, Start track, len msb, +- len lsb, flags */ ++ scsi_TOC *toc; + + /* read the header first */ +- memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 1, 0, 12, 0}, 10); +- d->sg_buffer[1]=d->lun<<5; +- +- if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ ++ sgi->setup_scsi_cmd(d, SCSI_READ_TOC(1), 10, 0, 12); ++#if 0 ++ sgi->dxferp[1] = d->lun << 5; ++#endif ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"004: Unable to read table of contents header\n"); + return(-4); + } + +- first=d->sg_buffer[2]; +- last=d->sg_buffer[3]; ++ first = sgi->dxferp[2]; ++ last = sgi->dxferp[3]; + tracks=last-first+1; + + if (last > MAXTRK || first > MAXTRK || last<0 || first<0) { +@@ -488,335 +720,208 @@ + } + + for (i = first; i <= last; i++){ +- memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); +- d->sg_buffer[1]=d->lun<<5; +- d->sg_buffer[6]=i; ++ sgi->setup_scsi_cmd(d, SCSI_READ_TOC(i), 10, 0, 12); ++#if 0 ++ sgi->dxferp[1] = d->lun << 5; ++#endif + +- if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"005: Unable to read table of contents entry\n"); + return(-5); + } +- { +- scsi_TOC *toc=(scsi_TOC *)(d->sg_buffer+4); +- +- d->disc_toc[i-first].bFlags=toc->bFlags; +- d->disc_toc[i-first].bTrack=i; +- d->disc_toc[i-first].dwStartSector= d->adjust_ssize * +- (((int)(toc->start_MSB)<<24) | +- (toc->start_1<<16)| +- (toc->start_2<<8)| +- (toc->start_LSB)); +- } +- } ++ toc = (scsi_TOC *)(sgi->dxferp+4); ++ d->disc_toc[i-first].bFlags = toc->bFlags; ++ d->disc_toc[i-first].bTrack = i; ++ d->disc_toc[i-first].dwStartSector = ++ d->adjust_ssize * ( ++ ((int)(toc->start_MSB)<<24) | (toc->start_1 << 16) | ++ (toc->start_2 << 8) | (toc->start_LSB) ++ ); ++ } ++ ++ sgi->setup_scsi_cmd(d, SCSI_READ_TOC(0xAA), 10, 0, 12); ++#if 0 ++ sgi->dxferp[1] = d->lun << 5; ++#endif + +- memcpy(d->sg_buffer, (char []){ 0x43, 0, 0, 0, 0, 0, 0, 0, 12, 0}, 10); +- d->sg_buffer[1]=d->lun<<5; +- d->sg_buffer[6]=0xAA; +- +- if (handle_scsi_cmd (d,10, 0, 12,'\377',1)){ ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"002: Unable to read table of contents lead-out\n"); + return(-2); + } +- { +- scsi_TOC *toc=(scsi_TOC *)(d->sg_buffer+4); +- +- d->disc_toc[i-first].bFlags=toc->bFlags; +- d->disc_toc[i-first].bTrack=0xAA; +- d->disc_toc[i-first].dwStartSector= d->adjust_ssize * +- (((int)(toc->start_MSB)<<24) | +- (toc->start_1<<16)| +- (toc->start_2<<8)| +- (toc->start_LSB)); +- } ++ ++ toc = (scsi_TOC *)(sgi->dxferp+4); ++ d->disc_toc[i-first].bFlags = toc->bFlags; ++ d->disc_toc[i-first].bTrack = 0xAA; ++ d->disc_toc[i-first].dwStartSector = ++ d->adjust_ssize * ( ++ ((int)(toc->start_MSB)<<24) | (toc->start_1 << 16) | ++ (toc->start_2 << 8) | (toc->start_LSB) ++ ); + + d->cd_extra = FixupTOC(d,tracks+1); /* include lead-out */ +- return(tracks); ++ return tracks; + } + + /* a contribution from Boris for IMS cdd 522 */ + /* check this for ACER/Creative/Foo 525,620E,622E, etc? */ + static int scsi_read_toc2 (cdrom_drive *d){ +- u_int32_t foo,bar; ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ u_int32_t msb,lsb; + + int i; + unsigned tracks; + +- memcpy(d->sg_buffer, (char[]){ 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10); +- d->sg_buffer[5]=1; +- d->sg_buffer[8]=255; +- +- if (handle_scsi_cmd (d,10, 0, 256,'\377',1)){ ++ sgi->setup_scsi_cmd(d, CDD522_READ_TOC(1), 10, 0, 256); ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"004: Unable to read table of contents header\n"); + return(-4); + } + + /* copy to our structure and convert start sector */ +- tracks = d->sg_buffer[1]; ++ tracks = sgi->dxferp[1]; + if (tracks > MAXTRK) { + cderror(d,"003: CDROM reporting illegal number of tracks\n"); + return(-3); + } + + for (i = 0; i < tracks; i++){ +- memcpy(d->sg_buffer, (char[]){ 0xe5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 10); +- d->sg_buffer[5]=i+1; +- d->sg_buffer[8]=255; ++ sgi->setup_scsi_cmd(d, CDD522_READ_TOC(i+1), 10, 0, 256); + +- if (handle_scsi_cmd (d,10, 0, 256,'\377',1)){ ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"005: Unable to read table of contents entry\n"); + return(-5); + } + +- d->disc_toc[i].bFlags = d->sg_buffer[10]; ++ d->disc_toc[i].bFlags = sgi->dxferp[10]; + d->disc_toc[i].bTrack = i + 1; + +- d->disc_toc[i].dwStartSector= d->adjust_ssize * +- (((signed char)(d->sg_buffer[2])<<24) | +- (d->sg_buffer[3]<<16)| +- (d->sg_buffer[4]<<8)| +- (d->sg_buffer[5])); ++ d->disc_toc[i].dwStartSector = d->adjust_ssize * ( ++ ((signed char)(sgi->dxferp[2])<<24) | ++ (sgi->dxferp[3]<<16) | ++ (sgi->dxferp[4]<<8) | ++ (sgi->dxferp[5]) ++ ); + } + + d->disc_toc[i].bFlags = 0; + d->disc_toc[i].bTrack = i + 1; +- memcpy (&foo, d->sg_buffer+2, 4); +- memcpy (&bar, d->sg_buffer+6, 4); +- d->disc_toc[i].dwStartSector = d->adjust_ssize * (be32_to_cpu(foo) + +- be32_to_cpu(bar)); +- +- d->disc_toc[i].dwStartSector= d->adjust_ssize * +- ((((signed char)(d->sg_buffer[2])<<24) | +- (d->sg_buffer[3]<<16)| +- (d->sg_buffer[4]<<8)| +- (d->sg_buffer[5]))+ +- +- ((((signed char)(d->sg_buffer[6])<<24) | +- (d->sg_buffer[7]<<16)| +- (d->sg_buffer[8]<<8)| +- (d->sg_buffer[9])))); +- ++ memcpy (&msb, sgi->dxferp+2, 4); ++ memcpy (&lsb, sgi->dxferp+6, 4); ++ d->disc_toc[i].dwStartSector = d->adjust_ssize * ++ (be32_to_cpu(msb) + be32_to_cpu(lsb)); ++ ++ d->disc_toc[i].dwStartSector= d->adjust_ssize * ( ++ ((((signed char)(sgi->dxferp[2])<<24) | ++ (sgi->dxferp[3]<<16) | ++ (sgi->dxferp[4]<<8) | ++ (sgi->dxferp[5]) ++ ) + ( ++ ((signed char)(sgi->dxferp[6])<<24) | ++ (sgi->dxferp[7]<<16) | ++ (sgi->dxferp[8]<<8) | ++ (sgi->dxferp[9]))) ++ ); + + d->cd_extra = FixupTOC(d,tracks+1); +- return(tracks); ++ return tracks; + } + + /* These do one 'extra' copy in the name of clean code */ + +-static int i_read_28 (cdrom_drive *d, void *p, long begin, long sectors){ ++static int generic_scsi_read(cdrom_drive *d, void *p, long begin, long sectors, ++ char *read_cmd, int len, int in_size, int out_size) { ++ struct sg_info *sgi = (struct sg_info *)d->sg; + int ret; +- memcpy(d->sg_buffer,(char []){0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; + +- d->sg_buffer[1]|=d->lun<<5; ++ sgi->setup_scsi_cmd(d, read_cmd, len, in_size, out_size); ++#if 0 ++ sgi->dxferp[1] = d->lun << 5; ++#endif + +- 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((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++ ret = sgi->handle_scsi_cmd(d); ++ if (ret) ++ return ret; ++ if (p) ++ memcpy(p, sgi->dxferp, sectors * CD_FRAMESIZE_RAW); ++ return 0; + } + +-static int i_read_A8 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; +- +- d->sg_buffer[1]|=d->lun<<5; +- +- d->sg_buffer[3] = (begin >> 16) & 0xFF; +- d->sg_buffer[4] = (begin >> 8) & 0xFF; +- d->sg_buffer[5] = begin & 0xFF; +- d->sg_buffer[9] = sectors; +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_28(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ SCSI_READ_10(d->fua, begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_D4_10 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; +- +- d->sg_buffer[1]|=d->lun<<5; +- 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((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_A8(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ SCSI_READ_12(d->fua, begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_D4_12 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xd4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; +- +- d->sg_buffer[1]|=d->lun<<5; +- d->sg_buffer[3] = (begin >> 16) & 0xFF; +- d->sg_buffer[4] = (begin >> 8) & 0xFF; +- d->sg_buffer[5] = begin & 0xFF; +- d->sg_buffer[9] = sectors; +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_D4_10(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ D4_READ_10(begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_D5 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xd5, 0, 0, 0, 0, 0, 0, 0, 0, 0},10); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; +- +- d->sg_buffer[1]|=d->lun<<5; +- 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((ret=handle_scsi_cmd(d,10,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_D4_12(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ D4_READ_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_D8 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xd8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},12); +- +- if(d->fua) +- d->sg_buffer[1]=0x08; +- +- d->sg_buffer[1]|=d->lun<<5; +- d->sg_buffer[3] = (begin >> 16) & 0xFF; +- d->sg_buffer[4] = (begin >> 8) & 0xFF; +- d->sg_buffer[5] = begin & 0xFF; +- d->sg_buffer[9] = sectors; +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_D5(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ D5_READ_10(begin, sectors), 10, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_mmc (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- /* if(begin<=12007 && begin+sectors>12000){ +- errno=EIO; +- return(TR_ILLEGAL); +- }*/ +- +- memcpy(d->sg_buffer,(char []){0xbe, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 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((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_D8(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ D8_READ_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_mmc2 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xbe, 0, 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((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_mmc(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ READ_CD_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); + } + +-static int i_read_mmc3 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xbe, 4, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); ++static int i_read_mmc2(cdrom_drive *d, void *p, long begin, long sectors){ ++ char cmd[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((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++ memcpy(cmd, READ_CD_12(begin, sectors), 12); ++ cmd[9] = 0xf8; ++ return generic_scsi_read(d, p, begin, sectors, ++ cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); + } + +-/* straight from the MMC3 spec */ +-static inline void LBA_to_MSF(long lba, +- unsigned char *M, +- unsigned char *S, +- unsigned char *F){ +- if(lba>=-150){ +- *M=(lba+150)/(60*75); +- lba-=(*M)*60*75; +- *S=(lba+150)/75; +- lba-=(*S)*75; +- *F=(lba+150); +- }else{ +- *M=(lba+450150)/(60*75); +- lba-=(*M)*60*75; +- *S=(lba+450150)/75; +- lba-=(*S)*75; +- *F=(lba+450150); +- } +-} +- +- +-static int i_read_msf (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xb9, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0},12); ++static int i_read_mmc3(cdrom_drive *d, void *p, long begin, long sectors){ ++ char cmd[12]; + +- LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); +- LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); ++ memcpy(cmd, READ_CD_12(begin, sectors), 12); ++ cmd[1] = 4; ++ cmd[9] = 0xf8; ++ return generic_scsi_read(d, p, begin, sectors, ++ cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); ++} + +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++static int i_read_msf(cdrom_drive *d, void *p, long begin, long sectors){ ++ return generic_scsi_read(d, p, begin, sectors, ++ READ_CD_MSF_12(begin, sectors), 12, 0, sectors * CD_FRAMESIZE_RAW); + } + + static int i_read_msf2 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xb9, 0, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); ++ char cmd[12]; + +- LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); +- LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); +- +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++ memcpy(cmd, READ_CD_MSF_12(begin, sectors), 12); ++ cmd[9] = 0xf8; ++ return generic_scsi_read(d, p, begin, sectors, ++ cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); + } + + static int i_read_msf3 (cdrom_drive *d, void *p, long begin, long sectors){ +- int ret; +- memcpy(d->sg_buffer,(char []){0xb9, 4, 0, 0, 0, 0, 0, 0, 0, 0xf8, 0, 0},12); ++ char cmd[12]; + +- LBA_to_MSF(begin,d->sg_buffer+3,d->sg_buffer+4,d->sg_buffer+5); +- LBA_to_MSF(begin+sectors,d->sg_buffer+6,d->sg_buffer+7,d->sg_buffer+8); +- +- if((ret=handle_scsi_cmd(d,12,0,sectors * CD_FRAMESIZE_RAW,'\177',1))) +- return(ret); +- if(p)memcpy(p,d->sg_buffer,sectors*CD_FRAMESIZE_RAW); +- return(0); ++ memcpy(cmd, READ_CD_MSF_12(begin, sectors), 12); ++ cmd[1] = 4; ++ cmd[9] = 0xf8; ++ return generic_scsi_read(d, p, begin, sectors, ++ cmd, 12, 0, sectors * CD_FRAMESIZE_RAW); + } + + static long scsi_read_map (cdrom_drive *d, void *p, long begin, long sectors, +@@ -824,6 +929,10 @@ + int retry_count,err; + char *buffer=(char *)p; + ++ struct sg_info *sgi = (struct sg_info *)d->sg; ++ struct sg_io_hdr *hdr = sgi->hdr; ++ unsigned char key, ASC, ASCQ; ++ + /* read d->nsectors at a time, max. */ + sectors=(sectors>d->nsectors?d->nsectors:sectors); + sectors=(sectors<1?1:sectors); +@@ -832,17 +941,32 @@ + + while(1) { + if((err=map(d,(p?buffer:NULL),begin,sectors))){ ++ /* Dunno if we even need this now that scsi_reset does it, ++ * but try to take "device is becoming ready" into account */ ++ key = hdr->sbp[2] & 0xf; ++ ASC = hdr->sbp[12]; ++ ASCQ = hdr->sbp[13]; ++ ++ if(key == 2 & ASC == 4 & ASCQ == 1) { ++ if(retry_count > MAX_RETRIES-1) { ++ char b[256]; ++ sprintf(b,"010: Unable to access sector %ld\n", ++ begin); ++ cderror(d,b); ++ return(-10); ++ } else { ++ retry_count++; ++ usleep(100); ++ continue; ++ } ++ } + if(d->report_all){ +- struct sg_header *sg_hd=(struct sg_header *)d->sg; + char b[256]; +- + sprintf(b,"scsi_read error: sector=%ld length=%ld retry=%d\n", + begin,sectors,retry_count); + cdmessage(d,b); + sprintf(b," Sense key: %x ASC: %x ASCQ: %x\n", +- (int)(sg_hd->sense_buffer[2]&0xf), +- (int)(sg_hd->sense_buffer[12]), +- (int)(sg_hd->sense_buffer[13])); ++ key, ASC, ASCQ); + cdmessage(d,b); + sprintf(b," Transport error: %s\n",strerror_tr[err]); + cdmessage(d,b); +@@ -852,9 +976,7 @@ + fprintf(stderr,"scsi_read error: sector=%ld length=%ld retry=%d\n", + begin,sectors,retry_count); + fprintf(stderr," Sense key: %x ASC: %x ASCQ: %x\n", +- (int)(sg_hd->sense_buffer[2]&0xf), +- (int)(sg_hd->sense_buffer[12]), +- (int)(sg_hd->sense_buffer[13])); ++ key, ASC, ASCQ); + fprintf(stderr," Transport error: %s\n",strerror_tr[err]); + fprintf(stderr," System error: %s\n",strerror(errno)); + } +@@ -1014,7 +1136,7 @@ + static int count_2352_bytes(cdrom_drive *d){ + long i; + for(i=2351;i>=0;i--) +- if(d->sg_buffer[i]!=(unsigned char)'\177') ++ if(((struct sg_info *)d->sg)->dxferp[i]!=(unsigned char)'\177') + return(((i+3)>>2)<<2); + + return(0); +@@ -1023,7 +1145,7 @@ + static int verify_nonzero(cdrom_drive *d){ + long i,flag=0; + for(i=0;i<2352;i++) +- if(d->sg_buffer[i]!=0){ ++ if(((struct sg_info *)d->sg)->dxferp[i]!=0){ + flag=1; + break; + } +@@ -1307,7 +1429,17 @@ + return; + } + +-static int check_atapi(cdrom_drive *d){ ++static int check_sgio(cdrom_drive *d) { ++ int fd = d->cdda_fd; ++ ++#ifdef SG_IO ++ if (fd == check_fd_sgio(fd)) ++ return 1; ++#endif ++ return 0; ++} ++ ++static int check_atapi(cdrom_drive *d, int using_sgio){ + int atapiret=-1; + int fd = d->cdda_fd; /* this is the correct fd (not ioctl_fd), as the + generic device is the device we need to check */ +@@ -1321,7 +1453,7 @@ + if(atapiret==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)) ++ if (!using_sgio && ioctl(fd,SG_SET_TRANSFORM,0)) + cderror(d,"\tCouldn't disable kernel command translation layer\n"); + d->is_atapi=1; + }else{ +@@ -1340,7 +1472,7 @@ + d->is_mmc=0; + if(mode_sense(d,22,0x2A)==0){ + +- b=d->sg_buffer; ++ b=((struct sg_info *)d->sg)->dxferp; + b+=b[3]+4; + + if((b[0]&0x3F)==0x2A){ +@@ -1380,21 +1512,27 @@ + } + + /* request vendor brand and model */ +-unsigned char *scsi_inquiry(cdrom_drive *d){ +- memcpy(d->sg_buffer,(char[]){ 0x12,0,0,0,56,0},6); ++unsigned char *scsi_inquiry(cdrom_drive *d) { ++ static char ret[56]; ++ struct sg_info *sgi = (struct sg_info *)d->sg; + +- if(handle_scsi_cmd(d,6, 0, 56,'\377',1)) { ++ if (sgi->hdr == NULL) ++ scsi_init_drive(d); ++ ++ sgi->setup_scsi_cmd(d, SCSI_INQUIRY_6(56), 6, 0, 56); ++ if (sgi->handle_scsi_cmd(d)) { + cderror(d,"008: Unable to identify CDROM model\n"); +- return(NULL); ++ return NULL; + } +- return (d->sg_buffer); ++ memcpy(ret, ((struct sg_info *)d->sg)->dxferp, 56); ++ return ret; + } + +- + int scsi_init_drive(cdrom_drive *d){ +- int ret; ++ int ret, is_sgio; + +- check_atapi(d); ++ is_sgio = check_sgio(d); ++ check_atapi(d, is_sgio); + check_mmc(d); + + /* generic Sony type defaults; specialize from here */ +@@ -1451,15 +1589,16 @@ + if(d->tracks<1) + return(d->tracks); + +- tweak_SG_buffer(d); + d->opened=1; + + if((ret=verify_read_command(d)))return(ret); + check_fua_bit(d); + + d->error_retry=1; +- d->sg=realloc(d->sg,d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128); +- d->sg_buffer=d->sg+SG_OFF; ++#if 0 ++ ((struct sg_info *)d->sg)=realloc(((struct sg_info *)d->sg),d->nsectors*CD_FRAMESIZE_RAW + SG_OFF + 128); ++ ((struct sg_info *)d->sg)_buffer=((struct sg_info *)d->sg)+SG_OFF; ++#endif + d->report_all=1; + return(0); + } +--- cdparanoia-III-alpha9.8/interface/scsi_cmds.h.sgio 2004-03-30 12:46:03.306332320 -0500 ++++ cdparanoia-III-alpha9.8/interface/scsi_cmds.h 2004-03-30 14:09:53.760587032 -0500 +@@ -0,0 +1,197 @@ ++/****************************************************************** ++ * CopyPolicy: GNU General Public License version 2 ++ * Copyright 2004 Peter Jones ++ * ++ * macros to generate scsi commands. ++ * ++ ******************************************************************/ ++ ++#ifndef _SCSI_CMDS_H ++#define _SCSI_CMDS_H 1 ++#include ++ ++/* from the MMC3 spec, rewritten as seperate macros */ ++#define LBA_to_M(lba) (lba>=-150?((lba+150)/(60*75)):((lba+450150)/(60*75))) ++#define LBA_to_S(lba) (lba>=-150?((lba+150)/75):((lba+450150)/75)) ++#define LBA_to_F(lba) (lba>=-150?(lba+150):(lba+450150)) ++ ++/* Group 1 (10b) command */ ++#define SCSI_TWELVE_BYTE(a,b,c,d,e,f,g,h,i,j,k,l) ((char []) {a,b,c,d,e,f,g,h,i,j,k,l}) ++#define SCSI_READ_12(fua, a, l) SCSI_TWELVE_BYTE( \ ++ READ_12, /* READ_10 */ \ ++ (fua & 1) << 3, /* force unit access */ \ ++ (a >> 24) & 0xff, /* lba byte 3 */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ (l >> 24) & 0xff, /* len byte 3 */ \ ++ (l >> 16) & 0xff, /* len byte 2 */ \ ++ (l >> 8) & 0xff, /* len byte 1 */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0 /* control */ \ ++) ++#define D4_READ_12(a, l) SCSI_TWELVE_BYTE( \ ++ 0xD4, /* 0xD4 */ \ ++ 0, /* lun */ \ ++ 0, /* ? */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ 0, /* ? */ \ ++ 0, /* ? */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0, 0 /* ? */ \ ++) ++#define D8_READ_12(a, l) SCSI_TWELVE_BYTE( \ ++ 0xD8, /* 0xD4 */ \ ++ 0, /* lun */ \ ++ 0, /* ? */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ 0, /* ? */ \ ++ 0, /* ? */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0, 0 /* ? */ \ ++) ++#define READ_CD_12(a, l) SCSI_TWELVE_BYTE( \ ++ 0xBE, /* 0xD4 */ \ ++ 0, /* ? */ \ ++ (a >> 24) & 0xff, /* lba byte 3 */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ (l >> 16) & 0xff, /* len byte 2 */ \ ++ (l >> 8) & 0xff, /* len byte 1 */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 10, /* ecc */ \ ++ 0, 0 /* ? */ \ ++) ++#define READ_CD_MSF_12(a, l) SCSI_TWELVE_BYTE( \ ++ 0xB9, /* 0xD4 */ \ ++ 0, /* ? */ \ ++ 0, /* ? */ \ ++ LBA_to_M((a)), /* start M */ \ ++ LBA_to_S((a)), /* start S */ \ ++ LBA_to_F((a)), /* start F */ \ ++ LBA_to_M((a)+(l)), /* start M */ \ ++ LBA_to_S((a)+(l)), /* start S */ \ ++ LBA_to_F((a)+(l)), /* start F */ \ ++ 10, /* ecc */ \ ++ 0, 0 /* ? */ \ ++) ++ ++#define SCSI_TEN_BYTE(a,b,c,d,e,f,g,h,i,j) ((char []) {a,b,c,d,e,f,g,h,i,j}) ++#define SCSI_MODE_SENSE_10(page, size) SCSI_TEN_BYTE( \ ++ MODE_SENSE_10, /* MODE_SENSE */ \ ++ 0x00, /* reserved */ \ ++ page & 0x3F, /* page */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* MSB (0) */ \ ++ size, /* sizeof(modesense - SG_OFF) */ \ ++ 0 /* reserved */ \ ++) ++#define SCSI_MODE_SELECT_10 SCSI_TEN_BYTE( \ ++ MODE_SELECT_10, /* MODE_SELECT */ \ ++ 0x10, /* no save page */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 12, /* sizeof(mode) */ \ ++ 0 /* reserved */ \ ++) ++#define SCSI_READ_TOC(track_number) SCSI_TEN_BYTE( \ ++ READ_TOC, /* READ_TOC */ \ ++ 0, /* MSF format */ \ ++ 0, \ ++ 0, \ ++ 0, \ ++ 0, \ ++ track_number, /* start track */ \ ++ 0, /* len msb */ \ ++ 12, /* len lsb */ \ ++ 0 /* flags */ \ ++) ++/* a contribution from Boris for IMS cdd 522 */ ++/* check this for ACER/Creative/Foo 525,620E,622E, etc? */ ++#define CDD522_READ_TOC(track_number) SCSI_TEN_BYTE( \ ++ 0xE5, /* CDD522_READ_TOC */ \ ++ 0, 0, 0, 0, /* res */ \ ++ track_number, /* start track */ \ ++ 0, 0, 0, 0 /* ? */ \ ++) ++#define SCSI_READ_10(fua, a, l) SCSI_TEN_BYTE( \ ++ READ_10, /* READ_10 */ \ ++ (fua?8:0), /* force unit access */ \ ++ (a >> 24) & 0xff, /* lba byte 3 */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ (l >> 8) & 0xff, /* len byte 1 */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0 /* control */ \ ++) ++#define D4_READ_10(a, l) SCSI_TEN_BYTE( \ ++ 0xD4, /* 0xD4 */ \ ++ 0, /* ? */ \ ++ 0, /* ? */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ 0, /* ? */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0 /* control */ \ ++) ++#define D5_READ_10(a, l) SCSI_TEN_BYTE( \ ++ 0xD5, /* 0xD5 */ \ ++ 0, /* lun */ \ ++ 0, /* ? */ \ ++ (a >> 16) & 0xff, /* lba byte 2 */ \ ++ (a >> 8) & 0xff, /* lba byte 1 */ \ ++ a & 0xff, /* lba byte 0 */ \ ++ 0, /* reserved */ \ ++ 0, /* ? */ \ ++ l & 0xff, /* len byte 0 */ \ ++ 0 /* control */ \ ++) ++ ++ ++#define SCSI_SIX_BYTE(a,b,c,d,e,f) ((char []) {a,b,c,d,e,f}) ++#define SCSI_MODE_SENSE_6(page, size) SCSI_SIX_BYTE( \ ++ MODE_SENSE, /* MODE_SENSE */ \ ++ 0x00, /* return block descriptor/lun */ \ ++ page & 0x3F, /* page */ \ ++ 0, /* reserved */ \ ++ size, /* sizeof(modesense - SG_OFF) */ \ ++ 0 /* control */ \ ++) ++#define SCSI_MODE_SELECT_6 SCSI_SIX_BYTE( \ ++ MODE_SELECT, /* MODE_SELECT */ \ ++ 0x10, /* no save page */ \ ++ 0, /* reserved */ \ ++ 0, /* reserved */ \ ++ 12, /* sizeof(mode) */ \ ++ 0 /* reserved */ \ ++) ++#define SCSI_INQUIRY_6(len) SCSI_SIX_BYTE( \ ++ INQUIRY, /* INQUIRY */ \ ++ 0, 0, 0, /* ? */ \ ++ len, 0 /* len, ? */ \ ++) ++#define SCSI_TEST_UNIT_READY_6 SCSI_SIX_BYTE( \ ++ TEST_UNIT_READY,/* TEST_UNIT_READY */ \ ++ 0, 0, 0, 0, /* reserved */ \ ++ 0 /* control */ \ ++) ++#endif diff --git a/cdparanoia-III-alpha9.8.verbose.patch b/cdparanoia-III-alpha9.8.verbose.patch new file mode 100644 index 0000000..1fa1ea2 --- /dev/null +++ b/cdparanoia-III-alpha9.8.verbose.patch @@ -0,0 +1,24 @@ +--- cdparanoia-III-alpha9.8/main.c.verbose 2004-04-21 13:07:58.608136480 -0400 ++++ cdparanoia-III-alpha9.8/main.c 2004-04-21 13:09:04.660095056 -0400 +@@ -851,7 +851,7 @@ + if(verbose) + cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_PRINTIT); + else +- cdda_verbose_set(d,CDDA_MESSAGE_PRINTIT,CDDA_MESSAGE_FORGETIT); ++ cdda_verbose_set(d,CDDA_MESSAGE_FORGETIT,CDDA_MESSAGE_FORGETIT); + + /* possibly force hand on endianness of drive, sector request size */ + if(force_cdrom_endian!=-1){ +@@ -1032,10 +1032,12 @@ + paranoia_modeset(p,paranoia_mode); + if(force_cdrom_overlap!=-1)paranoia_overlapset(p,force_cdrom_overlap); + ++#if 0 + if(verbose) + cdda_verbose_set(d,CDDA_MESSAGE_LOGIT,CDDA_MESSAGE_LOGIT); + else + cdda_verbose_set(d,CDDA_MESSAGE_FORGETIT,CDDA_MESSAGE_FORGETIT); ++#endif + + paranoia_seek(p,cursor=first_sector,SEEK_SET); + diff --git a/cdparanoia-III-alpha9.8.verbosity3.patch b/cdparanoia-III-alpha9.8.verbosity3.patch new file mode 100644 index 0000000..be5df4f --- /dev/null +++ b/cdparanoia-III-alpha9.8.verbosity3.patch @@ -0,0 +1,21 @@ +--- cdparanoia-III-alpha9.8/interface/scan_devices.c.verbosity3 2004-07-06 23:22:03.000000000 -0400 ++++ cdparanoia-III-alpha9.8/interface/scan_devices.c 2004-07-06 23:22:03.000000000 -0400 +@@ -522,6 +522,7 @@ + d->ioctl_fd=fd; + d->bigendianp=-1; /* We don't know yet... */ + d->nsectors=-1; ++ d->messagedest=messagedest; + + d->interface=GENERIC_SCSI; + +--- cdparanoia-III-alpha9.8/report.c.verbosity3 1999-08-15 17:52:30.000000000 -0400 ++++ cdparanoia-III-alpha9.8/report.c 2004-07-06 23:22:03.000000000 -0400 +@@ -2,7 +2,7 @@ + #include "interface/cdda_interface.h" + + int quiet=0; +-int verbose=CDDA_MESSAGE_FORGETIT; ++int verbose=CDDA_MESSAGE_PRINTIT; + + void report(char *s){ + if(!quiet){ diff --git a/cdparanoia.spec b/cdparanoia.spec index 0770c76..7ccd2bc 100644 --- a/cdparanoia.spec +++ b/cdparanoia.spec @@ -3,13 +3,19 @@ Name: cdparanoia Version: %{realver} -Release: 21 +Release: 22 License: GPL Group: Applications/Multimedia Source: http://www.xiph.org/paranoia/download/%{name}-III-%{realver}.src.tgz Patch0: cdparanoia-III-alpha9.8.nostrip.patch Patch1: cdparanoia-III-alpha9.8.labels.patch Patch2: cdparanoia-III-alpha9.8.O_EXCL.patch +Patch3: cdparanoia-III-alpha9.8.cflags.patch +Patch4: cdparanoia-III-alpha9.8.sgio.patch +Patch5: cdparanoia-III-alpha9.8.verbose.patch +Patch6: cdparanoia-III-alpha9.8.louder.patch +Patch7: cdparanoia-III-alpha9.8.verbosity3.patch +Patch8: cdparanoia-III-alpha9.8.env.patch Url: http://www.xiph.org/paranoia/index.html BuildRoot: %{_tmppath}/cdparanoia-%{version}-root Requires: cdparanoia-libs = %{version}-%{release} @@ -45,14 +51,21 @@ applications which read CD Digital Audio disks. %prep %setup -q -n %{name}-III-%{realver} +%patch4 -p1 -b .sgio %patch0 -p1 -b .nostrip %patch1 -p1 -b .labels %patch2 -p1 -b .O_EXCL +%patch3 -p1 -b .cflags +%patch5 -p1 -b .verbose +%patch6 -p1 -b .louder +%patch7 -p1 -b .verbosity3 +%patch8 -p1 -b .env %build rm -rf $RPM_BUILD_ROOT +export OPT="${CFLAGS:-%optflags}" %configure --includedir=%{_includedir}/cdda -make +make OPT="$OPT" %install rm -rf $RPM_BUILD_ROOT @@ -106,6 +119,9 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/*.a %changelog +* Wed Jul 7 2004 Peter Jones alpha9.8-21sgio1 +- a new set of sgio patches + * Tue Jun 15 2004 Elliot Lee - rebuilt