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 <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> * * 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 [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/