Import 2.3.11pre5
[davej-history.git] / drivers / cdrom / cdrom.c
blob2e68d007b1da973cc0e575b979ccb579514dd94b
1 /* linux/drivers/cdrom/cdrom.c.
2 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
6 May be copied or modified under the terms of the GNU General Public
7 License. See linux/COPYING for more information.
9 Uniform CD-ROM driver for Linux.
10 See Documentation/cdrom/cdrom-standard.tex for usage information.
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. ;-)
17 To Do List:
18 ----------------------------------
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!
25 -- Change the CDROMREADMODE1, CDROMREADMODE2, CDROMREADAUDIO, and
26 CDROMREADRAW ioctls so they go through the Uniform CD-ROM driver.
28 -- Sync options and capability flags.
32 Revision History
33 ----------------------------------
34 1.00 Date Unknown -- David van Leeuwen <david@tm.tno.nl>
35 -- Initial version by David A. van Leeuwen. I don't have a detailed
36 changelog for the 1.x series, David?
38 2.00 Dec 2, 1997 -- Erik Andersen <andersee@debian.org>
39 -- New maintainer! As David A. van Leeuwen has been too busy to activly
40 maintain and improve this driver, I am now carrying on the torch. If
41 you have a problem with this driver, please feel free to contact me.
43 -- Added (rudimentary) sysctl interface. I realize this is really weak
44 right now, and is _very_ badly implemented. It will be improved...
46 -- Modified CDROM_DISC_STATUS so that it is now incorporated into
47 the Uniform CD-ROM driver via the cdrom_count_tracks function.
48 The cdrom_count_tracks function helps resolve some of the false
49 assumptions of the CDROM_DISC_STATUS ioctl, and is also used to check
50 for the correct media type when mounting or playing audio from a CD.
52 -- Remove the calls to verify_area and only use the copy_from_user and
53 copy_to_user stuff, since these calls now provide their own memory
54 checking with the 2.1.x kernels.
56 -- Major update to return codes so that errors from low-level drivers
57 are passed on through (thanks to Gerd Knorr for pointing out this
58 problem).
60 -- Made it so if a function isn't implemented in a low-level driver,
61 ENOSYS is now returned instead of EINVAL.
63 -- Simplified some complex logic so that the source code is easier to read.
65 -- Other stuff I probably forgot to mention (lots of changes).
67 2.01 to 2.11 Dec 1997-Jan 1998
68 -- TO-DO! Write changelogs for 2.01 to 2.12.
70 2.12 Jan 24, 1998 -- Erik Andersen <andersee@debian.org>
71 -- Fixed a bug in the IOCTL_IN and IOCTL_OUT macros. It turns out that
72 copy_*_user does not return EFAULT on error, but instead returns the number
73 of bytes not copied. I was returning whatever non-zero stuff came back from
74 the copy_*_user functions directly, which would result in strange errors.
76 2.13 July 17, 1998 -- Erik Andersen <andersee@debian.org>
77 -- Fixed a bug in CDROM_SELECT_SPEED where you couldn't lower the speed
78 of the drive. Thanks to Tobias Ringstr|m <tori@prosolvia.se> for pointing
79 this out and providing a simple fix.
80 -- Fixed the procfs-unload-module bug with the fill_inode procfs callback.
81 thanks to Andrea Arcangeli
82 -- Fixed it so that the /proc entry now also shows up when cdrom is
83 compiled into the kernel. Before it only worked when loaded as a module.
85 2.14 August 17, 1998 -- Erik Andersen <andersee@debian.org>
86 -- Fixed a bug in cdrom_media_changed and handling of reporting that
87 the media had changed for devices that _don't_ implement media_changed.
88 Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug.
89 -- Made a few things more pedanticly correct.
91 2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk>
92 -- New maintainers! Erik was too busy to continue the work on the driver,
93 so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk>
94 will do their best to follow in his footsteps
96 2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk>
97 -- Check if drive is capable of doing what we ask before blindly changing
98 cdi->options in various ioctl.
99 -- Added version to proc entry.
101 2.52 Jan 16, 1999 - Jens Axboe <axboe@image.dk>
102 -- Fixed an error in open_for_data where we would sometimes not return
103 the correct error value. Thanks Huba Gaspar <huba@softcell.hu>.
104 -- Fixed module usage count - usage was based on /proc/sys/dev
105 instead of /proc/sys/dev/cdrom. This could lead to an oops when other
106 modules had entries in dev. Feb 02 - real bug was in sysctl.c where
107 dev would be removed even though it was used. cdrom.c just illuminated
108 that bug.
110 2.53 Feb 22, 1999 - Jens Axboe <axboe@image.dk>
111 -- Fixup of several ioctl calls, in particular CDROM_SET_OPTIONS has
112 been "rewritten" because capabilities and options aren't in sync. They
113 should be...
114 -- Added CDROM_LOCKDOOR ioctl. Locks the door and keeps it that way.
115 -- Added CDROM_RESET ioctl.
116 -- Added CDROM_DEBUG ioctl. Enable debug messages on-the-fly.
117 -- Added CDROM_GET_CAPABILITY ioctl. This relieves userspace programs
118 from parsing /proc/sys/dev/cdrom/info.
120 2.54 Mar 15, 1999 - Jens Axboe <axboe@image.dk>
121 -- Check capability mask from low level driver when counting tracks as
122 per suggestion from Corey J. Scotts <cstotts@blue.weeg.uiowa.edu>.
124 2.55 Apr 25, 1999 - Jens Axboe <axboe@image.dk>
125 -- autoclose was mistakenly checked against CDC_OPEN_TRAY instead of
126 CDC_CLOSE_TRAY.
127 -- proc info didn't mask against capabilities mask.
129 -------------------------------------------------------------------------*/
131 #define REVISION "Revision: 2.55"
132 #define VERSION "Id: cdrom.c 2.55 1999/04/25"
134 /* I use an error-log mask to give fine grain control over the type of
135 messages dumped to the system logs. The available masks include: */
136 #define CD_NOTHING 0x0
137 #define CD_WARNING 0x1
138 #define CD_REG_UNREG 0x2
139 #define CD_DO_IOCTL 0x4
140 #define CD_OPEN 0x8
141 #define CD_CLOSE 0x10
142 #define CD_COUNT_TRACKS 0x20
144 /* Define this to remove _all_ the debugging messages */
145 /* #define ERRLOGMASK CD_NOTHING */
146 #define ERRLOGMASK (CD_WARNING)
147 /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
148 /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
151 #include <linux/config.h>
152 #include <linux/module.h>
153 #include <linux/fs.h>
154 #include <linux/major.h>
155 #include <linux/types.h>
156 #include <linux/errno.h>
157 #include <linux/kernel.h>
158 #include <linux/mm.h>
159 #include <linux/malloc.h>
160 #include <linux/cdrom.h>
161 #include <linux/sysctl.h>
162 #include <linux/proc_fs.h>
163 #include <asm/fcntl.h>
164 #include <asm/segment.h>
165 #include <asm/uaccess.h>
167 /* used to tell the module to turn on full debugging messages */
168 static int debug = 0;
169 /* used to keep tray locked at all times */
170 static int keeplocked = 0;
171 /* default compatibility mode */
172 static int autoclose=1;
173 static int autoeject=0;
174 static int lockdoor = 1;
175 static int check_media_type = 0;
176 MODULE_PARM(debug, "i");
177 MODULE_PARM(autoclose, "i");
178 MODULE_PARM(autoeject, "i");
179 MODULE_PARM(lockdoor, "i");
180 MODULE_PARM(check_media_type, "i");
182 #if (ERRLOGMASK!=CD_NOTHING)
183 #define cdinfo(type, fmt, args...) \
184 if ((ERRLOGMASK & type) || debug==1 ) \
185 printk(KERN_INFO "cdrom: " fmt, ## args)
186 #else
187 #define cdinfo(type, fmt, args...)
188 #endif
190 /* These are used to simplify getting data in from and back to user land */
191 #define IOCTL_IN(arg, type, in) \
192 copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT)
194 #define IOCTL_OUT(arg, type, out) \
195 copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT)
198 #define FM_WRITE 0x2 /* file mode write bit */
200 /* Not-exported routines. */
201 static int cdrom_open(struct inode *ip, struct file *fp);
202 static int cdrom_release(struct inode *ip, struct file *fp);
203 static int cdrom_ioctl(struct inode *ip, struct file *fp,
204 unsigned int cmd, unsigned long arg);
205 static int cdrom_media_changed(kdev_t dev);
206 static int open_for_data(struct cdrom_device_info * cdi);
207 static int check_for_audio_disc(struct cdrom_device_info * cdi,
208 struct cdrom_device_ops * cdo);
209 static void sanitize_format(union cdrom_addr *addr,
210 u_char * curr, u_char requested);
211 #ifdef CONFIG_SYSCTL
212 static void cdrom_sysctl_register(void);
213 #endif /* CONFIG_SYSCTL */
214 static struct cdrom_device_info *topCdromPtr = NULL;
216 struct file_operations cdrom_fops =
218 NULL, /* lseek */
219 block_read, /* read - general block-dev read */
220 block_write, /* write - general block-dev write */
221 NULL, /* readdir */
222 NULL, /* poll */
223 cdrom_ioctl, /* ioctl */
224 NULL, /* mmap */
225 cdrom_open, /* open */
226 NULL, /* flush */
227 cdrom_release, /* release */
228 NULL, /* fsync */
229 NULL, /* fasync */
230 cdrom_media_changed, /* media_change */
231 NULL /* revalidate */
234 /* This macro makes sure we don't have to check on cdrom_device_ops
235 * existence in the run-time routines below. Change_capability is a
236 * hack to have the capability flags defined const, while we can still
237 * change it here without gcc complaining at every line.
239 #define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
241 int register_cdrom(struct cdrom_device_info *cdi)
243 static char banner_printed = 0;
244 int major = MAJOR (cdi->dev);
245 struct cdrom_device_ops *cdo = cdi->ops;
246 int *change_capability = (int *)&cdo->capability; /* hack */
248 cdinfo(CD_OPEN, "entering register_cdrom\n");
250 if (major < 0 || major >= MAX_BLKDEV)
251 return -1;
252 if (cdo->open == NULL || cdo->release == NULL)
253 return -2;
254 if ( !banner_printed ) {
255 printk(KERN_INFO "Uniform CDROM driver " REVISION "\n");
256 banner_printed = 1;
257 #ifdef CONFIG_SYSCTL
258 cdrom_sysctl_register();
259 #endif /* CONFIG_SYSCTL */
261 ENSURE(drive_status, CDC_DRIVE_STATUS );
262 ENSURE(media_changed, CDC_MEDIA_CHANGED);
263 ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
264 ENSURE(lock_door, CDC_LOCK);
265 ENSURE(select_speed, CDC_SELECT_SPEED);
266 ENSURE(select_disc, CDC_SELECT_DISC);
267 ENSURE(get_last_session, CDC_MULTI_SESSION);
268 ENSURE(get_mcn, CDC_MCN);
269 ENSURE(reset, CDC_RESET);
270 ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
271 ENSURE(dev_ioctl, CDC_IOCTLS);
272 cdi->mc_flags = 0;
273 cdo->n_minors = 0;
274 cdi->options = CDO_USE_FFLAGS;
276 if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY)
277 cdi->options |= (int) CDO_AUTO_CLOSE;
278 if (autoeject==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
279 cdi->options |= (int) CDO_AUTO_EJECT;
280 if (lockdoor==1)
281 cdi->options |= (int) CDO_LOCK;
282 if (check_media_type==1)
283 cdi->options |= (int) CDO_CHECK_TYPE;
285 cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
286 cdi->next = topCdromPtr;
287 topCdromPtr = cdi;
288 return 0;
290 #undef ENSURE
292 int unregister_cdrom(struct cdrom_device_info *unreg)
294 struct cdrom_device_info *cdi, *prev;
295 int major = MAJOR (unreg->dev);
297 cdinfo(CD_OPEN, "entering unregister_cdrom\n");
299 if (major < 0 || major >= MAX_BLKDEV)
300 return -1;
302 prev = NULL;
303 cdi = topCdromPtr;
304 while (cdi != NULL && cdi->dev != unreg->dev) {
305 prev = cdi;
306 cdi = cdi->next;
309 if (cdi == NULL)
310 return -2;
311 if (prev)
312 prev->next = cdi->next;
313 else
314 topCdromPtr = cdi->next;
315 cdi->ops->n_minors--;
316 cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
317 return 0;
320 static
321 struct cdrom_device_info *cdrom_find_device (kdev_t dev)
323 struct cdrom_device_info *cdi;
325 cdi = topCdromPtr;
326 while (cdi != NULL && cdi->dev != dev)
327 cdi = cdi->next;
328 return cdi;
331 /* We use the open-option O_NONBLOCK to indicate that the
332 * purpose of opening is only for subsequent ioctl() calls; no device
333 * integrity checks are performed.
335 * We hope that all cd-player programs will adopt this convention. It
336 * is in their own interest: device control becomes a lot easier
337 * this way.
339 static
340 int cdrom_open(struct inode *ip, struct file *fp)
342 kdev_t dev = ip->i_rdev;
343 struct cdrom_device_info *cdi = cdrom_find_device(dev);
344 int purpose = !!(fp->f_flags & O_NONBLOCK);
345 int ret=0;
347 cdinfo(CD_OPEN, "entering cdrom_open\n");
348 if (cdi == NULL)
349 return -ENODEV;
350 if (fp->f_mode & FM_WRITE)
351 return -EROFS;
352 purpose = purpose || !(cdi->options & CDO_USE_FFLAGS);
353 if (purpose)
354 ret = cdi->ops->open(cdi, purpose);
355 else
356 ret = open_for_data(cdi);
357 if (!ret) cdi->use_count++;
358 cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n", cdi->name, cdi->use_count);
359 /* Do this on open. Don't wait for mount, because they might
360 not be mounting, but opening with O_NONBLOCK */
361 check_disk_change(dev);
362 return ret;
365 static
366 int open_for_data(struct cdrom_device_info * cdi)
368 int ret;
369 struct cdrom_device_ops *cdo = cdi->ops;
370 tracktype tracks;
371 cdinfo(CD_OPEN, "entering open_for_data\n");
372 /* Check if the driver can report drive status. If it can, we
373 can do clever things. If it can't, well, we at least tried! */
374 if (cdo->drive_status != NULL) {
375 ret = cdo->drive_status(cdi, CDSL_CURRENT);
376 cdinfo(CD_OPEN, "drive_status=%d\n", ret);
377 if (ret == CDS_TRAY_OPEN) {
378 cdinfo(CD_OPEN, "the tray is open...\n");
379 /* can/may i close it? */
380 if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&
381 cdi->options & CDO_AUTO_CLOSE) {
382 cdinfo(CD_OPEN, "trying to close the tray.\n");
383 ret=cdo->tray_move(cdi,0);
384 if (ret) {
385 cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n");
386 /* Ignore the error from the low
387 level driver. We don't care why it
388 couldn't close the tray. We only care
389 that there is no disc in the drive,
390 since that is the _REAL_ problem here.*/
391 ret=-ENOMEDIUM;
392 goto clean_up_and_return;
394 } else {
395 cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n");
396 ret=-ENOMEDIUM;
397 goto clean_up_and_return;
399 /* Ok, the door should be closed now.. Check again */
400 ret = cdo->drive_status(cdi, CDSL_CURRENT);
401 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
402 cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
403 cdinfo(CD_OPEN, "tray might not contain a medium.\n");
404 ret=-ENOMEDIUM;
405 goto clean_up_and_return;
407 cdinfo(CD_OPEN, "the tray is now closed.\n");
409 if (ret!=CDS_DISC_OK) {
410 ret = -ENOMEDIUM;
411 goto clean_up_and_return;
414 cdrom_count_tracks(cdi, &tracks);
415 if (tracks.error == CDS_NO_DISC) {
416 cdinfo(CD_OPEN, "bummer. no disc.\n");
417 ret=-ENOMEDIUM;
418 goto clean_up_and_return;
420 /* CD-Players which don't use O_NONBLOCK, workman
421 * for example, need bit CDO_CHECK_TYPE cleared! */
422 if (tracks.data==0) {
423 if (cdi->options & CDO_CHECK_TYPE) {
424 cdinfo(CD_OPEN, "bummer. wrong media type.\n");
425 ret=-EMEDIUMTYPE;
426 goto clean_up_and_return;
428 else {
429 cdinfo(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set.\n");
433 cdinfo(CD_OPEN, "all seems well, opening the device.\n");
435 /* all seems well, we can open the device */
436 ret = cdo->open(cdi, 0); /* open for data */
437 cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret);
438 /* After all this careful checking, we shouldn't have problems
439 opening the device, but we don't want the device locked if
440 this somehow fails... */
441 if (ret) {
442 cdinfo(CD_OPEN, "open device failed.\n");
443 goto clean_up_and_return;
445 if (cdo->capability & ~cdi->mask & CDC_LOCK &&
446 cdi->options & CDO_LOCK) {
447 cdo->lock_door(cdi, 1);
448 cdinfo(CD_OPEN, "door locked.\n");
450 cdinfo(CD_OPEN, "device opened successfully.\n");
451 return ret;
453 /* Something failed. Try to unlock the drive, because some drivers
454 (notably ide-cd) lock the drive after every command. This produced
455 a nasty bug where after mount failed, the drive would remain locked!
456 This ensures that the drive gets unlocked after a mount fails. This
457 is a goto to avoid bloating the driver with redundant code. */
458 clean_up_and_return:
459 cdinfo(CD_WARNING, "open failed.\n");
460 if (cdo->capability & ~cdi->mask & CDC_LOCK &&
461 cdi->options & CDO_LOCK) {
462 cdo->lock_door(cdi, 0);
463 cdinfo(CD_OPEN, "door unlocked.\n");
465 return ret;
468 /* This code is similar to that in open_for_data. The routine is called
469 whenever an audio play operation is requested.
471 int check_for_audio_disc(struct cdrom_device_info * cdi,
472 struct cdrom_device_ops * cdo)
474 int ret;
475 tracktype tracks;
476 cdinfo(CD_OPEN, "entering check_for_audio_disc\n");
477 if (!(cdi->options & CDO_CHECK_TYPE))
478 return 0;
479 if (cdo->drive_status != NULL) {
480 ret = cdo->drive_status(cdi, CDSL_CURRENT);
481 cdinfo(CD_OPEN, "drive_status=%d\n", ret);
482 if (ret == CDS_TRAY_OPEN) {
483 cdinfo(CD_OPEN, "the tray is open...\n");
484 /* can/may i close it? */
485 if (cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY &&
486 cdi->options & CDO_AUTO_CLOSE) {
487 cdinfo(CD_OPEN, "trying to close the tray.\n");
488 ret=cdo->tray_move(cdi,0);
489 if (ret) {
490 cdinfo(CD_OPEN, "bummer. tried to close tray but failed.\n");
491 /* Ignore the error from the low
492 level driver. We don't care why it
493 couldn't close the tray. We only care
494 that there is no disc in the drive,
495 since that is the _REAL_ problem here.*/
496 return -ENOMEDIUM;
498 } else {
499 cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n");
500 return -ENOMEDIUM;
502 /* Ok, the door should be closed now.. Check again */
503 ret = cdo->drive_status(cdi, CDSL_CURRENT);
504 if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
505 cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
506 return -ENOMEDIUM;
508 if (ret!=CDS_DISC_OK) {
509 cdinfo(CD_OPEN, "bummer. disc isn't ready.\n");
510 return -EIO;
512 cdinfo(CD_OPEN, "the tray is now closed.\n");
515 cdrom_count_tracks(cdi, &tracks);
516 if (tracks.error)
517 return(tracks.error);
519 if (tracks.audio==0)
520 return -EMEDIUMTYPE;
522 return 0;
526 /* Admittedly, the logic below could be performed in a nicer way. */
527 static
528 int cdrom_release(struct inode *ip, struct file *fp)
530 kdev_t dev = ip->i_rdev;
531 struct cdrom_device_info *cdi = cdrom_find_device (dev);
532 struct cdrom_device_ops *cdo = cdi->ops;
533 int opened_for_data;
535 cdinfo(CD_CLOSE, "entering cdrom_release\n");
536 if (cdi == NULL)
537 return 0;
538 if (cdi->use_count > 0) cdi->use_count--;
539 if (cdi->use_count == 0)
540 cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
541 if (cdi->use_count == 0 && /* last process that closes dev*/
542 cdo->capability & CDC_LOCK && !keeplocked) {
543 cdinfo(CD_CLOSE, "Unlocking door!\n");
544 cdo->lock_door(cdi, 0);
546 opened_for_data = !(cdi->options & CDO_USE_FFLAGS) ||
547 !(fp && fp->f_flags & O_NONBLOCK);
548 cdo->release(cdi);
549 if (cdi->use_count == 0) { /* last process that closes dev*/
550 struct super_block *sb;
551 sync_dev(dev);
552 sb = get_super(dev);
553 if (sb) invalidate_inodes(sb);
554 invalidate_buffers(dev);
555 if (opened_for_data &&
556 cdi->options & CDO_AUTO_EJECT &&
557 cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
558 cdo->tray_move(cdi, 1);
560 return 0;
563 /* We want to make media_changed accessible to the user through an
564 * ioctl. The main problem now is that we must double-buffer the
565 * low-level implementation, to assure that the VFS and the user both
566 * see a medium change once.
569 static
570 int media_changed(struct cdrom_device_info *cdi, int queue)
572 unsigned int mask = (1 << (queue & 1));
573 int ret = !!(cdi->mc_flags & mask);
575 if (!(cdi->ops->capability & ~cdi->mask & CDC_MEDIA_CHANGED))
576 return ret;
577 /* changed since last call? */
578 if (cdi->ops->media_changed(cdi, CDSL_CURRENT)) {
579 cdi->mc_flags = 0x3; /* set bit on both queues */
580 ret |= 1;
582 cdi->mc_flags &= ~mask; /* clear bit */
583 return ret;
586 static
587 int cdrom_media_changed(kdev_t dev)
589 struct cdrom_device_info *cdi = cdrom_find_device (dev);
590 /* This talks to the VFS, which doesn't like errors - just 1 or 0.
591 * Returning "0" is always safe (media hasn't been changed). Do that
592 * if the low-level cdrom driver dosn't support media changed. */
593 if (cdi == NULL)
594 return 0;
595 if (cdi->ops->media_changed == NULL)
596 return 0;
597 if (!(cdi->ops->capability & ~cdi->mask & CDC_MEDIA_CHANGED))
598 return 0;
599 return (media_changed(cdi, 0));
602 void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
604 struct cdrom_tochdr header;
605 struct cdrom_tocentry entry;
606 int ret, i;
607 tracks->data=0;
608 tracks->audio=0;
609 tracks->cdi=0;
610 tracks->xa=0;
611 tracks->error=0;
612 cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
613 if (!(cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)) {
614 tracks->error=CDS_NO_INFO;
615 return;
617 /* Grab the TOC header so we can see how many tracks there are */
618 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
619 if (ret) {
620 if (ret == -ENOMEDIUM)
621 tracks->error = CDS_NO_DISC;
622 else
623 tracks->error = CDS_NO_INFO;
624 return;
626 /* check what type of tracks are on this disc */
627 entry.cdte_format = CDROM_MSF;
628 for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
629 entry.cdte_track = i;
630 if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
631 tracks->error=CDS_NO_INFO;
632 return;
634 if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
635 if (entry.cdte_format == 0x10)
636 tracks->cdi++;
637 else if (entry.cdte_format == 0x20)
638 tracks->xa++;
639 else
640 tracks->data++;
641 } else
642 tracks->audio++;
643 cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
644 i, entry.cdte_format, entry.cdte_ctrl);
646 cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
647 header.cdth_trk1, tracks->audio, tracks->data,
648 tracks->cdi, tracks->xa);
651 /* Requests to the low-level drivers will /always/ be done in the
652 following format convention:
654 CDROM_LBA: all data-related requests.
655 CDROM_MSF: all audio-related requests.
657 However, a low-level implementation is allowed to refuse this
658 request, and return information in its own favorite format.
660 It doesn't make sense /at all/ to ask for a play_audio in LBA
661 format, or ask for multi-session info in MSF format. However, for
662 backward compatibility these format requests will be satisfied, but
663 the requests to the low-level drivers will be sanitized in the more
664 meaningful format indicated above.
667 static
668 void sanitize_format(union cdrom_addr *addr,
669 u_char * curr, u_char requested)
671 if (*curr == requested)
672 return; /* nothing to be done! */
673 if (requested == CDROM_LBA) {
674 addr->lba = (int) addr->msf.frame +
675 75 * (addr->msf.second - 2 + 60 * addr->msf.minute);
676 } else { /* CDROM_MSF */
677 int lba = addr->lba;
678 addr->msf.frame = lba % 75;
679 lba /= 75;
680 lba += 2;
681 addr->msf.second = lba % 60;
682 addr->msf.minute = lba / 60;
684 *curr = requested;
687 /* Some of the cdrom ioctls are not implemented here, because these
688 * appear to be either too device-specific, or it is not clear to me
689 * what use they are. These are (number of drivers that support them
690 * in parenthesis): CDROMREADMODE1 (2+ide), CDROMREADMODE2 (2+ide),
691 * CDROMREADAUDIO (2+ide), CDROMREADRAW (2), CDROMREADCOOKED (2),
692 * CDROMSEEK (2), CDROMPLAYBLK (scsi), CDROMREADALL (1). Read-audio,
693 * OK (although i guess the record companies aren't too happy with
694 * this, most drives therefore refuse to transport audio data). But
695 * why are there 5 different READs defined? For now, these functions
696 * are left over to the device-specific ioctl routine,
697 * cdo->dev_ioctl. Note that as a result of this, no
698 * memory-verification is performed for these ioctls.
700 static
701 int cdrom_ioctl(struct inode *ip, struct file *fp,
702 unsigned int cmd, unsigned long arg)
704 kdev_t dev = ip->i_rdev;
705 struct cdrom_device_info *cdi = cdrom_find_device (dev);
706 struct cdrom_device_ops *cdo;
708 if (cdi == NULL)
709 return -ENODEV;
710 cdo = cdi->ops;
712 /* the first few commands do not deal with audio drive_info, but
713 only with routines in cdrom device operations. */
714 switch (cmd) {
715 /* maybe we should order cases after statistics of use? */
717 case CDROMMULTISESSION: {
718 int ret;
719 struct cdrom_multisession ms_info;
720 u_char requested_format;
721 cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
722 if (!(cdo->capability & CDC_MULTI_SESSION))
723 return -ENOSYS;
724 IOCTL_IN(arg, struct cdrom_multisession, ms_info);
725 requested_format = ms_info.addr_format;
726 if (!((requested_format == CDROM_MSF) ||
727 (requested_format == CDROM_LBA)))
728 return -EINVAL;
729 ms_info.addr_format = CDROM_LBA;
730 if ((ret=cdo->get_last_session(cdi, &ms_info)))
731 return ret;
732 sanitize_format(&ms_info.addr, &ms_info.addr_format,
733 requested_format);
734 IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
735 cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
736 return 0;
739 case CDROMEJECT: {
740 int ret;
741 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
742 if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
743 return -ENOSYS;
744 if (cdi->use_count != 1 || keeplocked)
745 return -EBUSY;
746 if (cdo->capability & ~cdi->mask & CDC_LOCK)
747 if ((ret=cdo->lock_door(cdi, 0)))
748 return ret;
750 return cdo->tray_move(cdi, 1);
753 case CDROMCLOSETRAY:
754 cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
755 if (!(cdo->capability & ~cdi->mask & CDC_CLOSE_TRAY))
756 return -ENOSYS;
757 return cdo->tray_move(cdi, 0);
759 case CDROMEJECT_SW:
760 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
761 if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
762 return -ENOSYS;
763 if (keeplocked)
764 return -EBUSY;
765 cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
766 if (arg)
767 cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
768 return 0;
770 case CDROM_MEDIA_CHANGED: {
771 cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
772 if (!(cdo->capability & ~cdi->mask & CDC_MEDIA_CHANGED))
773 return -ENOSYS;
774 if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC)
775 || arg == CDSL_CURRENT)
776 /* cannot select disc or select current disc */
777 return media_changed(cdi, 1);
778 if ((unsigned int)arg >= cdi->capacity)
779 return -EINVAL;
780 return cdo->media_changed (cdi, arg);
783 case CDROM_SET_OPTIONS:
784 cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
785 /* options need to be in sync with capability. too late for
786 that, so we have to check each one separately... */
787 switch (arg) {
788 case CDO_USE_FFLAGS:
789 case CDO_CHECK_TYPE:
790 break;
791 case CDO_LOCK:
792 if (!(cdo->capability & ~cdi->mask & CDC_LOCK))
793 return -ENOSYS;
794 break;
795 case 0:
796 return cdi->options;
797 /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
798 default:
799 if (!(cdo->capability & ~cdi->mask & arg))
800 return -ENOSYS;
802 cdi->options |= (int) arg;
803 return cdi->options;
805 case CDROM_CLEAR_OPTIONS:
806 cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n");
807 cdi->options &= ~(int) arg;
808 return cdi->options;
810 case CDROM_SELECT_SPEED: {
811 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n");
812 if (!(cdo->capability & ~cdi->mask & CDC_SELECT_SPEED))
813 return -ENOSYS;
814 return cdo->select_speed(cdi, arg);
817 case CDROM_SELECT_DISC: {
818 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
819 if (!(cdo->capability & ~cdi->mask & CDC_SELECT_DISC))
820 return -ENOSYS;
821 if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
822 return cdo->select_disc(cdi, arg);
823 if ((int)arg >= cdi->capacity)
824 return -EDRIVE_CANT_DO_THIS;
825 return cdo->select_disc(cdi, arg);
828 case CDROMRESET: {
829 cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
830 if (!(cdo->capability & ~cdi->mask & CDC_RESET))
831 return -ENOSYS;
832 return cdo->reset(cdi);
835 case CDROM_LOCKDOOR: {
836 cdinfo(CD_DO_IOCTL, "%socking door.\n",arg?"L":"Unl");
837 if (!(cdo->capability & ~cdi->mask & CDC_LOCK)) {
838 return -EDRIVE_CANT_DO_THIS;
839 } else {
840 keeplocked = arg ? 1 : 0;
841 return cdo->lock_door(cdi, arg);
845 case CDROM_DEBUG: {
846 if (!capable(CAP_SYS_ADMIN))
847 return -EACCES;
848 cdinfo(CD_DO_IOCTL, "%sabling debug.\n",arg?"En":"Dis");
849 debug = arg ? 1 : 0;
850 return debug;
853 case CDROM_GET_CAPABILITY: {
854 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
855 return cdo->capability;
858 /* The following function is implemented, although very few audio
859 * discs give Universal Product Code information, which should just be
860 * the Medium Catalog Number on the box. Note, that the way the code
861 * is written on the CD is /not/ uniform across all discs!
863 case CDROM_GET_MCN: {
864 int ret;
865 struct cdrom_mcn mcn;
866 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n");
867 if (!(cdo->capability & CDC_MCN))
868 return -ENOSYS;
869 if ((ret=cdo->get_mcn(cdi, &mcn)))
870 return ret;
871 IOCTL_OUT(arg, struct cdrom_mcn, mcn);
872 cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
873 return 0;
876 case CDROM_DRIVE_STATUS: {
877 cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
878 if (!(cdo->capability & CDC_DRIVE_STATUS))
879 return -ENOSYS;
880 if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
881 return cdo->drive_status(cdi, arg);
882 if (((int)arg > cdi->capacity))
883 return -EINVAL;
884 return cdo->drive_status(cdi, arg);
887 /* Ok, this is where problems start. The current interface for the
888 CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption
889 that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly,
890 while this is often the case, it is also very common for CDs to
891 have some tracks with data, and some tracks with audio. Just
892 because I feel like it, I declare the following to be the best
893 way to cope. If the CD has ANY data tracks on it, it will be
894 returned as a data CD. If it has any XA tracks, I will return
895 it as that. Now I could simplify this interface by combining these
896 returns with the above, but this more clearly demonstrates
897 the problem with the current interface. Too bad this wasn't
898 designed to use bitmasks... -Erik
900 Well, now we have the option CDS_MIXED: a mixed-type CD.
901 User level programmers might feel the ioctl is not very useful.
902 ---david
904 case CDROM_DISC_STATUS: {
905 tracktype tracks;
906 cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
907 cdrom_count_tracks(cdi, &tracks);
908 if (tracks.error)
909 return(tracks.error);
911 /* Policy mode on */
912 if (tracks.audio > 0) {
913 if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
914 return CDS_AUDIO;
915 else return CDS_MIXED;
917 if (tracks.cdi > 0) return CDS_XA_2_2;
918 if (tracks.xa > 0) return CDS_XA_2_1;
919 if (tracks.data > 0) return CDS_DATA_1;
920 /* Policy mode off */
922 cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n");
923 return CDS_NO_INFO;
926 case CDROM_CHANGER_NSLOTS:
927 cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n");
928 return cdi->capacity;
930 /* The following is not implemented, because there are too many
931 * different data types. We could support /1/ raw mode, that is large
932 * enough to hold everything.
935 #if 0
936 case CDROMREADMODE1: {
937 int ret;
938 struct cdrom_msf msf;
939 char buf[CD_FRAMESIZE];
940 cdinfo(CD_DO_IOCTL, "entering CDROMREADMODE1\n");
941 IOCTL_IN(arg, struct cdrom_msf, msf);
942 if (ret=cdo->read_audio(dev, cmd, &msf, &buf, cdi))
943 return ret;
944 IOCTL_OUT(arg, __typeof__(buf), buf);
945 return 0;
947 #endif
948 } /* switch */
950 /* Now all the audio-ioctls follow, they are all routed through the
951 same call audio_ioctl(). */
953 #define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
955 if (!(cdo->capability & CDC_PLAY_AUDIO))
956 return -ENOSYS;
957 else {
958 switch (cmd) {
959 case CDROMSUBCHNL: {
960 int ret;
961 struct cdrom_subchnl q;
962 u_char requested, back;
963 /* comment out the cdinfo calls here because they
964 fill up the sys logs when CD players poll the drive*/
965 /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
966 IOCTL_IN(arg, struct cdrom_subchnl, q);
967 requested = q.cdsc_format;
968 if (!((requested == CDROM_MSF) ||
969 (requested == CDROM_LBA)))
970 return -EINVAL;
971 q.cdsc_format = CDROM_MSF;
972 if ((ret=cdo->audio_ioctl(cdi, cmd, &q)))
973 return ret;
974 back = q.cdsc_format; /* local copy */
975 sanitize_format(&q.cdsc_absaddr, &back, requested);
976 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
977 IOCTL_OUT(arg, struct cdrom_subchnl, q);
978 /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
979 return 0;
981 case CDROMREADTOCHDR: {
982 int ret;
983 struct cdrom_tochdr header;
984 /* comment out the cdinfo calls here because they
985 fill up the sys logs when CD players poll the drive*/
986 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
987 IOCTL_IN(arg, struct cdrom_tochdr, header);
988 if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
989 return ret;
990 IOCTL_OUT(arg, struct cdrom_tochdr, header);
991 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
992 return 0;
994 case CDROMREADTOCENTRY: {
995 int ret;
996 struct cdrom_tocentry entry;
997 u_char requested_format;
998 /* comment out the cdinfo calls here because they
999 fill up the sys logs when CD players poll the drive*/
1000 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
1001 IOCTL_IN(arg, struct cdrom_tocentry, entry);
1002 requested_format = entry.cdte_format;
1003 if (!((requested_format == CDROM_MSF) ||
1004 (requested_format == CDROM_LBA)))
1005 return -EINVAL;
1006 /* make interface to low-level uniform */
1007 entry.cdte_format = CDROM_MSF;
1008 if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
1009 return ret;
1010 sanitize_format(&entry.cdte_addr,
1011 &entry.cdte_format, requested_format);
1012 IOCTL_OUT(arg, struct cdrom_tocentry, entry);
1013 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
1014 return 0;
1016 case CDROMPLAYMSF: {
1017 int ret;
1018 struct cdrom_msf msf;
1019 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
1020 IOCTL_IN(arg, struct cdrom_msf, msf);
1021 CHECKAUDIO;
1022 return cdo->audio_ioctl(cdi, cmd, &msf);
1024 case CDROMPLAYTRKIND: {
1025 int ret;
1026 struct cdrom_ti ti;
1027 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
1028 IOCTL_IN(arg, struct cdrom_ti, ti);
1029 CHECKAUDIO;
1030 return cdo->audio_ioctl(cdi, cmd, &ti);
1032 case CDROMVOLCTRL: {
1033 struct cdrom_volctrl volume;
1034 cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
1035 IOCTL_IN(arg, struct cdrom_volctrl, volume);
1036 return cdo->audio_ioctl(cdi, cmd, &volume);
1038 case CDROMVOLREAD: {
1039 int ret;
1040 struct cdrom_volctrl volume;
1041 cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
1042 if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
1043 return ret;
1044 IOCTL_OUT(arg, struct cdrom_volctrl, volume);
1045 return 0;
1047 case CDROMSTART:
1048 case CDROMSTOP:
1049 case CDROMPAUSE:
1050 case CDROMRESUME: {
1051 int ret;
1052 cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
1053 CHECKAUDIO;
1054 return cdo->audio_ioctl(cdi, cmd, NULL);
1056 } /* switch */
1059 /* device specific ioctls? */
1060 if (!(cdo->capability & CDC_IOCTLS))
1061 return -ENOSYS;
1062 else
1063 return cdo->dev_ioctl(cdi, cmd, arg);
1066 EXPORT_SYMBOL(cdrom_count_tracks);
1067 EXPORT_SYMBOL(register_cdrom);
1068 EXPORT_SYMBOL(unregister_cdrom);
1069 EXPORT_SYMBOL(cdrom_fops);
1071 #ifdef CONFIG_SYSCTL
1073 #define CDROM_STR_SIZE 1000
1075 static char cdrom_drive_info[CDROM_STR_SIZE]="info\n";
1077 int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
1078 void *buffer, size_t *lenp)
1080 int pos;
1081 struct cdrom_device_info *cdi;
1083 if (!*lenp || (filp->f_pos && !write)) {
1084 *lenp = 0;
1085 return 0;
1088 pos = sprintf(cdrom_drive_info, "CD-ROM information, " VERSION "\n");
1090 pos += sprintf(cdrom_drive_info+pos, "\ndrive name:\t");
1091 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1092 pos += sprintf(cdrom_drive_info+pos, "\t%s", cdi->name);
1094 pos += sprintf(cdrom_drive_info+pos, "\ndrive speed:\t");
1095 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1096 pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->speed);
1098 pos += sprintf(cdrom_drive_info+pos, "\ndrive # of slots:");
1099 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1100 pos += sprintf(cdrom_drive_info+pos, "\t%d", cdi->capacity);
1102 pos += sprintf(cdrom_drive_info+pos, "\nCan close tray:\t");
1103 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1104 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1105 ((cdi->ops->capability & ~cdi->mask & CDC_CLOSE_TRAY)!=0));
1107 pos += sprintf(cdrom_drive_info+pos, "\nCan open tray:\t");
1108 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1109 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1110 ((cdi->ops->capability & ~cdi->mask & CDC_OPEN_TRAY)!=0));
1112 pos += sprintf(cdrom_drive_info+pos, "\nCan lock tray:\t");
1113 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1114 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1115 ((cdi->ops->capability & ~cdi->mask & CDC_LOCK)!=0));
1117 pos += sprintf(cdrom_drive_info+pos, "\nCan change speed:");
1118 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1119 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1120 ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_SPEED)!=0));
1122 pos += sprintf(cdrom_drive_info+pos, "\nCan select disk:");
1123 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1124 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1125 ((cdi->ops->capability & ~cdi->mask & CDC_SELECT_DISC)!=0));
1127 pos += sprintf(cdrom_drive_info+pos, "\nCan read multisession:");
1128 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1129 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1130 ((cdi->ops->capability & CDC_MULTI_SESSION)!=0));
1132 pos += sprintf(cdrom_drive_info+pos, "\nCan read MCN:\t");
1133 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1134 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1135 ((cdi->ops->capability & CDC_MCN)!=0));
1137 pos += sprintf(cdrom_drive_info+pos, "\nReports media changed:");
1138 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1139 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1140 ((cdi->ops->capability & CDC_MEDIA_CHANGED)!=0));
1142 pos += sprintf(cdrom_drive_info+pos, "\nCan play audio:\t");
1143 for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
1144 pos += sprintf(cdrom_drive_info+pos, "\t%d",
1145 ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0));
1147 strcpy(cdrom_drive_info+pos,"\n\n");
1148 pos += 3;
1149 if (*lenp > pos)
1150 *lenp = pos;
1152 return proc_dostring(ctl, write, filp, buffer, lenp);
1155 /* Place files in /proc/sys/dev/cdrom */
1156 ctl_table cdrom_table[] = {
1157 {DEV_CDROM_INFO, "info", &cdrom_drive_info,
1158 CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
1162 ctl_table cdrom_cdrom_table[] = {
1163 {DEV_CDROM, "cdrom", NULL, 0, 0555, cdrom_table},
1167 /* Make sure that /proc/sys/dev is there */
1168 ctl_table cdrom_root_table[] = {
1169 {CTL_DEV, "dev", NULL, 0, 0555, cdrom_cdrom_table},
1173 static struct ctl_table_header *cdrom_sysctl_header;
1176 * This is called as the fill_inode function when an inode
1177 * is going into (fill = 1) or out of service (fill = 0).
1178 * We use it here to manage the module use counts.
1180 * Note: only the top-level directory needs to do this; if
1181 * a lower level is referenced, the parent will be as well.
1183 static void cdrom_procfs_modcount(struct inode *inode, int fill)
1185 if (fill) {
1186 MOD_INC_USE_COUNT;
1187 } else {
1188 MOD_DEC_USE_COUNT;
1192 static void cdrom_sysctl_register(void)
1194 static int initialized = 0;
1196 if (initialized == 1)
1197 return;
1199 cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
1200 cdrom_root_table->child->de->fill_inode = &cdrom_procfs_modcount;
1202 initialized = 1;
1205 #ifdef MODULE
1206 static void cdrom_sysctl_unregister(void)
1208 unregister_sysctl_table(cdrom_sysctl_header);
1210 #endif /* endif MODULE */
1211 #endif /* endif CONFIG_SYSCTL */
1213 #ifdef MODULE
1215 int init_module(void)
1217 #ifdef CONFIG_SYSCTL
1218 cdrom_sysctl_register();
1219 #endif /* CONFIG_SYSCTL */
1220 return 0;
1223 void cleanup_module(void)
1225 printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
1226 #ifdef CONFIG_SYSCTL
1227 cdrom_sysctl_unregister();
1228 #endif /* CONFIG_SYSCTL */
1231 #endif /* endif MODULE */
1236 * Local variables:
1237 * comment-column: 40
1238 * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -m486 -DCPU=486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o cdrom.o cdrom.c"
1239 * End: