blob: 5a38b5681ca39ecd0a211d02d81fa84bc273df3c [file] [log] [blame]
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02001/* linux/drivers/cdrom/cdrom.c
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 Copyright (c) 1996, 1997 David A. van Leeuwen.
3 Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
4 Copyright (c) 1998, 1999 Jens Axboe <axboe@image.dk>
5
6 May be copied or modified under the terms of the GNU General Public
7 License. See linux/COPYING for more information.
8
9 Uniform CD-ROM driver for Linux.
10 See Documentation/cdrom/cdrom-standard.tex for usage information.
11
12 The routines in the file provide a uniform interface between the
13 software that uses CD-ROMs and the various low-level drivers that
14 actually talk to the hardware. Suggestions are welcome.
15 Patches that work are more welcome though. ;-)
16
17 To Do List:
18 ----------------------------------
19
20 -- Modify sysctl/proc interface. I plan on having one directory per
21 drive, with entries for outputing general drive information, and sysctl
22 based tunable parameters such as whether the tray should auto-close for
23 that drive. Suggestions (or patches) for this welcome!
24
25
26 Revision History
27 ----------------------------------
28 1.00 Date Unknown -- David van Leeuwen <david@tm.tno.nl>
29 -- Initial version by David A. van Leeuwen. I don't have a detailed
30 changelog for the 1.x series, David?
31
322.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org>
Lucas De Marchi25985ed2011-03-30 22:57:33 -030033 -- New maintainer! As David A. van Leeuwen has been too busy to actively
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 maintain and improve this driver, I am now carrying on the torch. If
35 you have a problem with this driver, please feel free to contact me.
36
37 -- Added (rudimentary) sysctl interface. I realize this is really weak
38 right now, and is _very_ badly implemented. It will be improved...
39
40 -- Modified CDROM_DISC_STATUS so that it is now incorporated into
41 the Uniform CD-ROM driver via the cdrom_count_tracks function.
42 The cdrom_count_tracks function helps resolve some of the false
43 assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
44 for the correct media type when mounting or playing audio from a CD.
45
46 -- Remove the calls to verify_area and only use the copy_from_user and
47 copy_to_user stuff, since these calls now provide their own memory
48 checking with the 2.1.x kernels.
49
50 -- Major update to return codes so that errors from low-level drivers
51 are passed on through (thanks to Gerd Knorr for pointing out this
52 problem).
53
54 -- Made it so if a function isn't implemented in a low-level driver,
55 ENOSYS is now returned instead of EINVAL.
56
57 -- Simplified some complex logic so that the source code is easier to read.
58
59 -- Other stuff I probably forgot to mention (lots of changes).
60
612.01 to 2.11 Dec 1997-Jan 1998
62 -- TO-DO! Write changelogs for 2.01 to 2.12.
63
642.12 Jan 24, 1998 -- Erik Andersen <andersee@debian.org>
65 -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that
66 copy_*_user does not return EFAULT on error, but instead returns the number
67 of bytes not copied. I was returning whatever non-zero stuff came back from
68 the copy_*_user functions directly, which would result in strange errors.
69
702.13 July 17, 1998 -- Erik Andersen <andersee@debian.org>
71 -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed
72 of the drive. Thanks to Tobias Ringstr|m <tori@prosolvia.se> for pointing
73 this out and providing a simple fix.
74 -- Fixed the procfs-unload-module bug with the fill_inode procfs callback.
75 thanks to Andrea Arcangeli
76 -- Fixed it so that the /proc entry now also shows up when cdrom is
77 compiled into the kernel. Before it only worked when loaded as a module.
78
79 2.14 August 17, 1998 -- Erik Andersen <andersee@debian.org>
80 -- Fixed a bug in cdrom_media_changed and handling of reporting that
81 the media had changed for devices that _don't_ implement media_changed.
82 Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug.
83 -- Made a few things more pedanticly correct.
84
852.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk>
86 -- New maintainers! Erik was too busy to continue the work on the driver,
87 so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk>
88 will do their best to follow in his footsteps
89
90 2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk>
91 -- Check if drive is capable of doing what we ask before blindly changing
92 cdi->options in various ioctl.
93 -- Added version to proc entry.
94
95 2.52 Jan 16, 1999 - Jens Axboe <axboe@image.dk>
96 -- Fixed an error in open_for_data where we would sometimes not return
97 the correct error value. Thanks Huba Gaspar <huba@softcell.hu>.
98 -- Fixed module usage count - usage was based on /proc/sys/dev
99 instead of /proc/sys/dev/cdrom. This could lead to an oops when other
100 modules had entries in dev. Feb 02 - real bug was in sysctl.c where
101 dev would be removed even though it was used. cdrom.c just illuminated
102 that bug.
103
104 2.53 Feb 22, 1999 - Jens Axboe <axboe@image.dk>
105 -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has
106 been "rewritten" because capabilities and options aren't in sync. They
107 should be...
108 -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way.
109 -- Added CDROM_RESET ioctl.
110 -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly.
111 -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs
112 from parsing /proc/sys/dev/cdrom/info.
113
114 2.54 Mar 15, 1999 - Jens Axboe <axboe@image.dk>
115 -- Check capability mask from low level driver when counting tracks as
116 per suggestion from Corey J. Scotts <cstotts@blue.weeg.uiowa.edu>.
117
118 2.55 Apr 25, 1999 - Jens Axboe <axboe@image.dk>
119 -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of
120 CDC_CLOSE_TRAY.
121 -- proc info didn't mask against capabilities mask.
122
123 3.00 Aug 5, 1999 - Jens Axboe <axboe@image.dk>
124 -- Unified audio ioctl handling across CD-ROM drivers. A lot of the
125 code was duplicated before. Drives that support the generic packet
126 interface are now being fed packets from here instead.
127 -- First attempt at adding support for MMC2 commands - for DVD and
128 CD-R(W) drives. Only the DVD parts are in now - the interface used is
129 the same as for the audio ioctls.
130 -- ioctl cleanups. if a drive couldn't play audio, it didn't get
131 a change to perform device specific ioctls as well.
132 -- Defined CDROM_CAN(CDC_XXX) for checking the capabilities.
133 -- Put in sysctl files for autoclose, autoeject, check_media, debug,
134 and lock.
135 -- /proc/sys/dev/cdrom/info has been updated to also contain info about
136 CD-Rx and DVD capabilities.
137 -- Now default to checking media type.
138 -- CDROM_SEND_PACKET ioctl added. The infrastructure was in place for
139 doing this anyway, with the generic_packet addition.
140
141 3.01 Aug 6, 1999 - Jens Axboe <axboe@image.dk>
142 -- Fix up the sysctl handling so that the option flags get set
143 correctly.
144 -- Fix up ioctl handling so the device specific ones actually get
145 called :).
146
147 3.02 Aug 8, 1999 - Jens Axboe <axboe@image.dk>
148 -- Fixed volume control on SCSI drives (or others with longer audio
149 page).
150 -- Fixed a couple of DVD minors. Thanks to Andrew T. Veliath
151 <andrewtv@usa.net> for telling me and for having defined the various
152 DVD structures and ioctls in the first place! He designed the original
153 DVD patches for ide-cd and while I rearranged and unified them, the
154 interface is still the same.
155
156 3.03 Sep 1, 1999 - Jens Axboe <axboe@image.dk>
157 -- Moved the rest of the audio ioctls from the CD-ROM drivers here. Only
158 CDROMREADTOCENTRY and CDROMREADTOCHDR are left.
159 -- Moved the CDROMREADxxx ioctls in here.
160 -- Defined the cdrom_get_last_written and cdrom_get_next_block as ioctls
161 and exported functions.
162 -- Erik Andersen <andersen@xmission.com> modified all SCMD_ commands
163 to now read GPCMD_ for the new generic packet interface. All low level
164 drivers are updated as well.
165 -- Various other cleanups.
166
167 3.04 Sep 12, 1999 - Jens Axboe <axboe@image.dk>
168 -- Fixed a couple of possible memory leaks (if an operation failed and
169 we didn't free the buffer before returning the error).
170 -- Integrated Uniform CD Changer handling from Richard Sharman
171 <rsharman@pobox.com>.
172 -- Defined CD_DVD and CD_CHANGER log levels.
173 -- Fixed the CDROMREADxxx ioctls.
174 -- CDROMPLAYTRKIND uses the GPCMD_PLAY_AUDIO_MSF command - too few
175 drives supported it. We lose the index part, however.
176 -- Small modifications to accommodate opens of /dev/hdc1, required
177 for ide-cd to handle multisession discs.
178 -- Export cdrom_mode_sense and cdrom_mode_select.
179 -- init_cdrom_command() for setting up a cgc command.
180
181 3.05 Oct 24, 1999 - Jens Axboe <axboe@image.dk>
182 -- Changed the interface for CDROM_SEND_PACKET. Before it was virtually
183 impossible to send the drive data in a sensible way.
184 -- Lowered stack usage in mmc_ioctl(), dvd_read_disckey(), and
185 dvd_read_manufact.
186 -- Added setup of write mode for packet writing.
187 -- Fixed CDDA ripping with cdda2wav - accept much larger requests of
188 number of frames and split the reads in blocks of 8.
189
190 3.06 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
191 -- Added support for changing the region of DVD drives.
192 -- Added sense data to generic command.
193
194 3.07 Feb 2, 2000 - Jens Axboe <axboe@suse.de>
195 -- Do same "read header length" trick in cdrom_get_disc_info() as
196 we do in cdrom_get_track_info() -- some drive don't obey specs and
197 fail if they can't supply the full Mt Fuji size table.
198 -- Deleted stuff related to setting up write modes. It has a different
199 home now.
200 -- Clear header length in mode_select unconditionally.
201 -- Removed the register_disk() that was added, not needed here.
202
203 3.08 May 1, 2000 - Jens Axboe <axboe@suse.de>
204 -- Fix direction flag in setup_send_key and setup_report_key. This
205 gave some SCSI adapters problems.
206 -- Always return -EROFS for write opens
207 -- Convert to module_init/module_exit style init and remove some
208 of the #ifdef MODULE stuff
209 -- Fix several dvd errors - DVD_LU_SEND_ASF should pass agid,
210 DVD_HOST_SEND_RPC_STATE did not set buffer size in cdb, and
211 dvd_do_auth passed uninitialized data to drive because init_cdrom_command
212 did not clear a 0 sized buffer.
213
214 3.09 May 12, 2000 - Jens Axboe <axboe@suse.de>
215 -- Fix Video-CD on SCSI drives that don't support READ_CD command. In
216 that case switch block size and issue plain READ_10 again, then switch
217 back.
218
219 3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de>
220 -- Fix volume control on CD's - old SCSI-II drives now use their own
221 code, as doing MODE6 stuff in here is really not my intention.
222 -- Use READ_DISC_INFO for more reliable end-of-disc.
223
224 3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de>
225 -- Fix bug in getting rpc phase 2 region info.
226 -- Reinstate "correct" CDROMPLAYTRKIND
227
228 3.12 Oct 18, 2000 - Jens Axboe <axboe@suse.de>
229 -- Use quiet bit on packet commands not known to work
230
231 3.20 Dec 17, 2003 - Jens Axboe <axboe@suse.de>
232 -- Various fixes and lots of cleanups not listed :-)
233 -- Locking fixes
234 -- Mt Rainier support
235 -- DVD-RAM write open fixes
236
237 Nov 5 2001, Aug 8 2002. Modified by Andy Polyakov
238 <appro@fy.chalmers.se> to support MMC-3 compliant DVD+RW units.
239
240 Modified by Nigel Kukard <nkukard@lbsd.net> - support DVD+RW
241 2.4.x patch by Andy Polyakov <appro@fy.chalmers.se>
242
243-------------------------------------------------------------------------*/
244
Joe Perchese597cd02010-07-01 08:24:32 +0200245#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
246
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247#define REVISION "Revision: 3.20"
248#define VERSION "Id: cdrom.c 3.20 2003/12/17"
249
250/* I use an error-log mask to give fine grain control over the type of
251 messages dumped to the system logs. The available masks include: */
252#define CD_NOTHING 0x0
253#define CD_WARNING 0x1
254#define CD_REG_UNREG 0x2
255#define CD_DO_IOCTL 0x4
256#define CD_OPEN 0x8
257#define CD_CLOSE 0x10
258#define CD_COUNT_TRACKS 0x20
259#define CD_CHANGER 0x40
260#define CD_DVD 0x80
261
262/* Define this to remove _all_ the debugging messages */
263/* #define ERRLOGMASK CD_NOTHING */
264#define ERRLOGMASK CD_WARNING
265/* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
266/* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268#include <linux/module.h>
269#include <linux/fs.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270#include <linux/major.h>
271#include <linux/types.h>
272#include <linux/errno.h>
273#include <linux/kernel.h>
274#include <linux/mm.h>
275#include <linux/slab.h>
276#include <linux/cdrom.h>
277#include <linux/sysctl.h>
278#include <linux/proc_fs.h>
279#include <linux/blkpg.h>
280#include <linux/init.h>
281#include <linux/fcntl.h>
282#include <linux/blkdev.h>
283#include <linux/times.h>
284
285#include <asm/uaccess.h>
286
287/* used to tell the module to turn on full debugging messages */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030288static bool debug;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289/* default compatibility mode */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030290static bool autoclose=1;
291static bool autoeject;
292static bool lockdoor = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293/* will we ever get to use this... sigh. */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030294static bool check_media_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295/* automatically restart mrw format */
Rusty Russell90ab5ee2012-01-13 09:32:20 +1030296static bool mrw_format_restart = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297module_param(debug, bool, 0);
298module_param(autoclose, bool, 0);
299module_param(autoeject, bool, 0);
300module_param(lockdoor, bool, 0);
301module_param(check_media_type, bool, 0);
302module_param(mrw_format_restart, bool, 0);
303
Dave Young554988d2007-06-19 09:14:26 +0200304static DEFINE_MUTEX(cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
306static const char *mrw_format_status[] = {
307 "not mrw",
308 "bgformat inactive",
309 "bgformat active",
310 "mrw complete",
311};
312
313static const char *mrw_address_space[] = { "DMA", "GAA" };
314
Joe Perches5944b2c2014-05-04 17:05:02 -0700315#if (ERRLOGMASK != CD_NOTHING)
316#define cd_dbg(type, fmt, ...) \
Joe Perchese597cd02010-07-01 08:24:32 +0200317do { \
318 if ((ERRLOGMASK & type) || debug == 1) \
Joe Perches5944b2c2014-05-04 17:05:02 -0700319 pr_debug(fmt, ##__VA_ARGS__); \
Joe Perchese597cd02010-07-01 08:24:32 +0200320} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321#else
Joe Perches5944b2c2014-05-04 17:05:02 -0700322#define cd_dbg(type, fmt, ...) \
Joe Perchese597cd02010-07-01 08:24:32 +0200323do { \
324 if (0 && (ERRLOGMASK & type) || debug == 1) \
Joe Perches5944b2c2014-05-04 17:05:02 -0700325 pr_debug(fmt, ##__VA_ARGS__); \
Joe Perchese597cd02010-07-01 08:24:32 +0200326} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327#endif
328
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
330 a lot of places. This macro makes the code more clear. */
331#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type))
332
Jens Axboe2e11c202007-01-03 08:10:35 +0100333/*
334 * Another popular OS uses 7 seconds as the hard timeout for default
335 * commands, so it is a good choice for us as well.
336 */
337#define CDROM_DEF_TIMEOUT (7 * HZ)
338
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339/* Not-exported routines. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340static int check_for_audio_disc(struct cdrom_device_info * cdi,
341 struct cdrom_device_ops * cdo);
342static void sanitize_format(union cdrom_addr *addr,
343 u_char * curr, u_char requested);
344static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
345 unsigned long arg);
346
347int cdrom_get_last_written(struct cdrom_device_info *, long *);
348static int cdrom_get_next_writable(struct cdrom_device_info *, long *);
349static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*);
350
351static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
352
353static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
354
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355static void cdrom_sysctl_register(void);
Akinobu Mita17672cf2008-03-26 12:08:59 +0100356
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100357static LIST_HEAD(cdrom_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358
359static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
360 struct packet_command *cgc)
361{
362 if (cgc->sense) {
363 cgc->sense->sense_key = 0x05;
364 cgc->sense->asc = 0x20;
365 cgc->sense->ascq = 0x00;
366 }
367
368 cgc->stat = -EIO;
369 return -EIO;
370}
371
372/* This macro makes sure we don't have to check on cdrom_device_ops
373 * existence in the run-time routines below. Change_capability is a
374 * hack to have the capability flags defined const, while we can still
375 * change it here without gcc complaining at every line.
376 */
377#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
378
379int register_cdrom(struct cdrom_device_info *cdi)
380{
381 static char banner_printed;
382 struct cdrom_device_ops *cdo = cdi->ops;
383 int *change_capability = (int *)&cdo->capability; /* hack */
384
Joe Perches5944b2c2014-05-04 17:05:02 -0700385 cd_dbg(CD_OPEN, "entering register_cdrom\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
387 if (cdo->open == NULL || cdo->release == NULL)
Akinobu Mita3c3f4e02008-03-26 12:09:00 +0100388 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (!banner_printed) {
Joe Perchese597cd02010-07-01 08:24:32 +0200390 pr_info("Uniform CD-ROM driver " REVISION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 banner_printed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 cdrom_sysctl_register();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394
395 ENSURE(drive_status, CDC_DRIVE_STATUS );
Simon Arlottb8cf0e02011-02-09 14:21:07 +0100396 if (cdo->check_events == NULL && cdo->media_changed == NULL)
397 *change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
399 ENSURE(lock_door, CDC_LOCK);
400 ENSURE(select_speed, CDC_SELECT_SPEED);
401 ENSURE(get_last_session, CDC_MULTI_SESSION);
402 ENSURE(get_mcn, CDC_MCN);
403 ENSURE(reset, CDC_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 ENSURE(generic_packet, CDC_GENERIC_PACKET);
405 cdi->mc_flags = 0;
406 cdo->n_minors = 0;
407 cdi->options = CDO_USE_FFLAGS;
408
409 if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY))
410 cdi->options |= (int) CDO_AUTO_CLOSE;
411 if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY))
412 cdi->options |= (int) CDO_AUTO_EJECT;
413 if (lockdoor==1)
414 cdi->options |= (int) CDO_LOCK;
415 if (check_media_type==1)
416 cdi->options |= (int) CDO_CHECK_TYPE;
417
418 if (CDROM_CAN(CDC_MRW_W))
419 cdi->exit = cdrom_mrw_exit;
420
421 if (cdi->disk)
422 cdi->cdda_method = CDDA_BPC_FULL;
423 else
424 cdi->cdda_method = CDDA_OLD;
425
426 if (!cdo->generic_packet)
427 cdo->generic_packet = cdrom_dummy_generic_packet;
428
Joe Perches5944b2c2014-05-04 17:05:02 -0700429 cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
Dave Young554988d2007-06-19 09:14:26 +0200430 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100431 list_add(&cdi->list, &cdrom_list);
Dave Young554988d2007-06-19 09:14:26 +0200432 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 return 0;
434}
435#undef ENSURE
436
Akinobu Mita0a0c4112008-03-26 12:09:02 +0100437void unregister_cdrom(struct cdrom_device_info *cdi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
Joe Perches5944b2c2014-05-04 17:05:02 -0700439 cd_dbg(CD_OPEN, "entering unregister_cdrom\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Dave Young554988d2007-06-19 09:14:26 +0200441 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100442 list_del(&cdi->list);
Dave Young554988d2007-06-19 09:14:26 +0200443 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445 if (cdi->exit)
446 cdi->exit(cdi);
447
448 cdi->ops->n_minors--;
Joe Perches5944b2c2014-05-04 17:05:02 -0700449 cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450}
451
452int cdrom_get_media_event(struct cdrom_device_info *cdi,
453 struct media_event_desc *med)
454{
455 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200456 unsigned char buffer[8];
457 struct event_header *eh = (struct event_header *) buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200459 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
461 cgc.cmd[1] = 1; /* IMMED */
462 cgc.cmd[4] = 1 << 4; /* media event */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200463 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464 cgc.quiet = 1;
465
466 if (cdi->ops->generic_packet(cdi, &cgc))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200467 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469 if (be16_to_cpu(eh->data_len) < sizeof(*med))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200470 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 if (eh->nea || eh->notification_class != 0x4)
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200473 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200475 memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
476 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477}
478
479/*
480 * the first prototypes used 0x2c as the page code for the mrw mode page,
481 * subsequently this was changed to 0x03. probe the one used by this drive
482 */
483static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
484{
485 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200486 char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200488 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
490 cgc.timeout = HZ;
491 cgc.quiet = 1;
492
493 if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
494 cdi->mrw_mode_page = MRW_MODE_PC;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200495 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
497 cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200498 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200500
501 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502}
503
504static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
505{
506 struct packet_command cgc;
507 struct mrw_feature_desc *mfd;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200508 unsigned char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 int ret;
510
511 *write = 0;
512
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200513 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
516 cgc.cmd[3] = CDF_MRW;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200517 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 cgc.quiet = 1;
519
520 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200521 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522
523 mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200524 if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
525 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 *write = mfd->write;
527
528 if ((ret = cdrom_mrw_probe_pc(cdi))) {
529 *write = 0;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200530 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200532
533 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534}
535
536static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
537{
538 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200539 unsigned char buffer[12];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 int ret;
541
Joe Perchese597cd02010-07-01 08:24:32 +0200542 pr_info("%sstarting format\n", cont ? "Re" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544 /*
545 * FmtData bit set (bit 4), format type is 1
546 */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200547 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 cgc.cmd[0] = GPCMD_FORMAT_UNIT;
549 cgc.cmd[1] = (1 << 4) | 1;
550
551 cgc.timeout = 5 * 60 * HZ;
552
553 /*
554 * 4 byte format list header, 8 byte format list descriptor
555 */
556 buffer[1] = 1 << 1;
557 buffer[3] = 8;
558
559 /*
560 * nr_blocks field
561 */
562 buffer[4] = 0xff;
563 buffer[5] = 0xff;
564 buffer[6] = 0xff;
565 buffer[7] = 0xff;
566
567 buffer[8] = 0x24 << 2;
568 buffer[11] = cont;
569
570 ret = cdi->ops->generic_packet(cdi, &cgc);
571 if (ret)
Joe Perchese597cd02010-07-01 08:24:32 +0200572 pr_info("bgformat failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
574 return ret;
575}
576
577static int cdrom_mrw_bgformat_susp(struct cdrom_device_info *cdi, int immed)
578{
579 struct packet_command cgc;
580
581 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
582 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
583
584 /*
585 * Session = 1, Track = 0
586 */
587 cgc.cmd[1] = !!immed;
588 cgc.cmd[2] = 1 << 1;
589
590 cgc.timeout = 5 * 60 * HZ;
591
592 return cdi->ops->generic_packet(cdi, &cgc);
593}
594
595static int cdrom_flush_cache(struct cdrom_device_info *cdi)
596{
597 struct packet_command cgc;
598
599 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
600 cgc.cmd[0] = GPCMD_FLUSH_CACHE;
601
602 cgc.timeout = 5 * 60 * HZ;
603
604 return cdi->ops->generic_packet(cdi, &cgc);
605}
606
607static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
608{
609 disc_information di;
610 int ret;
611
612 ret = cdrom_get_disc_info(cdi, &di);
613 if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type))
614 return 1;
615
616 ret = 0;
617 if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) {
Joe Perchese597cd02010-07-01 08:24:32 +0200618 pr_info("issuing MRW background format suspend\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 ret = cdrom_mrw_bgformat_susp(cdi, 0);
620 }
621
Jens Axboe7da21a02005-05-01 12:12:52 -0700622 if (!ret && cdi->media_written)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 ret = cdrom_flush_cache(cdi);
624
625 return ret;
626}
627
628static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
629{
630 struct packet_command cgc;
631 struct mode_page_header *mph;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200632 char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 int ret, offset, size;
634
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200635 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200637 cgc.buffer = buffer;
638 cgc.buflen = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200641 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643 mph = (struct mode_page_header *) buffer;
644 offset = be16_to_cpu(mph->desc_length);
645 size = be16_to_cpu(mph->mode_data_length) + 2;
646
647 buffer[offset + 3] = space;
648 cgc.buflen = size;
649
650 if ((ret = cdrom_mode_select(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200651 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Joe Perchese597cd02010-07-01 08:24:32 +0200653 pr_info("%s: mrw address space %s selected\n",
654 cdi->name, mrw_address_space[space]);
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200655 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656}
657
658static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
659 struct rwrt_feature_desc *rfd)
660{
661 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200662 char buffer[24];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 int ret;
664
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200665 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */
668 cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200669 cgc.cmd[8] = sizeof(buffer); /* often 0x18 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 cgc.quiet = 1;
671
672 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200673 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675 memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200676 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677}
678
679static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
680{
681 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200682 char buffer[16];
Alexey Dobriyan56052d52005-12-01 17:10:40 -0500683 __be16 *feature_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 int ret;
685
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200686 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
688 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
689 cgc.cmd[3] = CDF_HWDM;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200690 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 cgc.quiet = 1;
692
693 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200694 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Alexey Dobriyan56052d52005-12-01 17:10:40 -0500696 feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 if (be16_to_cpu(*feature_code) == CDF_HWDM)
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200698 return 0;
699
700 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701}
702
703
704static int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
705{
706 struct rwrt_feature_desc rfd;
707 int ret;
708
709 *write = 0;
710
711 if ((ret = cdrom_get_random_writable(cdi, &rfd)))
712 return ret;
713
714 if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
715 *write = 1;
716
717 return 0;
718}
719
720static int cdrom_media_erasable(struct cdrom_device_info *cdi)
721{
722 disc_information di;
723 int ret;
724
725 ret = cdrom_get_disc_info(cdi, &di);
726 if (ret < 0 || ret < offsetof(typeof(di), n_first_track))
727 return -1;
728
729 return di.erasable;
730}
731
732/*
733 * FIXME: check RO bit
734 */
735static int cdrom_dvdram_open_write(struct cdrom_device_info *cdi)
736{
737 int ret = cdrom_media_erasable(cdi);
738
739 /*
740 * allow writable open if media info read worked and media is
741 * erasable, _or_ if it fails since not all drives support it
742 */
743 if (!ret)
744 return 1;
745
746 return 0;
747}
748
749static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
750{
751 disc_information di;
752 int ret;
753
754 /*
755 * always reset to DMA lba space on open
756 */
757 if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_DMA)) {
Joe Perchese597cd02010-07-01 08:24:32 +0200758 pr_err("failed setting lba address space\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 return 1;
760 }
761
762 ret = cdrom_get_disc_info(cdi, &di);
763 if (ret < 0 || ret < offsetof(typeof(di),disc_type))
764 return 1;
765
766 if (!di.erasable)
767 return 1;
768
769 /*
770 * mrw_status
771 * 0 - not MRW formatted
772 * 1 - MRW bgformat started, but not running or complete
773 * 2 - MRW bgformat in progress
774 * 3 - MRW formatting complete
775 */
776 ret = 0;
Joe Perchese597cd02010-07-01 08:24:32 +0200777 pr_info("open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (!di.mrw_status)
779 ret = 1;
780 else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE &&
781 mrw_format_restart)
782 ret = cdrom_mrw_bgformat(cdi, 1);
783
784 return ret;
785}
786
787static int mo_open_write(struct cdrom_device_info *cdi)
788{
789 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200790 char buffer[255];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 int ret;
792
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200793 init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 cgc.quiet = 1;
795
796 /*
797 * obtain write protect information as per
798 * drivers/scsi/sd.c:sd_read_write_protect_flag
799 */
800
801 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0);
802 if (ret)
803 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_VENDOR_PAGE, 0);
804 if (ret) {
805 cgc.buflen = 255;
806 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0);
807 }
808
809 /* drive gave us no info, let the user go ahead */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200810 if (ret)
811 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200813 return buffer[3] & 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814}
815
816static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
817{
818 struct rwrt_feature_desc rfd;
819 int ret;
820
821 if ((ret = cdrom_has_defect_mgt(cdi)))
822 return ret;
823
824 if ((ret = cdrom_get_random_writable(cdi, &rfd)))
825 return ret;
826 else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
827 ret = !rfd.curr;
828
Joe Perches5944b2c2014-05-04 17:05:02 -0700829 cd_dbg(CD_OPEN, "can open for random write\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 return ret;
831}
832
833static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
834{
835 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200836 char buffer[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 int ret, mmc3_profile;
838
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200839 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
841 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
842 cgc.cmd[1] = 0;
843 cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200844 cgc.cmd[8] = sizeof(buffer); /* Allocation Length */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 cgc.quiet = 1;
846
847 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
848 mmc3_profile = 0xffff;
849 else
850 mmc3_profile = (buffer[6] << 8) | buffer[7];
851
852 cdi->mmc3_profile = mmc3_profile;
853}
854
855static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
856{
857 switch (cdi->mmc3_profile) {
858 case 0x12: /* DVD-RAM */
859 case 0x1A: /* DVD+RW */
860 return 0;
861 default:
862 return 1;
863 }
864}
865
866/*
867 * returns 0 for ok to open write, non-0 to disallow
868 */
869static int cdrom_open_write(struct cdrom_device_info *cdi)
870{
871 int mrw, mrw_write, ram_write;
872 int ret = 1;
873
874 mrw = 0;
875 if (!cdrom_is_mrw(cdi, &mrw_write))
876 mrw = 1;
877
878 if (CDROM_CAN(CDC_MO_DRIVE))
879 ram_write = 1;
880 else
881 (void) cdrom_is_random_writable(cdi, &ram_write);
882
883 if (mrw)
884 cdi->mask &= ~CDC_MRW;
885 else
886 cdi->mask |= CDC_MRW;
887
888 if (mrw_write)
889 cdi->mask &= ~CDC_MRW_W;
890 else
891 cdi->mask |= CDC_MRW_W;
892
893 if (ram_write)
894 cdi->mask &= ~CDC_RAM;
895 else
896 cdi->mask |= CDC_RAM;
897
898 if (CDROM_CAN(CDC_MRW_W))
899 ret = cdrom_mrw_open_write(cdi);
900 else if (CDROM_CAN(CDC_DVD_RAM))
901 ret = cdrom_dvdram_open_write(cdi);
902 else if (CDROM_CAN(CDC_RAM) &&
903 !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_MRW|CDC_MO_DRIVE))
904 ret = cdrom_ram_open_write(cdi);
905 else if (CDROM_CAN(CDC_MO_DRIVE))
906 ret = mo_open_write(cdi);
907 else if (!cdrom_is_dvd_rw(cdi))
908 ret = 0;
909
910 return ret;
911}
912
913static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi)
914{
915 struct packet_command cgc;
916
917 if (cdi->mmc3_profile != 0x1a) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700918 cd_dbg(CD_CLOSE, "%s: No DVD+RW\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 return;
920 }
921
922 if (!cdi->media_written) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700923 cd_dbg(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 return;
925 }
926
Joe Perchese597cd02010-07-01 08:24:32 +0200927 pr_info("%s: dirty DVD+RW media, \"finalizing\"\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928
929 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
930 cgc.cmd[0] = GPCMD_FLUSH_CACHE;
931 cgc.timeout = 30*HZ;
932 cdi->ops->generic_packet(cdi, &cgc);
933
934 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
935 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
936 cgc.timeout = 3000*HZ;
937 cgc.quiet = 1;
938 cdi->ops->generic_packet(cdi, &cgc);
939
940 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
941 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
942 cgc.cmd[2] = 2; /* Close session */
943 cgc.quiet = 1;
944 cgc.timeout = 3000*HZ;
945 cdi->ops->generic_packet(cdi, &cgc);
946
947 cdi->media_written = 0;
948}
949
950static int cdrom_close_write(struct cdrom_device_info *cdi)
951{
952#if 0
953 return cdrom_flush_cache(cdi);
954#else
955 return 0;
956#endif
957}
958
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959static
Joe Perches82b91542014-05-04 17:05:05 -0700960int open_for_data(struct cdrom_device_info *cdi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
962 int ret;
963 struct cdrom_device_ops *cdo = cdi->ops;
964 tracktype tracks;
Joe Perches5944b2c2014-05-04 17:05:02 -0700965 cd_dbg(CD_OPEN, "entering open_for_data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 /* Check if the driver can report drive status. If it can, we
967 can do clever things. If it can't, well, we at least tried! */
968 if (cdo->drive_status != NULL) {
969 ret = cdo->drive_status(cdi, CDSL_CURRENT);
Joe Perches5944b2c2014-05-04 17:05:02 -0700970 cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (ret == CDS_TRAY_OPEN) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700972 cd_dbg(CD_OPEN, "the tray is open...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 /* can/may i close it? */
974 if (CDROM_CAN(CDC_CLOSE_TRAY) &&
975 cdi->options & CDO_AUTO_CLOSE) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700976 cd_dbg(CD_OPEN, "trying to close the tray\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 ret=cdo->tray_move(cdi,0);
978 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700979 cd_dbg(CD_OPEN, "bummer. tried to close the tray but failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 /* Ignore the error from the low
981 level driver. We don't care why it
982 couldn't close the tray. We only care
983 that there is no disc in the drive,
984 since that is the _REAL_ problem here.*/
985 ret=-ENOMEDIUM;
986 goto clean_up_and_return;
987 }
988 } else {
Joe Perches5944b2c2014-05-04 17:05:02 -0700989 cd_dbg(CD_OPEN, "bummer. this drive can't close the tray.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 ret=-ENOMEDIUM;
991 goto clean_up_and_return;
992 }
993 /* Ok, the door should be closed now.. Check again */
994 ret = cdo->drive_status(cdi, CDSL_CURRENT);
995 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700996 cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
997 cd_dbg(CD_OPEN, "tray might not contain a medium\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 ret=-ENOMEDIUM;
999 goto clean_up_and_return;
1000 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001001 cd_dbg(CD_OPEN, "the tray is now closed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 }
1003 /* the door should be closed now, check for the disc */
1004 ret = cdo->drive_status(cdi, CDSL_CURRENT);
1005 if (ret!=CDS_DISC_OK) {
1006 ret = -ENOMEDIUM;
1007 goto clean_up_and_return;
1008 }
1009 }
1010 cdrom_count_tracks(cdi, &tracks);
1011 if (tracks.error == CDS_NO_DISC) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001012 cd_dbg(CD_OPEN, "bummer. no disc.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 ret=-ENOMEDIUM;
1014 goto clean_up_and_return;
1015 }
1016 /* CD-Players which don't use O_NONBLOCK, workman
1017 * for example, need bit CDO_CHECK_TYPE cleared! */
1018 if (tracks.data==0) {
1019 if (cdi->options & CDO_CHECK_TYPE) {
1020 /* give people a warning shot, now that CDO_CHECK_TYPE
1021 is the default case! */
Joe Perches5944b2c2014-05-04 17:05:02 -07001022 cd_dbg(CD_OPEN, "bummer. wrong media type.\n");
1023 cd_dbg(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
1024 (unsigned int)task_pid_nr(current));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 ret=-EMEDIUMTYPE;
1026 goto clean_up_and_return;
1027 }
1028 else {
Joe Perches5944b2c2014-05-04 17:05:02 -07001029 cd_dbg(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
1031 }
1032
Joe Perches5944b2c2014-05-04 17:05:02 -07001033 cd_dbg(CD_OPEN, "all seems well, opening the devicen");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
1035 /* all seems well, we can open the device */
1036 ret = cdo->open(cdi, 0); /* open for data */
Joe Perches5944b2c2014-05-04 17:05:02 -07001037 cd_dbg(CD_OPEN, "opening the device gave me %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 /* After all this careful checking, we shouldn't have problems
1039 opening the device, but we don't want the device locked if
1040 this somehow fails... */
1041 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001042 cd_dbg(CD_OPEN, "open device failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 goto clean_up_and_return;
1044 }
1045 if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) {
1046 cdo->lock_door(cdi, 1);
Joe Perches5944b2c2014-05-04 17:05:02 -07001047 cd_dbg(CD_OPEN, "door locked\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001049 cd_dbg(CD_OPEN, "device opened successfully\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 return ret;
1051
1052 /* Something failed. Try to unlock the drive, because some drivers
1053 (notably ide-cd) lock the drive after every command. This produced
1054 a nasty bug where after mount failed, the drive would remain locked!
1055 This ensures that the drive gets unlocked after a mount fails. This
1056 is a goto to avoid bloating the driver with redundant code. */
1057clean_up_and_return:
Joe Perches5944b2c2014-05-04 17:05:02 -07001058 cd_dbg(CD_OPEN, "open failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
1060 cdo->lock_door(cdi, 0);
Joe Perches5944b2c2014-05-04 17:05:02 -07001061 cd_dbg(CD_OPEN, "door unlocked\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063 return ret;
1064}
1065
Joe Perches82b91542014-05-04 17:05:05 -07001066/* We use the open-option O_NONBLOCK to indicate that the
1067 * purpose of opening is only for subsequent ioctl() calls; no device
1068 * integrity checks are performed.
1069 *
1070 * We hope that all cd-player programs will adopt this convention. It
1071 * is in their own interest: device control becomes a lot easier
1072 * this way.
1073 */
1074int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
1075 fmode_t mode)
1076{
1077 int ret;
1078
1079 cd_dbg(CD_OPEN, "entering cdrom_open\n");
1080
1081 /* open is event synchronization point, check events first */
1082 check_disk_change(bdev);
1083
1084 /* if this was a O_NONBLOCK open and we should honor the flags,
1085 * do a quick open without drive/disc integrity checks. */
1086 cdi->use_count++;
1087 if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
1088 ret = cdi->ops->open(cdi, 1);
1089 } else {
1090 ret = open_for_data(cdi);
1091 if (ret)
1092 goto err;
1093 cdrom_mmc3_profile(cdi);
1094 if (mode & FMODE_WRITE) {
1095 ret = -EROFS;
1096 if (cdrom_open_write(cdi))
1097 goto err_release;
1098 if (!CDROM_CAN(CDC_RAM))
1099 goto err_release;
1100 ret = 0;
1101 cdi->media_written = 0;
1102 }
1103 }
1104
1105 if (ret)
1106 goto err;
1107
1108 cd_dbg(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
1109 cdi->name, cdi->use_count);
1110 return 0;
1111err_release:
1112 if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
1113 cdi->ops->lock_door(cdi, 0);
1114 cd_dbg(CD_OPEN, "door unlocked\n");
1115 }
1116 cdi->ops->release(cdi);
1117err:
1118 cdi->use_count--;
1119 return ret;
1120}
1121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122/* This code is similar to that in open_for_data. The routine is called
1123 whenever an audio play operation is requested.
1124*/
Adrian Bunkecb80c62008-03-04 11:23:51 +01001125static int check_for_audio_disc(struct cdrom_device_info * cdi,
1126 struct cdrom_device_ops * cdo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
1128 int ret;
1129 tracktype tracks;
Joe Perches5944b2c2014-05-04 17:05:02 -07001130 cd_dbg(CD_OPEN, "entering check_for_audio_disc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 if (!(cdi->options & CDO_CHECK_TYPE))
1132 return 0;
1133 if (cdo->drive_status != NULL) {
1134 ret = cdo->drive_status(cdi, CDSL_CURRENT);
Joe Perches5944b2c2014-05-04 17:05:02 -07001135 cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 if (ret == CDS_TRAY_OPEN) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001137 cd_dbg(CD_OPEN, "the tray is open...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 /* can/may i close it? */
1139 if (CDROM_CAN(CDC_CLOSE_TRAY) &&
1140 cdi->options & CDO_AUTO_CLOSE) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001141 cd_dbg(CD_OPEN, "trying to close the tray\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 ret=cdo->tray_move(cdi,0);
1143 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001144 cd_dbg(CD_OPEN, "bummer. tried to close tray but failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 /* Ignore the error from the low
1146 level driver. We don't care why it
1147 couldn't close the tray. We only care
1148 that there is no disc in the drive,
1149 since that is the _REAL_ problem here.*/
1150 return -ENOMEDIUM;
1151 }
1152 } else {
Joe Perches5944b2c2014-05-04 17:05:02 -07001153 cd_dbg(CD_OPEN, "bummer. this driver can't close the tray.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 return -ENOMEDIUM;
1155 }
1156 /* Ok, the door should be closed now.. Check again */
1157 ret = cdo->drive_status(cdi, CDSL_CURRENT);
1158 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001159 cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 return -ENOMEDIUM;
1161 }
1162 if (ret!=CDS_DISC_OK) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001163 cd_dbg(CD_OPEN, "bummer. disc isn't ready.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 return -EIO;
1165 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001166 cd_dbg(CD_OPEN, "the tray is now closed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 }
1168 }
1169 cdrom_count_tracks(cdi, &tracks);
1170 if (tracks.error)
1171 return(tracks.error);
1172
1173 if (tracks.audio==0)
1174 return -EMEDIUMTYPE;
1175
1176 return 0;
1177}
1178
Al Virobbc1cc92007-10-07 17:54:28 -04001179void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180{
1181 struct cdrom_device_ops *cdo = cdi->ops;
1182 int opened_for_data;
1183
Joe Perches5944b2c2014-05-04 17:05:02 -07001184 cd_dbg(CD_CLOSE, "entering cdrom_release\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
1186 if (cdi->use_count > 0)
1187 cdi->use_count--;
Borislav Petkov35841f72008-02-06 01:38:08 -08001188
1189 if (cdi->use_count == 0) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001190 cd_dbg(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n",
1191 cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 cdrom_dvd_rw_close_write(cdi);
Borislav Petkov35841f72008-02-06 01:38:08 -08001193
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01001194 if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001195 cd_dbg(CD_CLOSE, "Unlocking door!\n");
Borislav Petkov35841f72008-02-06 01:38:08 -08001196 cdo->lock_door(cdi, 0);
1197 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
Borislav Petkov35841f72008-02-06 01:38:08 -08001199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
Al Virobbc1cc92007-10-07 17:54:28 -04001201 !(mode & FMODE_NDELAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
1203 /*
1204 * flush cache on last write release
1205 */
1206 if (CDROM_CAN(CDC_RAM) && !cdi->use_count && cdi->for_data)
1207 cdrom_close_write(cdi);
1208
1209 cdo->release(cdi);
1210 if (cdi->use_count == 0) { /* last process that closes dev*/
1211 if (opened_for_data &&
1212 cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
1213 cdo->tray_move(cdi, 1);
1214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215}
1216
1217static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
1218 struct cdrom_changer_info *buf)
1219{
1220 struct packet_command cgc;
1221 struct cdrom_device_ops *cdo = cdi->ops;
1222 int length;
1223
1224 /*
1225 * Sanyo changer isn't spec compliant (doesn't use regular change
1226 * LOAD_UNLOAD command, and it doesn't implement the mech status
1227 * command below
1228 */
1229 if (cdi->sanyo_slot) {
1230 buf->hdr.nslots = 3;
1231 buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot;
1232 for (length = 0; length < 3; length++) {
1233 buf->slots[length].disc_present = 1;
1234 buf->slots[length].change = 0;
1235 }
1236 return 0;
1237 }
1238
1239 length = sizeof(struct cdrom_mechstat_header) +
1240 cdi->capacity * sizeof(struct cdrom_slot);
1241
1242 init_cdrom_command(&cgc, buf, length, CGC_DATA_READ);
1243 cgc.cmd[0] = GPCMD_MECHANISM_STATUS;
1244 cgc.cmd[8] = (length >> 8) & 0xff;
1245 cgc.cmd[9] = length & 0xff;
1246 return cdo->generic_packet(cdi, &cgc);
1247}
1248
1249static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
1250{
1251 struct cdrom_changer_info *info;
1252 int ret;
1253
Joe Perches5944b2c2014-05-04 17:05:02 -07001254 cd_dbg(CD_CHANGER, "entering cdrom_slot_status()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 if (cdi->sanyo_slot)
1256 return CDS_NO_INFO;
1257
1258 info = kmalloc(sizeof(*info), GFP_KERNEL);
1259 if (!info)
1260 return -ENOMEM;
1261
1262 if ((ret = cdrom_read_mech_status(cdi, info)))
1263 goto out_free;
1264
1265 if (info->slots[slot].disc_present)
1266 ret = CDS_DISC_OK;
1267 else
1268 ret = CDS_NO_DISC;
1269
1270out_free:
1271 kfree(info);
1272 return ret;
1273}
1274
1275/* Return the number of slots for an ATAPI/SCSI cdrom,
1276 * return 1 if not a changer.
1277 */
1278int cdrom_number_of_slots(struct cdrom_device_info *cdi)
1279{
1280 int status;
1281 int nslots = 1;
1282 struct cdrom_changer_info *info;
1283
Joe Perches5944b2c2014-05-04 17:05:02 -07001284 cd_dbg(CD_CHANGER, "entering cdrom_number_of_slots()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 /* cdrom_read_mech_status requires a valid value for capacity: */
1286 cdi->capacity = 0;
1287
1288 info = kmalloc(sizeof(*info), GFP_KERNEL);
1289 if (!info)
1290 return -ENOMEM;
1291
1292 if ((status = cdrom_read_mech_status(cdi, info)) == 0)
1293 nslots = info->hdr.nslots;
1294
1295 kfree(info);
1296 return nslots;
1297}
1298
1299
1300/* If SLOT < 0, unload the current slot. Otherwise, try to load SLOT. */
1301static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
1302{
1303 struct packet_command cgc;
1304
Joe Perches5944b2c2014-05-04 17:05:02 -07001305 cd_dbg(CD_CHANGER, "entering cdrom_load_unload()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 if (cdi->sanyo_slot && slot < 0)
1307 return 0;
1308
1309 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
1310 cgc.cmd[0] = GPCMD_LOAD_UNLOAD;
1311 cgc.cmd[4] = 2 + (slot >= 0);
1312 cgc.cmd[8] = slot;
1313 cgc.timeout = 60 * HZ;
1314
1315 /* The Sanyo 3 CD changer uses byte 7 of the
1316 GPCMD_TEST_UNIT_READY to command to switch CDs instead of
1317 using the GPCMD_LOAD_UNLOAD opcode. */
1318 if (cdi->sanyo_slot && -1 < slot) {
1319 cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
1320 cgc.cmd[7] = slot;
1321 cgc.cmd[4] = cgc.cmd[8] = 0;
1322 cdi->sanyo_slot = slot ? slot : 3;
1323 }
1324
1325 return cdi->ops->generic_packet(cdi, &cgc);
1326}
1327
1328static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
1329{
1330 struct cdrom_changer_info *info;
1331 int curslot;
1332 int ret;
1333
Joe Perches5944b2c2014-05-04 17:05:02 -07001334 cd_dbg(CD_CHANGER, "entering cdrom_select_disc()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 if (!CDROM_CAN(CDC_SELECT_DISC))
1336 return -EDRIVE_CANT_DO_THIS;
1337
Tejun Heo2d921722010-12-08 20:57:38 +01001338 if (cdi->ops->check_events)
1339 cdi->ops->check_events(cdi, 0, slot);
1340 else
1341 cdi->ops->media_changed(cdi, slot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
1343 if (slot == CDSL_NONE) {
1344 /* set media changed bits, on both queues */
1345 cdi->mc_flags = 0x3;
1346 return cdrom_load_unload(cdi, -1);
1347 }
1348
1349 info = kmalloc(sizeof(*info), GFP_KERNEL);
1350 if (!info)
1351 return -ENOMEM;
1352
1353 if ((ret = cdrom_read_mech_status(cdi, info))) {
1354 kfree(info);
1355 return ret;
1356 }
1357
1358 curslot = info->hdr.curslot;
1359 kfree(info);
1360
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01001361 if (cdi->use_count > 1 || cdi->keeplocked) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 if (slot == CDSL_CURRENT) {
1363 return curslot;
1364 } else {
1365 return -EBUSY;
1366 }
1367 }
1368
1369 /* Specifying CDSL_CURRENT will attempt to load the currnet slot,
1370 which is useful if it had been previously unloaded.
1371 Whether it can or not, it returns the current slot.
1372 Similarly, if slot happens to be the current one, we still
1373 try and load it. */
1374 if (slot == CDSL_CURRENT)
1375 slot = curslot;
1376
1377 /* set media changed bits on both queues */
1378 cdi->mc_flags = 0x3;
1379 if ((ret = cdrom_load_unload(cdi, slot)))
1380 return ret;
1381
1382 return slot;
1383}
1384
Tejun Heo2d921722010-12-08 20:57:38 +01001385/*
1386 * As cdrom implements an extra ioctl consumer for media changed
1387 * event, it needs to buffer ->check_events() output, such that event
1388 * is not lost for both the usual VFS and ioctl paths.
1389 * cdi->{vfs|ioctl}_events are used to buffer pending events for each
1390 * path.
1391 *
1392 * XXX: Locking is non-existent. cdi->ops->check_events() can be
1393 * called in parallel and buffering fields are accessed without any
1394 * exclusion. The original media_changed code had the same problem.
1395 * It might be better to simply deprecate CDROM_MEDIA_CHANGED ioctl
1396 * and remove this cruft altogether. It doesn't have much usefulness
1397 * at this point.
1398 */
1399static void cdrom_update_events(struct cdrom_device_info *cdi,
1400 unsigned int clearing)
1401{
1402 unsigned int events;
1403
1404 events = cdi->ops->check_events(cdi, clearing, CDSL_CURRENT);
1405 cdi->vfs_events |= events;
1406 cdi->ioctl_events |= events;
1407}
1408
1409unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
1410 unsigned int clearing)
1411{
1412 unsigned int events;
1413
1414 cdrom_update_events(cdi, clearing);
1415 events = cdi->vfs_events;
1416 cdi->vfs_events = 0;
1417 return events;
1418}
Jens Axboe30a7caa2010-12-16 17:58:50 +01001419EXPORT_SYMBOL(cdrom_check_events);
Tejun Heo2d921722010-12-08 20:57:38 +01001420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421/* We want to make media_changed accessible to the user through an
1422 * ioctl. The main problem now is that we must double-buffer the
1423 * low-level implementation, to assure that the VFS and the user both
1424 * see a medium change once.
1425 */
1426
1427static
1428int media_changed(struct cdrom_device_info *cdi, int queue)
1429{
1430 unsigned int mask = (1 << (queue & 1));
1431 int ret = !!(cdi->mc_flags & mask);
Tejun Heo2d921722010-12-08 20:57:38 +01001432 bool changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
1434 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
Tejun Heo2d921722010-12-08 20:57:38 +01001435 return ret;
1436
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 /* changed since last call? */
Tejun Heo2d921722010-12-08 20:57:38 +01001438 if (cdi->ops->check_events) {
1439 BUG_ON(!queue); /* shouldn't be called from VFS path */
1440 cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE);
1441 changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE;
1442 cdi->ioctl_events = 0;
1443 } else
1444 changed = cdi->ops->media_changed(cdi, CDSL_CURRENT);
1445
1446 if (changed) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 cdi->mc_flags = 0x3; /* set bit on both queues */
1448 ret |= 1;
1449 cdi->media_written = 0;
1450 }
Tejun Heo2d921722010-12-08 20:57:38 +01001451
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 cdi->mc_flags &= ~mask; /* clear bit */
1453 return ret;
1454}
1455
1456int cdrom_media_changed(struct cdrom_device_info *cdi)
1457{
1458 /* This talks to the VFS, which doesn't like errors - just 1 or 0.
1459 * Returning "0" is always safe (media hasn't been changed). Do that
1460 * if the low-level cdrom driver dosn't support media changed. */
1461 if (cdi == NULL || cdi->ops->media_changed == NULL)
1462 return 0;
1463 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
1464 return 0;
1465 return media_changed(cdi, 0);
1466}
1467
1468/* badly broken, I know. Is due for a fixup anytime. */
1469static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
1470{
1471 struct cdrom_tochdr header;
1472 struct cdrom_tocentry entry;
1473 int ret, i;
1474 tracks->data=0;
1475 tracks->audio=0;
1476 tracks->cdi=0;
1477 tracks->xa=0;
1478 tracks->error=0;
Joe Perches5944b2c2014-05-04 17:05:02 -07001479 cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 /* Grab the TOC header so we can see how many tracks there are */
1481 if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
1482 if (ret == -ENOMEDIUM)
1483 tracks->error = CDS_NO_DISC;
1484 else
1485 tracks->error = CDS_NO_INFO;
1486 return;
1487 }
1488 /* check what type of tracks are on this disc */
1489 entry.cdte_format = CDROM_MSF;
1490 for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
1491 entry.cdte_track = i;
1492 if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
1493 tracks->error=CDS_NO_INFO;
1494 return;
1495 }
1496 if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
1497 if (entry.cdte_format == 0x10)
1498 tracks->cdi++;
1499 else if (entry.cdte_format == 0x20)
1500 tracks->xa++;
1501 else
1502 tracks->data++;
1503 } else
1504 tracks->audio++;
Joe Perches5944b2c2014-05-04 17:05:02 -07001505 cd_dbg(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 i, entry.cdte_format, entry.cdte_ctrl);
1507 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001508 cd_dbg(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
1509 header.cdth_trk1, tracks->audio, tracks->data,
1510 tracks->cdi, tracks->xa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511}
1512
1513/* Requests to the low-level drivers will /always/ be done in the
1514 following format convention:
1515
1516 CDROM_LBA: all data-related requests.
1517 CDROM_MSF: all audio-related requests.
1518
1519 However, a low-level implementation is allowed to refuse this
1520 request, and return information in its own favorite format.
1521
1522 It doesn't make sense /at all/ to ask for a play_audio in LBA
1523 format, or ask for multi-session info in MSF format. However, for
1524 backward compatibility these format requests will be satisfied, but
1525 the requests to the low-level drivers will be sanitized in the more
1526 meaningful format indicated above.
1527 */
1528
1529static
1530void sanitize_format(union cdrom_addr *addr,
1531 u_char * curr, u_char requested)
1532{
1533 if (*curr == requested)
1534 return; /* nothing to be done! */
1535 if (requested == CDROM_LBA) {
1536 addr->lba = (int) addr->msf.frame +
1537 75 * (addr->msf.second - 2 + 60 * addr->msf.minute);
1538 } else { /* CDROM_MSF */
1539 int lba = addr->lba;
1540 addr->msf.frame = lba % 75;
1541 lba /= 75;
1542 lba += 2;
1543 addr->msf.second = lba % 60;
1544 addr->msf.minute = lba / 60;
1545 }
1546 *curr = requested;
1547}
1548
1549void init_cdrom_command(struct packet_command *cgc, void *buf, int len,
1550 int type)
1551{
1552 memset(cgc, 0, sizeof(struct packet_command));
1553 if (buf)
1554 memset(buf, 0, len);
1555 cgc->buffer = (char *) buf;
1556 cgc->buflen = len;
1557 cgc->data_direction = type;
Jens Axboe2e11c202007-01-03 08:10:35 +01001558 cgc->timeout = CDROM_DEF_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559}
1560
1561/* DVD handling */
1562
1563#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
1564#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
1565
1566static void setup_report_key(struct packet_command *cgc, unsigned agid, unsigned type)
1567{
1568 cgc->cmd[0] = GPCMD_REPORT_KEY;
1569 cgc->cmd[10] = type | (agid << 6);
1570 switch (type) {
1571 case 0: case 8: case 5: {
1572 cgc->buflen = 8;
1573 break;
1574 }
1575 case 1: {
1576 cgc->buflen = 16;
1577 break;
1578 }
1579 case 2: case 4: {
1580 cgc->buflen = 12;
1581 break;
1582 }
1583 }
1584 cgc->cmd[9] = cgc->buflen;
1585 cgc->data_direction = CGC_DATA_READ;
1586}
1587
1588static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned type)
1589{
1590 cgc->cmd[0] = GPCMD_SEND_KEY;
1591 cgc->cmd[10] = type | (agid << 6);
1592 switch (type) {
1593 case 1: {
1594 cgc->buflen = 16;
1595 break;
1596 }
1597 case 3: {
1598 cgc->buflen = 12;
1599 break;
1600 }
1601 case 6: {
1602 cgc->buflen = 8;
1603 break;
1604 }
1605 }
1606 cgc->cmd[9] = cgc->buflen;
1607 cgc->data_direction = CGC_DATA_WRITE;
1608}
1609
1610static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
1611{
1612 int ret;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001613 u_char buf[20];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 struct packet_command cgc;
1615 struct cdrom_device_ops *cdo = cdi->ops;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001616 rpc_state_t rpc_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001618 memset(buf, 0, sizeof(buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
1620
1621 switch (ai->type) {
1622 /* LU data send */
1623 case DVD_LU_SEND_AGID:
Joe Perches5944b2c2014-05-04 17:05:02 -07001624 cd_dbg(CD_DVD, "entering DVD_LU_SEND_AGID\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 cgc.quiet = 1;
1626 setup_report_key(&cgc, ai->lsa.agid, 0);
1627
1628 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001629 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
1631 ai->lsa.agid = buf[7] >> 6;
1632 /* Returning data, let host change state */
1633 break;
1634
1635 case DVD_LU_SEND_KEY1:
Joe Perches5944b2c2014-05-04 17:05:02 -07001636 cd_dbg(CD_DVD, "entering DVD_LU_SEND_KEY1\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 setup_report_key(&cgc, ai->lsk.agid, 2);
1638
1639 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001640 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
1642 copy_key(ai->lsk.key, &buf[4]);
1643 /* Returning data, let host change state */
1644 break;
1645
1646 case DVD_LU_SEND_CHALLENGE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001647 cd_dbg(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 setup_report_key(&cgc, ai->lsc.agid, 1);
1649
1650 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001651 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 copy_chal(ai->lsc.chal, &buf[4]);
1654 /* Returning data, let host change state */
1655 break;
1656
1657 /* Post-auth key */
1658 case DVD_LU_SEND_TITLE_KEY:
Joe Perches5944b2c2014-05-04 17:05:02 -07001659 cd_dbg(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 cgc.quiet = 1;
1661 setup_report_key(&cgc, ai->lstk.agid, 4);
1662 cgc.cmd[5] = ai->lstk.lba;
1663 cgc.cmd[4] = ai->lstk.lba >> 8;
1664 cgc.cmd[3] = ai->lstk.lba >> 16;
1665 cgc.cmd[2] = ai->lstk.lba >> 24;
1666
1667 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001668 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
1670 ai->lstk.cpm = (buf[4] >> 7) & 1;
1671 ai->lstk.cp_sec = (buf[4] >> 6) & 1;
1672 ai->lstk.cgms = (buf[4] >> 4) & 3;
1673 copy_key(ai->lstk.title_key, &buf[5]);
1674 /* Returning data, let host change state */
1675 break;
1676
1677 case DVD_LU_SEND_ASF:
Joe Perches5944b2c2014-05-04 17:05:02 -07001678 cd_dbg(CD_DVD, "entering DVD_LU_SEND_ASF\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 setup_report_key(&cgc, ai->lsasf.agid, 5);
1680
1681 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001682 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
1684 ai->lsasf.asf = buf[7] & 1;
1685 break;
1686
1687 /* LU data receive (LU changes state) */
1688 case DVD_HOST_SEND_CHALLENGE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001689 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 setup_send_key(&cgc, ai->hsc.agid, 1);
1691 buf[1] = 0xe;
1692 copy_chal(&buf[4], ai->hsc.chal);
1693
1694 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001695 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
1697 ai->type = DVD_LU_SEND_KEY1;
1698 break;
1699
1700 case DVD_HOST_SEND_KEY2:
Joe Perches5944b2c2014-05-04 17:05:02 -07001701 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_KEY2\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 setup_send_key(&cgc, ai->hsk.agid, 3);
1703 buf[1] = 0xa;
1704 copy_key(&buf[4], ai->hsk.key);
1705
1706 if ((ret = cdo->generic_packet(cdi, &cgc))) {
1707 ai->type = DVD_AUTH_FAILURE;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001708 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 }
1710 ai->type = DVD_AUTH_ESTABLISHED;
1711 break;
1712
1713 /* Misc */
1714 case DVD_INVALIDATE_AGID:
1715 cgc.quiet = 1;
Joe Perches5944b2c2014-05-04 17:05:02 -07001716 cd_dbg(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 setup_report_key(&cgc, ai->lsa.agid, 0x3f);
1718 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001719 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 break;
1721
1722 /* Get region settings */
1723 case DVD_LU_SEND_RPC_STATE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001724 cd_dbg(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 setup_report_key(&cgc, 0, 8);
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001726 memset(&rpc_state, 0, sizeof(rpc_state_t));
1727 cgc.buffer = (char *) &rpc_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
1729 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001730 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001732 ai->lrpcs.type = rpc_state.type_code;
1733 ai->lrpcs.vra = rpc_state.vra;
1734 ai->lrpcs.ucca = rpc_state.ucca;
1735 ai->lrpcs.region_mask = rpc_state.region_mask;
1736 ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 break;
1738
1739 /* Set region settings */
1740 case DVD_HOST_SEND_RPC_STATE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001741 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 setup_send_key(&cgc, 0, 6);
1743 buf[1] = 6;
1744 buf[4] = ai->hrpcs.pdrc;
1745
1746 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001747 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 break;
1749
1750 default:
Joe Perches5944b2c2014-05-04 17:05:02 -07001751 cd_dbg(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001752 return -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001754
1755 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756}
1757
Marcin Slusarzd1941392008-11-16 19:06:37 +01001758static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s,
1759 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760{
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001761 unsigned char buf[21], *base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 struct dvd_layer *layer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 struct cdrom_device_ops *cdo = cdi->ops;
1764 int ret, layer_num = s->physical.layer_num;
1765
1766 if (layer_num >= DVD_LAYERS)
1767 return -EINVAL;
1768
Marcin Slusarzd1941392008-11-16 19:06:37 +01001769 init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ);
1770 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1771 cgc->cmd[6] = layer_num;
1772 cgc->cmd[7] = s->type;
1773 cgc->cmd[9] = cgc->buflen & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 /*
1776 * refrain from reporting errors on non-existing layers (mainly)
1777 */
Marcin Slusarzd1941392008-11-16 19:06:37 +01001778 cgc->quiet = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
Marcin Slusarzd1941392008-11-16 19:06:37 +01001780 ret = cdo->generic_packet(cdi, cgc);
1781 if (ret)
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001782 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 base = &buf[4];
1785 layer = &s->physical.layer[layer_num];
1786
1787 /*
1788 * place the data... really ugly, but at least we won't have to
1789 * worry about endianess in userspace.
1790 */
1791 memset(layer, 0, sizeof(*layer));
1792 layer->book_version = base[0] & 0xf;
1793 layer->book_type = base[0] >> 4;
1794 layer->min_rate = base[1] & 0xf;
1795 layer->disc_size = base[1] >> 4;
1796 layer->layer_type = base[2] & 0xf;
1797 layer->track_path = (base[2] >> 4) & 1;
1798 layer->nlayers = (base[2] >> 5) & 3;
1799 layer->track_density = base[3] & 0xf;
1800 layer->linear_density = base[3] >> 4;
1801 layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
1802 layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
1803 layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
1804 layer->bca = base[16] >> 7;
1805
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001806 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807}
1808
Marcin Slusarzd1941392008-11-16 19:06:37 +01001809static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s,
1810 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811{
1812 int ret;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001813 u_char buf[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 struct cdrom_device_ops *cdo = cdi->ops;
1815
Marcin Slusarzd1941392008-11-16 19:06:37 +01001816 init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ);
1817 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1818 cgc->cmd[6] = s->copyright.layer_num;
1819 cgc->cmd[7] = s->type;
1820 cgc->cmd[8] = cgc->buflen >> 8;
1821 cgc->cmd[9] = cgc->buflen & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
Marcin Slusarzd1941392008-11-16 19:06:37 +01001823 ret = cdo->generic_packet(cdi, cgc);
1824 if (ret)
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001825 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 s->copyright.cpst = buf[4];
1828 s->copyright.rmi = buf[5];
1829
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001830 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831}
1832
Marcin Slusarzd1941392008-11-16 19:06:37 +01001833static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s,
1834 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835{
1836 int ret, size;
1837 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 struct cdrom_device_ops *cdo = cdi->ops;
1839
1840 size = sizeof(s->disckey.value) + 4;
1841
Marcin Slusarzd1941392008-11-16 19:06:37 +01001842 buf = kmalloc(size, GFP_KERNEL);
1843 if (!buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844 return -ENOMEM;
1845
Marcin Slusarzd1941392008-11-16 19:06:37 +01001846 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1847 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1848 cgc->cmd[7] = s->type;
1849 cgc->cmd[8] = size >> 8;
1850 cgc->cmd[9] = size & 0xff;
1851 cgc->cmd[10] = s->disckey.agid << 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852
Marcin Slusarzd1941392008-11-16 19:06:37 +01001853 ret = cdo->generic_packet(cdi, cgc);
1854 if (!ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
1856
1857 kfree(buf);
1858 return ret;
1859}
1860
Marcin Slusarzd1941392008-11-16 19:06:37 +01001861static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s,
1862 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863{
Marcin Slusarzd1941392008-11-16 19:06:37 +01001864 int ret, size = 4 + 188;
1865 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 struct cdrom_device_ops *cdo = cdi->ops;
1867
Marcin Slusarzd1941392008-11-16 19:06:37 +01001868 buf = kmalloc(size, GFP_KERNEL);
1869 if (!buf)
1870 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Marcin Slusarzd1941392008-11-16 19:06:37 +01001872 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1873 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1874 cgc->cmd[7] = s->type;
1875 cgc->cmd[9] = cgc->buflen & 0xff;
1876
1877 ret = cdo->generic_packet(cdi, cgc);
1878 if (ret)
1879 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
1881 s->bca.len = buf[0] << 8 | buf[1];
1882 if (s->bca.len < 12 || s->bca.len > 188) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001883 cd_dbg(CD_WARNING, "Received invalid BCA length (%d)\n",
1884 s->bca.len);
Marcin Slusarzd1941392008-11-16 19:06:37 +01001885 ret = -EIO;
1886 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 }
1888 memcpy(s->bca.value, &buf[4], s->bca.len);
Marcin Slusarzd1941392008-11-16 19:06:37 +01001889 ret = 0;
1890out:
1891 kfree(buf);
1892 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893}
1894
Marcin Slusarzd1941392008-11-16 19:06:37 +01001895static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s,
1896 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897{
1898 int ret = 0, size;
1899 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 struct cdrom_device_ops *cdo = cdi->ops;
1901
1902 size = sizeof(s->manufact.value) + 4;
1903
Marcin Slusarzd1941392008-11-16 19:06:37 +01001904 buf = kmalloc(size, GFP_KERNEL);
1905 if (!buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 return -ENOMEM;
1907
Marcin Slusarzd1941392008-11-16 19:06:37 +01001908 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1909 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1910 cgc->cmd[7] = s->type;
1911 cgc->cmd[8] = size >> 8;
1912 cgc->cmd[9] = size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
Marcin Slusarzd1941392008-11-16 19:06:37 +01001914 ret = cdo->generic_packet(cdi, cgc);
1915 if (ret)
1916 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917
1918 s->manufact.len = buf[0] << 8 | buf[1];
Andrew Mortonaec9f372011-08-02 12:43:50 +02001919 if (s->manufact.len < 0) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001920 cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d)\n",
1921 s->manufact.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 ret = -EIO;
1923 } else {
Andrew Mortonaec9f372011-08-02 12:43:50 +02001924 if (s->manufact.len > 2048) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001925 cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d): truncating to 2048\n",
1926 s->manufact.len);
Andrew Mortonaec9f372011-08-02 12:43:50 +02001927 s->manufact.len = 2048;
1928 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 memcpy(s->manufact.value, &buf[4], s->manufact.len);
1930 }
1931
Marcin Slusarzd1941392008-11-16 19:06:37 +01001932out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 kfree(buf);
1934 return ret;
1935}
1936
Marcin Slusarzd1941392008-11-16 19:06:37 +01001937static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s,
1938 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939{
1940 switch (s->type) {
1941 case DVD_STRUCT_PHYSICAL:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001942 return dvd_read_physical(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943
1944 case DVD_STRUCT_COPYRIGHT:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001945 return dvd_read_copyright(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946
1947 case DVD_STRUCT_DISCKEY:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001948 return dvd_read_disckey(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949
1950 case DVD_STRUCT_BCA:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001951 return dvd_read_bca(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952
1953 case DVD_STRUCT_MANUFACT:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001954 return dvd_read_manufact(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
1956 default:
Joe Perches5944b2c2014-05-04 17:05:02 -07001957 cd_dbg(CD_WARNING, ": Invalid DVD structure read requested (%d)\n",
1958 s->type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959 return -EINVAL;
1960 }
1961}
1962
1963int cdrom_mode_sense(struct cdrom_device_info *cdi,
1964 struct packet_command *cgc,
1965 int page_code, int page_control)
1966{
1967 struct cdrom_device_ops *cdo = cdi->ops;
1968
1969 memset(cgc->cmd, 0, sizeof(cgc->cmd));
1970
1971 cgc->cmd[0] = GPCMD_MODE_SENSE_10;
1972 cgc->cmd[2] = page_code | (page_control << 6);
1973 cgc->cmd[7] = cgc->buflen >> 8;
1974 cgc->cmd[8] = cgc->buflen & 0xff;
1975 cgc->data_direction = CGC_DATA_READ;
1976 return cdo->generic_packet(cdi, cgc);
1977}
1978
1979int cdrom_mode_select(struct cdrom_device_info *cdi,
1980 struct packet_command *cgc)
1981{
1982 struct cdrom_device_ops *cdo = cdi->ops;
1983
1984 memset(cgc->cmd, 0, sizeof(cgc->cmd));
1985 memset(cgc->buffer, 0, 2);
1986 cgc->cmd[0] = GPCMD_MODE_SELECT_10;
1987 cgc->cmd[1] = 0x10; /* PF */
1988 cgc->cmd[7] = cgc->buflen >> 8;
1989 cgc->cmd[8] = cgc->buflen & 0xff;
1990 cgc->data_direction = CGC_DATA_WRITE;
1991 return cdo->generic_packet(cdi, cgc);
1992}
1993
1994static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
1995 struct cdrom_subchnl *subchnl, int mcn)
1996{
1997 struct cdrom_device_ops *cdo = cdi->ops;
1998 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001999 char buffer[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 int ret;
2001
2002 init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
2003 cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
2004 cgc.cmd[1] = 2; /* MSF addressing */
2005 cgc.cmd[2] = 0x40; /* request subQ data */
2006 cgc.cmd[3] = mcn ? 2 : 1;
2007 cgc.cmd[8] = 16;
2008
2009 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02002010 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
2012 subchnl->cdsc_audiostatus = cgc.buffer[1];
2013 subchnl->cdsc_format = CDROM_MSF;
2014 subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf;
2015 subchnl->cdsc_trk = cgc.buffer[6];
2016 subchnl->cdsc_ind = cgc.buffer[7];
2017
2018 subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13];
2019 subchnl->cdsc_reladdr.msf.second = cgc.buffer[14];
2020 subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15];
2021 subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9];
2022 subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
2023 subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
2024
FUJITA Tomonorifce53842008-07-04 09:33:01 +02002025 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026}
2027
2028/*
2029 * Specific READ_10 interface
2030 */
2031static int cdrom_read_cd(struct cdrom_device_info *cdi,
2032 struct packet_command *cgc, int lba,
2033 int blocksize, int nblocks)
2034{
2035 struct cdrom_device_ops *cdo = cdi->ops;
2036
2037 memset(&cgc->cmd, 0, sizeof(cgc->cmd));
2038 cgc->cmd[0] = GPCMD_READ_10;
2039 cgc->cmd[2] = (lba >> 24) & 0xff;
2040 cgc->cmd[3] = (lba >> 16) & 0xff;
2041 cgc->cmd[4] = (lba >> 8) & 0xff;
2042 cgc->cmd[5] = lba & 0xff;
2043 cgc->cmd[6] = (nblocks >> 16) & 0xff;
2044 cgc->cmd[7] = (nblocks >> 8) & 0xff;
2045 cgc->cmd[8] = nblocks & 0xff;
2046 cgc->buflen = blocksize * nblocks;
2047 return cdo->generic_packet(cdi, cgc);
2048}
2049
2050/* very generic interface for reading the various types of blocks */
2051static int cdrom_read_block(struct cdrom_device_info *cdi,
2052 struct packet_command *cgc,
2053 int lba, int nblocks, int format, int blksize)
2054{
2055 struct cdrom_device_ops *cdo = cdi->ops;
2056
2057 memset(&cgc->cmd, 0, sizeof(cgc->cmd));
2058 cgc->cmd[0] = GPCMD_READ_CD;
2059 /* expected sector size - cdda,mode1,etc. */
2060 cgc->cmd[1] = format << 2;
2061 /* starting address */
2062 cgc->cmd[2] = (lba >> 24) & 0xff;
2063 cgc->cmd[3] = (lba >> 16) & 0xff;
2064 cgc->cmd[4] = (lba >> 8) & 0xff;
2065 cgc->cmd[5] = lba & 0xff;
2066 /* number of blocks */
2067 cgc->cmd[6] = (nblocks >> 16) & 0xff;
2068 cgc->cmd[7] = (nblocks >> 8) & 0xff;
2069 cgc->cmd[8] = nblocks & 0xff;
2070 cgc->buflen = blksize * nblocks;
2071
2072 /* set the header info returned */
2073 switch (blksize) {
2074 case CD_FRAMESIZE_RAW0 : cgc->cmd[9] = 0x58; break;
2075 case CD_FRAMESIZE_RAW1 : cgc->cmd[9] = 0x78; break;
2076 case CD_FRAMESIZE_RAW : cgc->cmd[9] = 0xf8; break;
2077 default : cgc->cmd[9] = 0x10;
2078 }
2079
2080 return cdo->generic_packet(cdi, cgc);
2081}
2082
2083static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2084 int lba, int nframes)
2085{
2086 struct packet_command cgc;
2087 int ret = 0;
2088 int nr;
2089
2090 cdi->last_sense = 0;
2091
2092 memset(&cgc, 0, sizeof(cgc));
2093
2094 /*
2095 * start with will ra.nframes size, back down if alloc fails
2096 */
2097 nr = nframes;
2098 do {
2099 cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL);
2100 if (cgc.buffer)
2101 break;
2102
2103 nr >>= 1;
2104 } while (nr);
2105
2106 if (!nr)
2107 return -ENOMEM;
2108
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 cgc.data_direction = CGC_DATA_READ;
2110 while (nframes > 0) {
2111 if (nr > nframes)
2112 nr = nframes;
2113
2114 ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
2115 if (ret)
2116 break;
Dan Carpenter822bfa52012-02-06 10:20:45 +01002117 if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 ret = -EFAULT;
2119 break;
2120 }
2121 ubuf += CD_FRAMESIZE_RAW * nr;
2122 nframes -= nr;
2123 lba += nr;
2124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 kfree(cgc.buffer);
2126 return ret;
2127}
2128
2129static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2130 int lba, int nframes)
2131{
Jens Axboe165125e2007-07-24 09:28:11 +02002132 struct request_queue *q = cdi->disk->queue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 struct request *rq;
2134 struct bio *bio;
2135 unsigned int len;
2136 int nr, ret = 0;
2137
2138 if (!q)
2139 return -ENXIO;
2140
2141 cdi->last_sense = 0;
2142
2143 while (nframes) {
2144 nr = nframes;
2145 if (cdi->cdda_method == CDDA_BPC_SINGLE)
2146 nr = 1;
Martin K. Petersenae03bf62009-05-22 17:17:50 -04002147 if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9))
2148 nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
2150 len = nr * CD_FRAMESIZE_RAW;
2151
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002152 rq = blk_get_request(q, READ, GFP_KERNEL);
2153 if (!rq) {
2154 ret = -ENOMEM;
Jens Axboedd1cab92005-06-20 14:06:01 +02002155 break;
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002156 }
2157
2158 ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
2159 if (ret) {
2160 blk_put_request(rq);
2161 break;
2162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 rq->cmd[0] = GPCMD_READ_CD;
2165 rq->cmd[1] = 1 << 2;
2166 rq->cmd[2] = (lba >> 24) & 0xff;
2167 rq->cmd[3] = (lba >> 16) & 0xff;
2168 rq->cmd[4] = (lba >> 8) & 0xff;
2169 rq->cmd[5] = lba & 0xff;
2170 rq->cmd[6] = (nr >> 16) & 0xff;
2171 rq->cmd[7] = (nr >> 8) & 0xff;
2172 rq->cmd[8] = nr & 0xff;
2173 rq->cmd[9] = 0xf8;
2174
2175 rq->cmd_len = 12;
Jens Axboe4aff5e22006-08-10 08:44:47 +02002176 rq->cmd_type = REQ_TYPE_BLOCK_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 rq->timeout = 60 * HZ;
2178 bio = rq->bio;
2179
James Bottomley 994ca9a2005-06-20 14:11:09 +02002180 if (blk_execute_rq(q, cdi->disk, rq, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 struct request_sense *s = rq->sense;
2182 ret = -EIO;
2183 cdi->last_sense = s->sense_key;
2184 }
2185
Jens Axboe8e5cfc42006-12-19 11:12:46 +01002186 if (blk_rq_unmap_user(bio))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 ret = -EFAULT;
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002188 blk_put_request(rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
2190 if (ret)
2191 break;
2192
2193 nframes -= nr;
2194 lba += nr;
2195 ubuf += len;
2196 }
2197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 return ret;
2199}
2200
2201static int cdrom_read_cdda(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2202 int lba, int nframes)
2203{
2204 int ret;
2205
2206 if (cdi->cdda_method == CDDA_OLD)
2207 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes);
2208
2209retry:
2210 /*
2211 * for anything else than success and io error, we need to retry
2212 */
2213 ret = cdrom_read_cdda_bpc(cdi, ubuf, lba, nframes);
2214 if (!ret || ret != -EIO)
2215 return ret;
2216
2217 /*
2218 * I've seen drives get sense 4/8/3 udma crc errors on multi
2219 * frame dma, so drop to single frame dma if we need to
2220 */
2221 if (cdi->cdda_method == CDDA_BPC_FULL && nframes > 1) {
Joe Perchese597cd02010-07-01 08:24:32 +02002222 pr_info("dropping to single frame dma\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223 cdi->cdda_method = CDDA_BPC_SINGLE;
2224 goto retry;
2225 }
2226
2227 /*
2228 * so we have an io error of some sort with multi frame dma. if the
2229 * condition wasn't a hardware error
2230 * problems, not for any error
2231 */
2232 if (cdi->last_sense != 0x04 && cdi->last_sense != 0x0b)
2233 return ret;
2234
Joe Perchese597cd02010-07-01 08:24:32 +02002235 pr_info("dropping to old style cdda (sense=%x)\n", cdi->last_sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002236 cdi->cdda_method = CDDA_OLD;
2237 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes);
2238}
2239
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002240static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi,
2241 void __user *argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242{
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002243 struct cdrom_multisession ms_info;
2244 u8 requested_format;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 int ret;
2246
Joe Perches5944b2c2014-05-04 17:05:02 -07002247 cd_dbg(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002248
2249 if (!(cdi->ops->capability & CDC_MULTI_SESSION))
2250 return -ENOSYS;
2251
2252 if (copy_from_user(&ms_info, argp, sizeof(ms_info)))
2253 return -EFAULT;
2254
2255 requested_format = ms_info.addr_format;
2256 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2257 return -EINVAL;
2258 ms_info.addr_format = CDROM_LBA;
2259
2260 ret = cdi->ops->get_last_session(cdi, &ms_info);
2261 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 return ret;
2263
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002264 sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format);
2265
2266 if (copy_to_user(argp, &ms_info, sizeof(ms_info)))
2267 return -EFAULT;
2268
Joe Perches5944b2c2014-05-04 17:05:02 -07002269 cd_dbg(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002270 return 0;
2271}
2272
2273static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
2274{
Joe Perches5944b2c2014-05-04 17:05:02 -07002275 cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002276
2277 if (!CDROM_CAN(CDC_OPEN_TRAY))
2278 return -ENOSYS;
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002279 if (cdi->use_count != 1 || cdi->keeplocked)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002280 return -EBUSY;
2281 if (CDROM_CAN(CDC_LOCK)) {
2282 int ret = cdi->ops->lock_door(cdi, 0);
2283 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 return ret;
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002287 return cdi->ops->tray_move(cdi, 1);
2288}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002290static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi)
2291{
Joe Perches5944b2c2014-05-04 17:05:02 -07002292 cd_dbg(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002294 if (!CDROM_CAN(CDC_CLOSE_TRAY))
2295 return -ENOSYS;
2296 return cdi->ops->tray_move(cdi, 0);
2297}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002299static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
2300 unsigned long arg)
2301{
Joe Perches5944b2c2014-05-04 17:05:02 -07002302 cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002304 if (!CDROM_CAN(CDC_OPEN_TRAY))
2305 return -ENOSYS;
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002306 if (cdi->keeplocked)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002307 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002309 cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
2310 if (arg)
2311 cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
2312 return 0;
2313}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002315static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
2316 unsigned long arg)
2317{
2318 struct cdrom_changer_info *info;
2319 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Joe Perches5944b2c2014-05-04 17:05:02 -07002321 cd_dbg(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002323 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
2324 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002326 /* cannot select disc or select current disc */
2327 if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
2328 return media_changed(cdi, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002330 if ((unsigned int)arg >= cdi->capacity)
2331 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002333 info = kmalloc(sizeof(*info), GFP_KERNEL);
2334 if (!info)
2335 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002337 ret = cdrom_read_mech_status(cdi, info);
2338 if (!ret)
2339 ret = info->slots[arg].change;
2340 kfree(info);
2341 return ret;
2342}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002344static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
2345 unsigned long arg)
2346{
Joe Perches5944b2c2014-05-04 17:05:02 -07002347 cd_dbg(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002349 /*
2350 * Options need to be in sync with capability.
2351 * Too late for that, so we have to check each one separately.
2352 */
2353 switch (arg) {
2354 case CDO_USE_FFLAGS:
2355 case CDO_CHECK_TYPE:
2356 break;
2357 case CDO_LOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 if (!CDROM_CAN(CDC_LOCK))
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002359 return -ENOSYS;
2360 break;
2361 case 0:
2362 return cdi->options;
2363 /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
2364 default:
2365 if (!CDROM_CAN(arg))
2366 return -ENOSYS;
2367 }
2368 cdi->options |= (int) arg;
2369 return cdi->options;
2370}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002372static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi,
2373 unsigned long arg)
2374{
Joe Perches5944b2c2014-05-04 17:05:02 -07002375 cd_dbg(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002377 cdi->options &= ~(int) arg;
2378 return cdi->options;
2379}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002381static int cdrom_ioctl_select_speed(struct cdrom_device_info *cdi,
2382 unsigned long arg)
2383{
Joe Perches5944b2c2014-05-04 17:05:02 -07002384 cd_dbg(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002385
2386 if (!CDROM_CAN(CDC_SELECT_SPEED))
2387 return -ENOSYS;
2388 return cdi->ops->select_speed(cdi, arg);
2389}
2390
2391static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi,
2392 unsigned long arg)
2393{
Joe Perches5944b2c2014-05-04 17:05:02 -07002394 cd_dbg(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002395
2396 if (!CDROM_CAN(CDC_SELECT_DISC))
2397 return -ENOSYS;
2398
2399 if (arg != CDSL_CURRENT && arg != CDSL_NONE) {
2400 if ((int)arg >= cdi->capacity)
2401 return -EINVAL;
2402 }
2403
2404 /*
2405 * ->select_disc is a hook to allow a driver-specific way of
2406 * seleting disc. However, since there is no equivalent hook for
2407 * cdrom_slot_status this may not actually be useful...
2408 */
2409 if (cdi->ops->select_disc)
2410 return cdi->ops->select_disc(cdi, arg);
2411
Joe Perches5944b2c2014-05-04 17:05:02 -07002412 cd_dbg(CD_CHANGER, "Using generic cdrom_select_disc()\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002413 return cdrom_select_disc(cdi, arg);
2414}
2415
2416static int cdrom_ioctl_reset(struct cdrom_device_info *cdi,
2417 struct block_device *bdev)
2418{
Joe Perches5944b2c2014-05-04 17:05:02 -07002419 cd_dbg(CD_DO_IOCTL, "entering CDROM_RESET\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002420
2421 if (!capable(CAP_SYS_ADMIN))
2422 return -EACCES;
2423 if (!CDROM_CAN(CDC_RESET))
2424 return -ENOSYS;
Peter Zijlstraf98393a2007-05-06 14:49:54 -07002425 invalidate_bdev(bdev);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002426 return cdi->ops->reset(cdi);
2427}
2428
2429static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,
2430 unsigned long arg)
2431{
Joe Perches5944b2c2014-05-04 17:05:02 -07002432 cd_dbg(CD_DO_IOCTL, "%socking door\n", arg ? "L" : "Unl");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002433
2434 if (!CDROM_CAN(CDC_LOCK))
2435 return -EDRIVE_CANT_DO_THIS;
2436
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002437 cdi->keeplocked = arg ? 1 : 0;
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002438
2439 /*
2440 * Don't unlock the door on multiple opens by default, but allow
2441 * root to do so.
2442 */
2443 if (cdi->use_count != 1 && !arg && !capable(CAP_SYS_ADMIN))
2444 return -EBUSY;
2445 return cdi->ops->lock_door(cdi, arg);
2446}
2447
2448static int cdrom_ioctl_debug(struct cdrom_device_info *cdi,
2449 unsigned long arg)
2450{
Joe Perches5944b2c2014-05-04 17:05:02 -07002451 cd_dbg(CD_DO_IOCTL, "%sabling debug\n", arg ? "En" : "Dis");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002452
2453 if (!capable(CAP_SYS_ADMIN))
2454 return -EACCES;
2455 debug = arg ? 1 : 0;
2456 return debug;
2457}
2458
2459static int cdrom_ioctl_get_capability(struct cdrom_device_info *cdi)
2460{
Joe Perches5944b2c2014-05-04 17:05:02 -07002461 cd_dbg(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002462 return (cdi->ops->capability & ~cdi->mask);
2463}
2464
2465/*
2466 * The following function is implemented, although very few audio
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 * discs give Universal Product Code information, which should just be
2468 * the Medium Catalog Number on the box. Note, that the way the code
2469 * is written on the CD is /not/ uniform across all discs!
2470 */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002471static int cdrom_ioctl_get_mcn(struct cdrom_device_info *cdi,
2472 void __user *argp)
2473{
2474 struct cdrom_mcn mcn;
2475 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Joe Perches5944b2c2014-05-04 17:05:02 -07002477 cd_dbg(CD_DO_IOCTL, "entering CDROM_GET_MCN\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002479 if (!(cdi->ops->capability & CDC_MCN))
2480 return -ENOSYS;
2481 ret = cdi->ops->get_mcn(cdi, &mcn);
2482 if (ret)
2483 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002485 if (copy_to_user(argp, &mcn, sizeof(mcn)))
2486 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002487 cd_dbg(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002488 return 0;
2489}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002491static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi,
2492 unsigned long arg)
2493{
Joe Perches5944b2c2014-05-04 17:05:02 -07002494 cd_dbg(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002496 if (!(cdi->ops->capability & CDC_DRIVE_STATUS))
2497 return -ENOSYS;
2498 if (!CDROM_CAN(CDC_SELECT_DISC) ||
2499 (arg == CDSL_CURRENT || arg == CDSL_NONE))
2500 return cdi->ops->drive_status(cdi, CDSL_CURRENT);
2501 if (((int)arg >= cdi->capacity))
2502 return -EINVAL;
2503 return cdrom_slot_status(cdi, arg);
2504}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002506/*
2507 * Ok, this is where problems start. The current interface for the
2508 * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002509 * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunately, while this
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002510 * is often the case, it is also very common for CDs to have some tracks
2511 * with data, and some tracks with audio. Just because I feel like it,
2512 * I declare the following to be the best way to cope. If the CD has ANY
2513 * data tracks on it, it will be returned as a data CD. If it has any XA
2514 * tracks, I will return it as that. Now I could simplify this interface
2515 * by combining these returns with the above, but this more clearly
2516 * demonstrates the problem with the current interface. Too bad this
2517 * wasn't designed to use bitmasks... -Erik
2518 *
2519 * Well, now we have the option CDS_MIXED: a mixed-type CD.
2520 * User level programmers might feel the ioctl is not very useful.
2521 * ---david
2522 */
2523static int cdrom_ioctl_disc_status(struct cdrom_device_info *cdi)
2524{
2525 tracktype tracks;
2526
Joe Perches5944b2c2014-05-04 17:05:02 -07002527 cd_dbg(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002528
2529 cdrom_count_tracks(cdi, &tracks);
2530 if (tracks.error)
2531 return tracks.error;
2532
2533 /* Policy mode on */
2534 if (tracks.audio > 0) {
2535 if (!tracks.data && !tracks.cdi && !tracks.xa)
2536 return CDS_AUDIO;
2537 else
2538 return CDS_MIXED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 }
2540
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002541 if (tracks.cdi > 0)
2542 return CDS_XA_2_2;
2543 if (tracks.xa > 0)
2544 return CDS_XA_2_1;
2545 if (tracks.data > 0)
2546 return CDS_DATA_1;
2547 /* Policy mode off */
2548
Joe Perches5944b2c2014-05-04 17:05:02 -07002549 cd_dbg(CD_WARNING, "This disc doesn't have any tracks I recognize!\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002550 return CDS_NO_INFO;
2551}
2552
2553static int cdrom_ioctl_changer_nslots(struct cdrom_device_info *cdi)
2554{
Joe Perches5944b2c2014-05-04 17:05:02 -07002555 cd_dbg(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002556 return cdi->capacity;
2557}
2558
2559static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi,
2560 void __user *argp)
2561{
2562 struct cdrom_subchnl q;
2563 u8 requested, back;
2564 int ret;
2565
Joe Perches5944b2c2014-05-04 17:05:02 -07002566 /* cd_dbg(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002567
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002568 if (copy_from_user(&q, argp, sizeof(q)))
2569 return -EFAULT;
2570
2571 requested = q.cdsc_format;
2572 if (requested != CDROM_MSF && requested != CDROM_LBA)
2573 return -EINVAL;
2574 q.cdsc_format = CDROM_MSF;
2575
2576 ret = cdi->ops->audio_ioctl(cdi, CDROMSUBCHNL, &q);
2577 if (ret)
2578 return ret;
2579
2580 back = q.cdsc_format; /* local copy */
2581 sanitize_format(&q.cdsc_absaddr, &back, requested);
2582 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
2583
2584 if (copy_to_user(argp, &q, sizeof(q)))
2585 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002586 /* cd_dbg(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002587 return 0;
2588}
2589
2590static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi,
2591 void __user *argp)
2592{
2593 struct cdrom_tochdr header;
2594 int ret;
2595
Joe Perches5944b2c2014-05-04 17:05:02 -07002596 /* cd_dbg(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002597
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002598 if (copy_from_user(&header, argp, sizeof(header)))
2599 return -EFAULT;
2600
2601 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
2602 if (ret)
2603 return ret;
2604
2605 if (copy_to_user(argp, &header, sizeof(header)))
2606 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002607 /* cd_dbg(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002608 return 0;
2609}
2610
2611static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi,
2612 void __user *argp)
2613{
2614 struct cdrom_tocentry entry;
2615 u8 requested_format;
2616 int ret;
2617
Joe Perches5944b2c2014-05-04 17:05:02 -07002618 /* cd_dbg(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002619
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002620 if (copy_from_user(&entry, argp, sizeof(entry)))
2621 return -EFAULT;
2622
2623 requested_format = entry.cdte_format;
2624 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2625 return -EINVAL;
2626 /* make interface to low-level uniform */
2627 entry.cdte_format = CDROM_MSF;
2628 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry);
2629 if (ret)
2630 return ret;
2631 sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format);
2632
2633 if (copy_to_user(argp, &entry, sizeof(entry)))
2634 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002635 /* cd_dbg(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002636 return 0;
2637}
2638
2639static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi,
2640 void __user *argp)
2641{
2642 struct cdrom_msf msf;
2643
Joe Perches5944b2c2014-05-04 17:05:02 -07002644 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002645
2646 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2647 return -ENOSYS;
2648 if (copy_from_user(&msf, argp, sizeof(msf)))
2649 return -EFAULT;
2650 return cdi->ops->audio_ioctl(cdi, CDROMPLAYMSF, &msf);
2651}
2652
2653static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi,
2654 void __user *argp)
2655{
2656 struct cdrom_ti ti;
2657 int ret;
2658
Joe Perches5944b2c2014-05-04 17:05:02 -07002659 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002660
2661 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2662 return -ENOSYS;
2663 if (copy_from_user(&ti, argp, sizeof(ti)))
2664 return -EFAULT;
2665
2666 ret = check_for_audio_disc(cdi, cdi->ops);
2667 if (ret)
2668 return ret;
2669 return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti);
2670}
2671static int cdrom_ioctl_volctrl(struct cdrom_device_info *cdi,
2672 void __user *argp)
2673{
2674 struct cdrom_volctrl volume;
2675
Joe Perches5944b2c2014-05-04 17:05:02 -07002676 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002677
2678 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2679 return -ENOSYS;
2680 if (copy_from_user(&volume, argp, sizeof(volume)))
2681 return -EFAULT;
2682 return cdi->ops->audio_ioctl(cdi, CDROMVOLCTRL, &volume);
2683}
2684
2685static int cdrom_ioctl_volread(struct cdrom_device_info *cdi,
2686 void __user *argp)
2687{
2688 struct cdrom_volctrl volume;
2689 int ret;
2690
Joe Perches5944b2c2014-05-04 17:05:02 -07002691 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002692
2693 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2694 return -ENOSYS;
2695
2696 ret = cdi->ops->audio_ioctl(cdi, CDROMVOLREAD, &volume);
2697 if (ret)
2698 return ret;
2699
2700 if (copy_to_user(argp, &volume, sizeof(volume)))
2701 return -EFAULT;
2702 return 0;
2703}
2704
2705static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi,
2706 unsigned int cmd)
2707{
2708 int ret;
2709
Joe Perches5944b2c2014-05-04 17:05:02 -07002710 cd_dbg(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002711
2712 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2713 return -ENOSYS;
2714 ret = check_for_audio_disc(cdi, cdi->ops);
2715 if (ret)
2716 return ret;
2717 return cdi->ops->audio_ioctl(cdi, cmd, NULL);
2718}
2719
2720/*
2721 * Just about every imaginable ioctl is supported in the Uniform layer
2722 * these days.
2723 * ATAPI / SCSI specific code now mainly resides in mmc_ioctl().
2724 */
Al Virobbc1cc92007-10-07 17:54:28 -04002725int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
2726 fmode_t mode, unsigned int cmd, unsigned long arg)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002727{
2728 void __user *argp = (void __user *)arg;
2729 int ret;
2730
2731 /*
2732 * Try the generic SCSI command ioctl's first.
2733 */
Paolo Bonzini577ebb32012-01-12 16:01:27 +01002734 ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002735 if (ret != -ENOTTY)
2736 return ret;
2737
2738 switch (cmd) {
2739 case CDROMMULTISESSION:
2740 return cdrom_ioctl_multisession(cdi, argp);
2741 case CDROMEJECT:
2742 return cdrom_ioctl_eject(cdi);
2743 case CDROMCLOSETRAY:
2744 return cdrom_ioctl_closetray(cdi);
2745 case CDROMEJECT_SW:
2746 return cdrom_ioctl_eject_sw(cdi, arg);
2747 case CDROM_MEDIA_CHANGED:
2748 return cdrom_ioctl_media_changed(cdi, arg);
2749 case CDROM_SET_OPTIONS:
2750 return cdrom_ioctl_set_options(cdi, arg);
2751 case CDROM_CLEAR_OPTIONS:
2752 return cdrom_ioctl_clear_options(cdi, arg);
2753 case CDROM_SELECT_SPEED:
2754 return cdrom_ioctl_select_speed(cdi, arg);
2755 case CDROM_SELECT_DISC:
2756 return cdrom_ioctl_select_disc(cdi, arg);
2757 case CDROMRESET:
Al Virobbc1cc92007-10-07 17:54:28 -04002758 return cdrom_ioctl_reset(cdi, bdev);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002759 case CDROM_LOCKDOOR:
2760 return cdrom_ioctl_lock_door(cdi, arg);
2761 case CDROM_DEBUG:
2762 return cdrom_ioctl_debug(cdi, arg);
2763 case CDROM_GET_CAPABILITY:
2764 return cdrom_ioctl_get_capability(cdi);
2765 case CDROM_GET_MCN:
2766 return cdrom_ioctl_get_mcn(cdi, argp);
2767 case CDROM_DRIVE_STATUS:
2768 return cdrom_ioctl_drive_status(cdi, arg);
2769 case CDROM_DISC_STATUS:
2770 return cdrom_ioctl_disc_status(cdi);
2771 case CDROM_CHANGER_NSLOTS:
2772 return cdrom_ioctl_changer_nslots(cdi);
2773 }
2774
2775 /*
2776 * Use the ioctls that are implemented through the generic_packet()
2777 * interface. this may look at bit funny, but if -ENOTTY is
2778 * returned that particular ioctl is not implemented and we
2779 * let it go through the device specific ones.
2780 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 if (CDROM_CAN(CDC_GENERIC_PACKET)) {
2782 ret = mmc_ioctl(cdi, cmd, arg);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002783 if (ret != -ENOTTY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 }
2786
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002787 /*
Joe Perches5944b2c2014-05-04 17:05:02 -07002788 * Note: most of the cd_dbg() calls are commented out here,
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002789 * because they fill up the sys log when CD players poll
2790 * the drive.
2791 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 switch (cmd) {
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002793 case CDROMSUBCHNL:
2794 return cdrom_ioctl_get_subchnl(cdi, argp);
2795 case CDROMREADTOCHDR:
2796 return cdrom_ioctl_read_tochdr(cdi, argp);
2797 case CDROMREADTOCENTRY:
2798 return cdrom_ioctl_read_tocentry(cdi, argp);
2799 case CDROMPLAYMSF:
2800 return cdrom_ioctl_play_msf(cdi, argp);
2801 case CDROMPLAYTRKIND:
2802 return cdrom_ioctl_play_trkind(cdi, argp);
2803 case CDROMVOLCTRL:
2804 return cdrom_ioctl_volctrl(cdi, argp);
2805 case CDROMVOLREAD:
2806 return cdrom_ioctl_volread(cdi, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 case CDROMSTART:
2808 case CDROMSTOP:
2809 case CDROMPAUSE:
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002810 case CDROMRESUME:
2811 return cdrom_ioctl_audioctl(cdi, cmd);
2812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 return -ENOSYS;
2815}
2816
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817/*
2818 * Required when we need to use READ_10 to issue other than 2048 block
2819 * reads
2820 */
2821static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
2822{
2823 struct cdrom_device_ops *cdo = cdi->ops;
2824 struct packet_command cgc;
2825 struct modesel_head mh;
2826
2827 memset(&mh, 0, sizeof(mh));
2828 mh.block_desc_length = 0x08;
2829 mh.block_length_med = (size >> 8) & 0xff;
2830 mh.block_length_lo = size & 0xff;
2831
2832 memset(&cgc, 0, sizeof(cgc));
2833 cgc.cmd[0] = 0x15;
2834 cgc.cmd[1] = 1 << 4;
2835 cgc.cmd[4] = 12;
2836 cgc.buflen = sizeof(mh);
2837 cgc.buffer = (char *) &mh;
2838 cgc.data_direction = CGC_DATA_WRITE;
2839 mh.block_desc_length = 0x08;
2840 mh.block_length_med = (size >> 8) & 0xff;
2841 mh.block_length_lo = size & 0xff;
2842
2843 return cdo->generic_packet(cdi, &cgc);
2844}
2845
Marcin Slusarz3147c532008-11-16 19:04:47 +01002846static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi,
2847 void __user *arg,
2848 struct packet_command *cgc,
2849 int cmd)
2850{
2851 struct request_sense sense;
2852 struct cdrom_msf msf;
2853 int blocksize = 0, format = 0, lba;
2854 int ret;
2855
2856 switch (cmd) {
2857 case CDROMREADRAW:
2858 blocksize = CD_FRAMESIZE_RAW;
2859 break;
2860 case CDROMREADMODE1:
2861 blocksize = CD_FRAMESIZE;
2862 format = 2;
2863 break;
2864 case CDROMREADMODE2:
2865 blocksize = CD_FRAMESIZE_RAW0;
2866 break;
2867 }
Joe Perchesa09c3912014-05-04 17:05:04 -07002868 if (copy_from_user(&msf, (struct cdrom_msf __user *)arg, sizeof(msf)))
2869 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01002870 lba = msf_to_lba(msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0);
2871 /* FIXME: we need upper bound checking, too!! */
2872 if (lba < 0)
2873 return -EINVAL;
2874
Jonathan Salwan542db012013-07-03 15:01:13 -07002875 cgc->buffer = kzalloc(blocksize, GFP_KERNEL);
Marcin Slusarz3147c532008-11-16 19:04:47 +01002876 if (cgc->buffer == NULL)
2877 return -ENOMEM;
2878
2879 memset(&sense, 0, sizeof(sense));
2880 cgc->sense = &sense;
2881 cgc->data_direction = CGC_DATA_READ;
2882 ret = cdrom_read_block(cdi, cgc, lba, 1, format, blocksize);
2883 if (ret && sense.sense_key == 0x05 &&
2884 sense.asc == 0x20 &&
2885 sense.ascq == 0x00) {
2886 /*
2887 * SCSI-II devices are not required to support
2888 * READ_CD, so let's try switching block size
2889 */
2890 /* FIXME: switch back again... */
2891 ret = cdrom_switch_blocksize(cdi, blocksize);
2892 if (ret)
2893 goto out;
2894 cgc->sense = NULL;
2895 ret = cdrom_read_cd(cdi, cgc, lba, blocksize, 1);
2896 ret |= cdrom_switch_blocksize(cdi, blocksize);
2897 }
2898 if (!ret && copy_to_user(arg, cgc->buffer, blocksize))
2899 ret = -EFAULT;
2900out:
2901 kfree(cgc->buffer);
2902 return ret;
2903}
2904
2905static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi,
2906 void __user *arg)
2907{
2908 struct cdrom_read_audio ra;
2909 int lba;
2910
Joe Perchesa09c3912014-05-04 17:05:04 -07002911 if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg,
2912 sizeof(ra)))
2913 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01002914
2915 if (ra.addr_format == CDROM_MSF)
2916 lba = msf_to_lba(ra.addr.msf.minute,
2917 ra.addr.msf.second,
2918 ra.addr.msf.frame);
2919 else if (ra.addr_format == CDROM_LBA)
2920 lba = ra.addr.lba;
2921 else
2922 return -EINVAL;
2923
2924 /* FIXME: we need upper bound checking, too!! */
2925 if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES)
2926 return -EINVAL;
2927
2928 return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes);
2929}
2930
2931static noinline int mmc_ioctl_cdrom_subchannel(struct cdrom_device_info *cdi,
2932 void __user *arg)
2933{
2934 int ret;
2935 struct cdrom_subchnl q;
2936 u_char requested, back;
Joe Perchesa09c3912014-05-04 17:05:04 -07002937 if (copy_from_user(&q, (struct cdrom_subchnl __user *)arg, sizeof(q)))
2938 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01002939 requested = q.cdsc_format;
2940 if (!((requested == CDROM_MSF) ||
2941 (requested == CDROM_LBA)))
2942 return -EINVAL;
2943 q.cdsc_format = CDROM_MSF;
2944 ret = cdrom_read_subchannel(cdi, &q, 0);
2945 if (ret)
2946 return ret;
2947 back = q.cdsc_format; /* local copy */
2948 sanitize_format(&q.cdsc_absaddr, &back, requested);
2949 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
Joe Perchesa09c3912014-05-04 17:05:04 -07002950 if (copy_to_user((struct cdrom_subchnl __user *)arg, &q, sizeof(q)))
2951 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002952 /* cd_dbg(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
Marcin Slusarz3147c532008-11-16 19:04:47 +01002953 return 0;
2954}
2955
2956static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi,
2957 void __user *arg,
2958 struct packet_command *cgc)
2959{
2960 struct cdrom_device_ops *cdo = cdi->ops;
2961 struct cdrom_msf msf;
Joe Perches5944b2c2014-05-04 17:05:02 -07002962 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
Joe Perchesa09c3912014-05-04 17:05:04 -07002963 if (copy_from_user(&msf, (struct cdrom_msf __user *)arg, sizeof(msf)))
2964 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01002965 cgc->cmd[0] = GPCMD_PLAY_AUDIO_MSF;
2966 cgc->cmd[3] = msf.cdmsf_min0;
2967 cgc->cmd[4] = msf.cdmsf_sec0;
2968 cgc->cmd[5] = msf.cdmsf_frame0;
2969 cgc->cmd[6] = msf.cdmsf_min1;
2970 cgc->cmd[7] = msf.cdmsf_sec1;
2971 cgc->cmd[8] = msf.cdmsf_frame1;
2972 cgc->data_direction = CGC_DATA_NONE;
2973 return cdo->generic_packet(cdi, cgc);
2974}
2975
2976static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi,
2977 void __user *arg,
2978 struct packet_command *cgc)
2979{
2980 struct cdrom_device_ops *cdo = cdi->ops;
2981 struct cdrom_blk blk;
Joe Perches5944b2c2014-05-04 17:05:02 -07002982 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
Joe Perchesa09c3912014-05-04 17:05:04 -07002983 if (copy_from_user(&blk, (struct cdrom_blk __user *)arg, sizeof(blk)))
2984 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01002985 cgc->cmd[0] = GPCMD_PLAY_AUDIO_10;
2986 cgc->cmd[2] = (blk.from >> 24) & 0xff;
2987 cgc->cmd[3] = (blk.from >> 16) & 0xff;
2988 cgc->cmd[4] = (blk.from >> 8) & 0xff;
2989 cgc->cmd[5] = blk.from & 0xff;
2990 cgc->cmd[7] = (blk.len >> 8) & 0xff;
2991 cgc->cmd[8] = blk.len & 0xff;
2992 cgc->data_direction = CGC_DATA_NONE;
2993 return cdo->generic_packet(cdi, cgc);
2994}
2995
2996static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi,
2997 void __user *arg,
2998 struct packet_command *cgc,
2999 unsigned int cmd)
3000{
3001 struct cdrom_volctrl volctrl;
3002 unsigned char buffer[32];
3003 char mask[sizeof(buffer)];
3004 unsigned short offset;
3005 int ret;
3006
Joe Perches5944b2c2014-05-04 17:05:02 -07003007 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLUME\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003008
Joe Perchesa09c3912014-05-04 17:05:04 -07003009 if (copy_from_user(&volctrl, (struct cdrom_volctrl __user *)arg,
3010 sizeof(volctrl)))
3011 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003012
3013 cgc->buffer = buffer;
3014 cgc->buflen = 24;
3015 ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 0);
3016 if (ret)
3017 return ret;
3018
3019 /* originally the code depended on buffer[1] to determine
3020 how much data is available for transfer. buffer[1] is
3021 unfortunately ambigious and the only reliable way seem
3022 to be to simply skip over the block descriptor... */
3023 offset = 8 + be16_to_cpu(*(__be16 *)(buffer + 6));
3024
3025 if (offset + 16 > sizeof(buffer))
3026 return -E2BIG;
3027
3028 if (offset + 16 > cgc->buflen) {
3029 cgc->buflen = offset + 16;
3030 ret = cdrom_mode_sense(cdi, cgc,
3031 GPMODE_AUDIO_CTL_PAGE, 0);
3032 if (ret)
3033 return ret;
3034 }
3035
3036 /* sanity check */
3037 if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE ||
3038 buffer[offset + 1] < 14)
3039 return -EINVAL;
3040
3041 /* now we have the current volume settings. if it was only
3042 a CDROMVOLREAD, return these values */
3043 if (cmd == CDROMVOLREAD) {
3044 volctrl.channel0 = buffer[offset+9];
3045 volctrl.channel1 = buffer[offset+11];
3046 volctrl.channel2 = buffer[offset+13];
3047 volctrl.channel3 = buffer[offset+15];
Joe Perchesa09c3912014-05-04 17:05:04 -07003048 if (copy_to_user((struct cdrom_volctrl __user *)arg, &volctrl,
3049 sizeof(volctrl)))
3050 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003051 return 0;
3052 }
3053
3054 /* get the volume mask */
3055 cgc->buffer = mask;
3056 ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 1);
3057 if (ret)
3058 return ret;
3059
3060 buffer[offset + 9] = volctrl.channel0 & mask[offset + 9];
3061 buffer[offset + 11] = volctrl.channel1 & mask[offset + 11];
3062 buffer[offset + 13] = volctrl.channel2 & mask[offset + 13];
3063 buffer[offset + 15] = volctrl.channel3 & mask[offset + 15];
3064
3065 /* set volume */
3066 cgc->buffer = buffer + offset - 8;
3067 memset(cgc->buffer, 0, 8);
3068 return cdrom_mode_select(cdi, cgc);
3069}
3070
3071static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi,
3072 struct packet_command *cgc,
3073 int cmd)
3074{
3075 struct cdrom_device_ops *cdo = cdi->ops;
Joe Perches5944b2c2014-05-04 17:05:02 -07003076 cd_dbg(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003077 cgc->cmd[0] = GPCMD_START_STOP_UNIT;
3078 cgc->cmd[1] = 1;
3079 cgc->cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
3080 cgc->data_direction = CGC_DATA_NONE;
3081 return cdo->generic_packet(cdi, cgc);
3082}
3083
3084static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi,
3085 struct packet_command *cgc,
3086 int cmd)
3087{
3088 struct cdrom_device_ops *cdo = cdi->ops;
Joe Perches5944b2c2014-05-04 17:05:02 -07003089 cd_dbg(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003090 cgc->cmd[0] = GPCMD_PAUSE_RESUME;
3091 cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
3092 cgc->data_direction = CGC_DATA_NONE;
3093 return cdo->generic_packet(cdi, cgc);
3094}
3095
3096static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi,
Marcin Slusarzd1941392008-11-16 19:06:37 +01003097 void __user *arg,
3098 struct packet_command *cgc)
Marcin Slusarz3147c532008-11-16 19:04:47 +01003099{
3100 int ret;
3101 dvd_struct *s;
3102 int size = sizeof(dvd_struct);
3103
3104 if (!CDROM_CAN(CDC_DVD))
3105 return -ENOSYS;
3106
3107 s = kmalloc(size, GFP_KERNEL);
3108 if (!s)
3109 return -ENOMEM;
3110
Joe Perches5944b2c2014-05-04 17:05:02 -07003111 cd_dbg(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003112 if (copy_from_user(s, arg, size)) {
3113 kfree(s);
3114 return -EFAULT;
3115 }
3116
Marcin Slusarzd1941392008-11-16 19:06:37 +01003117 ret = dvd_read_struct(cdi, s, cgc);
Marcin Slusarz3147c532008-11-16 19:04:47 +01003118 if (ret)
3119 goto out;
3120
3121 if (copy_to_user(arg, s, size))
3122 ret = -EFAULT;
3123out:
3124 kfree(s);
3125 return ret;
3126}
3127
3128static noinline int mmc_ioctl_dvd_auth(struct cdrom_device_info *cdi,
3129 void __user *arg)
3130{
3131 int ret;
3132 dvd_authinfo ai;
3133 if (!CDROM_CAN(CDC_DVD))
3134 return -ENOSYS;
Joe Perches5944b2c2014-05-04 17:05:02 -07003135 cd_dbg(CD_DO_IOCTL, "entering DVD_AUTH\n");
Joe Perchesa09c3912014-05-04 17:05:04 -07003136 if (copy_from_user(&ai, (dvd_authinfo __user *)arg, sizeof(ai)))
3137 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003138 ret = dvd_do_auth(cdi, &ai);
3139 if (ret)
3140 return ret;
Joe Perchesa09c3912014-05-04 17:05:04 -07003141 if (copy_to_user((dvd_authinfo __user *)arg, &ai, sizeof(ai)))
3142 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003143 return 0;
3144}
3145
3146static noinline int mmc_ioctl_cdrom_next_writable(struct cdrom_device_info *cdi,
3147 void __user *arg)
3148{
3149 int ret;
3150 long next = 0;
Joe Perches5944b2c2014-05-04 17:05:02 -07003151 cd_dbg(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003152 ret = cdrom_get_next_writable(cdi, &next);
3153 if (ret)
3154 return ret;
Joe Perchesa09c3912014-05-04 17:05:04 -07003155 if (copy_to_user((long __user *)arg, &next, sizeof(next)))
3156 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003157 return 0;
3158}
3159
3160static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi,
3161 void __user *arg)
3162{
3163 int ret;
3164 long last = 0;
Joe Perches5944b2c2014-05-04 17:05:02 -07003165 cd_dbg(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n");
Marcin Slusarz3147c532008-11-16 19:04:47 +01003166 ret = cdrom_get_last_written(cdi, &last);
3167 if (ret)
3168 return ret;
Joe Perchesa09c3912014-05-04 17:05:04 -07003169 if (copy_to_user((long __user *)arg, &last, sizeof(last)))
3170 return -EFAULT;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003171 return 0;
3172}
3173
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
3175 unsigned long arg)
Marcin Slusarz3147c532008-11-16 19:04:47 +01003176{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 struct packet_command cgc;
Marcin Slusarz3147c532008-11-16 19:04:47 +01003178 void __user *userptr = (void __user *)arg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
3180 memset(&cgc, 0, sizeof(cgc));
3181
3182 /* build a unified command and queue it through
3183 cdo->generic_packet() */
3184 switch (cmd) {
3185 case CDROMREADRAW:
3186 case CDROMREADMODE1:
Marcin Slusarz3147c532008-11-16 19:04:47 +01003187 case CDROMREADMODE2:
3188 return mmc_ioctl_cdrom_read_data(cdi, userptr, &cgc, cmd);
3189 case CDROMREADAUDIO:
3190 return mmc_ioctl_cdrom_read_audio(cdi, userptr);
3191 case CDROMSUBCHNL:
3192 return mmc_ioctl_cdrom_subchannel(cdi, userptr);
3193 case CDROMPLAYMSF:
3194 return mmc_ioctl_cdrom_play_msf(cdi, userptr, &cgc);
3195 case CDROMPLAYBLK:
3196 return mmc_ioctl_cdrom_play_blk(cdi, userptr, &cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 case CDROMVOLCTRL:
Marcin Slusarz3147c532008-11-16 19:04:47 +01003198 case CDROMVOLREAD:
3199 return mmc_ioctl_cdrom_volume(cdi, userptr, &cgc, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 case CDROMSTART:
Marcin Slusarz3147c532008-11-16 19:04:47 +01003201 case CDROMSTOP:
3202 return mmc_ioctl_cdrom_start_stop(cdi, &cgc, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 case CDROMPAUSE:
Marcin Slusarz3147c532008-11-16 19:04:47 +01003204 case CDROMRESUME:
3205 return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd);
3206 case DVD_READ_STRUCT:
Marcin Slusarzd1941392008-11-16 19:06:37 +01003207 return mmc_ioctl_dvd_read_struct(cdi, userptr, &cgc);
Marcin Slusarz3147c532008-11-16 19:04:47 +01003208 case DVD_AUTH:
3209 return mmc_ioctl_dvd_auth(cdi, userptr);
3210 case CDROM_NEXT_WRITABLE:
3211 return mmc_ioctl_cdrom_next_writable(cdi, userptr);
3212 case CDROM_LAST_WRITTEN:
3213 return mmc_ioctl_cdrom_last_written(cdi, userptr);
3214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215
3216 return -ENOTTY;
3217}
3218
3219static int cdrom_get_track_info(struct cdrom_device_info *cdi, __u16 track, __u8 type,
3220 track_information *ti)
3221{
3222 struct cdrom_device_ops *cdo = cdi->ops;
3223 struct packet_command cgc;
3224 int ret, buflen;
3225
3226 init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
3227 cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
3228 cgc.cmd[1] = type & 3;
3229 cgc.cmd[4] = (track & 0xff00) >> 8;
3230 cgc.cmd[5] = track & 0xff;
3231 cgc.cmd[8] = 8;
3232 cgc.quiet = 1;
3233
3234 if ((ret = cdo->generic_packet(cdi, &cgc)))
3235 return ret;
3236
3237 buflen = be16_to_cpu(ti->track_information_length) +
3238 sizeof(ti->track_information_length);
3239
3240 if (buflen > sizeof(track_information))
3241 buflen = sizeof(track_information);
3242
3243 cgc.cmd[8] = cgc.buflen = buflen;
3244 if ((ret = cdo->generic_packet(cdi, &cgc)))
3245 return ret;
3246
3247 /* return actual fill size */
3248 return buflen;
3249}
3250
3251/* requires CD R/RW */
3252static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di)
3253{
3254 struct cdrom_device_ops *cdo = cdi->ops;
3255 struct packet_command cgc;
3256 int ret, buflen;
3257
3258 /* set up command and get the disc info */
3259 init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
3260 cgc.cmd[0] = GPCMD_READ_DISC_INFO;
3261 cgc.cmd[8] = cgc.buflen = 2;
3262 cgc.quiet = 1;
3263
3264 if ((ret = cdo->generic_packet(cdi, &cgc)))
3265 return ret;
3266
3267 /* not all drives have the same disc_info length, so requeue
3268 * packet with the length the drive tells us it can supply
3269 */
3270 buflen = be16_to_cpu(di->disc_information_length) +
3271 sizeof(di->disc_information_length);
3272
3273 if (buflen > sizeof(disc_information))
3274 buflen = sizeof(disc_information);
3275
3276 cgc.cmd[8] = cgc.buflen = buflen;
3277 if ((ret = cdo->generic_packet(cdi, &cgc)))
3278 return ret;
3279
3280 /* return actual fill size */
3281 return buflen;
3282}
3283
3284/* return the last written block on the CD-R media. this is for the udf
3285 file system. */
3286int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
3287{
3288 struct cdrom_tocentry toc;
3289 disc_information di;
3290 track_information ti;
3291 __u32 last_track;
3292 int ret = -1, ti_size;
3293
3294 if (!CDROM_CAN(CDC_GENERIC_PACKET))
3295 goto use_toc;
3296
3297 ret = cdrom_get_disc_info(cdi, &di);
3298 if (ret < (int)(offsetof(typeof(di), last_track_lsb)
3299 + sizeof(di.last_track_lsb)))
3300 goto use_toc;
3301
3302 /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
3303 last_track = (di.last_track_msb << 8) | di.last_track_lsb;
3304 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
3305 if (ti_size < (int)offsetof(typeof(ti), track_start))
3306 goto use_toc;
3307
3308 /* if this track is blank, try the previous. */
3309 if (ti.blank) {
3310 if (last_track==1)
3311 goto use_toc;
3312 last_track--;
3313 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
3314 }
3315
3316 if (ti_size < (int)(offsetof(typeof(ti), track_size)
3317 + sizeof(ti.track_size)))
3318 goto use_toc;
3319
3320 /* if last recorded field is valid, return it. */
3321 if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address)
3322 + sizeof(ti.last_rec_address))) {
3323 *last_written = be32_to_cpu(ti.last_rec_address);
3324 } else {
3325 /* make it up instead */
3326 *last_written = be32_to_cpu(ti.track_start) +
3327 be32_to_cpu(ti.track_size);
3328 if (ti.free_blocks)
3329 *last_written -= (be32_to_cpu(ti.free_blocks) + 7);
3330 }
3331 return 0;
3332
3333 /* this is where we end up if the drive either can't do a
3334 GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
3335 it doesn't give enough information or fails. then we return
3336 the toc contents. */
3337use_toc:
3338 toc.cdte_format = CDROM_MSF;
3339 toc.cdte_track = CDROM_LEADOUT;
3340 if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)))
3341 return ret;
3342 sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
3343 *last_written = toc.cdte_addr.lba;
3344 return 0;
3345}
3346
3347/* return the next writable block. also for udf file system. */
3348static int cdrom_get_next_writable(struct cdrom_device_info *cdi, long *next_writable)
3349{
3350 disc_information di;
3351 track_information ti;
3352 __u16 last_track;
3353 int ret, ti_size;
3354
3355 if (!CDROM_CAN(CDC_GENERIC_PACKET))
3356 goto use_last_written;
3357
3358 ret = cdrom_get_disc_info(cdi, &di);
3359 if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb)
3360 + sizeof(di.last_track_lsb))
3361 goto use_last_written;
3362
3363 /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
3364 last_track = (di.last_track_msb << 8) | di.last_track_lsb;
3365 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
3366 if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start))
3367 goto use_last_written;
3368
3369 /* if this track is blank, try the previous. */
3370 if (ti.blank) {
3371 if (last_track == 1)
3372 goto use_last_written;
3373 last_track--;
3374 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
3375 if (ti_size < 0)
3376 goto use_last_written;
3377 }
3378
3379 /* if next recordable address field is valid, use it. */
3380 if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable)
3381 + sizeof(ti.next_writable)) {
3382 *next_writable = be32_to_cpu(ti.next_writable);
3383 return 0;
3384 }
3385
3386use_last_written:
3387 if ((ret = cdrom_get_last_written(cdi, next_writable))) {
3388 *next_writable = 0;
3389 return ret;
3390 } else {
3391 *next_writable += 7;
3392 return 0;
3393 }
3394}
3395
3396EXPORT_SYMBOL(cdrom_get_last_written);
3397EXPORT_SYMBOL(register_cdrom);
3398EXPORT_SYMBOL(unregister_cdrom);
3399EXPORT_SYMBOL(cdrom_open);
3400EXPORT_SYMBOL(cdrom_release);
3401EXPORT_SYMBOL(cdrom_ioctl);
3402EXPORT_SYMBOL(cdrom_media_changed);
3403EXPORT_SYMBOL(cdrom_number_of_slots);
3404EXPORT_SYMBOL(cdrom_mode_select);
3405EXPORT_SYMBOL(cdrom_mode_sense);
3406EXPORT_SYMBOL(init_cdrom_command);
3407EXPORT_SYMBOL(cdrom_get_media_event);
3408
3409#ifdef CONFIG_SYSCTL
3410
3411#define CDROM_STR_SIZE 1000
3412
3413static struct cdrom_sysctl_settings {
3414 char info[CDROM_STR_SIZE]; /* general info */
3415 int autoclose; /* close tray upon mount, etc */
3416 int autoeject; /* eject on umount */
3417 int debug; /* turn on debugging messages */
3418 int lock; /* lock the door on device open */
3419 int check; /* check media type */
3420} cdrom_sysctl_settings;
3421
Dave Young554988d2007-06-19 09:14:26 +02003422enum cdrom_print_option {
3423 CTL_NAME,
3424 CTL_SPEED,
3425 CTL_SLOTS,
3426 CTL_CAPABILITY
3427};
3428
3429static int cdrom_print_info(const char *header, int val, char *info,
3430 int *pos, enum cdrom_print_option option)
3431{
3432 const int max_size = sizeof(cdrom_sysctl_settings.info);
3433 struct cdrom_device_info *cdi;
3434 int ret;
3435
3436 ret = scnprintf(info + *pos, max_size - *pos, header);
3437 if (!ret)
3438 return 1;
3439
3440 *pos += ret;
3441
Akinobu Mita7fd097d2008-03-26 12:09:02 +01003442 list_for_each_entry(cdi, &cdrom_list, list) {
Dave Young554988d2007-06-19 09:14:26 +02003443 switch (option) {
3444 case CTL_NAME:
3445 ret = scnprintf(info + *pos, max_size - *pos,
3446 "\t%s", cdi->name);
3447 break;
3448 case CTL_SPEED:
3449 ret = scnprintf(info + *pos, max_size - *pos,
3450 "\t%d", cdi->speed);
3451 break;
3452 case CTL_SLOTS:
3453 ret = scnprintf(info + *pos, max_size - *pos,
3454 "\t%d", cdi->capacity);
3455 break;
3456 case CTL_CAPABILITY:
3457 ret = scnprintf(info + *pos, max_size - *pos,
3458 "\t%d", CDROM_CAN(val) != 0);
3459 break;
3460 default:
Joe Perchese597cd02010-07-01 08:24:32 +02003461 pr_info("invalid option%d\n", option);
Dave Young554988d2007-06-19 09:14:26 +02003462 return 1;
3463 }
3464 if (!ret)
3465 return 1;
3466 *pos += ret;
3467 }
3468
3469 return 0;
3470}
3471
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003472static int cdrom_sysctl_info(ctl_table *ctl, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473 void __user *buffer, size_t *lenp, loff_t *ppos)
3474{
Dave Young554988d2007-06-19 09:14:26 +02003475 int pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 char *info = cdrom_sysctl_settings.info;
Dave Young554988d2007-06-19 09:14:26 +02003477 const int max_size = sizeof(cdrom_sysctl_settings.info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478
3479 if (!*lenp || (*ppos && !write)) {
3480 *lenp = 0;
3481 return 0;
3482 }
3483
Dave Young554988d2007-06-19 09:14:26 +02003484 mutex_lock(&cdrom_mutex);
3485
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486 pos = sprintf(info, "CD-ROM information, " VERSION "\n");
3487
Dave Young554988d2007-06-19 09:14:26 +02003488 if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
3489 goto done;
3490 if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
3491 goto done;
3492 if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
3493 goto done;
3494 if (cdrom_print_info("\nCan close tray:\t",
3495 CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
3496 goto done;
3497 if (cdrom_print_info("\nCan open tray:\t",
3498 CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
3499 goto done;
3500 if (cdrom_print_info("\nCan lock tray:\t",
3501 CDC_LOCK, info, &pos, CTL_CAPABILITY))
3502 goto done;
3503 if (cdrom_print_info("\nCan change speed:",
3504 CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
3505 goto done;
3506 if (cdrom_print_info("\nCan select disk:",
3507 CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
3508 goto done;
3509 if (cdrom_print_info("\nCan read multisession:",
3510 CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
3511 goto done;
3512 if (cdrom_print_info("\nCan read MCN:\t",
3513 CDC_MCN, info, &pos, CTL_CAPABILITY))
3514 goto done;
3515 if (cdrom_print_info("\nReports media changed:",
3516 CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
3517 goto done;
3518 if (cdrom_print_info("\nCan play audio:\t",
3519 CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
3520 goto done;
3521 if (cdrom_print_info("\nCan write CD-R:\t",
3522 CDC_CD_R, info, &pos, CTL_CAPABILITY))
3523 goto done;
3524 if (cdrom_print_info("\nCan write CD-RW:",
3525 CDC_CD_RW, info, &pos, CTL_CAPABILITY))
3526 goto done;
3527 if (cdrom_print_info("\nCan read DVD:\t",
3528 CDC_DVD, info, &pos, CTL_CAPABILITY))
3529 goto done;
3530 if (cdrom_print_info("\nCan write DVD-R:",
3531 CDC_DVD_R, info, &pos, CTL_CAPABILITY))
3532 goto done;
3533 if (cdrom_print_info("\nCan write DVD-RAM:",
3534 CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
3535 goto done;
3536 if (cdrom_print_info("\nCan read MRW:\t",
3537 CDC_MRW, info, &pos, CTL_CAPABILITY))
3538 goto done;
3539 if (cdrom_print_info("\nCan write MRW:\t",
3540 CDC_MRW_W, info, &pos, CTL_CAPABILITY))
3541 goto done;
3542 if (cdrom_print_info("\nCan write RAM:\t",
3543 CDC_RAM, info, &pos, CTL_CAPABILITY))
3544 goto done;
3545 if (!scnprintf(info + pos, max_size - pos, "\n\n"))
3546 goto done;
3547doit:
3548 mutex_unlock(&cdrom_mutex);
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003549 return proc_dostring(ctl, write, buffer, lenp, ppos);
Dave Young554988d2007-06-19 09:14:26 +02003550done:
Joe Perchese597cd02010-07-01 08:24:32 +02003551 pr_info("info buffer too small\n");
Dave Young554988d2007-06-19 09:14:26 +02003552 goto doit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003553}
3554
3555/* Unfortunately, per device settings are not implemented through
3556 procfs/sysctl yet. When they are, this will naturally disappear. For now
3557 just update all drives. Later this will become the template on which
3558 new registered drives will be based. */
3559static void cdrom_update_settings(void)
3560{
3561 struct cdrom_device_info *cdi;
3562
Akinobu Mita032d8d92008-03-26 12:09:01 +01003563 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +01003564 list_for_each_entry(cdi, &cdrom_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
3566 cdi->options |= CDO_AUTO_CLOSE;
3567 else if (!autoclose)
3568 cdi->options &= ~CDO_AUTO_CLOSE;
3569 if (autoeject && CDROM_CAN(CDC_OPEN_TRAY))
3570 cdi->options |= CDO_AUTO_EJECT;
3571 else if (!autoeject)
3572 cdi->options &= ~CDO_AUTO_EJECT;
3573 if (lockdoor && CDROM_CAN(CDC_LOCK))
3574 cdi->options |= CDO_LOCK;
3575 else if (!lockdoor)
3576 cdi->options &= ~CDO_LOCK;
3577 if (check_media_type)
3578 cdi->options |= CDO_CHECK_TYPE;
3579 else
3580 cdi->options &= ~CDO_CHECK_TYPE;
3581 }
Akinobu Mita032d8d92008-03-26 12:09:01 +01003582 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003583}
3584
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003585static int cdrom_sysctl_handler(ctl_table *ctl, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003586 void __user *buffer, size_t *lenp, loff_t *ppos)
3587{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 int ret;
3589
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003590 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591
Eric W. Biederman06489b42007-10-18 03:05:28 -07003592 if (write) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593
3594 /* we only care for 1 or 0. */
Eric W. Biederman06489b42007-10-18 03:05:28 -07003595 autoclose = !!cdrom_sysctl_settings.autoclose;
3596 autoeject = !!cdrom_sysctl_settings.autoeject;
3597 debug = !!cdrom_sysctl_settings.debug;
3598 lockdoor = !!cdrom_sysctl_settings.lock;
3599 check_media_type = !!cdrom_sysctl_settings.check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 /* update the option flags according to the changes. we
3602 don't have per device options through sysctl yet,
3603 but we will have and then this will disappear. */
3604 cdrom_update_settings();
3605 }
3606
3607 return ret;
3608}
3609
3610/* Place files in /proc/sys/dev/cdrom */
3611static ctl_table cdrom_table[] = {
3612 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613 .procname = "info",
3614 .data = &cdrom_sysctl_settings.info,
3615 .maxlen = CDROM_STR_SIZE,
3616 .mode = 0444,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003617 .proc_handler = cdrom_sysctl_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 },
3619 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620 .procname = "autoclose",
3621 .data = &cdrom_sysctl_settings.autoclose,
3622 .maxlen = sizeof(int),
3623 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003624 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625 },
3626 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627 .procname = "autoeject",
3628 .data = &cdrom_sysctl_settings.autoeject,
3629 .maxlen = sizeof(int),
3630 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003631 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632 },
3633 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634 .procname = "debug",
3635 .data = &cdrom_sysctl_settings.debug,
3636 .maxlen = sizeof(int),
3637 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003638 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003639 },
3640 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641 .procname = "lock",
3642 .data = &cdrom_sysctl_settings.lock,
3643 .maxlen = sizeof(int),
3644 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003645 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646 },
3647 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648 .procname = "check_media",
3649 .data = &cdrom_sysctl_settings.check,
3650 .maxlen = sizeof(int),
3651 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003652 .proc_handler = cdrom_sysctl_handler
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003654 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655};
3656
3657static ctl_table cdrom_cdrom_table[] = {
3658 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 .procname = "cdrom",
3660 .maxlen = 0,
3661 .mode = 0555,
3662 .child = cdrom_table,
3663 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003664 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665};
3666
3667/* Make sure that /proc/sys/dev is there */
3668static ctl_table cdrom_root_table[] = {
3669 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 .procname = "dev",
3671 .maxlen = 0,
3672 .mode = 0555,
3673 .child = cdrom_cdrom_table,
3674 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003675 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676};
3677static struct ctl_table_header *cdrom_sysctl_header;
3678
3679static void cdrom_sysctl_register(void)
3680{
3681 static int initialized;
3682
3683 if (initialized == 1)
3684 return;
3685
Eric W. Biederman0b4d4142007-02-14 00:34:09 -08003686 cdrom_sysctl_header = register_sysctl_table(cdrom_root_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
3688 /* set the defaults */
3689 cdrom_sysctl_settings.autoclose = autoclose;
3690 cdrom_sysctl_settings.autoeject = autoeject;
3691 cdrom_sysctl_settings.debug = debug;
3692 cdrom_sysctl_settings.lock = lockdoor;
3693 cdrom_sysctl_settings.check = check_media_type;
3694
3695 initialized = 1;
3696}
3697
3698static void cdrom_sysctl_unregister(void)
3699{
3700 if (cdrom_sysctl_header)
3701 unregister_sysctl_table(cdrom_sysctl_header);
3702}
3703
Akinobu Mita17672cf2008-03-26 12:08:59 +01003704#else /* CONFIG_SYSCTL */
3705
3706static void cdrom_sysctl_register(void)
3707{
3708}
3709
3710static void cdrom_sysctl_unregister(void)
3711{
3712}
3713
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714#endif /* CONFIG_SYSCTL */
3715
3716static int __init cdrom_init(void)
3717{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718 cdrom_sysctl_register();
Akinobu Mita17672cf2008-03-26 12:08:59 +01003719
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720 return 0;
3721}
3722
3723static void __exit cdrom_exit(void)
3724{
Joe Perchese597cd02010-07-01 08:24:32 +02003725 pr_info("Uniform CD-ROM driver unloaded\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 cdrom_sysctl_unregister();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727}
3728
3729module_init(cdrom_init);
3730module_exit(cdrom_exit);
3731MODULE_LICENSE("GPL");