blob: 8888ed3a8d4fb028d820ee438ca1f5a799d6d40b [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 -0700340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*);
342
343static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
344
345static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347static void cdrom_sysctl_register(void);
Akinobu Mita17672cf2008-03-26 12:08:59 +0100348
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100349static LIST_HEAD(cdrom_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350
351static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
352 struct packet_command *cgc)
353{
354 if (cgc->sense) {
355 cgc->sense->sense_key = 0x05;
356 cgc->sense->asc = 0x20;
357 cgc->sense->ascq = 0x00;
358 }
359
360 cgc->stat = -EIO;
361 return -EIO;
362}
363
364/* This macro makes sure we don't have to check on cdrom_device_ops
365 * existence in the run-time routines below. Change_capability is a
366 * hack to have the capability flags defined const, while we can still
367 * change it here without gcc complaining at every line.
368 */
369#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
370
371int register_cdrom(struct cdrom_device_info *cdi)
372{
373 static char banner_printed;
374 struct cdrom_device_ops *cdo = cdi->ops;
375 int *change_capability = (int *)&cdo->capability; /* hack */
376
Joe Perches5944b2c2014-05-04 17:05:02 -0700377 cd_dbg(CD_OPEN, "entering register_cdrom\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 if (cdo->open == NULL || cdo->release == NULL)
Akinobu Mita3c3f4e02008-03-26 12:09:00 +0100380 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 if (!banner_printed) {
Joe Perchese597cd02010-07-01 08:24:32 +0200382 pr_info("Uniform CD-ROM driver " REVISION "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 banner_printed = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 cdrom_sysctl_register();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 }
386
387 ENSURE(drive_status, CDC_DRIVE_STATUS );
Simon Arlottb8cf0e02011-02-09 14:21:07 +0100388 if (cdo->check_events == NULL && cdo->media_changed == NULL)
389 *change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
391 ENSURE(lock_door, CDC_LOCK);
392 ENSURE(select_speed, CDC_SELECT_SPEED);
393 ENSURE(get_last_session, CDC_MULTI_SESSION);
394 ENSURE(get_mcn, CDC_MCN);
395 ENSURE(reset, CDC_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 ENSURE(generic_packet, CDC_GENERIC_PACKET);
397 cdi->mc_flags = 0;
398 cdo->n_minors = 0;
399 cdi->options = CDO_USE_FFLAGS;
400
401 if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY))
402 cdi->options |= (int) CDO_AUTO_CLOSE;
403 if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY))
404 cdi->options |= (int) CDO_AUTO_EJECT;
405 if (lockdoor==1)
406 cdi->options |= (int) CDO_LOCK;
407 if (check_media_type==1)
408 cdi->options |= (int) CDO_CHECK_TYPE;
409
410 if (CDROM_CAN(CDC_MRW_W))
411 cdi->exit = cdrom_mrw_exit;
412
413 if (cdi->disk)
414 cdi->cdda_method = CDDA_BPC_FULL;
415 else
416 cdi->cdda_method = CDDA_OLD;
417
418 if (!cdo->generic_packet)
419 cdo->generic_packet = cdrom_dummy_generic_packet;
420
Joe Perches5944b2c2014-05-04 17:05:02 -0700421 cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
Dave Young554988d2007-06-19 09:14:26 +0200422 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100423 list_add(&cdi->list, &cdrom_list);
Dave Young554988d2007-06-19 09:14:26 +0200424 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 return 0;
426}
427#undef ENSURE
428
Akinobu Mita0a0c4112008-03-26 12:09:02 +0100429void unregister_cdrom(struct cdrom_device_info *cdi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430{
Joe Perches5944b2c2014-05-04 17:05:02 -0700431 cd_dbg(CD_OPEN, "entering unregister_cdrom\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Dave Young554988d2007-06-19 09:14:26 +0200433 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +0100434 list_del(&cdi->list);
Dave Young554988d2007-06-19 09:14:26 +0200435 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 if (cdi->exit)
438 cdi->exit(cdi);
439
440 cdi->ops->n_minors--;
Joe Perches5944b2c2014-05-04 17:05:02 -0700441 cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442}
443
444int cdrom_get_media_event(struct cdrom_device_info *cdi,
445 struct media_event_desc *med)
446{
447 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200448 unsigned char buffer[8];
449 struct event_header *eh = (struct event_header *) buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200451 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
453 cgc.cmd[1] = 1; /* IMMED */
454 cgc.cmd[4] = 1 << 4; /* media event */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200455 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 cgc.quiet = 1;
457
458 if (cdi->ops->generic_packet(cdi, &cgc))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200459 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 if (be16_to_cpu(eh->data_len) < sizeof(*med))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200462 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 if (eh->nea || eh->notification_class != 0x4)
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200465 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200467 memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
468 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
471/*
472 * the first prototypes used 0x2c as the page code for the mrw mode page,
473 * subsequently this was changed to 0x03. probe the one used by this drive
474 */
475static int cdrom_mrw_probe_pc(struct cdrom_device_info *cdi)
476{
477 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200478 char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200480 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
482 cgc.timeout = HZ;
483 cgc.quiet = 1;
484
485 if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC, 0)) {
486 cdi->mrw_mode_page = MRW_MODE_PC;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200487 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 } else if (!cdrom_mode_sense(cdi, &cgc, MRW_MODE_PC_PRE1, 0)) {
489 cdi->mrw_mode_page = MRW_MODE_PC_PRE1;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200490 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200492
493 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
496static int cdrom_is_mrw(struct cdrom_device_info *cdi, int *write)
497{
498 struct packet_command cgc;
499 struct mrw_feature_desc *mfd;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200500 unsigned char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501 int ret;
502
503 *write = 0;
504
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200505 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
507 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
508 cgc.cmd[3] = CDF_MRW;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200509 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 cgc.quiet = 1;
511
512 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200513 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
515 mfd = (struct mrw_feature_desc *)&buffer[sizeof(struct feature_header)];
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200516 if (be16_to_cpu(mfd->feature_code) != CDF_MRW)
517 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 *write = mfd->write;
519
520 if ((ret = cdrom_mrw_probe_pc(cdi))) {
521 *write = 0;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200522 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200524
525 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526}
527
528static int cdrom_mrw_bgformat(struct cdrom_device_info *cdi, int cont)
529{
530 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200531 unsigned char buffer[12];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 int ret;
533
Joe Perchese597cd02010-07-01 08:24:32 +0200534 pr_info("%sstarting format\n", cont ? "Re" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
536 /*
537 * FmtData bit set (bit 4), format type is 1
538 */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200539 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 cgc.cmd[0] = GPCMD_FORMAT_UNIT;
541 cgc.cmd[1] = (1 << 4) | 1;
542
543 cgc.timeout = 5 * 60 * HZ;
544
545 /*
546 * 4 byte format list header, 8 byte format list descriptor
547 */
548 buffer[1] = 1 << 1;
549 buffer[3] = 8;
550
551 /*
552 * nr_blocks field
553 */
554 buffer[4] = 0xff;
555 buffer[5] = 0xff;
556 buffer[6] = 0xff;
557 buffer[7] = 0xff;
558
559 buffer[8] = 0x24 << 2;
560 buffer[11] = cont;
561
562 ret = cdi->ops->generic_packet(cdi, &cgc);
563 if (ret)
Joe Perchese597cd02010-07-01 08:24:32 +0200564 pr_info("bgformat failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
566 return ret;
567}
568
569static int cdrom_mrw_bgformat_susp(struct cdrom_device_info *cdi, int immed)
570{
571 struct packet_command cgc;
572
573 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
574 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
575
576 /*
577 * Session = 1, Track = 0
578 */
579 cgc.cmd[1] = !!immed;
580 cgc.cmd[2] = 1 << 1;
581
582 cgc.timeout = 5 * 60 * HZ;
583
584 return cdi->ops->generic_packet(cdi, &cgc);
585}
586
587static int cdrom_flush_cache(struct cdrom_device_info *cdi)
588{
589 struct packet_command cgc;
590
591 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
592 cgc.cmd[0] = GPCMD_FLUSH_CACHE;
593
594 cgc.timeout = 5 * 60 * HZ;
595
596 return cdi->ops->generic_packet(cdi, &cgc);
597}
598
599static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
600{
601 disc_information di;
602 int ret;
603
604 ret = cdrom_get_disc_info(cdi, &di);
605 if (ret < 0 || ret < (int)offsetof(typeof(di),disc_type))
606 return 1;
607
608 ret = 0;
609 if (di.mrw_status == CDM_MRW_BGFORMAT_ACTIVE) {
Joe Perchese597cd02010-07-01 08:24:32 +0200610 pr_info("issuing MRW background format suspend\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 ret = cdrom_mrw_bgformat_susp(cdi, 0);
612 }
613
Jens Axboe7da21a02005-05-01 12:12:52 -0700614 if (!ret && cdi->media_written)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 ret = cdrom_flush_cache(cdi);
616
617 return ret;
618}
619
620static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
621{
622 struct packet_command cgc;
623 struct mode_page_header *mph;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200624 char buffer[16];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 int ret, offset, size;
626
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200627 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200629 cgc.buffer = buffer;
630 cgc.buflen = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
632 if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200633 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
635 mph = (struct mode_page_header *) buffer;
636 offset = be16_to_cpu(mph->desc_length);
637 size = be16_to_cpu(mph->mode_data_length) + 2;
638
639 buffer[offset + 3] = space;
640 cgc.buflen = size;
641
642 if ((ret = cdrom_mode_select(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200643 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Joe Perchese597cd02010-07-01 08:24:32 +0200645 pr_info("%s: mrw address space %s selected\n",
646 cdi->name, mrw_address_space[space]);
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
650static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
651 struct rwrt_feature_desc *rfd)
652{
653 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200654 char buffer[24];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 int ret;
656
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200657 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 cgc.cmd[0] = GPCMD_GET_CONFIGURATION; /* often 0x46 */
660 cgc.cmd[3] = CDF_RWRT; /* often 0x0020 */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200661 cgc.cmd[8] = sizeof(buffer); /* often 0x18 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 cgc.quiet = 1;
663
664 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200665 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 memcpy(rfd, &buffer[sizeof(struct feature_header)], sizeof (*rfd));
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200668 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669}
670
671static int cdrom_has_defect_mgt(struct cdrom_device_info *cdi)
672{
673 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200674 char buffer[16];
Alexey Dobriyan56052d52005-12-01 17:10:40 -0500675 __be16 *feature_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 int ret;
677
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200678 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
681 cgc.cmd[3] = CDF_HWDM;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200682 cgc.cmd[8] = sizeof(buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 cgc.quiet = 1;
684
685 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200686 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Alexey Dobriyan56052d52005-12-01 17:10:40 -0500688 feature_code = (__be16 *) &buffer[sizeof(struct feature_header)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 if (be16_to_cpu(*feature_code) == CDF_HWDM)
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200690 return 0;
691
692 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
695
696static int cdrom_is_random_writable(struct cdrom_device_info *cdi, int *write)
697{
698 struct rwrt_feature_desc rfd;
699 int ret;
700
701 *write = 0;
702
703 if ((ret = cdrom_get_random_writable(cdi, &rfd)))
704 return ret;
705
706 if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
707 *write = 1;
708
709 return 0;
710}
711
712static int cdrom_media_erasable(struct cdrom_device_info *cdi)
713{
714 disc_information di;
715 int ret;
716
717 ret = cdrom_get_disc_info(cdi, &di);
718 if (ret < 0 || ret < offsetof(typeof(di), n_first_track))
719 return -1;
720
721 return di.erasable;
722}
723
724/*
725 * FIXME: check RO bit
726 */
727static int cdrom_dvdram_open_write(struct cdrom_device_info *cdi)
728{
729 int ret = cdrom_media_erasable(cdi);
730
731 /*
732 * allow writable open if media info read worked and media is
733 * erasable, _or_ if it fails since not all drives support it
734 */
735 if (!ret)
736 return 1;
737
738 return 0;
739}
740
741static int cdrom_mrw_open_write(struct cdrom_device_info *cdi)
742{
743 disc_information di;
744 int ret;
745
746 /*
747 * always reset to DMA lba space on open
748 */
749 if (cdrom_mrw_set_lba_space(cdi, MRW_LBA_DMA)) {
Joe Perchese597cd02010-07-01 08:24:32 +0200750 pr_err("failed setting lba address space\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 return 1;
752 }
753
754 ret = cdrom_get_disc_info(cdi, &di);
755 if (ret < 0 || ret < offsetof(typeof(di),disc_type))
756 return 1;
757
758 if (!di.erasable)
759 return 1;
760
761 /*
762 * mrw_status
763 * 0 - not MRW formatted
764 * 1 - MRW bgformat started, but not running or complete
765 * 2 - MRW bgformat in progress
766 * 3 - MRW formatting complete
767 */
768 ret = 0;
Joe Perchese597cd02010-07-01 08:24:32 +0200769 pr_info("open: mrw_status '%s'\n", mrw_format_status[di.mrw_status]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 if (!di.mrw_status)
771 ret = 1;
772 else if (di.mrw_status == CDM_MRW_BGFORMAT_INACTIVE &&
773 mrw_format_restart)
774 ret = cdrom_mrw_bgformat(cdi, 1);
775
776 return ret;
777}
778
779static int mo_open_write(struct cdrom_device_info *cdi)
780{
781 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200782 char buffer[255];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 int ret;
784
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200785 init_cdrom_command(&cgc, &buffer, 4, CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 cgc.quiet = 1;
787
788 /*
789 * obtain write protect information as per
790 * drivers/scsi/sd.c:sd_read_write_protect_flag
791 */
792
793 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0);
794 if (ret)
795 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_VENDOR_PAGE, 0);
796 if (ret) {
797 cgc.buflen = 255;
798 ret = cdrom_mode_sense(cdi, &cgc, GPMODE_ALL_PAGES, 0);
799 }
800
801 /* drive gave us no info, let the user go ahead */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200802 if (ret)
803 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200805 return buffer[3] & 0x80;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806}
807
808static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
809{
810 struct rwrt_feature_desc rfd;
811 int ret;
812
813 if ((ret = cdrom_has_defect_mgt(cdi)))
814 return ret;
815
816 if ((ret = cdrom_get_random_writable(cdi, &rfd)))
817 return ret;
818 else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
819 ret = !rfd.curr;
820
Joe Perches5944b2c2014-05-04 17:05:02 -0700821 cd_dbg(CD_OPEN, "can open for random write\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 return ret;
823}
824
825static void cdrom_mmc3_profile(struct cdrom_device_info *cdi)
826{
827 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200828 char buffer[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 int ret, mmc3_profile;
830
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200831 init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
833 cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
834 cgc.cmd[1] = 0;
835 cgc.cmd[2] = cgc.cmd[3] = 0; /* Starting Feature Number */
FUJITA Tomonorifce53842008-07-04 09:33:01 +0200836 cgc.cmd[8] = sizeof(buffer); /* Allocation Length */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 cgc.quiet = 1;
838
839 if ((ret = cdi->ops->generic_packet(cdi, &cgc)))
840 mmc3_profile = 0xffff;
841 else
842 mmc3_profile = (buffer[6] << 8) | buffer[7];
843
844 cdi->mmc3_profile = mmc3_profile;
845}
846
847static int cdrom_is_dvd_rw(struct cdrom_device_info *cdi)
848{
849 switch (cdi->mmc3_profile) {
850 case 0x12: /* DVD-RAM */
851 case 0x1A: /* DVD+RW */
852 return 0;
853 default:
854 return 1;
855 }
856}
857
858/*
859 * returns 0 for ok to open write, non-0 to disallow
860 */
861static int cdrom_open_write(struct cdrom_device_info *cdi)
862{
863 int mrw, mrw_write, ram_write;
864 int ret = 1;
865
866 mrw = 0;
867 if (!cdrom_is_mrw(cdi, &mrw_write))
868 mrw = 1;
869
870 if (CDROM_CAN(CDC_MO_DRIVE))
871 ram_write = 1;
872 else
873 (void) cdrom_is_random_writable(cdi, &ram_write);
874
875 if (mrw)
876 cdi->mask &= ~CDC_MRW;
877 else
878 cdi->mask |= CDC_MRW;
879
880 if (mrw_write)
881 cdi->mask &= ~CDC_MRW_W;
882 else
883 cdi->mask |= CDC_MRW_W;
884
885 if (ram_write)
886 cdi->mask &= ~CDC_RAM;
887 else
888 cdi->mask |= CDC_RAM;
889
890 if (CDROM_CAN(CDC_MRW_W))
891 ret = cdrom_mrw_open_write(cdi);
892 else if (CDROM_CAN(CDC_DVD_RAM))
893 ret = cdrom_dvdram_open_write(cdi);
894 else if (CDROM_CAN(CDC_RAM) &&
895 !CDROM_CAN(CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_MRW|CDC_MO_DRIVE))
896 ret = cdrom_ram_open_write(cdi);
897 else if (CDROM_CAN(CDC_MO_DRIVE))
898 ret = mo_open_write(cdi);
899 else if (!cdrom_is_dvd_rw(cdi))
900 ret = 0;
901
902 return ret;
903}
904
905static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi)
906{
907 struct packet_command cgc;
908
909 if (cdi->mmc3_profile != 0x1a) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700910 cd_dbg(CD_CLOSE, "%s: No DVD+RW\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 return;
912 }
913
914 if (!cdi->media_written) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700915 cd_dbg(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 return;
917 }
918
Joe Perchese597cd02010-07-01 08:24:32 +0200919 pr_info("%s: dirty DVD+RW media, \"finalizing\"\n", cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
922 cgc.cmd[0] = GPCMD_FLUSH_CACHE;
923 cgc.timeout = 30*HZ;
924 cdi->ops->generic_packet(cdi, &cgc);
925
926 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
927 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
928 cgc.timeout = 3000*HZ;
929 cgc.quiet = 1;
930 cdi->ops->generic_packet(cdi, &cgc);
931
932 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
933 cgc.cmd[0] = GPCMD_CLOSE_TRACK;
934 cgc.cmd[2] = 2; /* Close session */
935 cgc.quiet = 1;
936 cgc.timeout = 3000*HZ;
937 cdi->ops->generic_packet(cdi, &cgc);
938
939 cdi->media_written = 0;
940}
941
942static int cdrom_close_write(struct cdrom_device_info *cdi)
943{
944#if 0
945 return cdrom_flush_cache(cdi);
946#else
947 return 0;
948#endif
949}
950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951static
Joe Perches82b91542014-05-04 17:05:05 -0700952int open_for_data(struct cdrom_device_info *cdi)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953{
954 int ret;
955 struct cdrom_device_ops *cdo = cdi->ops;
956 tracktype tracks;
Joe Perches5944b2c2014-05-04 17:05:02 -0700957 cd_dbg(CD_OPEN, "entering open_for_data\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 /* Check if the driver can report drive status. If it can, we
959 can do clever things. If it can't, well, we at least tried! */
960 if (cdo->drive_status != NULL) {
961 ret = cdo->drive_status(cdi, CDSL_CURRENT);
Joe Perches5944b2c2014-05-04 17:05:02 -0700962 cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 if (ret == CDS_TRAY_OPEN) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700964 cd_dbg(CD_OPEN, "the tray is open...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 /* can/may i close it? */
966 if (CDROM_CAN(CDC_CLOSE_TRAY) &&
967 cdi->options & CDO_AUTO_CLOSE) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700968 cd_dbg(CD_OPEN, "trying to close the tray\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 ret=cdo->tray_move(cdi,0);
970 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700971 cd_dbg(CD_OPEN, "bummer. tried to close the tray but failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 /* Ignore the error from the low
973 level driver. We don't care why it
974 couldn't close the tray. We only care
975 that there is no disc in the drive,
976 since that is the _REAL_ problem here.*/
977 ret=-ENOMEDIUM;
978 goto clean_up_and_return;
979 }
980 } else {
Joe Perches5944b2c2014-05-04 17:05:02 -0700981 cd_dbg(CD_OPEN, "bummer. this drive can't close the tray.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 ret=-ENOMEDIUM;
983 goto clean_up_and_return;
984 }
985 /* Ok, the door should be closed now.. Check again */
986 ret = cdo->drive_status(cdi, CDSL_CURRENT);
987 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
Joe Perches5944b2c2014-05-04 17:05:02 -0700988 cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
989 cd_dbg(CD_OPEN, "tray might not contain a medium\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 ret=-ENOMEDIUM;
991 goto clean_up_and_return;
992 }
Joe Perches5944b2c2014-05-04 17:05:02 -0700993 cd_dbg(CD_OPEN, "the tray is now closed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
995 /* the door should be closed now, check for the disc */
996 ret = cdo->drive_status(cdi, CDSL_CURRENT);
997 if (ret!=CDS_DISC_OK) {
998 ret = -ENOMEDIUM;
999 goto clean_up_and_return;
1000 }
1001 }
1002 cdrom_count_tracks(cdi, &tracks);
1003 if (tracks.error == CDS_NO_DISC) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001004 cd_dbg(CD_OPEN, "bummer. no disc.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 ret=-ENOMEDIUM;
1006 goto clean_up_and_return;
1007 }
1008 /* CD-Players which don't use O_NONBLOCK, workman
1009 * for example, need bit CDO_CHECK_TYPE cleared! */
1010 if (tracks.data==0) {
1011 if (cdi->options & CDO_CHECK_TYPE) {
1012 /* give people a warning shot, now that CDO_CHECK_TYPE
1013 is the default case! */
Joe Perches5944b2c2014-05-04 17:05:02 -07001014 cd_dbg(CD_OPEN, "bummer. wrong media type.\n");
1015 cd_dbg(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
1016 (unsigned int)task_pid_nr(current));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 ret=-EMEDIUMTYPE;
1018 goto clean_up_and_return;
1019 }
1020 else {
Joe Perches5944b2c2014-05-04 17:05:02 -07001021 cd_dbg(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 }
1023 }
1024
Joe Perches5944b2c2014-05-04 17:05:02 -07001025 cd_dbg(CD_OPEN, "all seems well, opening the devicen");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
1027 /* all seems well, we can open the device */
1028 ret = cdo->open(cdi, 0); /* open for data */
Joe Perches5944b2c2014-05-04 17:05:02 -07001029 cd_dbg(CD_OPEN, "opening the device gave me %d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 /* After all this careful checking, we shouldn't have problems
1031 opening the device, but we don't want the device locked if
1032 this somehow fails... */
1033 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001034 cd_dbg(CD_OPEN, "open device failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 goto clean_up_and_return;
1036 }
1037 if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) {
1038 cdo->lock_door(cdi, 1);
Joe Perches5944b2c2014-05-04 17:05:02 -07001039 cd_dbg(CD_OPEN, "door locked\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001041 cd_dbg(CD_OPEN, "device opened successfully\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 return ret;
1043
1044 /* Something failed. Try to unlock the drive, because some drivers
1045 (notably ide-cd) lock the drive after every command. This produced
1046 a nasty bug where after mount failed, the drive would remain locked!
1047 This ensures that the drive gets unlocked after a mount fails. This
1048 is a goto to avoid bloating the driver with redundant code. */
1049clean_up_and_return:
Joe Perches5944b2c2014-05-04 17:05:02 -07001050 cd_dbg(CD_OPEN, "open failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
1052 cdo->lock_door(cdi, 0);
Joe Perches5944b2c2014-05-04 17:05:02 -07001053 cd_dbg(CD_OPEN, "door unlocked\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 return ret;
1056}
1057
Joe Perches82b91542014-05-04 17:05:05 -07001058/* We use the open-option O_NONBLOCK to indicate that the
1059 * purpose of opening is only for subsequent ioctl() calls; no device
1060 * integrity checks are performed.
1061 *
1062 * We hope that all cd-player programs will adopt this convention. It
1063 * is in their own interest: device control becomes a lot easier
1064 * this way.
1065 */
1066int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
1067 fmode_t mode)
1068{
1069 int ret;
1070
1071 cd_dbg(CD_OPEN, "entering cdrom_open\n");
1072
1073 /* open is event synchronization point, check events first */
1074 check_disk_change(bdev);
1075
1076 /* if this was a O_NONBLOCK open and we should honor the flags,
1077 * do a quick open without drive/disc integrity checks. */
1078 cdi->use_count++;
1079 if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
1080 ret = cdi->ops->open(cdi, 1);
1081 } else {
1082 ret = open_for_data(cdi);
1083 if (ret)
1084 goto err;
1085 cdrom_mmc3_profile(cdi);
1086 if (mode & FMODE_WRITE) {
1087 ret = -EROFS;
1088 if (cdrom_open_write(cdi))
1089 goto err_release;
1090 if (!CDROM_CAN(CDC_RAM))
1091 goto err_release;
1092 ret = 0;
1093 cdi->media_written = 0;
1094 }
1095 }
1096
1097 if (ret)
1098 goto err;
1099
1100 cd_dbg(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
1101 cdi->name, cdi->use_count);
1102 return 0;
1103err_release:
1104 if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
1105 cdi->ops->lock_door(cdi, 0);
1106 cd_dbg(CD_OPEN, "door unlocked\n");
1107 }
1108 cdi->ops->release(cdi);
1109err:
1110 cdi->use_count--;
1111 return ret;
1112}
1113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114/* This code is similar to that in open_for_data. The routine is called
1115 whenever an audio play operation is requested.
1116*/
Adrian Bunkecb80c62008-03-04 11:23:51 +01001117static int check_for_audio_disc(struct cdrom_device_info * cdi,
1118 struct cdrom_device_ops * cdo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 int ret;
1121 tracktype tracks;
Joe Perches5944b2c2014-05-04 17:05:02 -07001122 cd_dbg(CD_OPEN, "entering check_for_audio_disc\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 if (!(cdi->options & CDO_CHECK_TYPE))
1124 return 0;
1125 if (cdo->drive_status != NULL) {
1126 ret = cdo->drive_status(cdi, CDSL_CURRENT);
Joe Perches5944b2c2014-05-04 17:05:02 -07001127 cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 if (ret == CDS_TRAY_OPEN) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001129 cd_dbg(CD_OPEN, "the tray is open...\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 /* can/may i close it? */
1131 if (CDROM_CAN(CDC_CLOSE_TRAY) &&
1132 cdi->options & CDO_AUTO_CLOSE) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001133 cd_dbg(CD_OPEN, "trying to close the tray\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 ret=cdo->tray_move(cdi,0);
1135 if (ret) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001136 cd_dbg(CD_OPEN, "bummer. tried to close tray but failed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 /* Ignore the error from the low
1138 level driver. We don't care why it
1139 couldn't close the tray. We only care
1140 that there is no disc in the drive,
1141 since that is the _REAL_ problem here.*/
1142 return -ENOMEDIUM;
1143 }
1144 } else {
Joe Perches5944b2c2014-05-04 17:05:02 -07001145 cd_dbg(CD_OPEN, "bummer. this driver can't close the tray.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 return -ENOMEDIUM;
1147 }
1148 /* Ok, the door should be closed now.. Check again */
1149 ret = cdo->drive_status(cdi, CDSL_CURRENT);
1150 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001151 cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 return -ENOMEDIUM;
1153 }
1154 if (ret!=CDS_DISC_OK) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001155 cd_dbg(CD_OPEN, "bummer. disc isn't ready.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 return -EIO;
1157 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001158 cd_dbg(CD_OPEN, "the tray is now closed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 }
1160 }
1161 cdrom_count_tracks(cdi, &tracks);
1162 if (tracks.error)
1163 return(tracks.error);
1164
1165 if (tracks.audio==0)
1166 return -EMEDIUMTYPE;
1167
1168 return 0;
1169}
1170
Al Virobbc1cc92007-10-07 17:54:28 -04001171void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172{
1173 struct cdrom_device_ops *cdo = cdi->ops;
1174 int opened_for_data;
1175
Joe Perches5944b2c2014-05-04 17:05:02 -07001176 cd_dbg(CD_CLOSE, "entering cdrom_release\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177
1178 if (cdi->use_count > 0)
1179 cdi->use_count--;
Borislav Petkov35841f72008-02-06 01:38:08 -08001180
1181 if (cdi->use_count == 0) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001182 cd_dbg(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n",
1183 cdi->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 cdrom_dvd_rw_close_write(cdi);
Borislav Petkov35841f72008-02-06 01:38:08 -08001185
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01001186 if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001187 cd_dbg(CD_CLOSE, "Unlocking door!\n");
Borislav Petkov35841f72008-02-06 01:38:08 -08001188 cdo->lock_door(cdi, 0);
1189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 }
Borislav Petkov35841f72008-02-06 01:38:08 -08001191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
Al Virobbc1cc92007-10-07 17:54:28 -04001193 !(mode & FMODE_NDELAY);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
1195 /*
1196 * flush cache on last write release
1197 */
1198 if (CDROM_CAN(CDC_RAM) && !cdi->use_count && cdi->for_data)
1199 cdrom_close_write(cdi);
1200
1201 cdo->release(cdi);
1202 if (cdi->use_count == 0) { /* last process that closes dev*/
1203 if (opened_for_data &&
1204 cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY))
1205 cdo->tray_move(cdi, 1);
1206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207}
1208
1209static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
1210 struct cdrom_changer_info *buf)
1211{
1212 struct packet_command cgc;
1213 struct cdrom_device_ops *cdo = cdi->ops;
1214 int length;
1215
1216 /*
1217 * Sanyo changer isn't spec compliant (doesn't use regular change
1218 * LOAD_UNLOAD command, and it doesn't implement the mech status
1219 * command below
1220 */
1221 if (cdi->sanyo_slot) {
1222 buf->hdr.nslots = 3;
1223 buf->hdr.curslot = cdi->sanyo_slot == 3 ? 0 : cdi->sanyo_slot;
1224 for (length = 0; length < 3; length++) {
1225 buf->slots[length].disc_present = 1;
1226 buf->slots[length].change = 0;
1227 }
1228 return 0;
1229 }
1230
1231 length = sizeof(struct cdrom_mechstat_header) +
1232 cdi->capacity * sizeof(struct cdrom_slot);
1233
1234 init_cdrom_command(&cgc, buf, length, CGC_DATA_READ);
1235 cgc.cmd[0] = GPCMD_MECHANISM_STATUS;
1236 cgc.cmd[8] = (length >> 8) & 0xff;
1237 cgc.cmd[9] = length & 0xff;
1238 return cdo->generic_packet(cdi, &cgc);
1239}
1240
1241static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
1242{
1243 struct cdrom_changer_info *info;
1244 int ret;
1245
Joe Perches5944b2c2014-05-04 17:05:02 -07001246 cd_dbg(CD_CHANGER, "entering cdrom_slot_status()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 if (cdi->sanyo_slot)
1248 return CDS_NO_INFO;
1249
1250 info = kmalloc(sizeof(*info), GFP_KERNEL);
1251 if (!info)
1252 return -ENOMEM;
1253
1254 if ((ret = cdrom_read_mech_status(cdi, info)))
1255 goto out_free;
1256
1257 if (info->slots[slot].disc_present)
1258 ret = CDS_DISC_OK;
1259 else
1260 ret = CDS_NO_DISC;
1261
1262out_free:
1263 kfree(info);
1264 return ret;
1265}
1266
1267/* Return the number of slots for an ATAPI/SCSI cdrom,
1268 * return 1 if not a changer.
1269 */
1270int cdrom_number_of_slots(struct cdrom_device_info *cdi)
1271{
1272 int status;
1273 int nslots = 1;
1274 struct cdrom_changer_info *info;
1275
Joe Perches5944b2c2014-05-04 17:05:02 -07001276 cd_dbg(CD_CHANGER, "entering cdrom_number_of_slots()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 /* cdrom_read_mech_status requires a valid value for capacity: */
1278 cdi->capacity = 0;
1279
1280 info = kmalloc(sizeof(*info), GFP_KERNEL);
1281 if (!info)
1282 return -ENOMEM;
1283
1284 if ((status = cdrom_read_mech_status(cdi, info)) == 0)
1285 nslots = info->hdr.nslots;
1286
1287 kfree(info);
1288 return nslots;
1289}
1290
1291
1292/* If SLOT < 0, unload the current slot. Otherwise, try to load SLOT. */
1293static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
1294{
1295 struct packet_command cgc;
1296
Joe Perches5944b2c2014-05-04 17:05:02 -07001297 cd_dbg(CD_CHANGER, "entering cdrom_load_unload()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 if (cdi->sanyo_slot && slot < 0)
1299 return 0;
1300
1301 init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
1302 cgc.cmd[0] = GPCMD_LOAD_UNLOAD;
1303 cgc.cmd[4] = 2 + (slot >= 0);
1304 cgc.cmd[8] = slot;
1305 cgc.timeout = 60 * HZ;
1306
1307 /* The Sanyo 3 CD changer uses byte 7 of the
1308 GPCMD_TEST_UNIT_READY to command to switch CDs instead of
1309 using the GPCMD_LOAD_UNLOAD opcode. */
1310 if (cdi->sanyo_slot && -1 < slot) {
1311 cgc.cmd[0] = GPCMD_TEST_UNIT_READY;
1312 cgc.cmd[7] = slot;
1313 cgc.cmd[4] = cgc.cmd[8] = 0;
1314 cdi->sanyo_slot = slot ? slot : 3;
1315 }
1316
1317 return cdi->ops->generic_packet(cdi, &cgc);
1318}
1319
1320static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
1321{
1322 struct cdrom_changer_info *info;
1323 int curslot;
1324 int ret;
1325
Joe Perches5944b2c2014-05-04 17:05:02 -07001326 cd_dbg(CD_CHANGER, "entering cdrom_select_disc()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (!CDROM_CAN(CDC_SELECT_DISC))
1328 return -EDRIVE_CANT_DO_THIS;
1329
Tejun Heo2d921722010-12-08 20:57:38 +01001330 if (cdi->ops->check_events)
1331 cdi->ops->check_events(cdi, 0, slot);
1332 else
1333 cdi->ops->media_changed(cdi, slot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 if (slot == CDSL_NONE) {
1336 /* set media changed bits, on both queues */
1337 cdi->mc_flags = 0x3;
1338 return cdrom_load_unload(cdi, -1);
1339 }
1340
1341 info = kmalloc(sizeof(*info), GFP_KERNEL);
1342 if (!info)
1343 return -ENOMEM;
1344
1345 if ((ret = cdrom_read_mech_status(cdi, info))) {
1346 kfree(info);
1347 return ret;
1348 }
1349
1350 curslot = info->hdr.curslot;
1351 kfree(info);
1352
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01001353 if (cdi->use_count > 1 || cdi->keeplocked) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if (slot == CDSL_CURRENT) {
1355 return curslot;
1356 } else {
1357 return -EBUSY;
1358 }
1359 }
1360
1361 /* Specifying CDSL_CURRENT will attempt to load the currnet slot,
1362 which is useful if it had been previously unloaded.
1363 Whether it can or not, it returns the current slot.
1364 Similarly, if slot happens to be the current one, we still
1365 try and load it. */
1366 if (slot == CDSL_CURRENT)
1367 slot = curslot;
1368
1369 /* set media changed bits on both queues */
1370 cdi->mc_flags = 0x3;
1371 if ((ret = cdrom_load_unload(cdi, slot)))
1372 return ret;
1373
1374 return slot;
1375}
1376
Tejun Heo2d921722010-12-08 20:57:38 +01001377/*
1378 * As cdrom implements an extra ioctl consumer for media changed
1379 * event, it needs to buffer ->check_events() output, such that event
1380 * is not lost for both the usual VFS and ioctl paths.
1381 * cdi->{vfs|ioctl}_events are used to buffer pending events for each
1382 * path.
1383 *
1384 * XXX: Locking is non-existent. cdi->ops->check_events() can be
1385 * called in parallel and buffering fields are accessed without any
1386 * exclusion. The original media_changed code had the same problem.
1387 * It might be better to simply deprecate CDROM_MEDIA_CHANGED ioctl
1388 * and remove this cruft altogether. It doesn't have much usefulness
1389 * at this point.
1390 */
1391static void cdrom_update_events(struct cdrom_device_info *cdi,
1392 unsigned int clearing)
1393{
1394 unsigned int events;
1395
1396 events = cdi->ops->check_events(cdi, clearing, CDSL_CURRENT);
1397 cdi->vfs_events |= events;
1398 cdi->ioctl_events |= events;
1399}
1400
1401unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
1402 unsigned int clearing)
1403{
1404 unsigned int events;
1405
1406 cdrom_update_events(cdi, clearing);
1407 events = cdi->vfs_events;
1408 cdi->vfs_events = 0;
1409 return events;
1410}
Jens Axboe30a7caa2010-12-16 17:58:50 +01001411EXPORT_SYMBOL(cdrom_check_events);
Tejun Heo2d921722010-12-08 20:57:38 +01001412
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413/* We want to make media_changed accessible to the user through an
1414 * ioctl. The main problem now is that we must double-buffer the
1415 * low-level implementation, to assure that the VFS and the user both
1416 * see a medium change once.
1417 */
1418
1419static
1420int media_changed(struct cdrom_device_info *cdi, int queue)
1421{
1422 unsigned int mask = (1 << (queue & 1));
1423 int ret = !!(cdi->mc_flags & mask);
Tejun Heo2d921722010-12-08 20:57:38 +01001424 bool changed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425
1426 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
Tejun Heo2d921722010-12-08 20:57:38 +01001427 return ret;
1428
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 /* changed since last call? */
Tejun Heo2d921722010-12-08 20:57:38 +01001430 if (cdi->ops->check_events) {
1431 BUG_ON(!queue); /* shouldn't be called from VFS path */
1432 cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE);
1433 changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE;
1434 cdi->ioctl_events = 0;
1435 } else
1436 changed = cdi->ops->media_changed(cdi, CDSL_CURRENT);
1437
1438 if (changed) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 cdi->mc_flags = 0x3; /* set bit on both queues */
1440 ret |= 1;
1441 cdi->media_written = 0;
1442 }
Tejun Heo2d921722010-12-08 20:57:38 +01001443
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 cdi->mc_flags &= ~mask; /* clear bit */
1445 return ret;
1446}
1447
1448int cdrom_media_changed(struct cdrom_device_info *cdi)
1449{
1450 /* This talks to the VFS, which doesn't like errors - just 1 or 0.
1451 * Returning "0" is always safe (media hasn't been changed). Do that
1452 * if the low-level cdrom driver dosn't support media changed. */
1453 if (cdi == NULL || cdi->ops->media_changed == NULL)
1454 return 0;
1455 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
1456 return 0;
1457 return media_changed(cdi, 0);
1458}
1459
1460/* badly broken, I know. Is due for a fixup anytime. */
1461static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
1462{
1463 struct cdrom_tochdr header;
1464 struct cdrom_tocentry entry;
1465 int ret, i;
1466 tracks->data=0;
1467 tracks->audio=0;
1468 tracks->cdi=0;
1469 tracks->xa=0;
1470 tracks->error=0;
Joe Perches5944b2c2014-05-04 17:05:02 -07001471 cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 /* Grab the TOC header so we can see how many tracks there are */
1473 if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
1474 if (ret == -ENOMEDIUM)
1475 tracks->error = CDS_NO_DISC;
1476 else
1477 tracks->error = CDS_NO_INFO;
1478 return;
1479 }
1480 /* check what type of tracks are on this disc */
1481 entry.cdte_format = CDROM_MSF;
1482 for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
1483 entry.cdte_track = i;
1484 if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
1485 tracks->error=CDS_NO_INFO;
1486 return;
1487 }
1488 if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
1489 if (entry.cdte_format == 0x10)
1490 tracks->cdi++;
1491 else if (entry.cdte_format == 0x20)
1492 tracks->xa++;
1493 else
1494 tracks->data++;
1495 } else
1496 tracks->audio++;
Joe Perches5944b2c2014-05-04 17:05:02 -07001497 cd_dbg(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 i, entry.cdte_format, entry.cdte_ctrl);
1499 }
Joe Perches5944b2c2014-05-04 17:05:02 -07001500 cd_dbg(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
1501 header.cdth_trk1, tracks->audio, tracks->data,
1502 tracks->cdi, tracks->xa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503}
1504
1505/* Requests to the low-level drivers will /always/ be done in the
1506 following format convention:
1507
1508 CDROM_LBA: all data-related requests.
1509 CDROM_MSF: all audio-related requests.
1510
1511 However, a low-level implementation is allowed to refuse this
1512 request, and return information in its own favorite format.
1513
1514 It doesn't make sense /at all/ to ask for a play_audio in LBA
1515 format, or ask for multi-session info in MSF format. However, for
1516 backward compatibility these format requests will be satisfied, but
1517 the requests to the low-level drivers will be sanitized in the more
1518 meaningful format indicated above.
1519 */
1520
1521static
1522void sanitize_format(union cdrom_addr *addr,
1523 u_char * curr, u_char requested)
1524{
1525 if (*curr == requested)
1526 return; /* nothing to be done! */
1527 if (requested == CDROM_LBA) {
1528 addr->lba = (int) addr->msf.frame +
1529 75 * (addr->msf.second - 2 + 60 * addr->msf.minute);
1530 } else { /* CDROM_MSF */
1531 int lba = addr->lba;
1532 addr->msf.frame = lba % 75;
1533 lba /= 75;
1534 lba += 2;
1535 addr->msf.second = lba % 60;
1536 addr->msf.minute = lba / 60;
1537 }
1538 *curr = requested;
1539}
1540
1541void init_cdrom_command(struct packet_command *cgc, void *buf, int len,
1542 int type)
1543{
1544 memset(cgc, 0, sizeof(struct packet_command));
1545 if (buf)
1546 memset(buf, 0, len);
1547 cgc->buffer = (char *) buf;
1548 cgc->buflen = len;
1549 cgc->data_direction = type;
Jens Axboe2e11c202007-01-03 08:10:35 +01001550 cgc->timeout = CDROM_DEF_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551}
1552
1553/* DVD handling */
1554
1555#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
1556#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
1557
1558static void setup_report_key(struct packet_command *cgc, unsigned agid, unsigned type)
1559{
1560 cgc->cmd[0] = GPCMD_REPORT_KEY;
1561 cgc->cmd[10] = type | (agid << 6);
1562 switch (type) {
1563 case 0: case 8: case 5: {
1564 cgc->buflen = 8;
1565 break;
1566 }
1567 case 1: {
1568 cgc->buflen = 16;
1569 break;
1570 }
1571 case 2: case 4: {
1572 cgc->buflen = 12;
1573 break;
1574 }
1575 }
1576 cgc->cmd[9] = cgc->buflen;
1577 cgc->data_direction = CGC_DATA_READ;
1578}
1579
1580static void setup_send_key(struct packet_command *cgc, unsigned agid, unsigned type)
1581{
1582 cgc->cmd[0] = GPCMD_SEND_KEY;
1583 cgc->cmd[10] = type | (agid << 6);
1584 switch (type) {
1585 case 1: {
1586 cgc->buflen = 16;
1587 break;
1588 }
1589 case 3: {
1590 cgc->buflen = 12;
1591 break;
1592 }
1593 case 6: {
1594 cgc->buflen = 8;
1595 break;
1596 }
1597 }
1598 cgc->cmd[9] = cgc->buflen;
1599 cgc->data_direction = CGC_DATA_WRITE;
1600}
1601
1602static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
1603{
1604 int ret;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001605 u_char buf[20];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 struct packet_command cgc;
1607 struct cdrom_device_ops *cdo = cdi->ops;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001608 rpc_state_t rpc_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001610 memset(buf, 0, sizeof(buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
1612
1613 switch (ai->type) {
1614 /* LU data send */
1615 case DVD_LU_SEND_AGID:
Joe Perches5944b2c2014-05-04 17:05:02 -07001616 cd_dbg(CD_DVD, "entering DVD_LU_SEND_AGID\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 cgc.quiet = 1;
1618 setup_report_key(&cgc, ai->lsa.agid, 0);
1619
1620 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001621 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 ai->lsa.agid = buf[7] >> 6;
1624 /* Returning data, let host change state */
1625 break;
1626
1627 case DVD_LU_SEND_KEY1:
Joe Perches5944b2c2014-05-04 17:05:02 -07001628 cd_dbg(CD_DVD, "entering DVD_LU_SEND_KEY1\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 setup_report_key(&cgc, ai->lsk.agid, 2);
1630
1631 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001632 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 copy_key(ai->lsk.key, &buf[4]);
1635 /* Returning data, let host change state */
1636 break;
1637
1638 case DVD_LU_SEND_CHALLENGE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001639 cd_dbg(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 setup_report_key(&cgc, ai->lsc.agid, 1);
1641
1642 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001643 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
1645 copy_chal(ai->lsc.chal, &buf[4]);
1646 /* Returning data, let host change state */
1647 break;
1648
1649 /* Post-auth key */
1650 case DVD_LU_SEND_TITLE_KEY:
Joe Perches5944b2c2014-05-04 17:05:02 -07001651 cd_dbg(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 cgc.quiet = 1;
1653 setup_report_key(&cgc, ai->lstk.agid, 4);
1654 cgc.cmd[5] = ai->lstk.lba;
1655 cgc.cmd[4] = ai->lstk.lba >> 8;
1656 cgc.cmd[3] = ai->lstk.lba >> 16;
1657 cgc.cmd[2] = ai->lstk.lba >> 24;
1658
1659 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001660 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
1662 ai->lstk.cpm = (buf[4] >> 7) & 1;
1663 ai->lstk.cp_sec = (buf[4] >> 6) & 1;
1664 ai->lstk.cgms = (buf[4] >> 4) & 3;
1665 copy_key(ai->lstk.title_key, &buf[5]);
1666 /* Returning data, let host change state */
1667 break;
1668
1669 case DVD_LU_SEND_ASF:
Joe Perches5944b2c2014-05-04 17:05:02 -07001670 cd_dbg(CD_DVD, "entering DVD_LU_SEND_ASF\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 setup_report_key(&cgc, ai->lsasf.agid, 5);
1672
1673 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001674 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
1676 ai->lsasf.asf = buf[7] & 1;
1677 break;
1678
1679 /* LU data receive (LU changes state) */
1680 case DVD_HOST_SEND_CHALLENGE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001681 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 setup_send_key(&cgc, ai->hsc.agid, 1);
1683 buf[1] = 0xe;
1684 copy_chal(&buf[4], ai->hsc.chal);
1685
1686 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001687 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688
1689 ai->type = DVD_LU_SEND_KEY1;
1690 break;
1691
1692 case DVD_HOST_SEND_KEY2:
Joe Perches5944b2c2014-05-04 17:05:02 -07001693 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_KEY2\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 setup_send_key(&cgc, ai->hsk.agid, 3);
1695 buf[1] = 0xa;
1696 copy_key(&buf[4], ai->hsk.key);
1697
1698 if ((ret = cdo->generic_packet(cdi, &cgc))) {
1699 ai->type = DVD_AUTH_FAILURE;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001700 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 }
1702 ai->type = DVD_AUTH_ESTABLISHED;
1703 break;
1704
1705 /* Misc */
1706 case DVD_INVALIDATE_AGID:
1707 cgc.quiet = 1;
Joe Perches5944b2c2014-05-04 17:05:02 -07001708 cd_dbg(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 setup_report_key(&cgc, ai->lsa.agid, 0x3f);
1710 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001711 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 break;
1713
1714 /* Get region settings */
1715 case DVD_LU_SEND_RPC_STATE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001716 cd_dbg(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 setup_report_key(&cgc, 0, 8);
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001718 memset(&rpc_state, 0, sizeof(rpc_state_t));
1719 cgc.buffer = (char *) &rpc_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
1721 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001722 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001724 ai->lrpcs.type = rpc_state.type_code;
1725 ai->lrpcs.vra = rpc_state.vra;
1726 ai->lrpcs.ucca = rpc_state.ucca;
1727 ai->lrpcs.region_mask = rpc_state.region_mask;
1728 ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 break;
1730
1731 /* Set region settings */
1732 case DVD_HOST_SEND_RPC_STATE:
Joe Perches5944b2c2014-05-04 17:05:02 -07001733 cd_dbg(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 setup_send_key(&cgc, 0, 6);
1735 buf[1] = 6;
1736 buf[4] = ai->hrpcs.pdrc;
1737
1738 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001739 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 break;
1741
1742 default:
Joe Perches5944b2c2014-05-04 17:05:02 -07001743 cd_dbg(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001744 return -ENOTTY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 }
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001746
1747 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748}
1749
Marcin Slusarzd1941392008-11-16 19:06:37 +01001750static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s,
1751 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752{
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001753 unsigned char buf[21], *base;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 struct dvd_layer *layer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 struct cdrom_device_ops *cdo = cdi->ops;
1756 int ret, layer_num = s->physical.layer_num;
1757
1758 if (layer_num >= DVD_LAYERS)
1759 return -EINVAL;
1760
Marcin Slusarzd1941392008-11-16 19:06:37 +01001761 init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ);
1762 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1763 cgc->cmd[6] = layer_num;
1764 cgc->cmd[7] = s->type;
1765 cgc->cmd[9] = cgc->buflen & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
1767 /*
1768 * refrain from reporting errors on non-existing layers (mainly)
1769 */
Marcin Slusarzd1941392008-11-16 19:06:37 +01001770 cgc->quiet = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Marcin Slusarzd1941392008-11-16 19:06:37 +01001772 ret = cdo->generic_packet(cdi, cgc);
1773 if (ret)
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001774 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
1776 base = &buf[4];
1777 layer = &s->physical.layer[layer_num];
1778
1779 /*
1780 * place the data... really ugly, but at least we won't have to
1781 * worry about endianess in userspace.
1782 */
1783 memset(layer, 0, sizeof(*layer));
1784 layer->book_version = base[0] & 0xf;
1785 layer->book_type = base[0] >> 4;
1786 layer->min_rate = base[1] & 0xf;
1787 layer->disc_size = base[1] >> 4;
1788 layer->layer_type = base[2] & 0xf;
1789 layer->track_path = (base[2] >> 4) & 1;
1790 layer->nlayers = (base[2] >> 5) & 3;
1791 layer->track_density = base[3] & 0xf;
1792 layer->linear_density = base[3] >> 4;
1793 layer->start_sector = base[5] << 16 | base[6] << 8 | base[7];
1794 layer->end_sector = base[9] << 16 | base[10] << 8 | base[11];
1795 layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15];
1796 layer->bca = base[16] >> 7;
1797
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001798 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799}
1800
Marcin Slusarzd1941392008-11-16 19:06:37 +01001801static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s,
1802 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803{
1804 int ret;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001805 u_char buf[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 struct cdrom_device_ops *cdo = cdi->ops;
1807
Marcin Slusarzd1941392008-11-16 19:06:37 +01001808 init_cdrom_command(cgc, buf, sizeof(buf), CGC_DATA_READ);
1809 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1810 cgc->cmd[6] = s->copyright.layer_num;
1811 cgc->cmd[7] = s->type;
1812 cgc->cmd[8] = cgc->buflen >> 8;
1813 cgc->cmd[9] = cgc->buflen & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Marcin Slusarzd1941392008-11-16 19:06:37 +01001815 ret = cdo->generic_packet(cdi, cgc);
1816 if (ret)
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001817 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
1819 s->copyright.cpst = buf[4];
1820 s->copyright.rmi = buf[5];
1821
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001822 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823}
1824
Marcin Slusarzd1941392008-11-16 19:06:37 +01001825static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s,
1826 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827{
1828 int ret, size;
1829 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830 struct cdrom_device_ops *cdo = cdi->ops;
1831
1832 size = sizeof(s->disckey.value) + 4;
1833
Marcin Slusarzd1941392008-11-16 19:06:37 +01001834 buf = kmalloc(size, GFP_KERNEL);
1835 if (!buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836 return -ENOMEM;
1837
Marcin Slusarzd1941392008-11-16 19:06:37 +01001838 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1839 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1840 cgc->cmd[7] = s->type;
1841 cgc->cmd[8] = size >> 8;
1842 cgc->cmd[9] = size & 0xff;
1843 cgc->cmd[10] = s->disckey.agid << 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001844
Marcin Slusarzd1941392008-11-16 19:06:37 +01001845 ret = cdo->generic_packet(cdi, cgc);
1846 if (!ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 memcpy(s->disckey.value, &buf[4], sizeof(s->disckey.value));
1848
1849 kfree(buf);
1850 return ret;
1851}
1852
Marcin Slusarzd1941392008-11-16 19:06:37 +01001853static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s,
1854 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855{
Marcin Slusarzd1941392008-11-16 19:06:37 +01001856 int ret, size = 4 + 188;
1857 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 struct cdrom_device_ops *cdo = cdi->ops;
1859
Marcin Slusarzd1941392008-11-16 19:06:37 +01001860 buf = kmalloc(size, GFP_KERNEL);
1861 if (!buf)
1862 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Marcin Slusarzd1941392008-11-16 19:06:37 +01001864 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1865 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1866 cgc->cmd[7] = s->type;
1867 cgc->cmd[9] = cgc->buflen & 0xff;
1868
1869 ret = cdo->generic_packet(cdi, cgc);
1870 if (ret)
1871 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
1873 s->bca.len = buf[0] << 8 | buf[1];
1874 if (s->bca.len < 12 || s->bca.len > 188) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001875 cd_dbg(CD_WARNING, "Received invalid BCA length (%d)\n",
1876 s->bca.len);
Marcin Slusarzd1941392008-11-16 19:06:37 +01001877 ret = -EIO;
1878 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 }
1880 memcpy(s->bca.value, &buf[4], s->bca.len);
Marcin Slusarzd1941392008-11-16 19:06:37 +01001881 ret = 0;
1882out:
1883 kfree(buf);
1884 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885}
1886
Marcin Slusarzd1941392008-11-16 19:06:37 +01001887static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s,
1888 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889{
1890 int ret = 0, size;
1891 u_char *buf;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 struct cdrom_device_ops *cdo = cdi->ops;
1893
1894 size = sizeof(s->manufact.value) + 4;
1895
Marcin Slusarzd1941392008-11-16 19:06:37 +01001896 buf = kmalloc(size, GFP_KERNEL);
1897 if (!buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898 return -ENOMEM;
1899
Marcin Slusarzd1941392008-11-16 19:06:37 +01001900 init_cdrom_command(cgc, buf, size, CGC_DATA_READ);
1901 cgc->cmd[0] = GPCMD_READ_DVD_STRUCTURE;
1902 cgc->cmd[7] = s->type;
1903 cgc->cmd[8] = size >> 8;
1904 cgc->cmd[9] = size & 0xff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
Marcin Slusarzd1941392008-11-16 19:06:37 +01001906 ret = cdo->generic_packet(cdi, cgc);
1907 if (ret)
1908 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909
1910 s->manufact.len = buf[0] << 8 | buf[1];
Andrew Mortonaec9f372011-08-02 12:43:50 +02001911 if (s->manufact.len < 0) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001912 cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d)\n",
1913 s->manufact.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 ret = -EIO;
1915 } else {
Andrew Mortonaec9f372011-08-02 12:43:50 +02001916 if (s->manufact.len > 2048) {
Joe Perches5944b2c2014-05-04 17:05:02 -07001917 cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d): truncating to 2048\n",
1918 s->manufact.len);
Andrew Mortonaec9f372011-08-02 12:43:50 +02001919 s->manufact.len = 2048;
1920 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 memcpy(s->manufact.value, &buf[4], s->manufact.len);
1922 }
1923
Marcin Slusarzd1941392008-11-16 19:06:37 +01001924out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001925 kfree(buf);
1926 return ret;
1927}
1928
Marcin Slusarzd1941392008-11-16 19:06:37 +01001929static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s,
1930 struct packet_command *cgc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931{
1932 switch (s->type) {
1933 case DVD_STRUCT_PHYSICAL:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001934 return dvd_read_physical(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001935
1936 case DVD_STRUCT_COPYRIGHT:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001937 return dvd_read_copyright(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938
1939 case DVD_STRUCT_DISCKEY:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001940 return dvd_read_disckey(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941
1942 case DVD_STRUCT_BCA:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001943 return dvd_read_bca(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
1945 case DVD_STRUCT_MANUFACT:
Marcin Slusarzd1941392008-11-16 19:06:37 +01001946 return dvd_read_manufact(cdi, s, cgc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947
1948 default:
Joe Perches5944b2c2014-05-04 17:05:02 -07001949 cd_dbg(CD_WARNING, ": Invalid DVD structure read requested (%d)\n",
1950 s->type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001951 return -EINVAL;
1952 }
1953}
1954
1955int cdrom_mode_sense(struct cdrom_device_info *cdi,
1956 struct packet_command *cgc,
1957 int page_code, int page_control)
1958{
1959 struct cdrom_device_ops *cdo = cdi->ops;
1960
1961 memset(cgc->cmd, 0, sizeof(cgc->cmd));
1962
1963 cgc->cmd[0] = GPCMD_MODE_SENSE_10;
1964 cgc->cmd[2] = page_code | (page_control << 6);
1965 cgc->cmd[7] = cgc->buflen >> 8;
1966 cgc->cmd[8] = cgc->buflen & 0xff;
1967 cgc->data_direction = CGC_DATA_READ;
1968 return cdo->generic_packet(cdi, cgc);
1969}
1970
1971int cdrom_mode_select(struct cdrom_device_info *cdi,
1972 struct packet_command *cgc)
1973{
1974 struct cdrom_device_ops *cdo = cdi->ops;
1975
1976 memset(cgc->cmd, 0, sizeof(cgc->cmd));
1977 memset(cgc->buffer, 0, 2);
1978 cgc->cmd[0] = GPCMD_MODE_SELECT_10;
1979 cgc->cmd[1] = 0x10; /* PF */
1980 cgc->cmd[7] = cgc->buflen >> 8;
1981 cgc->cmd[8] = cgc->buflen & 0xff;
1982 cgc->data_direction = CGC_DATA_WRITE;
1983 return cdo->generic_packet(cdi, cgc);
1984}
1985
1986static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
1987 struct cdrom_subchnl *subchnl, int mcn)
1988{
1989 struct cdrom_device_ops *cdo = cdi->ops;
1990 struct packet_command cgc;
FUJITA Tomonorifce53842008-07-04 09:33:01 +02001991 char buffer[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 int ret;
1993
1994 init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
1995 cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
1996 cgc.cmd[1] = 2; /* MSF addressing */
1997 cgc.cmd[2] = 0x40; /* request subQ data */
1998 cgc.cmd[3] = mcn ? 2 : 1;
1999 cgc.cmd[8] = 16;
2000
2001 if ((ret = cdo->generic_packet(cdi, &cgc)))
FUJITA Tomonorifce53842008-07-04 09:33:01 +02002002 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003
2004 subchnl->cdsc_audiostatus = cgc.buffer[1];
2005 subchnl->cdsc_format = CDROM_MSF;
2006 subchnl->cdsc_ctrl = cgc.buffer[5] & 0xf;
2007 subchnl->cdsc_trk = cgc.buffer[6];
2008 subchnl->cdsc_ind = cgc.buffer[7];
2009
2010 subchnl->cdsc_reladdr.msf.minute = cgc.buffer[13];
2011 subchnl->cdsc_reladdr.msf.second = cgc.buffer[14];
2012 subchnl->cdsc_reladdr.msf.frame = cgc.buffer[15];
2013 subchnl->cdsc_absaddr.msf.minute = cgc.buffer[9];
2014 subchnl->cdsc_absaddr.msf.second = cgc.buffer[10];
2015 subchnl->cdsc_absaddr.msf.frame = cgc.buffer[11];
2016
FUJITA Tomonorifce53842008-07-04 09:33:01 +02002017 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018}
2019
2020/*
2021 * Specific READ_10 interface
2022 */
2023static int cdrom_read_cd(struct cdrom_device_info *cdi,
2024 struct packet_command *cgc, int lba,
2025 int blocksize, int nblocks)
2026{
2027 struct cdrom_device_ops *cdo = cdi->ops;
2028
2029 memset(&cgc->cmd, 0, sizeof(cgc->cmd));
2030 cgc->cmd[0] = GPCMD_READ_10;
2031 cgc->cmd[2] = (lba >> 24) & 0xff;
2032 cgc->cmd[3] = (lba >> 16) & 0xff;
2033 cgc->cmd[4] = (lba >> 8) & 0xff;
2034 cgc->cmd[5] = lba & 0xff;
2035 cgc->cmd[6] = (nblocks >> 16) & 0xff;
2036 cgc->cmd[7] = (nblocks >> 8) & 0xff;
2037 cgc->cmd[8] = nblocks & 0xff;
2038 cgc->buflen = blocksize * nblocks;
2039 return cdo->generic_packet(cdi, cgc);
2040}
2041
2042/* very generic interface for reading the various types of blocks */
2043static int cdrom_read_block(struct cdrom_device_info *cdi,
2044 struct packet_command *cgc,
2045 int lba, int nblocks, int format, int blksize)
2046{
2047 struct cdrom_device_ops *cdo = cdi->ops;
2048
2049 memset(&cgc->cmd, 0, sizeof(cgc->cmd));
2050 cgc->cmd[0] = GPCMD_READ_CD;
2051 /* expected sector size - cdda,mode1,etc. */
2052 cgc->cmd[1] = format << 2;
2053 /* starting address */
2054 cgc->cmd[2] = (lba >> 24) & 0xff;
2055 cgc->cmd[3] = (lba >> 16) & 0xff;
2056 cgc->cmd[4] = (lba >> 8) & 0xff;
2057 cgc->cmd[5] = lba & 0xff;
2058 /* number of blocks */
2059 cgc->cmd[6] = (nblocks >> 16) & 0xff;
2060 cgc->cmd[7] = (nblocks >> 8) & 0xff;
2061 cgc->cmd[8] = nblocks & 0xff;
2062 cgc->buflen = blksize * nblocks;
2063
2064 /* set the header info returned */
2065 switch (blksize) {
2066 case CD_FRAMESIZE_RAW0 : cgc->cmd[9] = 0x58; break;
2067 case CD_FRAMESIZE_RAW1 : cgc->cmd[9] = 0x78; break;
2068 case CD_FRAMESIZE_RAW : cgc->cmd[9] = 0xf8; break;
2069 default : cgc->cmd[9] = 0x10;
2070 }
2071
2072 return cdo->generic_packet(cdi, cgc);
2073}
2074
2075static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2076 int lba, int nframes)
2077{
2078 struct packet_command cgc;
2079 int ret = 0;
2080 int nr;
2081
2082 cdi->last_sense = 0;
2083
2084 memset(&cgc, 0, sizeof(cgc));
2085
2086 /*
2087 * start with will ra.nframes size, back down if alloc fails
2088 */
2089 nr = nframes;
2090 do {
2091 cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL);
2092 if (cgc.buffer)
2093 break;
2094
2095 nr >>= 1;
2096 } while (nr);
2097
2098 if (!nr)
2099 return -ENOMEM;
2100
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 cgc.data_direction = CGC_DATA_READ;
2102 while (nframes > 0) {
2103 if (nr > nframes)
2104 nr = nframes;
2105
2106 ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
2107 if (ret)
2108 break;
Dan Carpenter822bfa52012-02-06 10:20:45 +01002109 if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 ret = -EFAULT;
2111 break;
2112 }
2113 ubuf += CD_FRAMESIZE_RAW * nr;
2114 nframes -= nr;
2115 lba += nr;
2116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 kfree(cgc.buffer);
2118 return ret;
2119}
2120
2121static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2122 int lba, int nframes)
2123{
Jens Axboe165125e2007-07-24 09:28:11 +02002124 struct request_queue *q = cdi->disk->queue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 struct request *rq;
2126 struct bio *bio;
2127 unsigned int len;
2128 int nr, ret = 0;
2129
2130 if (!q)
2131 return -ENXIO;
2132
2133 cdi->last_sense = 0;
2134
2135 while (nframes) {
2136 nr = nframes;
2137 if (cdi->cdda_method == CDDA_BPC_SINGLE)
2138 nr = 1;
Martin K. Petersenae03bf62009-05-22 17:17:50 -04002139 if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9))
2140 nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
2142 len = nr * CD_FRAMESIZE_RAW;
2143
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002144 rq = blk_get_request(q, READ, GFP_KERNEL);
2145 if (!rq) {
2146 ret = -ENOMEM;
Jens Axboedd1cab92005-06-20 14:06:01 +02002147 break;
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002148 }
2149
2150 ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL);
2151 if (ret) {
2152 blk_put_request(rq);
2153 break;
2154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 rq->cmd[0] = GPCMD_READ_CD;
2157 rq->cmd[1] = 1 << 2;
2158 rq->cmd[2] = (lba >> 24) & 0xff;
2159 rq->cmd[3] = (lba >> 16) & 0xff;
2160 rq->cmd[4] = (lba >> 8) & 0xff;
2161 rq->cmd[5] = lba & 0xff;
2162 rq->cmd[6] = (nr >> 16) & 0xff;
2163 rq->cmd[7] = (nr >> 8) & 0xff;
2164 rq->cmd[8] = nr & 0xff;
2165 rq->cmd[9] = 0xf8;
2166
2167 rq->cmd_len = 12;
Jens Axboe4aff5e22006-08-10 08:44:47 +02002168 rq->cmd_type = REQ_TYPE_BLOCK_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 rq->timeout = 60 * HZ;
2170 bio = rq->bio;
2171
James Bottomley 994ca9a2005-06-20 14:11:09 +02002172 if (blk_execute_rq(q, cdi->disk, rq, 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173 struct request_sense *s = rq->sense;
2174 ret = -EIO;
2175 cdi->last_sense = s->sense_key;
2176 }
2177
Jens Axboe8e5cfc42006-12-19 11:12:46 +01002178 if (blk_rq_unmap_user(bio))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 ret = -EFAULT;
Alan D. Brunellefebd7a52008-12-09 15:52:15 +01002180 blk_put_request(rq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
2182 if (ret)
2183 break;
2184
2185 nframes -= nr;
2186 lba += nr;
2187 ubuf += len;
2188 }
2189
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 return ret;
2191}
2192
2193static int cdrom_read_cdda(struct cdrom_device_info *cdi, __u8 __user *ubuf,
2194 int lba, int nframes)
2195{
2196 int ret;
2197
2198 if (cdi->cdda_method == CDDA_OLD)
2199 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes);
2200
2201retry:
2202 /*
2203 * for anything else than success and io error, we need to retry
2204 */
2205 ret = cdrom_read_cdda_bpc(cdi, ubuf, lba, nframes);
2206 if (!ret || ret != -EIO)
2207 return ret;
2208
2209 /*
2210 * I've seen drives get sense 4/8/3 udma crc errors on multi
2211 * frame dma, so drop to single frame dma if we need to
2212 */
2213 if (cdi->cdda_method == CDDA_BPC_FULL && nframes > 1) {
Joe Perchese597cd02010-07-01 08:24:32 +02002214 pr_info("dropping to single frame dma\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 cdi->cdda_method = CDDA_BPC_SINGLE;
2216 goto retry;
2217 }
2218
2219 /*
2220 * so we have an io error of some sort with multi frame dma. if the
2221 * condition wasn't a hardware error
2222 * problems, not for any error
2223 */
2224 if (cdi->last_sense != 0x04 && cdi->last_sense != 0x0b)
2225 return ret;
2226
Joe Perchese597cd02010-07-01 08:24:32 +02002227 pr_info("dropping to old style cdda (sense=%x)\n", cdi->last_sense);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 cdi->cdda_method = CDDA_OLD;
2229 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes);
2230}
2231
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002232static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi,
2233 void __user *argp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234{
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002235 struct cdrom_multisession ms_info;
2236 u8 requested_format;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 int ret;
2238
Joe Perches5944b2c2014-05-04 17:05:02 -07002239 cd_dbg(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002240
2241 if (!(cdi->ops->capability & CDC_MULTI_SESSION))
2242 return -ENOSYS;
2243
2244 if (copy_from_user(&ms_info, argp, sizeof(ms_info)))
2245 return -EFAULT;
2246
2247 requested_format = ms_info.addr_format;
2248 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2249 return -EINVAL;
2250 ms_info.addr_format = CDROM_LBA;
2251
2252 ret = cdi->ops->get_last_session(cdi, &ms_info);
2253 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 return ret;
2255
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002256 sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format);
2257
2258 if (copy_to_user(argp, &ms_info, sizeof(ms_info)))
2259 return -EFAULT;
2260
Joe Perches5944b2c2014-05-04 17:05:02 -07002261 cd_dbg(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002262 return 0;
2263}
2264
2265static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
2266{
Joe Perches5944b2c2014-05-04 17:05:02 -07002267 cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002268
2269 if (!CDROM_CAN(CDC_OPEN_TRAY))
2270 return -ENOSYS;
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002271 if (cdi->use_count != 1 || cdi->keeplocked)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002272 return -EBUSY;
2273 if (CDROM_CAN(CDC_LOCK)) {
2274 int ret = cdi->ops->lock_door(cdi, 0);
2275 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 return ret;
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002279 return cdi->ops->tray_move(cdi, 1);
2280}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002282static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi)
2283{
Joe Perches5944b2c2014-05-04 17:05:02 -07002284 cd_dbg(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002286 if (!CDROM_CAN(CDC_CLOSE_TRAY))
2287 return -ENOSYS;
2288 return cdi->ops->tray_move(cdi, 0);
2289}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002291static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
2292 unsigned long arg)
2293{
Joe Perches5944b2c2014-05-04 17:05:02 -07002294 cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002296 if (!CDROM_CAN(CDC_OPEN_TRAY))
2297 return -ENOSYS;
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002298 if (cdi->keeplocked)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002299 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002301 cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
2302 if (arg)
2303 cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
2304 return 0;
2305}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002307static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
2308 unsigned long arg)
2309{
2310 struct cdrom_changer_info *info;
2311 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
Joe Perches5944b2c2014-05-04 17:05:02 -07002313 cd_dbg(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002315 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
2316 return -ENOSYS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002318 /* cannot select disc or select current disc */
2319 if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
2320 return media_changed(cdi, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002322 if ((unsigned int)arg >= cdi->capacity)
2323 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002325 info = kmalloc(sizeof(*info), GFP_KERNEL);
2326 if (!info)
2327 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002329 ret = cdrom_read_mech_status(cdi, info);
2330 if (!ret)
2331 ret = info->slots[arg].change;
2332 kfree(info);
2333 return ret;
2334}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002336static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
2337 unsigned long arg)
2338{
Joe Perches5944b2c2014-05-04 17:05:02 -07002339 cd_dbg(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002341 /*
2342 * Options need to be in sync with capability.
2343 * Too late for that, so we have to check each one separately.
2344 */
2345 switch (arg) {
2346 case CDO_USE_FFLAGS:
2347 case CDO_CHECK_TYPE:
2348 break;
2349 case CDO_LOCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002350 if (!CDROM_CAN(CDC_LOCK))
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002351 return -ENOSYS;
2352 break;
2353 case 0:
2354 return cdi->options;
2355 /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
2356 default:
2357 if (!CDROM_CAN(arg))
2358 return -ENOSYS;
2359 }
2360 cdi->options |= (int) arg;
2361 return cdi->options;
2362}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002364static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi,
2365 unsigned long arg)
2366{
Joe Perches5944b2c2014-05-04 17:05:02 -07002367 cd_dbg(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002369 cdi->options &= ~(int) arg;
2370 return cdi->options;
2371}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002373static int cdrom_ioctl_select_speed(struct cdrom_device_info *cdi,
2374 unsigned long arg)
2375{
Joe Perches5944b2c2014-05-04 17:05:02 -07002376 cd_dbg(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002377
2378 if (!CDROM_CAN(CDC_SELECT_SPEED))
2379 return -ENOSYS;
2380 return cdi->ops->select_speed(cdi, arg);
2381}
2382
2383static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi,
2384 unsigned long arg)
2385{
Joe Perches5944b2c2014-05-04 17:05:02 -07002386 cd_dbg(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002387
2388 if (!CDROM_CAN(CDC_SELECT_DISC))
2389 return -ENOSYS;
2390
2391 if (arg != CDSL_CURRENT && arg != CDSL_NONE) {
2392 if ((int)arg >= cdi->capacity)
2393 return -EINVAL;
2394 }
2395
2396 /*
2397 * ->select_disc is a hook to allow a driver-specific way of
2398 * seleting disc. However, since there is no equivalent hook for
2399 * cdrom_slot_status this may not actually be useful...
2400 */
2401 if (cdi->ops->select_disc)
2402 return cdi->ops->select_disc(cdi, arg);
2403
Joe Perches5944b2c2014-05-04 17:05:02 -07002404 cd_dbg(CD_CHANGER, "Using generic cdrom_select_disc()\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002405 return cdrom_select_disc(cdi, arg);
2406}
2407
2408static int cdrom_ioctl_reset(struct cdrom_device_info *cdi,
2409 struct block_device *bdev)
2410{
Joe Perches5944b2c2014-05-04 17:05:02 -07002411 cd_dbg(CD_DO_IOCTL, "entering CDROM_RESET\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002412
2413 if (!capable(CAP_SYS_ADMIN))
2414 return -EACCES;
2415 if (!CDROM_CAN(CDC_RESET))
2416 return -ENOSYS;
Peter Zijlstraf98393a2007-05-06 14:49:54 -07002417 invalidate_bdev(bdev);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002418 return cdi->ops->reset(cdi);
2419}
2420
2421static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,
2422 unsigned long arg)
2423{
Joe Perches5944b2c2014-05-04 17:05:02 -07002424 cd_dbg(CD_DO_IOCTL, "%socking door\n", arg ? "L" : "Unl");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002425
2426 if (!CDROM_CAN(CDC_LOCK))
2427 return -EDRIVE_CANT_DO_THIS;
2428
Paolo Bonzinicdccaa92012-02-08 20:03:14 +01002429 cdi->keeplocked = arg ? 1 : 0;
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002430
2431 /*
2432 * Don't unlock the door on multiple opens by default, but allow
2433 * root to do so.
2434 */
2435 if (cdi->use_count != 1 && !arg && !capable(CAP_SYS_ADMIN))
2436 return -EBUSY;
2437 return cdi->ops->lock_door(cdi, arg);
2438}
2439
2440static int cdrom_ioctl_debug(struct cdrom_device_info *cdi,
2441 unsigned long arg)
2442{
Joe Perches5944b2c2014-05-04 17:05:02 -07002443 cd_dbg(CD_DO_IOCTL, "%sabling debug\n", arg ? "En" : "Dis");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002444
2445 if (!capable(CAP_SYS_ADMIN))
2446 return -EACCES;
2447 debug = arg ? 1 : 0;
2448 return debug;
2449}
2450
2451static int cdrom_ioctl_get_capability(struct cdrom_device_info *cdi)
2452{
Joe Perches5944b2c2014-05-04 17:05:02 -07002453 cd_dbg(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002454 return (cdi->ops->capability & ~cdi->mask);
2455}
2456
2457/*
2458 * The following function is implemented, although very few audio
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 * discs give Universal Product Code information, which should just be
2460 * the Medium Catalog Number on the box. Note, that the way the code
2461 * is written on the CD is /not/ uniform across all discs!
2462 */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002463static int cdrom_ioctl_get_mcn(struct cdrom_device_info *cdi,
2464 void __user *argp)
2465{
2466 struct cdrom_mcn mcn;
2467 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
Joe Perches5944b2c2014-05-04 17:05:02 -07002469 cd_dbg(CD_DO_IOCTL, "entering CDROM_GET_MCN\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002471 if (!(cdi->ops->capability & CDC_MCN))
2472 return -ENOSYS;
2473 ret = cdi->ops->get_mcn(cdi, &mcn);
2474 if (ret)
2475 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002477 if (copy_to_user(argp, &mcn, sizeof(mcn)))
2478 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002479 cd_dbg(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002480 return 0;
2481}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002483static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi,
2484 unsigned long arg)
2485{
Joe Perches5944b2c2014-05-04 17:05:02 -07002486 cd_dbg(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002488 if (!(cdi->ops->capability & CDC_DRIVE_STATUS))
2489 return -ENOSYS;
2490 if (!CDROM_CAN(CDC_SELECT_DISC) ||
2491 (arg == CDSL_CURRENT || arg == CDSL_NONE))
2492 return cdi->ops->drive_status(cdi, CDSL_CURRENT);
2493 if (((int)arg >= cdi->capacity))
2494 return -EINVAL;
2495 return cdrom_slot_status(cdi, arg);
2496}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002498/*
2499 * Ok, this is where problems start. The current interface for the
2500 * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002501 * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunately, while this
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002502 * is often the case, it is also very common for CDs to have some tracks
2503 * with data, and some tracks with audio. Just because I feel like it,
2504 * I declare the following to be the best way to cope. If the CD has ANY
2505 * data tracks on it, it will be returned as a data CD. If it has any XA
2506 * tracks, I will return it as that. Now I could simplify this interface
2507 * by combining these returns with the above, but this more clearly
2508 * demonstrates the problem with the current interface. Too bad this
2509 * wasn't designed to use bitmasks... -Erik
2510 *
2511 * Well, now we have the option CDS_MIXED: a mixed-type CD.
2512 * User level programmers might feel the ioctl is not very useful.
2513 * ---david
2514 */
2515static int cdrom_ioctl_disc_status(struct cdrom_device_info *cdi)
2516{
2517 tracktype tracks;
2518
Joe Perches5944b2c2014-05-04 17:05:02 -07002519 cd_dbg(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002520
2521 cdrom_count_tracks(cdi, &tracks);
2522 if (tracks.error)
2523 return tracks.error;
2524
2525 /* Policy mode on */
2526 if (tracks.audio > 0) {
2527 if (!tracks.data && !tracks.cdi && !tracks.xa)
2528 return CDS_AUDIO;
2529 else
2530 return CDS_MIXED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 }
2532
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002533 if (tracks.cdi > 0)
2534 return CDS_XA_2_2;
2535 if (tracks.xa > 0)
2536 return CDS_XA_2_1;
2537 if (tracks.data > 0)
2538 return CDS_DATA_1;
2539 /* Policy mode off */
2540
Joe Perches5944b2c2014-05-04 17:05:02 -07002541 cd_dbg(CD_WARNING, "This disc doesn't have any tracks I recognize!\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002542 return CDS_NO_INFO;
2543}
2544
2545static int cdrom_ioctl_changer_nslots(struct cdrom_device_info *cdi)
2546{
Joe Perches5944b2c2014-05-04 17:05:02 -07002547 cd_dbg(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002548 return cdi->capacity;
2549}
2550
2551static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi,
2552 void __user *argp)
2553{
2554 struct cdrom_subchnl q;
2555 u8 requested, back;
2556 int ret;
2557
Joe Perches5944b2c2014-05-04 17:05:02 -07002558 /* cd_dbg(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002559
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002560 if (copy_from_user(&q, argp, sizeof(q)))
2561 return -EFAULT;
2562
2563 requested = q.cdsc_format;
2564 if (requested != CDROM_MSF && requested != CDROM_LBA)
2565 return -EINVAL;
2566 q.cdsc_format = CDROM_MSF;
2567
2568 ret = cdi->ops->audio_ioctl(cdi, CDROMSUBCHNL, &q);
2569 if (ret)
2570 return ret;
2571
2572 back = q.cdsc_format; /* local copy */
2573 sanitize_format(&q.cdsc_absaddr, &back, requested);
2574 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
2575
2576 if (copy_to_user(argp, &q, sizeof(q)))
2577 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002578 /* cd_dbg(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002579 return 0;
2580}
2581
2582static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi,
2583 void __user *argp)
2584{
2585 struct cdrom_tochdr header;
2586 int ret;
2587
Joe Perches5944b2c2014-05-04 17:05:02 -07002588 /* cd_dbg(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002589
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002590 if (copy_from_user(&header, argp, sizeof(header)))
2591 return -EFAULT;
2592
2593 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
2594 if (ret)
2595 return ret;
2596
2597 if (copy_to_user(argp, &header, sizeof(header)))
2598 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002599 /* cd_dbg(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002600 return 0;
2601}
2602
2603static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi,
2604 void __user *argp)
2605{
2606 struct cdrom_tocentry entry;
2607 u8 requested_format;
2608 int ret;
2609
Joe Perches5944b2c2014-05-04 17:05:02 -07002610 /* cd_dbg(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002611
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002612 if (copy_from_user(&entry, argp, sizeof(entry)))
2613 return -EFAULT;
2614
2615 requested_format = entry.cdte_format;
2616 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2617 return -EINVAL;
2618 /* make interface to low-level uniform */
2619 entry.cdte_format = CDROM_MSF;
2620 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry);
2621 if (ret)
2622 return ret;
2623 sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format);
2624
2625 if (copy_to_user(argp, &entry, sizeof(entry)))
2626 return -EFAULT;
Joe Perches5944b2c2014-05-04 17:05:02 -07002627 /* cd_dbg(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002628 return 0;
2629}
2630
2631static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi,
2632 void __user *argp)
2633{
2634 struct cdrom_msf msf;
2635
Joe Perches5944b2c2014-05-04 17:05:02 -07002636 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002637
2638 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2639 return -ENOSYS;
2640 if (copy_from_user(&msf, argp, sizeof(msf)))
2641 return -EFAULT;
2642 return cdi->ops->audio_ioctl(cdi, CDROMPLAYMSF, &msf);
2643}
2644
2645static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi,
2646 void __user *argp)
2647{
2648 struct cdrom_ti ti;
2649 int ret;
2650
Joe Perches5944b2c2014-05-04 17:05:02 -07002651 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002652
2653 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2654 return -ENOSYS;
2655 if (copy_from_user(&ti, argp, sizeof(ti)))
2656 return -EFAULT;
2657
2658 ret = check_for_audio_disc(cdi, cdi->ops);
2659 if (ret)
2660 return ret;
2661 return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti);
2662}
2663static int cdrom_ioctl_volctrl(struct cdrom_device_info *cdi,
2664 void __user *argp)
2665{
2666 struct cdrom_volctrl volume;
2667
Joe Perches5944b2c2014-05-04 17:05:02 -07002668 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002669
2670 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2671 return -ENOSYS;
2672 if (copy_from_user(&volume, argp, sizeof(volume)))
2673 return -EFAULT;
2674 return cdi->ops->audio_ioctl(cdi, CDROMVOLCTRL, &volume);
2675}
2676
2677static int cdrom_ioctl_volread(struct cdrom_device_info *cdi,
2678 void __user *argp)
2679{
2680 struct cdrom_volctrl volume;
2681 int ret;
2682
Joe Perches5944b2c2014-05-04 17:05:02 -07002683 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002684
2685 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2686 return -ENOSYS;
2687
2688 ret = cdi->ops->audio_ioctl(cdi, CDROMVOLREAD, &volume);
2689 if (ret)
2690 return ret;
2691
2692 if (copy_to_user(argp, &volume, sizeof(volume)))
2693 return -EFAULT;
2694 return 0;
2695}
2696
2697static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi,
2698 unsigned int cmd)
2699{
2700 int ret;
2701
Joe Perches5944b2c2014-05-04 17:05:02 -07002702 cd_dbg(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08002703
2704 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2705 return -ENOSYS;
2706 ret = check_for_audio_disc(cdi, cdi->ops);
2707 if (ret)
2708 return ret;
2709 return cdi->ops->audio_ioctl(cdi, cmd, NULL);
2710}
2711
2712/*
Joe Perches2e9aa082014-05-04 17:05:08 -07002713 * Required when we need to use READ_10 to issue other than 2048 block
2714 * reads
2715 */
2716static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
2717{
2718 struct cdrom_device_ops *cdo = cdi->ops;
2719 struct packet_command cgc;
2720 struct modesel_head mh;
2721
2722 memset(&mh, 0, sizeof(mh));
2723 mh.block_desc_length = 0x08;
2724 mh.block_length_med = (size >> 8) & 0xff;
2725 mh.block_length_lo = size & 0xff;
2726
2727 memset(&cgc, 0, sizeof(cgc));
2728 cgc.cmd[0] = 0x15;
2729 cgc.cmd[1] = 1 << 4;
2730 cgc.cmd[4] = 12;
2731 cgc.buflen = sizeof(mh);
2732 cgc.buffer = (char *) &mh;
2733 cgc.data_direction = CGC_DATA_WRITE;
2734 mh.block_desc_length = 0x08;
2735 mh.block_length_med = (size >> 8) & 0xff;
2736 mh.block_length_lo = size & 0xff;
2737
2738 return cdo->generic_packet(cdi, &cgc);
2739}
2740
Joe Perchese1e60fd2014-05-04 17:05:09 -07002741static int cdrom_get_track_info(struct cdrom_device_info *cdi,
2742 __u16 track, __u8 type, track_information *ti)
2743{
2744 struct cdrom_device_ops *cdo = cdi->ops;
2745 struct packet_command cgc;
2746 int ret, buflen;
2747
2748 init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
2749 cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
2750 cgc.cmd[1] = type & 3;
2751 cgc.cmd[4] = (track & 0xff00) >> 8;
2752 cgc.cmd[5] = track & 0xff;
2753 cgc.cmd[8] = 8;
2754 cgc.quiet = 1;
2755
2756 ret = cdo->generic_packet(cdi, &cgc);
2757 if (ret)
2758 return ret;
2759
2760 buflen = be16_to_cpu(ti->track_information_length) +
2761 sizeof(ti->track_information_length);
2762
2763 if (buflen > sizeof(track_information))
2764 buflen = sizeof(track_information);
2765
2766 cgc.cmd[8] = cgc.buflen = buflen;
2767 ret = cdo->generic_packet(cdi, &cgc);
2768 if (ret)
2769 return ret;
2770
2771 /* return actual fill size */
2772 return buflen;
2773}
2774
2775/* return the last written block on the CD-R media. this is for the udf
2776 file system. */
2777int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written)
2778{
2779 struct cdrom_tocentry toc;
2780 disc_information di;
2781 track_information ti;
2782 __u32 last_track;
2783 int ret = -1, ti_size;
2784
2785 if (!CDROM_CAN(CDC_GENERIC_PACKET))
2786 goto use_toc;
2787
2788 ret = cdrom_get_disc_info(cdi, &di);
2789 if (ret < (int)(offsetof(typeof(di), last_track_lsb)
2790 + sizeof(di.last_track_lsb)))
2791 goto use_toc;
2792
2793 /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
2794 last_track = (di.last_track_msb << 8) | di.last_track_lsb;
2795 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
2796 if (ti_size < (int)offsetof(typeof(ti), track_start))
2797 goto use_toc;
2798
2799 /* if this track is blank, try the previous. */
2800 if (ti.blank) {
2801 if (last_track == 1)
2802 goto use_toc;
2803 last_track--;
2804 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
2805 }
2806
2807 if (ti_size < (int)(offsetof(typeof(ti), track_size)
2808 + sizeof(ti.track_size)))
2809 goto use_toc;
2810
2811 /* if last recorded field is valid, return it. */
2812 if (ti.lra_v && ti_size >= (int)(offsetof(typeof(ti), last_rec_address)
2813 + sizeof(ti.last_rec_address))) {
2814 *last_written = be32_to_cpu(ti.last_rec_address);
2815 } else {
2816 /* make it up instead */
2817 *last_written = be32_to_cpu(ti.track_start) +
2818 be32_to_cpu(ti.track_size);
2819 if (ti.free_blocks)
2820 *last_written -= (be32_to_cpu(ti.free_blocks) + 7);
2821 }
2822 return 0;
2823
2824 /* this is where we end up if the drive either can't do a
2825 GPCMD_READ_DISC_INFO or GPCMD_READ_TRACK_RZONE_INFO or if
2826 it doesn't give enough information or fails. then we return
2827 the toc contents. */
2828use_toc:
2829 toc.cdte_format = CDROM_MSF;
2830 toc.cdte_track = CDROM_LEADOUT;
2831 if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)))
2832 return ret;
2833 sanitize_format(&toc.cdte_addr, &toc.cdte_format, CDROM_LBA);
2834 *last_written = toc.cdte_addr.lba;
2835 return 0;
2836}
2837
Joe Perchesdac1c5c2014-05-04 17:05:10 -07002838/* return the next writable block. also for udf file system. */
2839static int cdrom_get_next_writable(struct cdrom_device_info *cdi,
2840 long *next_writable)
2841{
2842 disc_information di;
2843 track_information ti;
2844 __u16 last_track;
2845 int ret, ti_size;
2846
2847 if (!CDROM_CAN(CDC_GENERIC_PACKET))
2848 goto use_last_written;
2849
2850 ret = cdrom_get_disc_info(cdi, &di);
2851 if (ret < 0 || ret < offsetof(typeof(di), last_track_lsb)
2852 + sizeof(di.last_track_lsb))
2853 goto use_last_written;
2854
2855 /* if unit didn't return msb, it's zeroed by cdrom_get_disc_info */
2856 last_track = (di.last_track_msb << 8) | di.last_track_lsb;
2857 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
2858 if (ti_size < 0 || ti_size < offsetof(typeof(ti), track_start))
2859 goto use_last_written;
2860
2861 /* if this track is blank, try the previous. */
2862 if (ti.blank) {
2863 if (last_track == 1)
2864 goto use_last_written;
2865 last_track--;
2866 ti_size = cdrom_get_track_info(cdi, last_track, 1, &ti);
2867 if (ti_size < 0)
2868 goto use_last_written;
2869 }
2870
2871 /* if next recordable address field is valid, use it. */
2872 if (ti.nwa_v && ti_size >= offsetof(typeof(ti), next_writable)
2873 + sizeof(ti.next_writable)) {
2874 *next_writable = be32_to_cpu(ti.next_writable);
2875 return 0;
2876 }
2877
2878use_last_written:
2879 ret = cdrom_get_last_written(cdi, next_writable);
2880 if (ret) {
2881 *next_writable = 0;
2882 return ret;
2883 } else {
2884 *next_writable += 7;
2885 return 0;
2886 }
2887}
2888
Joe Perches2e9aa082014-05-04 17:05:08 -07002889static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi,
2890 void __user *arg,
2891 struct packet_command *cgc,
2892 int cmd)
2893{
2894 struct request_sense sense;
2895 struct cdrom_msf msf;
2896 int blocksize = 0, format = 0, lba;
2897 int ret;
2898
2899 switch (cmd) {
2900 case CDROMREADRAW:
2901 blocksize = CD_FRAMESIZE_RAW;
2902 break;
2903 case CDROMREADMODE1:
2904 blocksize = CD_FRAMESIZE;
2905 format = 2;
2906 break;
2907 case CDROMREADMODE2:
2908 blocksize = CD_FRAMESIZE_RAW0;
2909 break;
2910 }
2911 if (copy_from_user(&msf, (struct cdrom_msf __user *)arg, sizeof(msf)))
2912 return -EFAULT;
2913 lba = msf_to_lba(msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0);
2914 /* FIXME: we need upper bound checking, too!! */
2915 if (lba < 0)
2916 return -EINVAL;
2917
2918 cgc->buffer = kzalloc(blocksize, GFP_KERNEL);
2919 if (cgc->buffer == NULL)
2920 return -ENOMEM;
2921
2922 memset(&sense, 0, sizeof(sense));
2923 cgc->sense = &sense;
2924 cgc->data_direction = CGC_DATA_READ;
2925 ret = cdrom_read_block(cdi, cgc, lba, 1, format, blocksize);
2926 if (ret && sense.sense_key == 0x05 &&
2927 sense.asc == 0x20 &&
2928 sense.ascq == 0x00) {
2929 /*
2930 * SCSI-II devices are not required to support
2931 * READ_CD, so let's try switching block size
2932 */
2933 /* FIXME: switch back again... */
2934 ret = cdrom_switch_blocksize(cdi, blocksize);
2935 if (ret)
2936 goto out;
2937 cgc->sense = NULL;
2938 ret = cdrom_read_cd(cdi, cgc, lba, blocksize, 1);
2939 ret |= cdrom_switch_blocksize(cdi, blocksize);
2940 }
2941 if (!ret && copy_to_user(arg, cgc->buffer, blocksize))
2942 ret = -EFAULT;
2943out:
2944 kfree(cgc->buffer);
2945 return ret;
2946}
2947
2948static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi,
2949 void __user *arg)
2950{
2951 struct cdrom_read_audio ra;
2952 int lba;
2953
2954 if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg,
2955 sizeof(ra)))
2956 return -EFAULT;
2957
2958 if (ra.addr_format == CDROM_MSF)
2959 lba = msf_to_lba(ra.addr.msf.minute,
2960 ra.addr.msf.second,
2961 ra.addr.msf.frame);
2962 else if (ra.addr_format == CDROM_LBA)
2963 lba = ra.addr.lba;
2964 else
2965 return -EINVAL;
2966
2967 /* FIXME: we need upper bound checking, too!! */
2968 if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES)
2969 return -EINVAL;
2970
2971 return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes);
2972}
2973
2974static noinline int mmc_ioctl_cdrom_subchannel(struct cdrom_device_info *cdi,
2975 void __user *arg)
2976{
2977 int ret;
2978 struct cdrom_subchnl q;
2979 u_char requested, back;
2980 if (copy_from_user(&q, (struct cdrom_subchnl __user *)arg, sizeof(q)))
2981 return -EFAULT;
2982 requested = q.cdsc_format;
2983 if (!((requested == CDROM_MSF) ||
2984 (requested == CDROM_LBA)))
2985 return -EINVAL;
2986 q.cdsc_format = CDROM_MSF;
2987 ret = cdrom_read_subchannel(cdi, &q, 0);
2988 if (ret)
2989 return ret;
2990 back = q.cdsc_format; /* local copy */
2991 sanitize_format(&q.cdsc_absaddr, &back, requested);
2992 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
2993 if (copy_to_user((struct cdrom_subchnl __user *)arg, &q, sizeof(q)))
2994 return -EFAULT;
2995 /* cd_dbg(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
2996 return 0;
2997}
2998
2999static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi,
3000 void __user *arg,
3001 struct packet_command *cgc)
3002{
3003 struct cdrom_device_ops *cdo = cdi->ops;
3004 struct cdrom_msf msf;
3005 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
3006 if (copy_from_user(&msf, (struct cdrom_msf __user *)arg, sizeof(msf)))
3007 return -EFAULT;
3008 cgc->cmd[0] = GPCMD_PLAY_AUDIO_MSF;
3009 cgc->cmd[3] = msf.cdmsf_min0;
3010 cgc->cmd[4] = msf.cdmsf_sec0;
3011 cgc->cmd[5] = msf.cdmsf_frame0;
3012 cgc->cmd[6] = msf.cdmsf_min1;
3013 cgc->cmd[7] = msf.cdmsf_sec1;
3014 cgc->cmd[8] = msf.cdmsf_frame1;
3015 cgc->data_direction = CGC_DATA_NONE;
3016 return cdo->generic_packet(cdi, cgc);
3017}
3018
3019static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi,
3020 void __user *arg,
3021 struct packet_command *cgc)
3022{
3023 struct cdrom_device_ops *cdo = cdi->ops;
3024 struct cdrom_blk blk;
3025 cd_dbg(CD_DO_IOCTL, "entering CDROMPLAYBLK\n");
3026 if (copy_from_user(&blk, (struct cdrom_blk __user *)arg, sizeof(blk)))
3027 return -EFAULT;
3028 cgc->cmd[0] = GPCMD_PLAY_AUDIO_10;
3029 cgc->cmd[2] = (blk.from >> 24) & 0xff;
3030 cgc->cmd[3] = (blk.from >> 16) & 0xff;
3031 cgc->cmd[4] = (blk.from >> 8) & 0xff;
3032 cgc->cmd[5] = blk.from & 0xff;
3033 cgc->cmd[7] = (blk.len >> 8) & 0xff;
3034 cgc->cmd[8] = blk.len & 0xff;
3035 cgc->data_direction = CGC_DATA_NONE;
3036 return cdo->generic_packet(cdi, cgc);
3037}
3038
3039static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi,
3040 void __user *arg,
3041 struct packet_command *cgc,
3042 unsigned int cmd)
3043{
3044 struct cdrom_volctrl volctrl;
3045 unsigned char buffer[32];
3046 char mask[sizeof(buffer)];
3047 unsigned short offset;
3048 int ret;
3049
3050 cd_dbg(CD_DO_IOCTL, "entering CDROMVOLUME\n");
3051
3052 if (copy_from_user(&volctrl, (struct cdrom_volctrl __user *)arg,
3053 sizeof(volctrl)))
3054 return -EFAULT;
3055
3056 cgc->buffer = buffer;
3057 cgc->buflen = 24;
3058 ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 0);
3059 if (ret)
3060 return ret;
3061
3062 /* originally the code depended on buffer[1] to determine
3063 how much data is available for transfer. buffer[1] is
3064 unfortunately ambigious and the only reliable way seem
3065 to be to simply skip over the block descriptor... */
3066 offset = 8 + be16_to_cpu(*(__be16 *)(buffer + 6));
3067
3068 if (offset + 16 > sizeof(buffer))
3069 return -E2BIG;
3070
3071 if (offset + 16 > cgc->buflen) {
3072 cgc->buflen = offset + 16;
3073 ret = cdrom_mode_sense(cdi, cgc,
3074 GPMODE_AUDIO_CTL_PAGE, 0);
3075 if (ret)
3076 return ret;
3077 }
3078
3079 /* sanity check */
3080 if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE ||
3081 buffer[offset + 1] < 14)
3082 return -EINVAL;
3083
3084 /* now we have the current volume settings. if it was only
3085 a CDROMVOLREAD, return these values */
3086 if (cmd == CDROMVOLREAD) {
3087 volctrl.channel0 = buffer[offset+9];
3088 volctrl.channel1 = buffer[offset+11];
3089 volctrl.channel2 = buffer[offset+13];
3090 volctrl.channel3 = buffer[offset+15];
3091 if (copy_to_user((struct cdrom_volctrl __user *)arg, &volctrl,
3092 sizeof(volctrl)))
3093 return -EFAULT;
3094 return 0;
3095 }
3096
3097 /* get the volume mask */
3098 cgc->buffer = mask;
3099 ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 1);
3100 if (ret)
3101 return ret;
3102
3103 buffer[offset + 9] = volctrl.channel0 & mask[offset + 9];
3104 buffer[offset + 11] = volctrl.channel1 & mask[offset + 11];
3105 buffer[offset + 13] = volctrl.channel2 & mask[offset + 13];
3106 buffer[offset + 15] = volctrl.channel3 & mask[offset + 15];
3107
3108 /* set volume */
3109 cgc->buffer = buffer + offset - 8;
3110 memset(cgc->buffer, 0, 8);
3111 return cdrom_mode_select(cdi, cgc);
3112}
3113
3114static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi,
3115 struct packet_command *cgc,
3116 int cmd)
3117{
3118 struct cdrom_device_ops *cdo = cdi->ops;
3119 cd_dbg(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n");
3120 cgc->cmd[0] = GPCMD_START_STOP_UNIT;
3121 cgc->cmd[1] = 1;
3122 cgc->cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
3123 cgc->data_direction = CGC_DATA_NONE;
3124 return cdo->generic_packet(cdi, cgc);
3125}
3126
3127static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi,
3128 struct packet_command *cgc,
3129 int cmd)
3130{
3131 struct cdrom_device_ops *cdo = cdi->ops;
3132 cd_dbg(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n");
3133 cgc->cmd[0] = GPCMD_PAUSE_RESUME;
3134 cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
3135 cgc->data_direction = CGC_DATA_NONE;
3136 return cdo->generic_packet(cdi, cgc);
3137}
3138
3139static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi,
3140 void __user *arg,
3141 struct packet_command *cgc)
3142{
3143 int ret;
3144 dvd_struct *s;
3145 int size = sizeof(dvd_struct);
3146
3147 if (!CDROM_CAN(CDC_DVD))
3148 return -ENOSYS;
3149
3150 s = kmalloc(size, GFP_KERNEL);
3151 if (!s)
3152 return -ENOMEM;
3153
3154 cd_dbg(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n");
3155 if (copy_from_user(s, arg, size)) {
3156 kfree(s);
3157 return -EFAULT;
3158 }
3159
3160 ret = dvd_read_struct(cdi, s, cgc);
3161 if (ret)
3162 goto out;
3163
3164 if (copy_to_user(arg, s, size))
3165 ret = -EFAULT;
3166out:
3167 kfree(s);
3168 return ret;
3169}
3170
3171static noinline int mmc_ioctl_dvd_auth(struct cdrom_device_info *cdi,
3172 void __user *arg)
3173{
3174 int ret;
3175 dvd_authinfo ai;
3176 if (!CDROM_CAN(CDC_DVD))
3177 return -ENOSYS;
3178 cd_dbg(CD_DO_IOCTL, "entering DVD_AUTH\n");
3179 if (copy_from_user(&ai, (dvd_authinfo __user *)arg, sizeof(ai)))
3180 return -EFAULT;
3181 ret = dvd_do_auth(cdi, &ai);
3182 if (ret)
3183 return ret;
3184 if (copy_to_user((dvd_authinfo __user *)arg, &ai, sizeof(ai)))
3185 return -EFAULT;
3186 return 0;
3187}
3188
3189static noinline int mmc_ioctl_cdrom_next_writable(struct cdrom_device_info *cdi,
3190 void __user *arg)
3191{
3192 int ret;
3193 long next = 0;
3194 cd_dbg(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n");
3195 ret = cdrom_get_next_writable(cdi, &next);
3196 if (ret)
3197 return ret;
3198 if (copy_to_user((long __user *)arg, &next, sizeof(next)))
3199 return -EFAULT;
3200 return 0;
3201}
3202
3203static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi,
3204 void __user *arg)
3205{
3206 int ret;
3207 long last = 0;
3208 cd_dbg(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n");
3209 ret = cdrom_get_last_written(cdi, &last);
3210 if (ret)
3211 return ret;
3212 if (copy_to_user((long __user *)arg, &last, sizeof(last)))
3213 return -EFAULT;
3214 return 0;
3215}
3216
3217static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
3218 unsigned long arg)
3219{
3220 struct packet_command cgc;
3221 void __user *userptr = (void __user *)arg;
3222
3223 memset(&cgc, 0, sizeof(cgc));
3224
3225 /* build a unified command and queue it through
3226 cdo->generic_packet() */
3227 switch (cmd) {
3228 case CDROMREADRAW:
3229 case CDROMREADMODE1:
3230 case CDROMREADMODE2:
3231 return mmc_ioctl_cdrom_read_data(cdi, userptr, &cgc, cmd);
3232 case CDROMREADAUDIO:
3233 return mmc_ioctl_cdrom_read_audio(cdi, userptr);
3234 case CDROMSUBCHNL:
3235 return mmc_ioctl_cdrom_subchannel(cdi, userptr);
3236 case CDROMPLAYMSF:
3237 return mmc_ioctl_cdrom_play_msf(cdi, userptr, &cgc);
3238 case CDROMPLAYBLK:
3239 return mmc_ioctl_cdrom_play_blk(cdi, userptr, &cgc);
3240 case CDROMVOLCTRL:
3241 case CDROMVOLREAD:
3242 return mmc_ioctl_cdrom_volume(cdi, userptr, &cgc, cmd);
3243 case CDROMSTART:
3244 case CDROMSTOP:
3245 return mmc_ioctl_cdrom_start_stop(cdi, &cgc, cmd);
3246 case CDROMPAUSE:
3247 case CDROMRESUME:
3248 return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd);
3249 case DVD_READ_STRUCT:
3250 return mmc_ioctl_dvd_read_struct(cdi, userptr, &cgc);
3251 case DVD_AUTH:
3252 return mmc_ioctl_dvd_auth(cdi, userptr);
3253 case CDROM_NEXT_WRITABLE:
3254 return mmc_ioctl_cdrom_next_writable(cdi, userptr);
3255 case CDROM_LAST_WRITTEN:
3256 return mmc_ioctl_cdrom_last_written(cdi, userptr);
3257 }
3258
3259 return -ENOTTY;
3260}
3261
3262/*
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003263 * Just about every imaginable ioctl is supported in the Uniform layer
3264 * these days.
3265 * ATAPI / SCSI specific code now mainly resides in mmc_ioctl().
3266 */
Al Virobbc1cc92007-10-07 17:54:28 -04003267int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
3268 fmode_t mode, unsigned int cmd, unsigned long arg)
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003269{
3270 void __user *argp = (void __user *)arg;
3271 int ret;
3272
3273 /*
3274 * Try the generic SCSI command ioctl's first.
3275 */
Paolo Bonzini577ebb32012-01-12 16:01:27 +01003276 ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003277 if (ret != -ENOTTY)
3278 return ret;
3279
3280 switch (cmd) {
3281 case CDROMMULTISESSION:
3282 return cdrom_ioctl_multisession(cdi, argp);
3283 case CDROMEJECT:
3284 return cdrom_ioctl_eject(cdi);
3285 case CDROMCLOSETRAY:
3286 return cdrom_ioctl_closetray(cdi);
3287 case CDROMEJECT_SW:
3288 return cdrom_ioctl_eject_sw(cdi, arg);
3289 case CDROM_MEDIA_CHANGED:
3290 return cdrom_ioctl_media_changed(cdi, arg);
3291 case CDROM_SET_OPTIONS:
3292 return cdrom_ioctl_set_options(cdi, arg);
3293 case CDROM_CLEAR_OPTIONS:
3294 return cdrom_ioctl_clear_options(cdi, arg);
3295 case CDROM_SELECT_SPEED:
3296 return cdrom_ioctl_select_speed(cdi, arg);
3297 case CDROM_SELECT_DISC:
3298 return cdrom_ioctl_select_disc(cdi, arg);
3299 case CDROMRESET:
Al Virobbc1cc92007-10-07 17:54:28 -04003300 return cdrom_ioctl_reset(cdi, bdev);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003301 case CDROM_LOCKDOOR:
3302 return cdrom_ioctl_lock_door(cdi, arg);
3303 case CDROM_DEBUG:
3304 return cdrom_ioctl_debug(cdi, arg);
3305 case CDROM_GET_CAPABILITY:
3306 return cdrom_ioctl_get_capability(cdi);
3307 case CDROM_GET_MCN:
3308 return cdrom_ioctl_get_mcn(cdi, argp);
3309 case CDROM_DRIVE_STATUS:
3310 return cdrom_ioctl_drive_status(cdi, arg);
3311 case CDROM_DISC_STATUS:
3312 return cdrom_ioctl_disc_status(cdi);
3313 case CDROM_CHANGER_NSLOTS:
3314 return cdrom_ioctl_changer_nslots(cdi);
3315 }
3316
3317 /*
3318 * Use the ioctls that are implemented through the generic_packet()
3319 * interface. this may look at bit funny, but if -ENOTTY is
3320 * returned that particular ioctl is not implemented and we
3321 * let it go through the device specific ones.
3322 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323 if (CDROM_CAN(CDC_GENERIC_PACKET)) {
3324 ret = mmc_ioctl(cdi, cmd, arg);
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003325 if (ret != -ENOTTY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327 }
3328
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003329 /*
Joe Perches5944b2c2014-05-04 17:05:02 -07003330 * Note: most of the cd_dbg() calls are commented out here,
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003331 * because they fill up the sys log when CD players poll
3332 * the drive.
3333 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334 switch (cmd) {
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003335 case CDROMSUBCHNL:
3336 return cdrom_ioctl_get_subchnl(cdi, argp);
3337 case CDROMREADTOCHDR:
3338 return cdrom_ioctl_read_tochdr(cdi, argp);
3339 case CDROMREADTOCENTRY:
3340 return cdrom_ioctl_read_tocentry(cdi, argp);
3341 case CDROMPLAYMSF:
3342 return cdrom_ioctl_play_msf(cdi, argp);
3343 case CDROMPLAYTRKIND:
3344 return cdrom_ioctl_play_trkind(cdi, argp);
3345 case CDROMVOLCTRL:
3346 return cdrom_ioctl_volctrl(cdi, argp);
3347 case CDROMVOLREAD:
3348 return cdrom_ioctl_volread(cdi, argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349 case CDROMSTART:
3350 case CDROMSTOP:
3351 case CDROMPAUSE:
Christoph Hellwigd2c5d4f2006-03-23 03:00:14 -08003352 case CDROMRESUME:
3353 return cdrom_ioctl_audioctl(cdi, cmd);
3354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356 return -ENOSYS;
3357}
3358
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359/* requires CD R/RW */
3360static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di)
3361{
3362 struct cdrom_device_ops *cdo = cdi->ops;
3363 struct packet_command cgc;
3364 int ret, buflen;
3365
3366 /* set up command and get the disc info */
3367 init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
3368 cgc.cmd[0] = GPCMD_READ_DISC_INFO;
3369 cgc.cmd[8] = cgc.buflen = 2;
3370 cgc.quiet = 1;
3371
3372 if ((ret = cdo->generic_packet(cdi, &cgc)))
3373 return ret;
3374
3375 /* not all drives have the same disc_info length, so requeue
3376 * packet with the length the drive tells us it can supply
3377 */
3378 buflen = be16_to_cpu(di->disc_information_length) +
3379 sizeof(di->disc_information_length);
3380
3381 if (buflen > sizeof(disc_information))
3382 buflen = sizeof(disc_information);
3383
3384 cgc.cmd[8] = cgc.buflen = buflen;
3385 if ((ret = cdo->generic_packet(cdi, &cgc)))
3386 return ret;
3387
3388 /* return actual fill size */
3389 return buflen;
3390}
3391
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392EXPORT_SYMBOL(cdrom_get_last_written);
3393EXPORT_SYMBOL(register_cdrom);
3394EXPORT_SYMBOL(unregister_cdrom);
3395EXPORT_SYMBOL(cdrom_open);
3396EXPORT_SYMBOL(cdrom_release);
3397EXPORT_SYMBOL(cdrom_ioctl);
3398EXPORT_SYMBOL(cdrom_media_changed);
3399EXPORT_SYMBOL(cdrom_number_of_slots);
3400EXPORT_SYMBOL(cdrom_mode_select);
3401EXPORT_SYMBOL(cdrom_mode_sense);
3402EXPORT_SYMBOL(init_cdrom_command);
3403EXPORT_SYMBOL(cdrom_get_media_event);
3404
3405#ifdef CONFIG_SYSCTL
3406
3407#define CDROM_STR_SIZE 1000
3408
3409static struct cdrom_sysctl_settings {
3410 char info[CDROM_STR_SIZE]; /* general info */
3411 int autoclose; /* close tray upon mount, etc */
3412 int autoeject; /* eject on umount */
3413 int debug; /* turn on debugging messages */
3414 int lock; /* lock the door on device open */
3415 int check; /* check media type */
3416} cdrom_sysctl_settings;
3417
Dave Young554988d2007-06-19 09:14:26 +02003418enum cdrom_print_option {
3419 CTL_NAME,
3420 CTL_SPEED,
3421 CTL_SLOTS,
3422 CTL_CAPABILITY
3423};
3424
3425static int cdrom_print_info(const char *header, int val, char *info,
3426 int *pos, enum cdrom_print_option option)
3427{
3428 const int max_size = sizeof(cdrom_sysctl_settings.info);
3429 struct cdrom_device_info *cdi;
3430 int ret;
3431
3432 ret = scnprintf(info + *pos, max_size - *pos, header);
3433 if (!ret)
3434 return 1;
3435
3436 *pos += ret;
3437
Akinobu Mita7fd097d2008-03-26 12:09:02 +01003438 list_for_each_entry(cdi, &cdrom_list, list) {
Dave Young554988d2007-06-19 09:14:26 +02003439 switch (option) {
3440 case CTL_NAME:
3441 ret = scnprintf(info + *pos, max_size - *pos,
3442 "\t%s", cdi->name);
3443 break;
3444 case CTL_SPEED:
3445 ret = scnprintf(info + *pos, max_size - *pos,
3446 "\t%d", cdi->speed);
3447 break;
3448 case CTL_SLOTS:
3449 ret = scnprintf(info + *pos, max_size - *pos,
3450 "\t%d", cdi->capacity);
3451 break;
3452 case CTL_CAPABILITY:
3453 ret = scnprintf(info + *pos, max_size - *pos,
3454 "\t%d", CDROM_CAN(val) != 0);
3455 break;
3456 default:
Joe Perchese597cd02010-07-01 08:24:32 +02003457 pr_info("invalid option%d\n", option);
Dave Young554988d2007-06-19 09:14:26 +02003458 return 1;
3459 }
3460 if (!ret)
3461 return 1;
3462 *pos += ret;
3463 }
3464
3465 return 0;
3466}
3467
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003468static int cdrom_sysctl_info(ctl_table *ctl, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 void __user *buffer, size_t *lenp, loff_t *ppos)
3470{
Dave Young554988d2007-06-19 09:14:26 +02003471 int pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003472 char *info = cdrom_sysctl_settings.info;
Dave Young554988d2007-06-19 09:14:26 +02003473 const int max_size = sizeof(cdrom_sysctl_settings.info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
3475 if (!*lenp || (*ppos && !write)) {
3476 *lenp = 0;
3477 return 0;
3478 }
3479
Dave Young554988d2007-06-19 09:14:26 +02003480 mutex_lock(&cdrom_mutex);
3481
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482 pos = sprintf(info, "CD-ROM information, " VERSION "\n");
3483
Dave Young554988d2007-06-19 09:14:26 +02003484 if (cdrom_print_info("\ndrive name:\t", 0, info, &pos, CTL_NAME))
3485 goto done;
3486 if (cdrom_print_info("\ndrive speed:\t", 0, info, &pos, CTL_SPEED))
3487 goto done;
3488 if (cdrom_print_info("\ndrive # of slots:", 0, info, &pos, CTL_SLOTS))
3489 goto done;
3490 if (cdrom_print_info("\nCan close tray:\t",
3491 CDC_CLOSE_TRAY, info, &pos, CTL_CAPABILITY))
3492 goto done;
3493 if (cdrom_print_info("\nCan open tray:\t",
3494 CDC_OPEN_TRAY, info, &pos, CTL_CAPABILITY))
3495 goto done;
3496 if (cdrom_print_info("\nCan lock tray:\t",
3497 CDC_LOCK, info, &pos, CTL_CAPABILITY))
3498 goto done;
3499 if (cdrom_print_info("\nCan change speed:",
3500 CDC_SELECT_SPEED, info, &pos, CTL_CAPABILITY))
3501 goto done;
3502 if (cdrom_print_info("\nCan select disk:",
3503 CDC_SELECT_DISC, info, &pos, CTL_CAPABILITY))
3504 goto done;
3505 if (cdrom_print_info("\nCan read multisession:",
3506 CDC_MULTI_SESSION, info, &pos, CTL_CAPABILITY))
3507 goto done;
3508 if (cdrom_print_info("\nCan read MCN:\t",
3509 CDC_MCN, info, &pos, CTL_CAPABILITY))
3510 goto done;
3511 if (cdrom_print_info("\nReports media changed:",
3512 CDC_MEDIA_CHANGED, info, &pos, CTL_CAPABILITY))
3513 goto done;
3514 if (cdrom_print_info("\nCan play audio:\t",
3515 CDC_PLAY_AUDIO, info, &pos, CTL_CAPABILITY))
3516 goto done;
3517 if (cdrom_print_info("\nCan write CD-R:\t",
3518 CDC_CD_R, info, &pos, CTL_CAPABILITY))
3519 goto done;
3520 if (cdrom_print_info("\nCan write CD-RW:",
3521 CDC_CD_RW, info, &pos, CTL_CAPABILITY))
3522 goto done;
3523 if (cdrom_print_info("\nCan read DVD:\t",
3524 CDC_DVD, info, &pos, CTL_CAPABILITY))
3525 goto done;
3526 if (cdrom_print_info("\nCan write DVD-R:",
3527 CDC_DVD_R, info, &pos, CTL_CAPABILITY))
3528 goto done;
3529 if (cdrom_print_info("\nCan write DVD-RAM:",
3530 CDC_DVD_RAM, info, &pos, CTL_CAPABILITY))
3531 goto done;
3532 if (cdrom_print_info("\nCan read MRW:\t",
3533 CDC_MRW, info, &pos, CTL_CAPABILITY))
3534 goto done;
3535 if (cdrom_print_info("\nCan write MRW:\t",
3536 CDC_MRW_W, info, &pos, CTL_CAPABILITY))
3537 goto done;
3538 if (cdrom_print_info("\nCan write RAM:\t",
3539 CDC_RAM, info, &pos, CTL_CAPABILITY))
3540 goto done;
3541 if (!scnprintf(info + pos, max_size - pos, "\n\n"))
3542 goto done;
3543doit:
3544 mutex_unlock(&cdrom_mutex);
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003545 return proc_dostring(ctl, write, buffer, lenp, ppos);
Dave Young554988d2007-06-19 09:14:26 +02003546done:
Joe Perchese597cd02010-07-01 08:24:32 +02003547 pr_info("info buffer too small\n");
Dave Young554988d2007-06-19 09:14:26 +02003548 goto doit;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549}
3550
3551/* Unfortunately, per device settings are not implemented through
3552 procfs/sysctl yet. When they are, this will naturally disappear. For now
3553 just update all drives. Later this will become the template on which
3554 new registered drives will be based. */
3555static void cdrom_update_settings(void)
3556{
3557 struct cdrom_device_info *cdi;
3558
Akinobu Mita032d8d92008-03-26 12:09:01 +01003559 mutex_lock(&cdrom_mutex);
Akinobu Mita7fd097d2008-03-26 12:09:02 +01003560 list_for_each_entry(cdi, &cdrom_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 if (autoclose && CDROM_CAN(CDC_CLOSE_TRAY))
3562 cdi->options |= CDO_AUTO_CLOSE;
3563 else if (!autoclose)
3564 cdi->options &= ~CDO_AUTO_CLOSE;
3565 if (autoeject && CDROM_CAN(CDC_OPEN_TRAY))
3566 cdi->options |= CDO_AUTO_EJECT;
3567 else if (!autoeject)
3568 cdi->options &= ~CDO_AUTO_EJECT;
3569 if (lockdoor && CDROM_CAN(CDC_LOCK))
3570 cdi->options |= CDO_LOCK;
3571 else if (!lockdoor)
3572 cdi->options &= ~CDO_LOCK;
3573 if (check_media_type)
3574 cdi->options |= CDO_CHECK_TYPE;
3575 else
3576 cdi->options &= ~CDO_CHECK_TYPE;
3577 }
Akinobu Mita032d8d92008-03-26 12:09:01 +01003578 mutex_unlock(&cdrom_mutex);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579}
3580
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003581static int cdrom_sysctl_handler(ctl_table *ctl, int write,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003582 void __user *buffer, size_t *lenp, loff_t *ppos)
3583{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 int ret;
3585
Alexey Dobriyan8d65af72009-09-23 15:57:19 -07003586 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Eric W. Biederman06489b42007-10-18 03:05:28 -07003588 if (write) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
3590 /* we only care for 1 or 0. */
Eric W. Biederman06489b42007-10-18 03:05:28 -07003591 autoclose = !!cdrom_sysctl_settings.autoclose;
3592 autoeject = !!cdrom_sysctl_settings.autoeject;
3593 debug = !!cdrom_sysctl_settings.debug;
3594 lockdoor = !!cdrom_sysctl_settings.lock;
3595 check_media_type = !!cdrom_sysctl_settings.check;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 /* update the option flags according to the changes. we
3598 don't have per device options through sysctl yet,
3599 but we will have and then this will disappear. */
3600 cdrom_update_settings();
3601 }
3602
3603 return ret;
3604}
3605
3606/* Place files in /proc/sys/dev/cdrom */
3607static ctl_table cdrom_table[] = {
3608 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 .procname = "info",
3610 .data = &cdrom_sysctl_settings.info,
3611 .maxlen = CDROM_STR_SIZE,
3612 .mode = 0444,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003613 .proc_handler = cdrom_sysctl_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 },
3615 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616 .procname = "autoclose",
3617 .data = &cdrom_sysctl_settings.autoclose,
3618 .maxlen = sizeof(int),
3619 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003620 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 },
3622 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 .procname = "autoeject",
3624 .data = &cdrom_sysctl_settings.autoeject,
3625 .maxlen = sizeof(int),
3626 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003627 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 },
3629 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 .procname = "debug",
3631 .data = &cdrom_sysctl_settings.debug,
3632 .maxlen = sizeof(int),
3633 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003634 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635 },
3636 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637 .procname = "lock",
3638 .data = &cdrom_sysctl_settings.lock,
3639 .maxlen = sizeof(int),
3640 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003641 .proc_handler = cdrom_sysctl_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642 },
3643 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 .procname = "check_media",
3645 .data = &cdrom_sysctl_settings.check,
3646 .maxlen = sizeof(int),
3647 .mode = 0644,
Eric W. Biederman6d456112009-11-16 03:11:48 -08003648 .proc_handler = cdrom_sysctl_handler
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003650 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651};
3652
3653static ctl_table cdrom_cdrom_table[] = {
3654 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655 .procname = "cdrom",
3656 .maxlen = 0,
3657 .mode = 0555,
3658 .child = cdrom_table,
3659 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003660 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661};
3662
3663/* Make sure that /proc/sys/dev is there */
3664static ctl_table cdrom_root_table[] = {
3665 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003666 .procname = "dev",
3667 .maxlen = 0,
3668 .mode = 0555,
3669 .child = cdrom_cdrom_table,
3670 },
Eric W. Biederman894d2492009-11-05 14:34:02 -08003671 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672};
3673static struct ctl_table_header *cdrom_sysctl_header;
3674
3675static void cdrom_sysctl_register(void)
3676{
3677 static int initialized;
3678
3679 if (initialized == 1)
3680 return;
3681
Eric W. Biederman0b4d4142007-02-14 00:34:09 -08003682 cdrom_sysctl_header = register_sysctl_table(cdrom_root_table);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003683
3684 /* set the defaults */
3685 cdrom_sysctl_settings.autoclose = autoclose;
3686 cdrom_sysctl_settings.autoeject = autoeject;
3687 cdrom_sysctl_settings.debug = debug;
3688 cdrom_sysctl_settings.lock = lockdoor;
3689 cdrom_sysctl_settings.check = check_media_type;
3690
3691 initialized = 1;
3692}
3693
3694static void cdrom_sysctl_unregister(void)
3695{
3696 if (cdrom_sysctl_header)
3697 unregister_sysctl_table(cdrom_sysctl_header);
3698}
3699
Akinobu Mita17672cf2008-03-26 12:08:59 +01003700#else /* CONFIG_SYSCTL */
3701
3702static void cdrom_sysctl_register(void)
3703{
3704}
3705
3706static void cdrom_sysctl_unregister(void)
3707{
3708}
3709
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710#endif /* CONFIG_SYSCTL */
3711
3712static int __init cdrom_init(void)
3713{
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 cdrom_sysctl_register();
Akinobu Mita17672cf2008-03-26 12:08:59 +01003715
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716 return 0;
3717}
3718
3719static void __exit cdrom_exit(void)
3720{
Joe Perchese597cd02010-07-01 08:24:32 +02003721 pr_info("Uniform CD-ROM driver unloaded\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722 cdrom_sysctl_unregister();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723}
3724
3725module_init(cdrom_init);
3726module_exit(cdrom_exit);
3727MODULE_LICENSE("GPL");