summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/scsi/scsi_cd.c47
-rw-r--r--sys/cam/scsi/scsi_cd.h11
-rw-r--r--sys/dev/ata/atapi-cd.c4
-rw-r--r--sys/sys/cdrio.h1
-rw-r--r--usr.sbin/burncd/burncd.81
-rw-r--r--usr.sbin/burncd/burncd.c5
-rw-r--r--usr.sbin/cdcontrol/cdcontrol.16
-rw-r--r--usr.sbin/cdcontrol/cdcontrol.c9
8 files changed, 74 insertions, 10 deletions
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index a7af9ba..3984f77 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -56,6 +56,7 @@
#include <sys/disk.h>
#include <sys/malloc.h>
#include <sys/cdio.h>
+#include <sys/cdrio.h>
#include <sys/dvdio.h>
#include <sys/devicestat.h>
#include <sys/sysctl.h>
@@ -230,6 +231,8 @@ static int cdplaytracks(struct cam_periph *periph,
static int cdpause(struct cam_periph *periph, u_int32_t go);
static int cdstopunit(struct cam_periph *periph, u_int32_t eject);
static int cdstartunit(struct cam_periph *periph);
+static int cdsetspeed(struct cam_periph *periph,
+ u_int32_t rdspeed, u_int32_t wrspeed);
static int cdreportkey(struct cam_periph *periph,
struct dvd_authinfo *authinfo);
static int cdsendkey(struct cam_periph *periph,
@@ -2379,6 +2382,12 @@ cdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
/* return (cd_reset(periph)); */
error = ENOTTY;
break;
+ case CDRIOCREADSPEED:
+ error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED);
+ break;
+ case CDRIOCWRITESPEED:
+ error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr);
+ break;
case DVDIOCSENDKEY:
case DVDIOCREPORTKEY: {
struct dvd_authinfo *authinfo;
@@ -2956,6 +2965,44 @@ cdstopunit(struct cam_periph *periph, u_int32_t eject)
}
static int
+cdsetspeed(struct cam_periph *periph, u_int32_t rdspeed, u_int32_t wrspeed)
+{
+ struct scsi_set_speed *scsi_cmd;
+ struct ccb_scsiio *csio;
+ union ccb *ccb;
+ int error;
+
+ error = 0;
+ ccb = cdgetccb(periph, /* priority */ 1);
+ csio = &ccb->csio;
+
+ cam_fill_csio(csio,
+ /* retries */ 1,
+ /* cbfcnp */ cddone,
+ /* flags */ CAM_DIR_NONE,
+ /* tag_action */ MSG_SIMPLE_Q_TAG,
+ /* data_ptr */ NULL,
+ /* dxfer_len */ 0,
+ /* sense_len */ SSD_FULL_SIZE,
+ sizeof(struct scsi_set_speed),
+ /* timeout */ 50000);
+
+ scsi_cmd = (struct scsi_set_speed *)&csio->cdb_io.cdb_bytes;
+ bzero(scsi_cmd, sizeof(*scsi_cmd));
+
+ scsi_cmd->opcode = SET_CD_SPEED;
+ scsi_ulto2b(rdspeed, scsi_cmd->readspeed);
+ scsi_ulto2b(wrspeed, scsi_cmd->writespeed);
+
+ error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
+ /*sense_flags*/SF_RETRY_UA);
+
+ xpt_release_ccb(ccb);
+
+ return(error);
+}
+
+static int
cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
{
union ccb *ccb;
diff --git a/sys/cam/scsi/scsi_cd.h b/sys/cam/scsi/scsi_cd.h
index fc52119..f242139 100644
--- a/sys/cam/scsi/scsi_cd.h
+++ b/sys/cam/scsi/scsi_cd.h
@@ -169,6 +169,16 @@ struct scsi_read_cd_capacity
u_int8_t control;
};
+struct scsi_set_speed
+{
+ u_int8_t opcode;
+ u_int8_t byte2;
+ u_int8_t readspeed[2];
+ u_int8_t writespeed[2];
+ u_int8_t reserved[5];
+ u_int8_t control;
+};
+
struct scsi_report_key
{
u_int8_t opcode;
@@ -251,6 +261,7 @@ struct scsi_read_dvd_structure
#define PLAY_12 0xa5 /* cdrom pause in 'play audio' mode */
#define PLAY_TRACK_REL_BIG 0xa9 /* cdrom play track/index mode */
#define READ_DVD_STRUCTURE 0xad /* read dvd structure */
+#define SET_CD_SPEED 0xbb /* set c/dvd speed */
struct scsi_report_key_data_header
{
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 6e91ef7..d3bcd60 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -1021,11 +1021,11 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
break;
case CDRIOCREADSPEED:
- error = acd_set_speed(cdp, 177 * (*(int *)addr), -1);
+ error = acd_set_speed(cdp, *(int *)addr, CDR_MAX_SPEED);
break;
case CDRIOCWRITESPEED:
- error = acd_set_speed(cdp, -1, 177 * (*(int *)addr));
+ error = acd_set_speed(cdp, CDR_MAX_SPEED, *(int *)addr);
break;
case CDRIOCGETBLOCKSIZE:
diff --git a/sys/sys/cdrio.h b/sys/sys/cdrio.h
index 77cb1be..b664a58 100644
--- a/sys/sys/cdrio.h
+++ b/sys/sys/cdrio.h
@@ -129,6 +129,7 @@ struct cdr_format_params {
#define CDRIOCFIXATE _IOW('c', 106, int)
#define CDRIOCREADSPEED _IOW('c', 107, int)
#define CDRIOCWRITESPEED _IOW('c', 108, int)
+#define CDR_MAX_SPEED 0xffff
#define CDRIOCGETBLOCKSIZE _IOR('c', 109, int)
#define CDRIOCSETBLOCKSIZE _IOW('c', 110, int)
#define CDRIOCGETPROGRESS _IOR('c', 111, int)
diff --git a/usr.sbin/burncd/burncd.8 b/usr.sbin/burncd/burncd.8
index 47dc84f..520ed9a 100644
--- a/usr.sbin/burncd/burncd.8
+++ b/usr.sbin/burncd/burncd.8
@@ -69,6 +69,7 @@ quiet, do not print progress messages.
.It Fl s Ar speed
set the speed of the burner device.
Defaults to 1.
+Specify "max" to use the drive's fastest speed.
.It Fl t
test write, do not actually write on the media.
.It Fl v
diff --git a/usr.sbin/burncd/burncd.c b/usr.sbin/burncd/burncd.c
index 1d3d2fd..9f3738e 100644
--- a/usr.sbin/burncd/burncd.c
+++ b/usr.sbin/burncd/burncd.c
@@ -116,7 +116,10 @@ main(int argc, char **argv)
break;
case 's':
- speed = atoi(optarg);
+ if (strcasecmp("max", optarg) == 0)
+ speed = CDR_MAX_SPEED;
+ else
+ speed = atoi(optarg);
if (speed <= 0)
errx(EX_USAGE, "Invalid speed: %s", optarg);
break;
diff --git a/usr.sbin/cdcontrol/cdcontrol.1 b/usr.sbin/cdcontrol/cdcontrol.1
index 3f986fe..94214f9 100644
--- a/usr.sbin/cdcontrol/cdcontrol.1
+++ b/usr.sbin/cdcontrol/cdcontrol.1
@@ -164,9 +164,9 @@ Set minute-second-frame ioctl mode (default).
.It Ic set Cm lba
Set LBA ioctl mode.
.It Ic speed Ar s
-Set the highest speed that the drive should use.
-The speed is a multiple of the single speed.
-This command is currently only supported on ATAPI drives.
+Set the highest speed that the drive should use for reading data.
+The units are multiples of a single speed CDROM (150 KB/s).
+Specify "max" to use the drive's fastest speed.
.It Ic quit
Quit the program.
.El
diff --git a/usr.sbin/cdcontrol/cdcontrol.c b/usr.sbin/cdcontrol/cdcontrol.c
index f497c52..5dd0585 100644
--- a/usr.sbin/cdcontrol/cdcontrol.c
+++ b/usr.sbin/cdcontrol/cdcontrol.c
@@ -282,7 +282,6 @@ int run (int cmd, char *arg)
{
long speed;
int l, r, rc;
- char *ep;
switch (cmd) {
@@ -435,9 +434,11 @@ int run (int cmd, char *arg)
return (0);
errno = 0;
- speed = strtol(arg, &ep, 10);
- if (*ep || ep == arg || speed <= 0 || speed > INT_MAX ||
- errno != 0) {
+ if (strcasecmp("max", arg) == 0)
+ speed = CDR_MAX_SPEED;
+ else
+ speed = strtol(arg, NULL, 10) * 177;
+ if (speed <= 0 || speed > INT_MAX) {
warnx("invalid command arguments %s", arg);
return (0);
}
OpenPOWER on IntegriCloud