1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * -- <linux/cdrom.h>
41da177e4SLinus Torvalds * General header file for linux CD-ROM drivers
51da177e4SLinus Torvalds * Copyright (C) 1992 David Giller, rafetmad@oxy.edu
696de0e25SJan Engelhardt * 1994, 1995 Eberhard Mönkeberg, emoenke@gwdg.de
71da177e4SLinus Torvalds * 1996 David van Leeuwen, david@tm.tno.nl
81da177e4SLinus Torvalds * 1997, 1998 Erik Andersen, andersee@debian.org
91da177e4SLinus Torvalds * 1998-2002 Jens Axboe, axboe@suse.de
101da177e4SLinus Torvalds */
111da177e4SLinus Torvalds #ifndef _LINUX_CDROM_H
121da177e4SLinus Torvalds #define _LINUX_CDROM_H
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include <linux/fs.h> /* not really needed, later.. */
157fd097d4SAkinobu Mita #include <linux/list.h>
16*05bdb996SChristoph Hellwig #include <linux/blkdev.h>
17e7d0748dSKees Cook #include <scsi/scsi_common.h>
18607ca46eSDavid Howells #include <uapi/linux/cdrom.h>
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds struct packet_command
211da177e4SLinus Torvalds {
221da177e4SLinus Torvalds unsigned char cmd[CDROM_PACKET_SIZE];
231da177e4SLinus Torvalds unsigned char *buffer;
241da177e4SLinus Torvalds unsigned int buflen;
251da177e4SLinus Torvalds int stat;
26e7d0748dSKees Cook struct scsi_sense_hdr *sshdr;
271da177e4SLinus Torvalds unsigned char data_direction;
281da177e4SLinus Torvalds int quiet;
291da177e4SLinus Torvalds int timeout;
301da177e4SLinus Torvalds void *reserved[1];
311da177e4SLinus Torvalds };
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds * _OLD will use PIO transfer on atapi devices, _BPC_* will use DMA
351da177e4SLinus Torvalds */
361da177e4SLinus Torvalds #define CDDA_OLD 0 /* old style */
371da177e4SLinus Torvalds #define CDDA_BPC_SINGLE 1 /* single frame block pc */
381da177e4SLinus Torvalds #define CDDA_BPC_FULL 2 /* multi frame block pc */
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds /* Uniform cdrom data structures for cdrom.c */
411da177e4SLinus Torvalds struct cdrom_device_info {
42853fe1bfSKees Cook const struct cdrom_device_ops *ops; /* link to device_ops */
437fd097d4SAkinobu Mita struct list_head list; /* linked list of all device_info */
441da177e4SLinus Torvalds struct gendisk *disk; /* matching block layer disk */
451da177e4SLinus Torvalds void *handle; /* driver-dependent data */
461da177e4SLinus Torvalds /* specifications */
471da177e4SLinus Torvalds int mask; /* mask of capability: disables them */
481da177e4SLinus Torvalds int speed; /* maximum speed for reading data */
491da177e4SLinus Torvalds int capacity; /* number of discs in jukebox */
501da177e4SLinus Torvalds /* device-related storage */
510cba01dbSRandy Dunlap unsigned int options : 30; /* options flags */
521da177e4SLinus Torvalds unsigned mc_flags : 2; /* media change buffer flags */
532d921729STejun Heo unsigned int vfs_events; /* cached events for vfs path */
542d921729STejun Heo unsigned int ioctl_events; /* cached events for ioctl path */
551da177e4SLinus Torvalds int use_count; /* number of times device opened */
561da177e4SLinus Torvalds char name[20]; /* name of the device type */
571da177e4SLinus Torvalds /* per-device flags */
581da177e4SLinus Torvalds __u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */
59cdccaa94SPaolo Bonzini __u8 keeplocked : 1; /* CDROM_LOCKDOOR status */
60cdccaa94SPaolo Bonzini __u8 reserved : 5; /* not used yet */
611da177e4SLinus Torvalds int cdda_method; /* see flags */
621da177e4SLinus Torvalds __u8 last_sense;
631da177e4SLinus Torvalds __u8 media_written; /* dirty flag, DVD+RW bookkeeping */
641da177e4SLinus Torvalds unsigned short mmc3_profile; /* current MMC3 profile */
651da177e4SLinus Torvalds int (*exit)(struct cdrom_device_info *);
661da177e4SLinus Torvalds int mrw_mode_page;
678cdf433eSChristoph Hellwig bool opened_for_data;
6867f1e027SLukas Prediger __s64 last_media_change_ms;
691da177e4SLinus Torvalds };
701da177e4SLinus Torvalds
711da177e4SLinus Torvalds struct cdrom_device_ops {
721da177e4SLinus Torvalds /* routines */
731da177e4SLinus Torvalds int (*open) (struct cdrom_device_info *, int);
741da177e4SLinus Torvalds void (*release) (struct cdrom_device_info *);
751da177e4SLinus Torvalds int (*drive_status) (struct cdrom_device_info *, int);
762d921729STejun Heo unsigned int (*check_events) (struct cdrom_device_info *cdi,
772d921729STejun Heo unsigned int clearing, int slot);
781da177e4SLinus Torvalds int (*tray_move) (struct cdrom_device_info *, int);
791da177e4SLinus Torvalds int (*lock_door) (struct cdrom_device_info *, int);
801da177e4SLinus Torvalds int (*select_speed) (struct cdrom_device_info *, int);
811da177e4SLinus Torvalds int (*get_last_session) (struct cdrom_device_info *,
821da177e4SLinus Torvalds struct cdrom_multisession *);
831da177e4SLinus Torvalds int (*get_mcn) (struct cdrom_device_info *,
841da177e4SLinus Torvalds struct cdrom_mcn *);
851da177e4SLinus Torvalds /* hard reset device */
861da177e4SLinus Torvalds int (*reset) (struct cdrom_device_info *);
871da177e4SLinus Torvalds /* play stuff */
881da177e4SLinus Torvalds int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
896a2900b6SChristoph Hellwig
901da177e4SLinus Torvalds /* handle uniform packets for scsi type devices (scsi,atapi) */
911da177e4SLinus Torvalds int (*generic_packet) (struct cdrom_device_info *,
921da177e4SLinus Torvalds struct packet_command *);
93ba51bdafSChristoph Hellwig int (*read_cdda_bpc)(struct cdrom_device_info *cdi, void __user *ubuf,
94ba51bdafSChristoph Hellwig u32 lba, u32 nframes, u8 *last_sense);
95ba51bdafSChristoph Hellwig /* driver specifications */
96ba51bdafSChristoph Hellwig const int capability; /* capability flags */
971da177e4SLinus Torvalds };
981da177e4SLinus Torvalds
99eaf8e3e4SChristoph Hellwig int cdrom_multisession(struct cdrom_device_info *cdi,
100eaf8e3e4SChristoph Hellwig struct cdrom_multisession *info);
1014c3cfcceSChristoph Hellwig int cdrom_read_tocentry(struct cdrom_device_info *cdi,
1024c3cfcceSChristoph Hellwig struct cdrom_tocentry *entry);
1034c3cfcceSChristoph Hellwig
1041da177e4SLinus Torvalds /* the general block_device operations structure: */
105*05bdb996SChristoph Hellwig int cdrom_open(struct cdrom_device_info *cdi, blk_mode_t mode);
1067ae24fceSChristoph Hellwig void cdrom_release(struct cdrom_device_info *cdi);
107473399b5SChristoph Hellwig int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
108473399b5SChristoph Hellwig unsigned int cmd, unsigned long arg);
1092d921729STejun Heo extern unsigned int cdrom_check_events(struct cdrom_device_info *cdi,
1102d921729STejun Heo unsigned int clearing);
1111da177e4SLinus Torvalds
112a711d91cSChristoph Hellwig extern int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi);
1130a0c4114SAkinobu Mita extern void unregister_cdrom(struct cdrom_device_info *cdi);
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds typedef struct {
1161da177e4SLinus Torvalds int data;
1171da177e4SLinus Torvalds int audio;
1181da177e4SLinus Torvalds int cdi;
1191da177e4SLinus Torvalds int xa;
1201da177e4SLinus Torvalds long error;
1211da177e4SLinus Torvalds } tracktype;
1221da177e4SLinus Torvalds
1231da177e4SLinus Torvalds extern int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written);
1241da177e4SLinus Torvalds extern int cdrom_number_of_slots(struct cdrom_device_info *cdi);
1251da177e4SLinus Torvalds extern int cdrom_mode_select(struct cdrom_device_info *cdi,
1261da177e4SLinus Torvalds struct packet_command *cgc);
1271da177e4SLinus Torvalds extern int cdrom_mode_sense(struct cdrom_device_info *cdi,
1281da177e4SLinus Torvalds struct packet_command *cgc,
1291da177e4SLinus Torvalds int page_code, int page_control);
1301da177e4SLinus Torvalds extern void init_cdrom_command(struct packet_command *cgc,
1311da177e4SLinus Torvalds void *buffer, int len, int type);
132853fe1bfSKees Cook extern int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
133853fe1bfSKees Cook struct packet_command *cgc);
1341da177e4SLinus Torvalds
1351da177e4SLinus Torvalds /* The SCSI spec says there could be 256 slots. */
1361da177e4SLinus Torvalds #define CDROM_MAX_SLOTS 256
1371da177e4SLinus Torvalds
1381da177e4SLinus Torvalds struct cdrom_mechstat_header {
1391da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
1401da177e4SLinus Torvalds __u8 fault : 1;
1411da177e4SLinus Torvalds __u8 changer_state : 2;
1421da177e4SLinus Torvalds __u8 curslot : 5;
1431da177e4SLinus Torvalds __u8 mech_state : 3;
1441da177e4SLinus Torvalds __u8 door_open : 1;
1451da177e4SLinus Torvalds __u8 reserved1 : 4;
1461da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
1471da177e4SLinus Torvalds __u8 curslot : 5;
1481da177e4SLinus Torvalds __u8 changer_state : 2;
1491da177e4SLinus Torvalds __u8 fault : 1;
1501da177e4SLinus Torvalds __u8 reserved1 : 4;
1511da177e4SLinus Torvalds __u8 door_open : 1;
1521da177e4SLinus Torvalds __u8 mech_state : 3;
1531da177e4SLinus Torvalds #endif
1541da177e4SLinus Torvalds __u8 curlba[3];
1551da177e4SLinus Torvalds __u8 nslots;
1561da177e4SLinus Torvalds __u16 slot_tablelen;
1571da177e4SLinus Torvalds };
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds struct cdrom_slot {
1601da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
1611da177e4SLinus Torvalds __u8 disc_present : 1;
1621da177e4SLinus Torvalds __u8 reserved1 : 6;
1631da177e4SLinus Torvalds __u8 change : 1;
1641da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
1651da177e4SLinus Torvalds __u8 change : 1;
1661da177e4SLinus Torvalds __u8 reserved1 : 6;
1671da177e4SLinus Torvalds __u8 disc_present : 1;
1681da177e4SLinus Torvalds #endif
1691da177e4SLinus Torvalds __u8 reserved2[3];
1701da177e4SLinus Torvalds };
1711da177e4SLinus Torvalds
1721da177e4SLinus Torvalds struct cdrom_changer_info {
1731da177e4SLinus Torvalds struct cdrom_mechstat_header hdr;
1741da177e4SLinus Torvalds struct cdrom_slot slots[CDROM_MAX_SLOTS];
1751da177e4SLinus Torvalds };
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds typedef enum {
1781da177e4SLinus Torvalds mechtype_caddy = 0,
1791da177e4SLinus Torvalds mechtype_tray = 1,
1801da177e4SLinus Torvalds mechtype_popup = 2,
1811da177e4SLinus Torvalds mechtype_individual_changer = 4,
1821da177e4SLinus Torvalds mechtype_cartridge_changer = 5
1831da177e4SLinus Torvalds } mechtype_t;
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds typedef struct {
1861da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
1871da177e4SLinus Torvalds __u8 ps : 1;
1881da177e4SLinus Torvalds __u8 reserved1 : 1;
1891da177e4SLinus Torvalds __u8 page_code : 6;
1901da177e4SLinus Torvalds __u8 page_length;
1911da177e4SLinus Torvalds __u8 reserved2 : 1;
1921da177e4SLinus Torvalds __u8 bufe : 1;
1931da177e4SLinus Torvalds __u8 ls_v : 1;
1941da177e4SLinus Torvalds __u8 test_write : 1;
1951da177e4SLinus Torvalds __u8 write_type : 4;
1961da177e4SLinus Torvalds __u8 multi_session : 2; /* or border, DVD */
1971da177e4SLinus Torvalds __u8 fp : 1;
1981da177e4SLinus Torvalds __u8 copy : 1;
1991da177e4SLinus Torvalds __u8 track_mode : 4;
2001da177e4SLinus Torvalds __u8 reserved3 : 4;
2011da177e4SLinus Torvalds __u8 data_block_type : 4;
2021da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
2031da177e4SLinus Torvalds __u8 page_code : 6;
2041da177e4SLinus Torvalds __u8 reserved1 : 1;
2051da177e4SLinus Torvalds __u8 ps : 1;
2061da177e4SLinus Torvalds __u8 page_length;
2071da177e4SLinus Torvalds __u8 write_type : 4;
2081da177e4SLinus Torvalds __u8 test_write : 1;
2091da177e4SLinus Torvalds __u8 ls_v : 1;
2101da177e4SLinus Torvalds __u8 bufe : 1;
2111da177e4SLinus Torvalds __u8 reserved2 : 1;
2121da177e4SLinus Torvalds __u8 track_mode : 4;
2131da177e4SLinus Torvalds __u8 copy : 1;
2141da177e4SLinus Torvalds __u8 fp : 1;
2151da177e4SLinus Torvalds __u8 multi_session : 2; /* or border, DVD */
2161da177e4SLinus Torvalds __u8 data_block_type : 4;
2171da177e4SLinus Torvalds __u8 reserved3 : 4;
2181da177e4SLinus Torvalds #endif
2191da177e4SLinus Torvalds __u8 link_size;
2201da177e4SLinus Torvalds __u8 reserved4;
2211da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
2221da177e4SLinus Torvalds __u8 reserved5 : 2;
2231da177e4SLinus Torvalds __u8 app_code : 6;
2241da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
2251da177e4SLinus Torvalds __u8 app_code : 6;
2261da177e4SLinus Torvalds __u8 reserved5 : 2;
2271da177e4SLinus Torvalds #endif
2281da177e4SLinus Torvalds __u8 session_format;
2291da177e4SLinus Torvalds __u8 reserved6;
23056052d52SAlexey Dobriyan __be32 packet_size;
2311da177e4SLinus Torvalds __u16 audio_pause;
2321da177e4SLinus Torvalds __u8 mcn[16];
2331da177e4SLinus Torvalds __u8 isrc[16];
2341da177e4SLinus Torvalds __u8 subhdr0;
2351da177e4SLinus Torvalds __u8 subhdr1;
2361da177e4SLinus Torvalds __u8 subhdr2;
2371da177e4SLinus Torvalds __u8 subhdr3;
2381da177e4SLinus Torvalds } __attribute__((packed)) write_param_page;
2391da177e4SLinus Torvalds
2401da177e4SLinus Torvalds struct modesel_head
2411da177e4SLinus Torvalds {
2421da177e4SLinus Torvalds __u8 reserved1;
2431da177e4SLinus Torvalds __u8 medium;
2441da177e4SLinus Torvalds __u8 reserved2;
2451da177e4SLinus Torvalds __u8 block_desc_length;
2461da177e4SLinus Torvalds __u8 density;
2471da177e4SLinus Torvalds __u8 number_of_blocks_hi;
2481da177e4SLinus Torvalds __u8 number_of_blocks_med;
2491da177e4SLinus Torvalds __u8 number_of_blocks_lo;
2501da177e4SLinus Torvalds __u8 reserved3;
2511da177e4SLinus Torvalds __u8 block_length_hi;
2521da177e4SLinus Torvalds __u8 block_length_med;
2531da177e4SLinus Torvalds __u8 block_length_lo;
2541da177e4SLinus Torvalds };
2551da177e4SLinus Torvalds
2561da177e4SLinus Torvalds typedef struct {
2571da177e4SLinus Torvalds __u16 report_key_length;
2581da177e4SLinus Torvalds __u8 reserved1;
2591da177e4SLinus Torvalds __u8 reserved2;
2601da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
2611da177e4SLinus Torvalds __u8 type_code : 2;
2621da177e4SLinus Torvalds __u8 vra : 3;
2631da177e4SLinus Torvalds __u8 ucca : 3;
2641da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
2651da177e4SLinus Torvalds __u8 ucca : 3;
2661da177e4SLinus Torvalds __u8 vra : 3;
2671da177e4SLinus Torvalds __u8 type_code : 2;
2681da177e4SLinus Torvalds #endif
2691da177e4SLinus Torvalds __u8 region_mask;
2701da177e4SLinus Torvalds __u8 rpc_scheme;
2711da177e4SLinus Torvalds __u8 reserved3;
2721da177e4SLinus Torvalds } rpc_state_t;
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds struct event_header {
27556052d52SAlexey Dobriyan __be16 data_len;
2761da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
2771da177e4SLinus Torvalds __u8 nea : 1;
2781da177e4SLinus Torvalds __u8 reserved1 : 4;
2791da177e4SLinus Torvalds __u8 notification_class : 3;
2801da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
2811da177e4SLinus Torvalds __u8 notification_class : 3;
2821da177e4SLinus Torvalds __u8 reserved1 : 4;
2831da177e4SLinus Torvalds __u8 nea : 1;
2841da177e4SLinus Torvalds #endif
2851da177e4SLinus Torvalds __u8 supp_event_class;
2861da177e4SLinus Torvalds };
2871da177e4SLinus Torvalds
2881da177e4SLinus Torvalds struct media_event_desc {
2891da177e4SLinus Torvalds #if defined(__BIG_ENDIAN_BITFIELD)
2901da177e4SLinus Torvalds __u8 reserved1 : 4;
2911da177e4SLinus Torvalds __u8 media_event_code : 4;
2921da177e4SLinus Torvalds __u8 reserved2 : 6;
2931da177e4SLinus Torvalds __u8 media_present : 1;
2941da177e4SLinus Torvalds __u8 door_open : 1;
2951da177e4SLinus Torvalds #elif defined(__LITTLE_ENDIAN_BITFIELD)
2961da177e4SLinus Torvalds __u8 media_event_code : 4;
2971da177e4SLinus Torvalds __u8 reserved1 : 4;
2981da177e4SLinus Torvalds __u8 door_open : 1;
2991da177e4SLinus Torvalds __u8 media_present : 1;
3001da177e4SLinus Torvalds __u8 reserved2 : 6;
3011da177e4SLinus Torvalds #endif
3021da177e4SLinus Torvalds __u8 start_slot;
3031da177e4SLinus Torvalds __u8 end_slot;
3041da177e4SLinus Torvalds };
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds extern int cdrom_get_media_event(struct cdrom_device_info *cdi, struct media_event_desc *med);
3071da177e4SLinus Torvalds
lba_to_msf(int lba,u8 * m,u8 * s,u8 * f)308a1bb9457SBartlomiej Zolnierkiewicz static inline void lba_to_msf(int lba, u8 *m, u8 *s, u8 *f)
309a1bb9457SBartlomiej Zolnierkiewicz {
310a1bb9457SBartlomiej Zolnierkiewicz lba += CD_MSF_OFFSET;
311a1bb9457SBartlomiej Zolnierkiewicz lba &= 0xffffff; /* negative lbas use only 24 bits */
312a1bb9457SBartlomiej Zolnierkiewicz *m = lba / (CD_SECS * CD_FRAMES);
313a1bb9457SBartlomiej Zolnierkiewicz lba %= (CD_SECS * CD_FRAMES);
314a1bb9457SBartlomiej Zolnierkiewicz *s = lba / CD_FRAMES;
315a1bb9457SBartlomiej Zolnierkiewicz *f = lba % CD_FRAMES;
316a1bb9457SBartlomiej Zolnierkiewicz }
317a1bb9457SBartlomiej Zolnierkiewicz
msf_to_lba(u8 m,u8 s,u8 f)318a1bb9457SBartlomiej Zolnierkiewicz static inline int msf_to_lba(u8 m, u8 s, u8 f)
319a1bb9457SBartlomiej Zolnierkiewicz {
320a1bb9457SBartlomiej Zolnierkiewicz return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
321a1bb9457SBartlomiej Zolnierkiewicz }
3221da177e4SLinus Torvalds #endif /* _LINUX_CDROM_H */
323