Commit 17802998d2c8007d06565c39101d218f579c4454

Authored by Bartlomiej Zolnierkiewicz
1 parent 139c829d9d

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 +}