From a3ed634fe58c9f71e694eaa0f7b0aff6b23a275c Mon Sep 17 00:00:00 2001 From: "R. Bernstein" Date: Fri, 25 Dec 2009 08:45:48 -0500 Subject: [PATCH] Recording and retrieval of SCSI sense reply for GNU/Linux. --- NEWS | 1 + THANKS | 1 + lib/driver/gnu_linux.c | 75 ++++++++++++++++++++++++++++++------------ lib/driver/solaris.c | 13 ++++---- 4 files changed, 62 insertions(+), 28 deletions(-) diff --git a/NEWS b/NEWS index c33965d0..a0557d90 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ version 0.83 (git) - Add Recording and retrieval of SCSI sense reply. - Add Write/burning interface. +- MMC bug fixes - Tolerance for OS's without timezone in their struct tm (e.g. Solaris) added iso9660_set_{d,l}time_with_timezone diff --git a/THANKS b/THANKS index ceda291d..f2a855b8 100644 --- a/THANKS +++ b/THANKS @@ -64,6 +64,7 @@ xboxmediacenter team (www.xboxmediacenter.de) Thomas Schmitt Recording and retrieval of SCSI sense reply. Write/burning interface. + MMC bug fixes Daniel Schwarz log-summary option in cd-paranoia. diff --git a/lib/driver/gnu_linux.c b/lib/driver/gnu_linux.c index 3a045c17..4956f9cd 100644 --- a/lib/driver/gnu_linux.c +++ b/lib/driver/gnu_linux.c @@ -1,6 +1,4 @@ /* - $Id: gnu_linux.c,v 1.33 2008/06/25 07:46:21 rocky Exp $ - Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004, 2005, 2006, 2008, 2009 Rocky Bernstein @@ -86,7 +84,8 @@ typedef enum { _AM_IOCTL, _AM_READ_CD, _AM_READ_10, - _AM_MMC_RDWR + _AM_MMC_RDWR, + _AM_MMC_RDWR_EXCL, } access_mode_t; typedef struct { @@ -135,6 +134,8 @@ str_to_access_mode_linux(const char *psz_access_mode) return _AM_READ_10; else if (!strcmp(psz_access_mode, "MMC_RDWR")) return _AM_MMC_RDWR; + else if (!strcmp(psz_access_mode, "MMC_RDWR_EXCL")) + return _AM_MMC_RDWR_EXCL; else { cdio_warn ("unknown access type: %s. Default IOCTL used.", psz_access_mode); @@ -379,6 +380,8 @@ get_arg_linux (void *env, const char key[]) return "READ_10"; case _AM_MMC_RDWR: return "MMC_RDWR"; + case _AM_MMC_RDWR_EXCL: + return "MMC_RDWR_EXCL"; case _AM_NONE: return "no access method"; } @@ -958,7 +961,7 @@ _read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba, */ static driver_return_code_t _read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, - bool b_form2) + bool b_form2) { #if 0 @@ -1029,7 +1032,7 @@ _read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, */ static driver_return_code_t _read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn, - bool b_form2, uint32_t i_blocks) + bool b_form2, uint32_t i_blocks) { _img_private_t *p_env = p_user_data; unsigned int i; @@ -1074,6 +1077,7 @@ _read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, case _AM_IOCTL: case _AM_MMC_RDWR: + case _AM_MMC_RDWR_EXCL: if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl()"); @@ -1120,7 +1124,7 @@ _read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, */ static driver_return_code_t _read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn, - bool b_form2, uint32_t i_blocks) + bool b_form2, uint32_t i_blocks) { _img_private_t *p_env = p_user_data; unsigned int i; @@ -1221,26 +1225,51 @@ read_toc_linux (void *p_user_data) We return true if command completed successfully and false if not. */ static driver_return_code_t -run_mmc_cmd_linux( void *p_user_data, - unsigned int i_timeout_ms, - unsigned int i_cdb, const mmc_cdb_t *p_cdb, - cdio_mmc_direction_t e_direction, - unsigned int i_buf, /*in/out*/ void *p_buf ) +run_mmc_cmd_linux(void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, const mmc_cdb_t *p_cdb, + cdio_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf) { - const _img_private_t *p_env = p_user_data; + _img_private_t *p_env = p_user_data; struct cdrom_generic_command cgc; + struct request_sense sense; + unsigned char *u_sense = (unsigned char *) &sense; + int sense_size; + + p_env->gen.scsi_mmc_sense_valid = 0; memset (&cgc, 0, sizeof (struct cdrom_generic_command)); - memcpy(&cgc.cmd, p_cdb, i_cdb); - cgc.buflen = i_buf; - cgc.buffer = p_buf; - cgc.data_direction = (SCSI_MMC_DATA_READ == e_direction) - ? CGC_DATA_READ : CGC_DATA_WRITE; - #ifdef HAVE_LINUX_CDROM_TIMEOUT + memcpy(&cgc.cmd, p_cdb, i_cdb); + cgc.buflen = i_buf; + cgc.buffer = p_buf; + + cgc.sense = &sense; + + if (SCSI_MMC_DATA_NONE == e_direction) + i_buf = 0; + cgc.data_direction = (SCSI_MMC_DATA_READ == e_direction) ? CGC_DATA_READ : + (SCSI_MMC_DATA_WRITE == e_direction) ? CGC_DATA_WRITE : + CGC_DATA_NONE; + +#ifdef HAVE_LINUX_CDROM_TIMEOUT cgc.timeout = i_timeout_ms; #endif + memset(u_sense, 0, sizeof(sense)); { int i_rc = ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc); + + /* Record SCSI sense reply for API call mmc_last_cmd_sense(). + */ + if (u_sense[7]) { + sense_size = u_sense[7] + 8; /* SPC 4.5.3, Table 26 : + 252 bytes legal , 263 bytes possible */ + if (sense_size > sizeof(sense)) + sense_size = sizeof(sense); + memcpy((void *) p_env->gen.scsi_mmc_sense, &sense, sense_size); + p_env->gen.scsi_mmc_sense_valid = sense_size; + } + if (0 == i_rc) return DRIVER_OP_SUCCESS; if (-1 == i_rc) { cdio_info ("ioctl CDROM_SEND_PACKET failed: %s", strerror(errno)); @@ -1648,9 +1677,13 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) ret->driver_id = DRIVER_LINUX; - open_access_mode = (_AM_MMC_RDWR == _data->access_mode) - ? (O_RDWR|O_EXCL|O_NONBLOCK) : (O_RDONLY|O_NONBLOCK); - + open_access_mode = O_NONBLOCK; + if (_AM_MMC_RDWR == _data->access_mode) + open_access_mode |= O_RDWR; + else if (_AM_MMC_RDWR_EXCL == _data->access_mode) + open_access_mode |= O_RDWR | O_EXCL; + else + open_access_mode |= O_RDONLY; if (cdio_generic_init(_data, open_access_mode)) { return ret; } else { diff --git a/lib/driver/solaris.c b/lib/driver/solaris.c index 71bcd51e..95e8b234 100644 --- a/lib/driver/solaris.c +++ b/lib/driver/solaris.c @@ -1,7 +1,6 @@ /* - $Id: solaris.c,v 1.12 2008/04/22 15:29:12 karl Exp $ - - Copyright (C) 2002, 2003, 2004, 2005, 2006 Rocky Bernstein + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009 + Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel This program is free software: you can redistribute it and/or modify @@ -277,10 +276,10 @@ init_solaris (_img_private_t *p_env) p_buf Buffer for data, both sending and receiving */ static driver_return_code_t -run_mmc_cmd_solaris( void *p_user_data, unsigned int i_timeout_ms, - unsigned int i_cdb, const mmc_cdb_t *p_cdb, - cdio_mmc_direction_t e_direction, - unsigned int i_buf, /*in/out*/ void *p_buf ) +run_mmc_cmd_solaris(void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const mmc_cdb_t *p_cdb, + cdio_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf) { const _img_private_t *p_env = p_user_data; struct uscsi_cmd cgc;