aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-02-01 17:09:25 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-02-01 17:09:25 -0500
commit17802998d2c8007d06565c39101d218f579c4454 (patch)
tree7d3c636f124ae4378bea28848a9f7d62af909947 /drivers/ide
parent139c829d9d83cfd6b51682f11a431283121e24b7 (diff)
ide-cd: move code handling cdrom.c IOCTLs to ide-cd_ioctl.c
There should be no functionality changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/Makefile2
-rw-r--r--drivers/ide/ide-cd.c271
-rw-r--r--drivers/ide/ide-cd.h17
-rw-r--r--drivers/ide/ide-cd_ioctl.c265
4 files changed, 290 insertions, 265 deletions
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 5ce1d8f17c06..a4a4323be911 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -40,7 +40,7 @@ obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o
40obj-$(CONFIG_IDE_H8300) += h8300/ 40obj-$(CONFIG_IDE_H8300) += h8300/
41obj-$(CONFIG_IDE_GENERIC) += ide-generic.o 41obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
42 42
43ide-cd_mod-y += ide-cd.o ide-cd_verbose.o 43ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
44 44
45obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o 45obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o
46obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o 46obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b82cabfda63e..1032bec54ee6 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -206,7 +206,7 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
206/* 206/*
207 * Initialize a ide-cd packet command request 207 * Initialize a ide-cd packet command request
208 */ 208 */
209static void ide_cd_init_rq(ide_drive_t *drive, struct request *rq) 209void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
210{ 210{
211 struct cdrom_info *cd = drive->driver_data; 211 struct cdrom_info *cd = drive->driver_data;
212 212
@@ -1168,7 +1168,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
1168 return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation); 1168 return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
1169} 1169}
1170 1170
1171static int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) 1171int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
1172{ 1172{
1173 struct request_sense sense; 1173 struct request_sense sense;
1174 int retries = 10; 1174 int retries = 10;
@@ -1685,8 +1685,8 @@ static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
1685} 1685}
1686 1686
1687/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ 1687/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
1688static int ide_cd_lockdoor(ide_drive_t *drive, int lockflag, 1688int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
1689 struct request_sense *sense) 1689 struct request_sense *sense)
1690{ 1690{
1691 struct cdrom_info *cd = drive->driver_data; 1691 struct cdrom_info *cd = drive->driver_data;
1692 struct request_sense my_sense; 1692 struct request_sense my_sense;
@@ -1817,9 +1817,8 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
1817 return ide_cd_queue_pc(drive, &req); 1817 return ide_cd_queue_pc(drive, &req);
1818} 1818}
1819 1819
1820
1821/* Try to read the entire TOC for the disk into our internal buffer. */ 1820/* Try to read the entire TOC for the disk into our internal buffer. */
1822static int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) 1821int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
1823{ 1822{
1824 int stat, ntracks, i; 1823 int stat, ntracks, i;
1825 struct cdrom_info *info = drive->driver_data; 1824 struct cdrom_info *info = drive->driver_data;
@@ -1979,112 +1978,6 @@ static int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
1979 return 0; 1978 return 0;
1980} 1979}
1981 1980
1982static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
1983{
1984 struct cdrom_info *cd = drive->driver_data;
1985 struct cdrom_tochdr *tochdr = arg;
1986 struct atapi_toc *toc;
1987 int stat;
1988
1989 /* Make sure our saved TOC is valid. */
1990 stat = ide_cd_read_toc(drive, NULL);
1991 if (stat)
1992 return stat;
1993
1994 toc = cd->toc;
1995 tochdr->cdth_trk0 = toc->hdr.first_track;
1996 tochdr->cdth_trk1 = toc->hdr.last_track;
1997
1998 return 0;
1999}
2000
2001static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
2002 struct atapi_toc_entry **ent)
2003{
2004 struct cdrom_info *info = drive->driver_data;
2005 struct atapi_toc *toc = info->toc;
2006 int ntracks;
2007
2008 /*
2009 * don't serve cached data, if the toc isn't valid
2010 */
2011 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
2012 return -EINVAL;
2013
2014 /* Check validity of requested track number. */
2015 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
2016
2017 if (toc->hdr.first_track == CDROM_LEADOUT)
2018 ntracks = 0;
2019
2020 if (track == CDROM_LEADOUT)
2021 *ent = &toc->ent[ntracks];
2022 else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
2023 return -EINVAL;
2024 else
2025 *ent = &toc->ent[track - toc->hdr.first_track];
2026
2027 return 0;
2028}
2029
2030static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
2031{
2032 struct cdrom_tocentry *tocentry = arg;
2033 struct atapi_toc_entry *toce;
2034 int stat;
2035
2036 stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
2037 if (stat)
2038 return stat;
2039
2040 tocentry->cdte_ctrl = toce->control;
2041 tocentry->cdte_adr = toce->adr;
2042 if (tocentry->cdte_format == CDROM_MSF) {
2043 lba_to_msf(toce->addr.lba,
2044 &tocentry->cdte_addr.msf.minute,
2045 &tocentry->cdte_addr.msf.second,
2046 &tocentry->cdte_addr.msf.frame);
2047 } else
2048 tocentry->cdte_addr.lba = toce->addr.lba;
2049
2050 return 0;
2051}
2052
2053static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
2054{
2055 struct cdrom_ti *ti = arg;
2056 struct atapi_toc_entry *first_toc, *last_toc;
2057 unsigned long lba_start, lba_end;
2058 int stat;
2059 struct request rq;
2060 struct request_sense sense;
2061
2062 stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
2063 if (stat)
2064 return stat;
2065
2066 stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
2067 if (stat)
2068 return stat;
2069
2070 if (ti->cdti_trk1 != CDROM_LEADOUT)
2071 ++last_toc;
2072 lba_start = first_toc->addr.lba;
2073 lba_end = last_toc->addr.lba;
2074
2075 if (lba_end <= lba_start)
2076 return -EINVAL;
2077
2078 ide_cd_init_rq(drive, &rq);
2079
2080 rq.sense = &sense;
2081 rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
2082 lba_to_msf(lba_start, &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
2083 lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
2084
2085 return ide_cd_queue_pc(drive, &rq);
2086}
2087
2088/* the generic packet interface to cdrom.c */ 1981/* the generic packet interface to cdrom.c */
2089static int ide_cdrom_packet(struct cdrom_device_info *cdi, 1982static int ide_cdrom_packet(struct cdrom_device_info *cdi,
2090 struct packet_command *cgc) 1983 struct packet_command *cgc)
@@ -2116,52 +2009,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
2116 return cgc->stat; 2009 return cgc->stat;
2117} 2010}
2118 2011
2119static int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
2120 unsigned int cmd, void *arg)
2121{
2122 ide_drive_t *drive = cdi->handle;
2123
2124 switch (cmd) {
2125 /*
2126 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
2127 * atapi doesn't support it
2128 */
2129 case CDROMPLAYTRKIND:
2130 return ide_cd_fake_play_trkind(drive, arg);
2131 case CDROMREADTOCHDR:
2132 return ide_cd_read_tochdr(drive, arg);
2133 case CDROMREADTOCENTRY:
2134 return ide_cd_read_tocentry(drive, arg);
2135 default:
2136 return -EINVAL;
2137 }
2138}
2139
2140static
2141int ide_cdrom_reset (struct cdrom_device_info *cdi)
2142{
2143 ide_drive_t *drive = cdi->handle;
2144 struct cdrom_info *cd = drive->driver_data;
2145 struct request_sense sense;
2146 struct request req;
2147 int ret;
2148
2149 ide_cd_init_rq(drive, &req);
2150 req.cmd_type = REQ_TYPE_SPECIAL;
2151 req.cmd_flags = REQ_QUIET;
2152 ret = ide_do_drive_cmd(drive, &req, ide_wait);
2153
2154 /*
2155 * A reset will unlock the door. If it was previously locked,
2156 * lock it again.
2157 */
2158 if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
2159 (void)ide_cd_lockdoor(drive, 1, &sense);
2160
2161 return ret;
2162}
2163
2164
2165static 2012static
2166int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) 2013int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
2167{ 2014{
@@ -2178,15 +2025,7 @@ int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
2178 return cdrom_eject(drive, !position, &sense); 2025 return cdrom_eject(drive, !position, &sense);
2179} 2026}
2180 2027
2181static 2028int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
2182int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
2183{
2184 ide_drive_t *drive = cdi->handle;
2185
2186 return ide_cd_lockdoor(drive, lock, NULL);
2187}
2188
2189static int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
2190{ 2029{
2191 struct cdrom_info *info = drive->driver_data; 2030 struct cdrom_info *info = drive->driver_data;
2192 struct cdrom_device_info *cdi = &info->devinfo; 2031 struct cdrom_device_info *cdi = &info->devinfo;
@@ -2205,7 +2044,7 @@ static int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
2205 return stat; 2044 return stat;
2206} 2045}
2207 2046
2208static void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf) 2047void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
2209{ 2048{
2210 struct cdrom_info *cd = drive->driver_data; 2049 struct cdrom_info *cd = drive->driver_data;
2211 u16 curspeed, maxspeed; 2050 u16 curspeed, maxspeed;
@@ -2226,49 +2065,6 @@ static void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
2226} 2065}
2227 2066
2228/* 2067/*
2229 * ATAPI devices are free to select the speed you request or any slower
2230 * rate. :-( Requesting too fast a speed will _not_ produce an error.
2231 */
2232static int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
2233{
2234 ide_drive_t *drive = cdi->handle;
2235 struct cdrom_info *cd = drive->driver_data;
2236 struct request rq;
2237 struct request_sense sense;
2238 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
2239 int stat;
2240
2241 ide_cd_init_rq(drive, &rq);
2242
2243 rq.sense = &sense;
2244
2245 if (speed == 0)
2246 speed = 0xffff; /* set to max */
2247 else
2248 speed *= 177; /* Nx to kbytes/s */
2249
2250 rq.cmd[0] = GPCMD_SET_SPEED;
2251 /* Read Drive speed in kbytes/second MSB/LSB */
2252 rq.cmd[2] = (speed >> 8) & 0xff;
2253 rq.cmd[3] = speed & 0xff;
2254 if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
2255 (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
2256 /* Write Drive speed in kbytes/second MSB/LSB */
2257 rq.cmd[4] = (speed >> 8) & 0xff;
2258 rq.cmd[5] = speed & 0xff;
2259 }
2260
2261 stat = ide_cd_queue_pc(drive, &rq);
2262
2263 if (!ide_cdrom_get_capabilities(drive, buf)) {
2264 ide_cdrom_update_speed(drive, buf);
2265 cdi->speed = cd->current_speed;
2266 }
2267
2268 return 0;
2269}
2270
2271/*
2272 * add logic to try GET_EVENT command first to check for media and tray 2068 * add logic to try GET_EVENT command first to check for media and tray
2273 * status. this should be supported by newer cd-r/w and all DVD etc 2069 * status. this should be supported by newer cd-r/w and all DVD etc
2274 * drives 2070 * drives
@@ -2314,59 +2110,6 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
2314 return CDS_DRIVE_NOT_READY; 2110 return CDS_DRIVE_NOT_READY;
2315} 2111}
2316 2112
2317static
2318int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
2319 struct cdrom_multisession *ms_info)
2320{
2321 struct atapi_toc *toc;
2322 ide_drive_t *drive = cdi->handle;
2323 struct cdrom_info *info = drive->driver_data;
2324 struct request_sense sense;
2325 int ret;
2326
2327 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
2328 ret = ide_cd_read_toc(drive, &sense);
2329 if (ret)
2330 return ret;
2331 }
2332
2333 toc = info->toc;
2334 ms_info->addr.lba = toc->last_session_lba;
2335 ms_info->xa_flag = toc->xa_flag;
2336
2337 return 0;
2338}
2339
2340static int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
2341 struct cdrom_mcn *mcn_info)
2342{
2343 ide_drive_t *drive = cdi->handle;
2344 int stat, mcnlen;
2345 struct request rq;
2346 char buf[24];
2347
2348 ide_cd_init_rq(drive, &rq);
2349
2350 rq.data = buf;
2351 rq.data_len = sizeof(buf);
2352
2353 rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
2354 rq.cmd[1] = 2; /* MSF addressing */
2355 rq.cmd[2] = 0x40; /* request subQ data */
2356 rq.cmd[3] = 2; /* format */
2357 rq.cmd[8] = sizeof(buf);
2358
2359 stat = ide_cd_queue_pc(drive, &rq);
2360 if (stat)
2361 return stat;
2362
2363 mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
2364 memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
2365 mcn_info->medium_catalog_number[mcnlen] = '\0';
2366
2367 return 0;
2368}
2369
2370/**************************************************************************** 2113/****************************************************************************
2371 * Other driver requests (open, close, check media change). 2114 * Other driver requests (open, close, check media change).
2372 */ 2115 */
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
index e1b401494a99..5343063e83f6 100644
--- a/drivers/ide/ide-cd.h
+++ b/drivers/ide/ide-cd.h
@@ -148,4 +148,21 @@ struct cdrom_info {
148/* ide-cd_verbose.c */ 148/* ide-cd_verbose.c */
149void ide_cd_log_error(const char *, struct request *, struct request_sense *); 149void ide_cd_log_error(const char *, struct request *, struct request_sense *);
150 150
151/* ide-cd.c functions used by ide-cd_ioctl.c */
152void ide_cd_init_rq(ide_drive_t *, struct request *);
153int ide_cd_queue_pc(ide_drive_t *, struct request *);
154int ide_cd_lockdoor(ide_drive_t *, int, struct request_sense *);
155int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
156int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
157void ide_cdrom_update_speed(ide_drive_t *, u8 *);
158
159/* ide-cd_ioctl.c */
160int ide_cdrom_lock_door(struct cdrom_device_info *, int);
161int ide_cdrom_select_speed(struct cdrom_device_info *, int);
162int ide_cdrom_get_last_session(struct cdrom_device_info *,
163 struct cdrom_multisession *);
164int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
165int ide_cdrom_reset(struct cdrom_device_info *cdi);
166int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
167
151#endif /* _IDE_CD_H */ 168#endif /* _IDE_CD_H */
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
new file mode 100644
index 000000000000..ec698c44e8bf
--- /dev/null
+++ b/drivers/ide/ide-cd_ioctl.c
@@ -0,0 +1,265 @@
1/*
2 * cdrom.c IOCTLs handling for ide-cd driver.
3 *
4 * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov>
5 * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
6 * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
7 */
8
9#include <linux/kernel.h>
10#include <linux/cdrom.h>
11#include <linux/ide.h>
12
13#include "ide-cd.h"
14
15int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
16{
17 ide_drive_t *drive = cdi->handle;
18
19 return ide_cd_lockdoor(drive, lock, NULL);
20}
21
22/*
23 * ATAPI devices are free to select the speed you request or any slower
24 * rate. :-( Requesting too fast a speed will _not_ produce an error.
25 */
26int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
27{
28 ide_drive_t *drive = cdi->handle;
29 struct cdrom_info *cd = drive->driver_data;
30 struct request rq;
31 struct request_sense sense;
32 u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
33 int stat;
34
35 ide_cd_init_rq(drive, &rq);
36
37 rq.sense = &sense;
38
39 if (speed == 0)
40 speed = 0xffff; /* set to max */
41 else
42 speed *= 177; /* Nx to kbytes/s */
43
44 rq.cmd[0] = GPCMD_SET_SPEED;
45 /* Read Drive speed in kbytes/second MSB/LSB */
46 rq.cmd[2] = (speed >> 8) & 0xff;
47 rq.cmd[3] = speed & 0xff;
48 if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
49 (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
50 /* Write Drive speed in kbytes/second MSB/LSB */
51 rq.cmd[4] = (speed >> 8) & 0xff;
52 rq.cmd[5] = speed & 0xff;
53 }
54
55 stat = ide_cd_queue_pc(drive, &rq);
56
57 if (!ide_cdrom_get_capabilities(drive, buf)) {
58 ide_cdrom_update_speed(drive, buf);
59 cdi->speed = cd->current_speed;
60 }
61
62 return 0;
63}
64
65int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
66 struct cdrom_multisession *ms_info)
67{
68 struct atapi_toc *toc;
69 ide_drive_t *drive = cdi->handle;
70 struct cdrom_info *info = drive->driver_data;
71 struct request_sense sense;
72 int ret;
73
74 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
75 ret = ide_cd_read_toc(drive, &sense);
76 if (ret)
77 return ret;
78 }
79
80 toc = info->toc;
81 ms_info->addr.lba = toc->last_session_lba;
82 ms_info->xa_flag = toc->xa_flag;
83
84 return 0;
85}
86
87int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
88 struct cdrom_mcn *mcn_info)
89{
90 ide_drive_t *drive = cdi->handle;
91 int stat, mcnlen;
92 struct request rq;
93 char buf[24];
94
95 ide_cd_init_rq(drive, &rq);
96
97 rq.data = buf;
98 rq.data_len = sizeof(buf);
99
100 rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
101 rq.cmd[1] = 2; /* MSF addressing */
102 rq.cmd[2] = 0x40; /* request subQ data */
103 rq.cmd[3] = 2; /* format */
104 rq.cmd[8] = sizeof(buf);
105
106 stat = ide_cd_queue_pc(drive, &rq);
107 if (stat)
108 return stat;
109
110 mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
111 memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
112 mcn_info->medium_catalog_number[mcnlen] = '\0';
113
114 return 0;
115}
116
117int ide_cdrom_reset(struct cdrom_device_info *cdi)
118{
119 ide_drive_t *drive = cdi->handle;
120 struct cdrom_info *cd = drive->driver_data;
121 struct request_sense sense;
122 struct request req;
123 int ret;
124
125 ide_cd_init_rq(drive, &req);
126 req.cmd_type = REQ_TYPE_SPECIAL;
127 req.cmd_flags = REQ_QUIET;
128 ret = ide_do_drive_cmd(drive, &req, ide_wait);
129
130 /*
131 * A reset will unlock the door. If it was previously locked,
132 * lock it again.
133 */
134 if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
135 (void)ide_cd_lockdoor(drive, 1, &sense);
136
137 return ret;
138}
139
140static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
141 struct atapi_toc_entry **ent)
142{
143 struct cdrom_info *info = drive->driver_data;
144 struct atapi_toc *toc = info->toc;
145 int ntracks;
146
147 /*
148 * don't serve cached data, if the toc isn't valid
149 */
150 if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
151 return -EINVAL;
152
153 /* Check validity of requested track number. */
154 ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
155
156 if (toc->hdr.first_track == CDROM_LEADOUT)
157 ntracks = 0;
158
159 if (track == CDROM_LEADOUT)
160 *ent = &toc->ent[ntracks];
161 else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
162 return -EINVAL;
163 else
164 *ent = &toc->ent[track - toc->hdr.first_track];
165
166 return 0;
167}
168
169static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
170{
171 struct cdrom_ti *ti = arg;
172 struct atapi_toc_entry *first_toc, *last_toc;
173 unsigned long lba_start, lba_end;
174 int stat;
175 struct request rq;
176 struct request_sense sense;
177
178 stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
179 if (stat)
180 return stat;
181
182 stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
183 if (stat)
184 return stat;
185
186 if (ti->cdti_trk1 != CDROM_LEADOUT)
187 ++last_toc;
188 lba_start = first_toc->addr.lba;
189 lba_end = last_toc->addr.lba;
190
191 if (lba_end <= lba_start)
192 return -EINVAL;
193
194 ide_cd_init_rq(drive, &rq);
195
196 rq.sense = &sense;
197 rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
198 lba_to_msf(lba_start, &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
199 lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
200
201 return ide_cd_queue_pc(drive, &rq);
202}
203
204static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
205{
206 struct cdrom_info *cd = drive->driver_data;
207 struct cdrom_tochdr *tochdr = arg;
208 struct atapi_toc *toc;
209 int stat;
210
211 /* Make sure our saved TOC is valid. */
212 stat = ide_cd_read_toc(drive, NULL);
213 if (stat)
214 return stat;
215
216 toc = cd->toc;
217 tochdr->cdth_trk0 = toc->hdr.first_track;
218 tochdr->cdth_trk1 = toc->hdr.last_track;
219
220 return 0;
221}
222
223static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
224{
225 struct cdrom_tocentry *tocentry = arg;
226 struct atapi_toc_entry *toce;
227 int stat;
228
229 stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
230 if (stat)
231 return stat;
232
233 tocentry->cdte_ctrl = toce->control;
234 tocentry->cdte_adr = toce->adr;
235 if (tocentry->cdte_format == CDROM_MSF) {
236 lba_to_msf(toce->addr.lba,
237 &tocentry->cdte_addr.msf.minute,
238 &tocentry->cdte_addr.msf.second,
239 &tocentry->cdte_addr.msf.frame);
240 } else
241 tocentry->cdte_addr.lba = toce->addr.lba;
242
243 return 0;
244}
245
246int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
247 unsigned int cmd, void *arg)
248{
249 ide_drive_t *drive = cdi->handle;
250
251 switch (cmd) {
252 /*
253 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
254 * atapi doesn't support it
255 */
256 case CDROMPLAYTRKIND:
257 return ide_cd_fake_play_trkind(drive, arg);
258 case CDROMREADTOCHDR:
259 return ide_cd_read_tochdr(drive, arg);
260 case CDROMREADTOCENTRY:
261 return ide_cd_read_tocentry(drive, arg);
262 default:
263 return -EINVAL;
264 }
265}