PATCH for changing of DVD speed via ioctl() call
From: cHitman
Date: Sun Aug 21 2005 - 10:55:50 EST
Hello, folks!
This patch implements changing of DVD speed via ioctl() call, like
CDROM_SELECT_SPEED do. In CDROM_SELECT_SPEED its implementation isn't
so good (diffirent values of 1x in KB/s, troubles with return value of
cdrom_select_speed() and other). I defined CDROM_SELECT_DVDSPEED ioctl
() call with value 0x5324. But some dvdroms (like Plexter) do not
support this feature.. :(
I've successfully tested this patch on:s
NEC ND-3500AG (fw 2.19)
BENQ DVD-ROM 16X 1650T (fw: A.DD)
HL-DT-ST DVD-RW GCA-4080N (fw: 0A31)
I've mailed this message to Jens Axboe but have not answer :(
Please try it and say what you think about this..
patch for kernel 2.6.12
Signed-off-by: Ilja Samartsev <samartsev@xxxxxxxxx>
PS: I'm not subscribed to LKML please CC me if you can.
=================== PATCH ====================
--- linux/include/linux/cdrom.h 2005-08-13 12:54:06.000000000 +0600
+++ my_linux/include/linux/cdrom.h 2005-08-14 15:06:06.000000000 +0600
@@ -120,6 +120,7 @@
#define CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */
#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
#define CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */
+#define CDROM_SELECT_DVDSPEED 0x5324 /* Set the DVD-ROM speed */
#define CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */
#define CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
#define CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
@@ -965,6 +966,7 @@ struct cdrom_device_ops {
int (*tray_move) (struct cdrom_device_info *, int);
int (*lock_door) (struct cdrom_device_info *, int);
int (*select_speed) (struct cdrom_device_info *, int);
+ int (*select_dvd_speed) (struct cdrom_device_info *, int);
int (*select_disc) (struct cdrom_device_info *, int);
int (*get_last_session) (struct cdrom_device_info *,
struct cdrom_multisession *);
--- linux/drivers/cdrom/cdrom.c 2005-08-13 12:54:06.000000000 +0600
+++ my_linux/drivers/cdrom/cdrom.c 2005-08-12 17:11:20.000000000 +0600
@@ -2327,6 +2327,11 @@ int cdrom_ioctl(struct file * file, stru
return cdo->select_speed(cdi, arg);
}
+ case CDROM_SELECT_DVDSPEED: {
+ cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DVDSPEED\n");
+ return cdo->select_dvd_speed(cdi, arg);
+ }
+
case CDROM_SELECT_DISC: {
cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
if (!CDROM_CAN(CDC_SELECT_DISC))
--- linux/drivers/ide/ide-cd.c 2005-08-13 12:54:06.000000000 +0600
+++ my_linux/drivers/ide/ide-cd.c 2005-08-16 01:00:09.000000000 +0600
@@ -2393,7 +2393,7 @@ static int cdrom_select_speed(ide_drive_
cdrom_prepare_request(drive, &req);
req.sense = sense;
- if (speed == 0)
+ if (speed <= 0)
speed = 0xffff; /* set to max */
else
speed *= 177; /* Nx to kbytes/s */
@@ -2415,6 +2415,63 @@ static int cdrom_select_speed(ide_drive_
return cdrom_queue_packet_command(drive, &req);
}
+static int cdrom_select_dvd_speed(ide_drive_t *drive, int speed,
+ struct request_sense *sense)
+{
+ struct request req;
+ struct request_sense cap_sense;
+ unsigned char pd[28];
+ unsigned long cap, spf;
+
+ if (!CDROM_CONFIG_FLAGS(drive)->dvd)
+ return -ENOSYS;
+
+ cdrom_prepare_request(drive, &req);
+
+ req.sense = sense;
+ req.data = pd;
+ req.data_len = sizeof(pd);
+
+ memset(pd, 0, sizeof(pd));
+
+ req.cmd[0] = GPCMD_SET_STREAMING;
+ req.cmd[10] = sizeof(pd); /* parameter list length */
+
+ if (speed <= 0) {
+ pd[0] = 4; /* restore drive defaults */
+ } else {
+
+ speed *= 1385; /* Nx to kbytes/s (FIXME: maybe not right value) */
+
+ if (!cdrom_read_capacity(drive, &cap, &spf, &cap_sense) && cap) {
+ /* good End LBA detected */
+ cap++;
+ pd[8] = (cap >> 24) & 0xff;
+ pd[9] = (cap >> 16) & 0xff;
+ pd[10] = (cap >> 8) & 0xff;
+ pd[11] = cap & 0xff;
+ } else {
+ /* no good End LBA detected, using max */
+ pd[8] = 0xff;
+ pd[9] = 0xff;
+ pd[10] = 0xff;
+ pd[11] = 0xff;
+ }
+
+ /* read and write size */
+ pd[12] = pd[20] = (speed >> 24) & 0xff;
+ pd[13] = pd[21] = (speed >> 16) & 0xff;
+ pd[14] = pd[22] = (speed >> 8) & 0xff;
+ pd[15] = pd[23] = speed & 0xff;
+
+ /* read and write time */
+ pd[18] = pd[26] = 1000 >> 8;
+ pd[19] = pd[27] = 1000 & 0xff;
+ }
+
+ return cdrom_queue_packet_command(drive, &req);
+}
+
static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
{
struct request_sense sense;
@@ -2670,6 +2727,19 @@ int ide_cdrom_select_speed (struct cdrom
return 0;
}
+static
+int ide_cdrom_select_dvd_speed (struct cdrom_device_info *cdi, int speed)
+{
+ ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct request_sense sense;
+ int stat;
+
+ if ((stat = cdrom_select_dvd_speed(drive, speed, &sense)) < 0)
+ return stat;
+
+ return 0;
+}
+
/*
* add logic to try GET_EVENT command first to check for media and tray
* status. this should be supported by newer cd-r/w and all DVD etc
@@ -2816,6 +2886,7 @@ static struct cdrom_device_ops ide_cdrom
.tray_move = ide_cdrom_tray_move,
.lock_door = ide_cdrom_lock_door,
.select_speed = ide_cdrom_select_speed,
+ .select_dvd_speed = ide_cdrom_select_dvd_speed,
.get_last_session = ide_cdrom_get_last_session,
.get_mcn = ide_cdrom_get_mcn,
.reset = ide_cdrom_reset,
====================== EOF ========================
=================== dvdspeed.c ====================
/*
* dvdspeed - small program for selecting speed of DVD drive
* Copyright (C) 2005 Ilja Samartsev <samartsev@xxxxxxxxx>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
int main (int argc, char **argv)
{
int fd, speed;
char *device;
if (argc < 3) {
printf("usage: %s device speed\n", argv[0]);
return -1;
}
device = argv[1];
speed = atoi(argv[2]);
if ((fd = open(device, O_RDONLY|O_NONBLOCK)) >= 0) {
if (ioctl(fd, CDROM_SELECT_DVDSPEED, speed) < 0) {
perror("ioctl()");
exit(-1);
}
}
return 0;
}
====================== EOF ========================
--
Samartsev Ilja
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/