Commit 17802998d2c8007d06565c39101d218f579c4454
1 parent
139c829d9d
Exists in
master
and in
39 other branches
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>
Showing 4 changed files with 290 additions and 265 deletions Side-by-side Diff
drivers/ide/Makefile
... | ... | @@ -40,7 +40,7 @@ |
40 | 40 | obj-$(CONFIG_IDE_H8300) += h8300/ |
41 | 41 | obj-$(CONFIG_IDE_GENERIC) += ide-generic.o |
42 | 42 | |
43 | -ide-cd_mod-y += ide-cd.o ide-cd_verbose.o | |
43 | +ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o | |
44 | 44 | |
45 | 45 | obj-$(CONFIG_BLK_DEV_IDEDISK) += ide-disk.o |
46 | 46 | obj-$(CONFIG_BLK_DEV_IDECD) += ide-cd_mod.o |
drivers/ide/ide-cd.c
... | ... | @@ -206,7 +206,7 @@ |
206 | 206 | /* |
207 | 207 | * Initialize a ide-cd packet command request |
208 | 208 | */ |
209 | -static void ide_cd_init_rq(ide_drive_t *drive, struct request *rq) | |
209 | +void ide_cd_init_rq(ide_drive_t *drive, struct request *rq) | |
210 | 210 | { |
211 | 211 | struct cdrom_info *cd = drive->driver_data; |
212 | 212 | |
... | ... | @@ -1168,7 +1168,7 @@ |
1168 | 1168 | return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation); |
1169 | 1169 | } |
1170 | 1170 | |
1171 | -static int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) | |
1171 | +int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq) | |
1172 | 1172 | { |
1173 | 1173 | struct request_sense sense; |
1174 | 1174 | int retries = 10; |
... | ... | @@ -1685,8 +1685,8 @@ |
1685 | 1685 | } |
1686 | 1686 | |
1687 | 1687 | /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ |
1688 | -static int ide_cd_lockdoor(ide_drive_t *drive, int lockflag, | |
1689 | - struct request_sense *sense) | |
1688 | +int ide_cd_lockdoor(ide_drive_t *drive, int lockflag, | |
1689 | + struct request_sense *sense) | |
1690 | 1690 | { |
1691 | 1691 | struct cdrom_info *cd = drive->driver_data; |
1692 | 1692 | struct request_sense my_sense; |
1693 | 1693 | |
... | ... | @@ -1817,9 +1817,8 @@ |
1817 | 1817 | return ide_cd_queue_pc(drive, &req); |
1818 | 1818 | } |
1819 | 1819 | |
1820 | - | |
1821 | 1820 | /* Try to read the entire TOC for the disk into our internal buffer. */ |
1822 | -static int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) | |
1821 | +int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) | |
1823 | 1822 | { |
1824 | 1823 | int stat, ntracks, i; |
1825 | 1824 | struct cdrom_info *info = drive->driver_data; |
... | ... | @@ -1979,112 +1978,6 @@ |
1979 | 1978 | return 0; |
1980 | 1979 | } |
1981 | 1980 | |
1982 | -static 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 | - | |
2001 | -static 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 | - | |
2030 | -static 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 | - | |
2053 | -static 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 | 1981 | /* the generic packet interface to cdrom.c */ |
2089 | 1982 | static int ide_cdrom_packet(struct cdrom_device_info *cdi, |
2090 | 1983 | struct packet_command *cgc) |
2091 | 1984 | |
... | ... | @@ -2116,53 +2009,7 @@ |
2116 | 2009 | return cgc->stat; |
2117 | 2010 | } |
2118 | 2011 | |
2119 | -static 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 | - | |
2140 | 2012 | static |
2141 | -int 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 | - | |
2165 | -static | |
2166 | 2013 | int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position) |
2167 | 2014 | { |
2168 | 2015 | ide_drive_t *drive = cdi->handle; |
2169 | 2016 | |
... | ... | @@ -2178,16 +2025,8 @@ |
2178 | 2025 | return cdrom_eject(drive, !position, &sense); |
2179 | 2026 | } |
2180 | 2027 | |
2181 | -static | |
2182 | -int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock) | |
2028 | +int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf) | |
2183 | 2029 | { |
2184 | - ide_drive_t *drive = cdi->handle; | |
2185 | - | |
2186 | - return ide_cd_lockdoor(drive, lock, NULL); | |
2187 | -} | |
2188 | - | |
2189 | -static int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf) | |
2190 | -{ | |
2191 | 2030 | struct cdrom_info *info = drive->driver_data; |
2192 | 2031 | struct cdrom_device_info *cdi = &info->devinfo; |
2193 | 2032 | struct packet_command cgc; |
... | ... | @@ -2205,7 +2044,7 @@ |
2205 | 2044 | return stat; |
2206 | 2045 | } |
2207 | 2046 | |
2208 | -static void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf) | |
2047 | +void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf) | |
2209 | 2048 | { |
2210 | 2049 | struct cdrom_info *cd = drive->driver_data; |
2211 | 2050 | u16 curspeed, maxspeed; |
... | ... | @@ -2226,49 +2065,6 @@ |
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 | - */ | |
2232 | -static 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 | 2068 | * add logic to try GET_EVENT command first to check for media and tray |
2273 | 2069 | * status. this should be supported by newer cd-r/w and all DVD etc |
2274 | 2070 | * drives |
... | ... | @@ -2312,59 +2108,6 @@ |
2312 | 2108 | return CDS_TRAY_OPEN; |
2313 | 2109 | } |
2314 | 2110 | return CDS_DRIVE_NOT_READY; |
2315 | -} | |
2316 | - | |
2317 | -static | |
2318 | -int 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 | - | |
2340 | -static 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 | 2111 | } |
2369 | 2112 | |
2370 | 2113 | /**************************************************************************** |
drivers/ide/ide-cd.h
... | ... | @@ -148,5 +148,22 @@ |
148 | 148 | /* ide-cd_verbose.c */ |
149 | 149 | void ide_cd_log_error(const char *, struct request *, struct request_sense *); |
150 | 150 | |
151 | +/* ide-cd.c functions used by ide-cd_ioctl.c */ | |
152 | +void ide_cd_init_rq(ide_drive_t *, struct request *); | |
153 | +int ide_cd_queue_pc(ide_drive_t *, struct request *); | |
154 | +int ide_cd_lockdoor(ide_drive_t *, int, struct request_sense *); | |
155 | +int ide_cd_read_toc(ide_drive_t *, struct request_sense *); | |
156 | +int ide_cdrom_get_capabilities(ide_drive_t *, u8 *); | |
157 | +void ide_cdrom_update_speed(ide_drive_t *, u8 *); | |
158 | + | |
159 | +/* ide-cd_ioctl.c */ | |
160 | +int ide_cdrom_lock_door(struct cdrom_device_info *, int); | |
161 | +int ide_cdrom_select_speed(struct cdrom_device_info *, int); | |
162 | +int ide_cdrom_get_last_session(struct cdrom_device_info *, | |
163 | + struct cdrom_multisession *); | |
164 | +int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); | |
165 | +int ide_cdrom_reset(struct cdrom_device_info *cdi); | |
166 | +int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); | |
167 | + | |
151 | 168 | #endif /* _IDE_CD_H */ |
drivers/ide/ide-cd_ioctl.c
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 | + | |
15 | +int 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 | + */ | |
26 | +int 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 | + | |
65 | +int 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 | + | |
87 | +int 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 | + | |
117 | +int 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 | + | |
140 | +static 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 | + | |
169 | +static 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 | + | |
204 | +static 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 | + | |
223 | +static 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 | + | |
246 | +int 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 | +} |