mcdx.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:49k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * The Mitsumi CDROM interface
  3.  * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
  4.  * VERSION: 2.14(hs)
  5.  *
  6.  * ... anyway, I'm back again, thanks to Marcin, he adopted
  7.  * large portions of my code (at least the parts containing
  8.  * my main thoughts ...)
  9.  *
  10.  ****************** H E L P *********************************
  11.  * If you ever plan to update your CD ROM drive and perhaps
  12.  * want to sell or simply give away your Mitsumi FX-001[DS]
  13.  * -- Please --
  14.  * mail me (heiko@lotte.sax.de).  When my last drive goes
  15.  * ballistic no more driver support will be available from me!
  16.  *************************************************************
  17.  *
  18.  * This program is free software; you can redistribute it and/or modify
  19.  * it under the terms of the GNU General Public License as published by
  20.  * the Free Software Foundation; either version 2, or (at your option)
  21.  * any later version.
  22.  *
  23.  * This program is distributed in the hope that it will be useful,
  24.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  26.  * GNU General Public License for more details.
  27.  *
  28.  * You should have received a copy of the GNU General Public License
  29.  * along with this program; see the file COPYING.  If not, write to
  30.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  31.  *
  32.  * Thanks to
  33.  *  The Linux Community at all and ...
  34.  *  Martin Harriss (he wrote the first Mitsumi Driver)
  35.  *  Eberhard Moenkeberg (he gave me much support and the initial kick)
  36.  *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
  37.  *      improved the original driver)
  38.  *  Jon Tombs, Bjorn Ekwall (module support)
  39.  *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
  40.  *  Gerd Knorr (he lent me his PhotoCD)
  41.  *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
  42.  *  Andreas Kies (testing the mysterious hang-ups)
  43.  *  Heiko Eissfeldt (VERIFY_READ/WRITE)
  44.  *  Marcin Dalecki (improved performance, shortened code)
  45.  *  ... somebody forgotten?
  46.  *
  47.  *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
  48.  *                Removed init_module & cleanup_module in favor of 
  49.  *        module_init & module_exit.
  50.  *        Torben Mathiasen <tmm@image.dk>
  51.  */
  52. #if RCS
  53. static const char *mcdx_c_version
  54.     = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
  55. #endif
  56. #include <linux/version.h>
  57. #include <linux/module.h>
  58. #include <linux/errno.h>
  59. #include <linux/sched.h>
  60. #include <linux/fs.h>
  61. #include <linux/kernel.h>
  62. #include <linux/cdrom.h>
  63. #include <linux/ioport.h>
  64. #include <linux/mm.h>
  65. #include <linux/slab.h>
  66. #include <linux/init.h>
  67. #include <asm/io.h>
  68. #include <asm/uaccess.h>
  69. #include <linux/major.h>
  70. #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
  71. #include <linux/blk.h>
  72. #include <linux/devfs_fs_kernel.h>
  73. /* for compatible parameter passing with "insmod" */
  74. #define mcdx_drive_map mcdx
  75. #include "mcdx.h"
  76. #if BITS_PER_LONG != 32
  77. #  error FIXME: this driver only works on 32-bit platforms
  78. #endif
  79. #ifndef HZ
  80. #error HZ not defined
  81. #endif
  82. #define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
  83. #if !MCDX_QUIET
  84. #define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
  85. #else
  86. #define xinfo(fmt, args...) { ; }
  87. #endif
  88. #if MCDX_DEBUG
  89. #define xtrace(lvl, fmt, args...) 
  90. { if (lvl > 0) 
  91. { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
  92. #define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
  93. #else
  94. #define xtrace(lvl, fmt, args...) { ; }
  95. #define xdebug(fmt, args...) { ; }
  96. #endif
  97. /* CONSTANTS *******************************************************/
  98. /* Following are the number of sectors we _request_ from the drive
  99.    every time an access outside the already requested range is done.
  100.    The _direct_ size is the number of sectors we're allowed to skip
  101.    directly (performing a read instead of requesting the new sector
  102.    needed */
  103. const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
  104. const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
  105. enum drivemodes { TOC, DATA, RAW, COOKED };
  106. enum datamodes { MODE0, MODE1, MODE2 };
  107. enum resetmodes { SOFT, HARD };
  108. const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */
  109. const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */
  110. const int DOOR = 0x04; /* door locking capability */
  111. const int MULTI = 0x08; /* multi session capability */
  112. const unsigned char READ1X = 0xc0;
  113. const unsigned char READ2X = 0xc1;
  114. /* DECLARATIONS ****************************************************/
  115. struct s_subqcode {
  116. unsigned char control;
  117. unsigned char tno;
  118. unsigned char index;
  119. struct cdrom_msf0 tt;
  120. struct cdrom_msf0 dt;
  121. };
  122. struct s_diskinfo {
  123. unsigned int n_first;
  124. unsigned int n_last;
  125. struct cdrom_msf0 msf_leadout;
  126. struct cdrom_msf0 msf_first;
  127. };
  128. struct s_multi {
  129. unsigned char multi;
  130. struct cdrom_msf0 msf_last;
  131. };
  132. struct s_version {
  133. unsigned char code;
  134. unsigned char ver;
  135. };
  136. /* Per drive/controller stuff **************************************/
  137. struct s_drive_stuff {
  138. /* waitqueues */
  139. wait_queue_head_t busyq;
  140. wait_queue_head_t lockq;
  141. wait_queue_head_t sleepq;
  142. /* flags */
  143. volatile int introk; /* status of last irq operation */
  144. volatile int busy; /* drive performs an operation */
  145. volatile int lock; /* exclusive usage */
  146. /* cd infos */
  147. struct s_diskinfo di;
  148. struct s_multi multi;
  149. struct s_subqcode *toc; /* first entry of the toc array */
  150. struct s_subqcode start;
  151. struct s_subqcode stop;
  152. int xa; /* 1 if xa disk */
  153. int audio; /* 1 if audio disk */
  154. int audiostatus;
  155. /* `buffer' control */
  156. volatile int valid; /* pending, ..., values are valid */
  157. volatile int pending; /* next sector to be read */
  158. volatile int low_border; /* first sector not to be skipped direct */
  159. volatile int high_border; /* first sector `out of area' */
  160. #ifdef AK2
  161. volatile int int_err;
  162. #endif /* AK2 */
  163. /* adds and odds */
  164. void *wreg_data; /* w data */
  165. void *wreg_reset; /* w hardware reset */
  166. void *wreg_hcon; /* w hardware conf */
  167. void *wreg_chn; /* w channel */
  168. void *rreg_data; /* r data */
  169. void *rreg_status; /* r status */
  170. int irq; /* irq used by this drive */
  171. int minor; /* minor number of this drive */
  172. int present; /* drive present and its capabilities */
  173. unsigned char readcmd; /* read cmd depends on single/double speed */
  174. unsigned char playcmd; /* play should always be single speed */
  175. unsigned int xxx; /* set if changed, reset while open */
  176. unsigned int yyy; /* set if changed, reset by media_changed */
  177. int users; /* keeps track of open/close */
  178. int lastsector; /* last block accessible */
  179. int status; /* last operation's error / status */
  180. int readerrs; /* # of blocks read w/o error */
  181. };
  182. /* Prototypes ******************************************************/
  183. /* The following prototypes are already declared elsewhere.  They are
  184.   repeated here to show what's going on.  And to sense, if they're
  185. changed elsewhere. */
  186. /* declared in blk.h */
  187. int mcdx_init(void);
  188. void do_mcdx_request(request_queue_t * q);
  189. struct block_device_operations mcdx_bdops =
  190. {
  191. owner: THIS_MODULE,
  192. open: cdrom_open,
  193. release: cdrom_release,
  194. ioctl: cdrom_ioctl,
  195. check_media_change: cdrom_media_changed,
  196. };
  197. /* Indirect exported functions. These functions are exported by their
  198. addresses, such as mcdx_open and mcdx_close in the
  199. structure mcdx_dops. */
  200. /* ???  exported by the mcdx_sigaction struct */
  201. static void mcdx_intr(int, void *, struct pt_regs *);
  202. /* exported by file_ops */
  203. static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
  204. static void mcdx_close(struct cdrom_device_info *cdi);
  205. static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
  206. static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
  207. static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
  208. static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
  209.     unsigned int cmd, void *arg);
  210. /* misc internal support functions */
  211. static void log2msf(unsigned int, struct cdrom_msf0 *);
  212. static unsigned int msf2log(const struct cdrom_msf0 *);
  213. static unsigned int uint2bcd(unsigned int);
  214. static unsigned int bcd2uint(unsigned char);
  215. static char *port(int *);
  216. static int irq(int *);
  217. static void mcdx_delay(struct s_drive_stuff *, long jifs);
  218. static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
  219.  int nr_sectors);
  220. static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
  221.      int nr_sectors);
  222. static int mcdx_config(struct s_drive_stuff *, int);
  223. static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
  224.        int);
  225. static int mcdx_stop(struct s_drive_stuff *, int);
  226. static int mcdx_hold(struct s_drive_stuff *, int);
  227. static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
  228. static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
  229. static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
  230. static int mcdx_requestsubqcode(struct s_drive_stuff *,
  231. struct s_subqcode *, int);
  232. static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
  233.      struct s_multi *, int);
  234. static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
  235.        int);
  236. static int mcdx_getstatus(struct s_drive_stuff *, int);
  237. static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
  238. static int mcdx_talk(struct s_drive_stuff *,
  239.      const unsigned char *cmd, size_t,
  240.      void *buffer, size_t size, unsigned int timeout, int);
  241. static int mcdx_readtoc(struct s_drive_stuff *);
  242. static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
  243. static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
  244. static int mcdx_setattentuator(struct s_drive_stuff *,
  245.        struct cdrom_volctrl *, int);
  246. /* static variables ************************************************/
  247. static int mcdx_blocksizes[MCDX_NDRIVES];
  248. static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
  249. static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
  250. static struct s_drive_stuff *mcdx_irq_map[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
  251. 0, 0, 0, 0, 0, 0, 0, 0
  252. };
  253. MODULE_PARM(mcdx, "1-4i");
  254. static struct cdrom_device_ops mcdx_dops = {
  255. open:mcdx_open,
  256. release:mcdx_close,
  257. media_changed:mcdx_media_changed,
  258. tray_move:mcdx_tray_move,
  259. lock_door:mcdx_lockdoor,
  260. audio_ioctl:mcdx_audio_ioctl,
  261. capability:CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
  262.     CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
  263. };
  264. static struct cdrom_device_info mcdx_info = {
  265. ops:&mcdx_dops,
  266. speed:2,
  267. capacity:1,
  268. name:"mcdx",
  269. };
  270. /* KERNEL INTERFACE FUNCTIONS **************************************/
  271. static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
  272.     unsigned int cmd, void *arg)
  273. {
  274. struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  275. if (!stuffp->present)
  276. return -ENXIO;
  277. if (stuffp->xxx) {
  278. if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
  279. stuffp->lastsector = -1;
  280. } else {
  281. stuffp->lastsector = (CD_FRAMESIZE / 512)
  282.     * msf2log(&stuffp->di.msf_leadout) - 1;
  283. }
  284. if (stuffp->toc) {
  285. kfree(stuffp->toc);
  286. stuffp->toc = NULL;
  287. if (-1 == mcdx_readtoc(stuffp))
  288. return -1;
  289. }
  290. stuffp->xxx = 0;
  291. }
  292. switch (cmd) {
  293. case CDROMSTART:{
  294. xtrace(IOCTL, "ioctl() STARTn");
  295. /* Spin up the drive.  Don't think we can do this.
  296.    * For now, ignore it.
  297.  */
  298. return 0;
  299. }
  300. case CDROMSTOP:{
  301. xtrace(IOCTL, "ioctl() STOPn");
  302. stuffp->audiostatus = CDROM_AUDIO_INVALID;
  303. if (-1 == mcdx_stop(stuffp, 1))
  304. return -EIO;
  305. return 0;
  306. }
  307. case CDROMPLAYTRKIND:{
  308. struct cdrom_ti *ti = (struct cdrom_ti *) arg;
  309. xtrace(IOCTL, "ioctl() PLAYTRKINDn");
  310. if ((ti->cdti_trk0 < stuffp->di.n_first)
  311.     || (ti->cdti_trk0 > stuffp->di.n_last)
  312.     || (ti->cdti_trk1 < stuffp->di.n_first))
  313. return -EINVAL;
  314. if (ti->cdti_trk1 > stuffp->di.n_last)
  315. ti->cdti_trk1 = stuffp->di.n_last;
  316. xtrace(PLAYTRK, "ioctl() track %d to %dn",
  317.        ti->cdti_trk0, ti->cdti_trk1);
  318. return mcdx_playtrk(stuffp, ti);
  319. }
  320. case CDROMPLAYMSF:{
  321. struct cdrom_msf *msf = (struct cdrom_msf *) arg;
  322. xtrace(IOCTL, "ioctl() PLAYMSFn");
  323. if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
  324.     && (-1 == mcdx_hold(stuffp, 1)))
  325. return -EIO;
  326. msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
  327. msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
  328. msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
  329. msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
  330. msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
  331. msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
  332. stuffp->stop.dt.minute = msf->cdmsf_min1;
  333. stuffp->stop.dt.second = msf->cdmsf_sec1;
  334. stuffp->stop.dt.frame = msf->cdmsf_frame1;
  335. return mcdx_playmsf(stuffp, msf);
  336. }
  337. case CDROMRESUME:{
  338. xtrace(IOCTL, "ioctl() RESUMEn");
  339. return mcdx_playtrk(stuffp, NULL);
  340. }
  341. case CDROMREADTOCENTRY:{
  342. struct cdrom_tocentry *entry =
  343.     (struct cdrom_tocentry *) arg;
  344. struct s_subqcode *tp = NULL;
  345. xtrace(IOCTL, "ioctl() READTOCENTRYn");
  346. if (-1 == mcdx_readtoc(stuffp))
  347. return -1;
  348. if (entry->cdte_track == CDROM_LEADOUT)
  349. tp = &stuffp->toc[stuffp->di.n_last -
  350.   stuffp->di.n_first + 1];
  351. else if (entry->cdte_track > stuffp->di.n_last
  352.  || entry->cdte_track < stuffp->di.n_first)
  353. return -EINVAL;
  354. else
  355. tp = &stuffp->toc[entry->cdte_track -
  356.   stuffp->di.n_first];
  357. if (NULL == tp)
  358. return -EIO;
  359. entry->cdte_adr = tp->control;
  360. entry->cdte_ctrl = tp->control >> 4;
  361. /* Always return stuff in MSF, and let the Uniform cdrom driver
  362.    worry about what the user actually wants */
  363. entry->cdte_addr.msf.minute =
  364.     bcd2uint(tp->dt.minute);
  365. entry->cdte_addr.msf.second =
  366.     bcd2uint(tp->dt.second);
  367. entry->cdte_addr.msf.frame =
  368.     bcd2uint(tp->dt.frame);
  369. return 0;
  370. }
  371. case CDROMSUBCHNL:{
  372. struct cdrom_subchnl *sub =
  373.     (struct cdrom_subchnl *) arg;
  374. struct s_subqcode q;
  375. xtrace(IOCTL, "ioctl() SUBCHNLn");
  376. if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
  377. return -EIO;
  378. xtrace(SUBCHNL, "audiostatus: %xn",
  379.        stuffp->audiostatus);
  380. sub->cdsc_audiostatus = stuffp->audiostatus;
  381. sub->cdsc_adr = q.control;
  382. sub->cdsc_ctrl = q.control >> 4;
  383. sub->cdsc_trk = bcd2uint(q.tno);
  384. sub->cdsc_ind = bcd2uint(q.index);
  385. xtrace(SUBCHNL, "trk %d, ind %dn",
  386.        sub->cdsc_trk, sub->cdsc_ind);
  387. /* Always return stuff in MSF, and let the Uniform cdrom driver
  388.    worry about what the user actually wants */
  389. sub->cdsc_absaddr.msf.minute =
  390.     bcd2uint(q.dt.minute);
  391. sub->cdsc_absaddr.msf.second =
  392.     bcd2uint(q.dt.second);
  393. sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
  394. sub->cdsc_reladdr.msf.minute =
  395.     bcd2uint(q.tt.minute);
  396. sub->cdsc_reladdr.msf.second =
  397.     bcd2uint(q.tt.second);
  398. sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
  399. xtrace(SUBCHNL,
  400.        "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02dn",
  401.        sub->cdsc_absaddr.msf.minute,
  402.        sub->cdsc_absaddr.msf.second,
  403.        sub->cdsc_absaddr.msf.frame,
  404.        sub->cdsc_reladdr.msf.minute,
  405.        sub->cdsc_reladdr.msf.second,
  406.        sub->cdsc_reladdr.msf.frame);
  407. return 0;
  408. }
  409. case CDROMREADTOCHDR:{
  410. struct cdrom_tochdr *toc =
  411.     (struct cdrom_tochdr *) arg;
  412. xtrace(IOCTL, "ioctl() READTOCHDRn");
  413. toc->cdth_trk0 = stuffp->di.n_first;
  414. toc->cdth_trk1 = stuffp->di.n_last;
  415. xtrace(TOCHDR,
  416.        "ioctl() track0 = %d, track1 = %dn",
  417.        stuffp->di.n_first, stuffp->di.n_last);
  418. return 0;
  419. }
  420. case CDROMPAUSE:{
  421. xtrace(IOCTL, "ioctl() PAUSEn");
  422. if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
  423. return -EINVAL;
  424. if (-1 == mcdx_stop(stuffp, 1))
  425. return -EIO;
  426. stuffp->audiostatus = CDROM_AUDIO_PAUSED;
  427. if (-1 ==
  428.     mcdx_requestsubqcode(stuffp, &stuffp->start,
  429.  1))
  430. return -EIO;
  431. return 0;
  432. }
  433. case CDROMMULTISESSION:{
  434. struct cdrom_multisession *ms =
  435.     (struct cdrom_multisession *) arg;
  436. xtrace(IOCTL, "ioctl() MULTISESSIONn");
  437. /* Always return stuff in LBA, and let the Uniform cdrom driver
  438.    worry about what the user actually wants */
  439. ms->addr.lba = msf2log(&stuffp->multi.msf_last);
  440. ms->xa_flag = !!stuffp->multi.multi;
  441. xtrace(MS,
  442.        "ioctl() (%d, 0x%08x [%02x:%02x.%02x])n",
  443.        ms->xa_flag, ms->addr.lba,
  444.        stuffp->multi.msf_last.minute,
  445.        stuffp->multi.msf_last.second,
  446.        stuffp->multi.msf_last.frame);
  447. return 0;
  448. }
  449. case CDROMEJECT:{
  450. xtrace(IOCTL, "ioctl() EJECTn");
  451. if (stuffp->users > 1)
  452. return -EBUSY;
  453. return (mcdx_tray_move(cdi, 1));
  454. }
  455. case CDROMCLOSETRAY:{
  456. xtrace(IOCTL, "ioctl() CDROMCLOSETRAYn");
  457. return (mcdx_tray_move(cdi, 0));
  458. }
  459. case CDROMVOLCTRL:{
  460. struct cdrom_volctrl *volctrl =
  461.     (struct cdrom_volctrl *) arg;
  462. xtrace(IOCTL, "ioctl() VOLCTRLn");
  463. #if 0 /* not tested! */
  464. /* adjust for the weirdness of workman (md) */
  465. /* can't test it (hs) */
  466. volctrl.channel2 = volctrl.channel1;
  467. volctrl.channel1 = volctrl.channel3 = 0x00;
  468. #endif
  469. return mcdx_setattentuator(stuffp, volctrl, 2);
  470. }
  471. default:
  472. return -EINVAL;
  473. }
  474. }
  475. void do_mcdx_request(request_queue_t * q)
  476. {
  477. int dev;
  478. struct s_drive_stuff *stuffp;
  479.       again:
  480. if (QUEUE_EMPTY) {
  481. xtrace(REQUEST, "end_request(0): CURRENT == NULLn");
  482. return;
  483. }
  484. if (CURRENT->rq_status == RQ_INACTIVE) {
  485. xtrace(REQUEST,
  486.        "end_request(0): rq_status == RQ_INACTIVEn");
  487. return;
  488. }
  489. INIT_REQUEST;
  490. dev = MINOR(CURRENT->rq_dev);
  491. stuffp = mcdx_stuffp[dev];
  492. if ((dev < 0)
  493.     || (dev >= MCDX_NDRIVES)
  494.     || !stuffp || (!stuffp->present)) {
  495. xwarn("do_request(): bad device: %sn",
  496.       kdevname(CURRENT->rq_dev));
  497. xtrace(REQUEST, "end_request(0): bad devicen");
  498. end_request(0);
  499. return;
  500. }
  501. if (stuffp->audio) {
  502. xwarn("do_request() attempt to read from audio cdn");
  503. xtrace(REQUEST, "end_request(0): read from audion");
  504. end_request(0);
  505. return;
  506. }
  507. xtrace(REQUEST, "do_request() (%lu + %lu)n",
  508.        CURRENT->sector, CURRENT->nr_sectors);
  509. switch (CURRENT->cmd) {
  510. case WRITE:
  511. xwarn("do_request(): attempt to write to cd!!n");
  512. xtrace(REQUEST, "end_request(0): writen");
  513. end_request(0);
  514. return;
  515. case READ:
  516. stuffp->status = 0;
  517. while (CURRENT->nr_sectors) {
  518. int i;
  519. i = mcdx_transfer(stuffp,
  520.   CURRENT->buffer,
  521.   CURRENT->sector,
  522.   CURRENT->nr_sectors);
  523. if (i == -1) {
  524. end_request(0);
  525. goto again;
  526. }
  527. CURRENT->sector += i;
  528. CURRENT->nr_sectors -= i;
  529. CURRENT->buffer += (i * 512);
  530. }
  531. end_request(1);
  532. goto again;
  533. xtrace(REQUEST, "end_request(1)n");
  534. end_request(1);
  535. break;
  536. default:
  537. panic(MCDX "do_request: unknown command.n");
  538. break;
  539. }
  540. goto again;
  541. }
  542. static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
  543. {
  544. struct s_drive_stuff *stuffp;
  545. xtrace(OPENCLOSE, "open()n");
  546. stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  547. if (!stuffp->present)
  548. return -ENXIO;
  549. /* Make the modules looking used ... (thanx bjorn).
  550.  * But we shouldn't forget to decrement the module counter
  551.  * on error return */
  552. /* this is only done to test if the drive talks with us */
  553. if (-1 == mcdx_getstatus(stuffp, 1))
  554. return -EIO;
  555. if (stuffp->xxx) {
  556. xtrace(OPENCLOSE, "open() media changedn");
  557. stuffp->audiostatus = CDROM_AUDIO_INVALID;
  558. stuffp->readcmd = 0;
  559. xtrace(OPENCLOSE, "open() Request multisession infon");
  560. if (-1 ==
  561.     mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
  562. xinfo("No multidiskinfon");
  563. } else {
  564. /* multisession ? */
  565. if (!stuffp->multi.multi)
  566. stuffp->multi.msf_last.second = 2;
  567. xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02xn",
  568.        stuffp->multi.multi,
  569.        stuffp->multi.msf_last.minute,
  570.        stuffp->multi.msf_last.second,
  571.        stuffp->multi.msf_last.frame);
  572. {;
  573. } /* got multisession information */
  574. /* request the disks table of contents (aka diskinfo) */
  575. if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
  576. stuffp->lastsector = -1;
  577. } else {
  578. stuffp->lastsector = (CD_FRAMESIZE / 512)
  579.     * msf2log(&stuffp->di.msf_leadout) - 1;
  580. xtrace(OPENCLOSE,
  581.        "open() start %d (%02x:%02x.%02x) %dn",
  582.        stuffp->di.n_first,
  583.        stuffp->di.msf_first.minute,
  584.        stuffp->di.msf_first.second,
  585.        stuffp->di.msf_first.frame,
  586.        msf2log(&stuffp->di.msf_first));
  587. xtrace(OPENCLOSE,
  588.        "open() last %d (%02x:%02x.%02x) %dn",
  589.        stuffp->di.n_last,
  590.        stuffp->di.msf_leadout.minute,
  591.        stuffp->di.msf_leadout.second,
  592.        stuffp->di.msf_leadout.frame,
  593.        msf2log(&stuffp->di.msf_leadout));
  594. }
  595. if (stuffp->toc) {
  596. xtrace(MALLOC, "open() free old toc @ %pn",
  597.        stuffp->toc);
  598. kfree(stuffp->toc);
  599. stuffp->toc = NULL;
  600. }
  601. xtrace(OPENCLOSE, "open() init irq generationn");
  602. if (-1 == mcdx_config(stuffp, 1))
  603. return -EIO;
  604. #if FALLBACK
  605. /* Set the read speed */
  606. xwarn("AAA %x AAAn", stuffp->readcmd);
  607. if (stuffp->readerrs)
  608. stuffp->readcmd = READ1X;
  609. else
  610. stuffp->readcmd =
  611.     stuffp->present | SINGLE ? READ1X : READ2X;
  612. xwarn("XXX %x XXXn", stuffp->readcmd);
  613. #else
  614. stuffp->readcmd =
  615.     stuffp->present | SINGLE ? READ1X : READ2X;
  616. #endif
  617. /* try to get the first sector, iff any ... */
  618. if (stuffp->lastsector >= 0) {
  619. char buf[512];
  620. int ans;
  621. int tries;
  622. stuffp->xa = 0;
  623. stuffp->audio = 0;
  624. for (tries = 6; tries; tries--) {
  625. stuffp->introk = 1;
  626. xtrace(OPENCLOSE, "open() try as %sn",
  627.        stuffp->xa ? "XA" : "normal");
  628. /* set data mode */
  629. if (-1 == (ans = mcdx_setdatamode(stuffp,
  630.   stuffp->
  631.   xa ?
  632.   MODE2 :
  633.   MODE1,
  634.   1))) {
  635. /* return -EIO; */
  636. stuffp->xa = 0;
  637. break;
  638. }
  639. if ((stuffp->audio = e_audio(ans)))
  640. break;
  641. while (0 ==
  642.        (ans =
  643. mcdx_transfer(stuffp, buf, 0, 1)));
  644. if (ans == 1)
  645. break;
  646. stuffp->xa = !stuffp->xa;
  647. }
  648. }
  649. /* xa disks will be read in raw mode, others not */
  650. if (-1 == mcdx_setdrivemode(stuffp,
  651.     stuffp->xa ? RAW : COOKED,
  652.     1))
  653. return -EIO;
  654. if (stuffp->audio) {
  655. xinfo("open() audio disk foundn");
  656. } else if (stuffp->lastsector >= 0) {
  657. xinfo("open() %s%s disk foundn",
  658.       stuffp->xa ? "XA / " : "",
  659.       stuffp->multi.
  660.       multi ? "Multi Session" : "Single Session");
  661. }
  662. }
  663. stuffp->xxx = 0;
  664. stuffp->users++;
  665. return 0;
  666. }
  667. static void mcdx_close(struct cdrom_device_info *cdi)
  668. {
  669. struct s_drive_stuff *stuffp;
  670. xtrace(OPENCLOSE, "close()n");
  671. stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  672. --stuffp->users;
  673. }
  674. static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
  675. /* Return: 1 if media changed since last call to this function
  676. 0 otherwise */
  677. {
  678. struct s_drive_stuff *stuffp;
  679. xinfo("mcdx_media_changed called for device %sn",
  680.       kdevname(cdi->dev));
  681. stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  682. mcdx_getstatus(stuffp, 1);
  683. if (stuffp->yyy == 0)
  684. return 0;
  685. stuffp->yyy = 0;
  686. return 1;
  687. }
  688. #ifndef MODULE
  689. static int __init mcdx_setup(char *str)
  690. {
  691. int pi[4];
  692. (void) get_options(str, ARRAY_SIZE(pi), pi);
  693. if (pi[0] > 0)
  694. mcdx_drive_map[0][0] = pi[1];
  695. if (pi[0] > 1)
  696. mcdx_drive_map[0][1] = pi[2];
  697. return 1;
  698. }
  699. __setup("mcdx=", mcdx_setup);
  700. #endif
  701. /* DIRTY PART ******************************************************/
  702. static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
  703. /* This routine is used for sleeping.
  704.  * A jifs value <0 means NO sleeping,
  705.  *              =0 means minimal sleeping (let the kernel
  706.  *                 run for other processes)
  707.  *              >0 means at least sleep for that amount.
  708.  * May be we could use a simple count loop w/ jumps to itself, but
  709.  * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
  710. {
  711. if (jifs < 0)
  712. return;
  713. xtrace(SLEEP, "*** delay: sleepqn");
  714. interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
  715. xtrace(SLEEP, "delay awokenn");
  716. if (signal_pending(current)) {
  717. xtrace(SLEEP, "got signaln");
  718. }
  719. }
  720. static void mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
  721. {
  722. struct s_drive_stuff *stuffp;
  723. unsigned char b;
  724. stuffp = mcdx_irq_map[irq];
  725. if (stuffp == NULL) {
  726. xwarn("mcdx: no device for intr %dn", irq);
  727. return;
  728. }
  729. #ifdef AK2
  730. if (!stuffp->busy && stuffp->pending)
  731. stuffp->int_err = 1;
  732. #endif /* AK2 */
  733. /* get the interrupt status */
  734. b = inb((unsigned int) stuffp->rreg_status);
  735. stuffp->introk = ~b & MCDX_RBIT_DTEN;
  736. /* NOTE: We only should get interrupts if the data we
  737.  * requested are ready to transfer.
  738.  * But the drive seems to generate ``asynchronous'' interrupts
  739.  * on several error conditions too.  (Despite the err int enable
  740.  * setting during initialisation) */
  741. /* if not ok, read the next byte as the drives status */
  742. if (!stuffp->introk) {
  743. xtrace(IRQ, "intr() irq %d hw status 0x%02xn", irq, b);
  744. if (~b & MCDX_RBIT_STEN) {
  745. xinfo("intr() irq %d    status 0x%02xn",
  746.       irq, inb((unsigned int) stuffp->rreg_data));
  747. } else {
  748. xinfo("intr() irq %d ambiguous hw statusn", irq);
  749. }
  750. } else {
  751. xtrace(IRQ, "irq() irq %d ok, status %02xn", irq, b);
  752. }
  753. stuffp->busy = 0;
  754. wake_up_interruptible(&stuffp->busyq);
  755. }
  756. static int mcdx_talk(struct s_drive_stuff *stuffp,
  757.   const unsigned char *cmd, size_t cmdlen,
  758.   void *buffer, size_t size, unsigned int timeout, int tries)
  759. /* Send a command to the drive, wait for the result.
  760.  * returns -1 on timeout, drive status otherwise
  761.  * If buffer is not zero, the result (length size) is stored there.
  762.  * If buffer is zero the size should be the number of bytes to read
  763.  * from the drive.  These bytes are discarded.
  764.  */
  765. {
  766. int st;
  767. char c;
  768. int discard;
  769. /* Somebody wants the data read? */
  770. if ((discard = (buffer == NULL)))
  771. buffer = &c;
  772. while (stuffp->lock) {
  773. xtrace(SLEEP, "*** talk: lockqn");
  774. interruptible_sleep_on(&stuffp->lockq);
  775. xtrace(SLEEP, "talk: awokenn");
  776. }
  777. stuffp->lock = 1;
  778. /* An operation other then reading data destroys the
  779.    * data already requested and remembered in stuffp->request, ... */
  780. stuffp->valid = 0;
  781. #if MCDX_DEBUG & TALK
  782. {
  783. unsigned char i;
  784. xtrace(TALK,
  785.        "talk() %d / %d tries, res.size %d, command 0x%02x",
  786.        tries, timeout, size, (unsigned char) cmd[0]);
  787. for (i = 1; i < cmdlen; i++)
  788. xtrace(TALK, " 0x%02x", cmd[i]);
  789. xtrace(TALK, "n");
  790. }
  791. #endif
  792. /*  give up if all tries are done (bad) or if the status
  793.  *  st != -1 (good) */
  794. for (st = -1; st == -1 && tries; tries--) {
  795. char *bp = (char *) buffer;
  796. size_t sz = size;
  797. outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen);
  798. xtrace(TALK, "talk() command sentn");
  799. /* get the status byte */
  800. if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
  801. xinfo("talk() %02x timed out (status), %d tr%s leftn",
  802.      cmd[0], tries - 1, tries == 2 ? "y" : "ies");
  803. continue;
  804. }
  805. st = *bp;
  806. sz--;
  807. if (!discard)
  808. bp++;
  809. xtrace(TALK, "talk() got status 0x%02xn", st);
  810. /* command error? */
  811. if (e_cmderr(st)) {
  812. xwarn("command error cmd = %02x %s n",
  813.       cmd[0], cmdlen > 1 ? "..." : "");
  814. st = -1;
  815. continue;
  816. }
  817. /* audio status? */
  818. if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
  819. stuffp->audiostatus =
  820.     e_audiobusy(st) ? CDROM_AUDIO_PLAY :
  821.     CDROM_AUDIO_NO_STATUS;
  822. else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
  823.  && e_audiobusy(st) == 0)
  824. stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
  825. /* media change? */
  826. if (e_changed(st)) {
  827. xinfo("talk() media changedn");
  828. stuffp->xxx = stuffp->yyy = 1;
  829. }
  830. /* now actually get the data */
  831. while (sz--) {
  832. if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
  833. xinfo("talk() %02x timed out (data), %d tr%s leftn",
  834.      cmd[0], tries - 1,
  835.      tries == 2 ? "y" : "ies");
  836. st = -1;
  837. break;
  838. }
  839. if (!discard)
  840. bp++;
  841. xtrace(TALK, "talk() got 0x%02xn", *(bp - 1));
  842. }
  843. }
  844. #if !MCDX_QUIET
  845. if (!tries && st == -1)
  846. xinfo("talk() giving upn");
  847. #endif
  848. stuffp->lock = 0;
  849. wake_up_interruptible(&stuffp->lockq);
  850. xtrace(TALK, "talk() done with 0x%02xn", st);
  851. return st;
  852. }
  853. /* MODULE STUFF ***********************************************************/
  854. EXPORT_NO_SYMBOLS;
  855. int __mcdx_init(void)
  856. {
  857. int i;
  858. int drives = 0;
  859. mcdx_init();
  860. for (i = 0; i < MCDX_NDRIVES; i++) {
  861. if (mcdx_stuffp[i]) {
  862. xtrace(INIT, "init_module() drive %d stuff @ %pn",
  863.        i, mcdx_stuffp[i]);
  864. drives++;
  865. }
  866. }
  867. if (!drives)
  868. return -EIO;
  869. return 0;
  870. }
  871. void __exit mcdx_exit(void)
  872. {
  873. int i;
  874. xinfo("cleanup_module calledn");
  875. for (i = 0; i < MCDX_NDRIVES; i++) {
  876. struct s_drive_stuff *stuffp;
  877. if (unregister_cdrom(&mcdx_info)) {
  878. printk(KERN_WARNING "Can't unregister cdrom mcdxn");
  879. return;
  880. }
  881. stuffp = mcdx_stuffp[i];
  882. if (!stuffp)
  883. continue;
  884. release_region((unsigned long) stuffp->wreg_data,
  885.        MCDX_IO_SIZE);
  886. free_irq(stuffp->irq, NULL);
  887. if (stuffp->toc) {
  888. xtrace(MALLOC, "cleanup_module() free toc @ %pn",
  889.        stuffp->toc);
  890. kfree(stuffp->toc);
  891. }
  892. xtrace(MALLOC, "cleanup_module() free stuffp @ %pn",
  893.        stuffp);
  894. mcdx_stuffp[i] = NULL;
  895. kfree(stuffp);
  896. }
  897. if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
  898. xwarn("cleanup() unregister_blkdev() failedn");
  899. }
  900. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  901. #if !MCDX_QUIET
  902. else
  903. xinfo("cleanup() succeededn");
  904. #endif
  905. }
  906. #ifdef MODULE
  907. module_init(__mcdx_init);
  908. #endif
  909. module_exit(mcdx_exit);
  910. /* Support functions ************************************************/
  911. int __init mcdx_init_drive(int drive)
  912. {
  913. struct s_version version;
  914. struct s_drive_stuff *stuffp;
  915. int size = sizeof(*stuffp);
  916. char msg[80];
  917. mcdx_blocksizes[drive] = 0;
  918. xtrace(INIT, "init() try drive %dn", drive);
  919. xtrace(INIT, "kmalloc space for stuffpt'sn");
  920. xtrace(MALLOC, "init() malloc %d bytesn", size);
  921. if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
  922. xwarn("init() malloc failedn");
  923. return 1;
  924. }
  925. xtrace(INIT, "init() got %d bytes for drive stuff @ %pn",
  926.        sizeof(*stuffp), stuffp);
  927. /* set default values */
  928. memset(stuffp, 0, sizeof(*stuffp));
  929. stuffp->present = 0; /* this should be 0 already */
  930. stuffp->toc = NULL; /* this should be NULL already */
  931. /* setup our irq and i/o addresses */
  932. stuffp->irq = irq(mcdx_drive_map[drive]);
  933. stuffp->wreg_data = stuffp->rreg_data =
  934.     port(mcdx_drive_map[drive]);
  935. stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
  936. stuffp->wreg_hcon = stuffp->wreg_reset + 1;
  937. stuffp->wreg_chn = stuffp->wreg_hcon + 1;
  938. init_waitqueue_head(&stuffp->busyq);
  939. init_waitqueue_head(&stuffp->lockq);
  940. init_waitqueue_head(&stuffp->sleepq);
  941. /* check if i/o addresses are available */
  942. if (check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
  943. xwarn("0x%3p,%d: Init failed. "
  944.       "I/O ports (0x%3p..0x%3p) already in use.n",
  945.       stuffp->wreg_data, stuffp->irq,
  946.       stuffp->wreg_data,
  947.       stuffp->wreg_data + MCDX_IO_SIZE - 1);
  948. xtrace(MALLOC, "init() free stuffp @ %pn", stuffp);
  949. kfree(stuffp);
  950. xtrace(INIT, "init() continue at next driven");
  951. return 0; /* next drive */
  952. }
  953. xtrace(INIT, "init() i/o port is available at 0x%3pn",
  954.        stuffp->wreg_data);
  955. xtrace(INIT, "init() hardware resetn");
  956. mcdx_reset(stuffp, HARD, 1);
  957. xtrace(INIT, "init() get versionn");
  958. if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
  959. /* failed, next drive */
  960. xwarn("%s=0x%3p,%d: Init failed. Can't get version.n",
  961.       MCDX, stuffp->wreg_data, stuffp->irq);
  962. xtrace(MALLOC, "init() free stuffp @ %pn", stuffp);
  963. kfree(stuffp);
  964. xtrace(INIT, "init() continue at next driven");
  965. return 0;
  966. }
  967. switch (version.code) {
  968. case 'D':
  969. stuffp->readcmd = READ2X;
  970. stuffp->present = DOUBLE | DOOR | MULTI;
  971. break;
  972. case 'F':
  973. stuffp->readcmd = READ1X;
  974. stuffp->present = SINGLE | DOOR | MULTI;
  975. break;
  976. case 'M':
  977. stuffp->readcmd = READ1X;
  978. stuffp->present = SINGLE;
  979. break;
  980. default:
  981. stuffp->present = 0;
  982. break;
  983. }
  984. stuffp->playcmd = READ1X;
  985. if (!stuffp->present) {
  986. xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.n",
  987.       MCDX, stuffp->wreg_data, stuffp->irq);
  988. kfree(stuffp);
  989. return 0; /* next drive */
  990. }
  991. xtrace(INIT, "init() register blkdevn");
  992. if (devfs_register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
  993. xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.n",
  994.       MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
  995. kfree(stuffp);
  996. return 1;
  997. }
  998. blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
  999. read_ahead[MAJOR_NR] = READ_AHEAD;
  1000. blksize_size[MAJOR_NR] = mcdx_blocksizes;
  1001. xtrace(INIT, "init() subscribe irq and i/on");
  1002. mcdx_irq_map[stuffp->irq] = stuffp;
  1003. if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
  1004. xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).n",
  1005.       MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
  1006. stuffp->irq = 0;
  1007. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  1008. kfree(stuffp);
  1009. return 0;
  1010. }
  1011. request_region((unsigned int) stuffp->wreg_data,
  1012.        MCDX_IO_SIZE, "mcdx");
  1013. xtrace(INIT, "init() get garbagen");
  1014. {
  1015. int i;
  1016. mcdx_delay(stuffp, HZ / 2);
  1017. for (i = 100; i; i--)
  1018. (void) inb((unsigned int) stuffp->rreg_status);
  1019. }
  1020. #if WE_KNOW_WHY
  1021. /* irq 11 -> channel register */
  1022. outb(0x50, (unsigned int) stuffp->wreg_chn);
  1023. #endif
  1024. xtrace(INIT, "init() set non dma but irq moden");
  1025. mcdx_config(stuffp, 1);
  1026. stuffp->minor = drive;
  1027. sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
  1028. " (Firmware version %c %x)n",
  1029. stuffp->wreg_data, stuffp->irq, version.code, version.ver);
  1030. mcdx_stuffp[drive] = stuffp;
  1031. xtrace(INIT, "init() mcdx_stuffp[%d] = %pn", drive, stuffp);
  1032. mcdx_info.dev = MKDEV(MAJOR_NR, 0);
  1033. if (register_cdrom(&mcdx_info) != 0) {
  1034. printk("Cannot register Mitsumi CD-ROM!n");
  1035. release_region((unsigned long) stuffp->wreg_data,
  1036.        MCDX_IO_SIZE);
  1037. free_irq(stuffp->irq, NULL);
  1038. kfree(stuffp);
  1039. if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0)
  1040. xwarn("cleanup() unregister_blkdev() failedn");
  1041. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  1042. return 2;
  1043. }
  1044. devfs_plain_cdrom(&mcdx_info, &mcdx_bdops);
  1045. printk(msg);
  1046. return 0;
  1047. }
  1048. int __init mcdx_init(void)
  1049. {
  1050. int drive;
  1051. #ifdef MODULE
  1052. xwarn("Version 2.14(hs) for " UTS_RELEASE "n");
  1053. #else
  1054. xwarn("Version 2.14(hs) n");
  1055. #endif
  1056. xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $n");
  1057. /* zero the pointer array */
  1058. for (drive = 0; drive < MCDX_NDRIVES; drive++)
  1059. mcdx_stuffp[drive] = NULL;
  1060. /* do the initialisation */
  1061. for (drive = 0; drive < MCDX_NDRIVES; drive++) {
  1062. switch (mcdx_init_drive(drive)) {
  1063. case 2:
  1064. return -EIO;
  1065. case 1:
  1066. break;
  1067. }
  1068. }
  1069. return 0;
  1070. }
  1071. static int mcdx_transfer(struct s_drive_stuff *stuffp,
  1072.       char *p, int sector, int nr_sectors)
  1073. /* This seems to do the actually transfer.  But it does more.  It
  1074. keeps track of errors occurred and will (if possible) fall back
  1075. to single speed on error.
  1076. Return: -1 on timeout or other error
  1077. else status byte (as in stuff->st) */
  1078. {
  1079. int ans;
  1080. ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
  1081. return ans;
  1082. #if FALLBACK
  1083. if (-1 == ans)
  1084. stuffp->readerrs++;
  1085. else
  1086. return ans;
  1087. if (stuffp->readerrs && stuffp->readcmd == READ1X) {
  1088. xwarn("XXX Already reading 1x -- no chancen");
  1089. return -1;
  1090. }
  1091. xwarn("XXX Fallback to 1xn");
  1092. stuffp->readcmd = READ1X;
  1093. return mcdx_transfer(stuffp, p, sector, nr_sectors);
  1094. #endif
  1095. }
  1096. static int mcdx_xfer(struct s_drive_stuff *stuffp,
  1097.      char *p, int sector, int nr_sectors)
  1098. /* This does actually the transfer from the drive.
  1099. Return: -1 on timeout or other error
  1100. else status byte (as in stuff->st) */
  1101. {
  1102. int border;
  1103. int done = 0;
  1104. long timeout;
  1105. if (stuffp->audio) {
  1106. xwarn("Attempt to read from audio CD.n");
  1107. return -1;
  1108. }
  1109. if (!stuffp->readcmd) {
  1110. xinfo("Can't transfer from missing disk.n");
  1111. return -1;
  1112. }
  1113. while (stuffp->lock) {
  1114. interruptible_sleep_on(&stuffp->lockq);
  1115. }
  1116. if (stuffp->valid && (sector >= stuffp->pending)
  1117.     && (sector < stuffp->low_border)) {
  1118. /* All (or at least a part of the sectors requested) seems
  1119.    * to be already requested, so we don't need to bother the
  1120.    * drive with new requests ...
  1121.    * Wait for the drive become idle, but first
  1122.    * check for possible occurred errors --- the drive
  1123.    * seems to report them asynchronously */
  1124. border = stuffp->high_border < (border =
  1125. sector + nr_sectors)
  1126.     ? stuffp->high_border : border;
  1127. stuffp->lock = current->pid;
  1128. do {
  1129. while (stuffp->busy) {
  1130. timeout =
  1131.     interruptible_sleep_on_timeout
  1132.     (&stuffp->busyq, 5 * HZ);
  1133. if (!stuffp->introk) {
  1134. xtrace(XFER,
  1135.        "error via interruptn");
  1136. } else if (!timeout) {
  1137. xtrace(XFER, "timeoutn");
  1138. } else if (signal_pending(current)) {
  1139. xtrace(XFER, "signaln");
  1140. } else
  1141. continue;
  1142. stuffp->lock = 0;
  1143. stuffp->busy = 0;
  1144. stuffp->valid = 0;
  1145. wake_up_interruptible(&stuffp->lockq);
  1146. xtrace(XFER, "transfer() done (-1)n");
  1147. return -1;
  1148. }
  1149. /* check if we need to set the busy flag (as we
  1150.  * expect an interrupt */
  1151. stuffp->busy = (3 == (stuffp->pending & 3));
  1152. /* Test if it's the first sector of a block,
  1153.  * there we have to skip some bytes as we read raw data */
  1154. if (stuffp->xa && (0 == (stuffp->pending & 3))) {
  1155. const int HEAD =
  1156.     CD_FRAMESIZE_RAW - CD_XA_TAIL -
  1157.     CD_FRAMESIZE;
  1158. insb((unsigned int) stuffp->rreg_data, p,
  1159.      HEAD);
  1160. }
  1161. /* now actually read the data */
  1162. insb((unsigned int) stuffp->rreg_data, p, 512);
  1163. /* test if it's the last sector of a block,
  1164.  * if so, we have to handle XA special */
  1165. if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
  1166. char dummy[CD_XA_TAIL];
  1167. insb((unsigned int) stuffp->rreg_data,
  1168.      &dummy[0], CD_XA_TAIL);
  1169. }
  1170. if (stuffp->pending == sector) {
  1171. p += 512;
  1172. done++;
  1173. sector++;
  1174. }
  1175. } while (++(stuffp->pending) < border);
  1176. stuffp->lock = 0;
  1177. wake_up_interruptible(&stuffp->lockq);
  1178. } else {
  1179. /* The requested sector(s) is/are out of the
  1180.  * already requested range, so we have to bother the drive
  1181.  * with a new request. */
  1182. static unsigned char cmd[] = {
  1183. 0,
  1184. 0, 0, 0,
  1185. 0, 0, 0
  1186. };
  1187. cmd[0] = stuffp->readcmd;
  1188. /* The numbers held in ->pending, ..., should be valid */
  1189. stuffp->valid = 1;
  1190. stuffp->pending = sector & ~3;
  1191. /* do some sanity checks */
  1192. if (stuffp->pending > stuffp->lastsector) {
  1193. xwarn
  1194.     ("transfer() sector %d from nirvana requested.n",
  1195.      stuffp->pending);
  1196. stuffp->status = MCDX_ST_EOM;
  1197. stuffp->valid = 0;
  1198. xtrace(XFER, "transfer() done (-1)n");
  1199. return -1;
  1200. }
  1201. if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
  1202.     > stuffp->lastsector + 1) {
  1203. xtrace(XFER, "cut low_bordern");
  1204. stuffp->low_border = stuffp->lastsector + 1;
  1205. }
  1206. if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
  1207.     > stuffp->lastsector + 1) {
  1208. xtrace(XFER, "cut high_bordern");
  1209. stuffp->high_border = stuffp->lastsector + 1;
  1210. }
  1211. { /* Convert the sector to be requested to MSF format */
  1212. struct cdrom_msf0 pending;
  1213. log2msf(stuffp->pending / 4, &pending);
  1214. cmd[1] = pending.minute;
  1215. cmd[2] = pending.second;
  1216. cmd[3] = pending.frame;
  1217. }
  1218. cmd[6] =
  1219.     (unsigned
  1220.      char) ((stuffp->high_border - stuffp->pending) / 4);
  1221. xtrace(XFER, "[%2d]n", cmd[6]);
  1222. stuffp->busy = 1;
  1223. /* Now really issue the request command */
  1224. outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
  1225. }
  1226. #ifdef AK2
  1227. if (stuffp->int_err) {
  1228. stuffp->valid = 0;
  1229. stuffp->int_err = 0;
  1230. return -1;
  1231. }
  1232. #endif /* AK2 */
  1233. stuffp->low_border = (stuffp->low_border +=
  1234.       done) <
  1235.     stuffp->high_border ? stuffp->low_border : stuffp->high_border;
  1236. return done;
  1237. }
  1238. /* Access to elements of the mcdx_drive_map members */
  1239. static char *port(int *ip)
  1240. {
  1241. return (char *) ip[0];
  1242. }
  1243. static int irq(int *ip)
  1244. {
  1245. return ip[1];
  1246. }
  1247. /* Misc number converters */
  1248. static unsigned int bcd2uint(unsigned char c)
  1249. {
  1250. return (c >> 4) * 10 + (c & 0x0f);
  1251. }
  1252. static unsigned int uint2bcd(unsigned int ival)
  1253. {
  1254. return ((ival / 10) << 4) | (ival % 10);
  1255. }
  1256. static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
  1257. {
  1258. l += CD_MSF_OFFSET;
  1259. pmsf->minute = uint2bcd(l / 4500), l %= 4500;
  1260. pmsf->second = uint2bcd(l / 75);
  1261. pmsf->frame = uint2bcd(l % 75);
  1262. }
  1263. static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
  1264. {
  1265. return bcd2uint(pmsf->frame)
  1266.     + bcd2uint(pmsf->second) * 75
  1267.     + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
  1268. }
  1269. int mcdx_readtoc(struct s_drive_stuff *stuffp)
  1270. /*  Read the toc entries from the CD,
  1271.  *  Return: -1 on failure, else 0 */
  1272. {
  1273. if (stuffp->toc) {
  1274. xtrace(READTOC, "ioctl() toc already readn");
  1275. return 0;
  1276. }
  1277. xtrace(READTOC, "ioctl() readtoc for %d tracksn",
  1278.        stuffp->di.n_last - stuffp->di.n_first + 1);
  1279. if (-1 == mcdx_hold(stuffp, 1))
  1280. return -1;
  1281. xtrace(READTOC, "ioctl() tocmoden");
  1282. if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
  1283. return -EIO;
  1284. /* all seems to be ok so far ... malloc */
  1285. {
  1286. int size;
  1287. size =
  1288.     sizeof(struct s_subqcode) * (stuffp->di.n_last -
  1289.  stuffp->di.n_first + 2);
  1290. xtrace(MALLOC, "ioctl() malloc %d bytesn", size);
  1291. stuffp->toc = kmalloc(size, GFP_KERNEL);
  1292. if (!stuffp->toc) {
  1293. xwarn("Cannot malloc %d bytes for tocn", size);
  1294. mcdx_setdrivemode(stuffp, DATA, 1);
  1295. return -EIO;
  1296. }
  1297. }
  1298. /* now read actually the index */
  1299. {
  1300. int trk;
  1301. int retries;
  1302. for (trk = 0;
  1303.      trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
  1304.      trk++)
  1305. stuffp->toc[trk].index = 0;
  1306. for (retries = 300; retries; retries--) { /* why 300? */
  1307. struct s_subqcode q;
  1308. unsigned int idx;
  1309. if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
  1310. mcdx_setdrivemode(stuffp, DATA, 1);
  1311. return -EIO;
  1312. }
  1313. idx = bcd2uint(q.index);
  1314. if ((idx > 0)
  1315.     && (idx <= stuffp->di.n_last)
  1316.     && (q.tno == 0)
  1317.     && (stuffp->toc[idx - stuffp->di.n_first].
  1318. index == 0)) {
  1319. stuffp->toc[idx - stuffp->di.n_first] = q;
  1320. xtrace(READTOC,
  1321.        "ioctl() toc idx %d (trk %d)n",
  1322.        idx, trk);
  1323. trk--;
  1324. }
  1325. if (trk == 0)
  1326. break;
  1327. }
  1328. memset(&stuffp->
  1329.        toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
  1330.        sizeof(stuffp->toc[0]));
  1331. stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
  1332.     1].dt = stuffp->di.msf_leadout;
  1333. }
  1334. /* unset toc mode */
  1335. xtrace(READTOC, "ioctl() undo toc moden");
  1336. if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
  1337. return -EIO;
  1338. #if MCDX_DEBUG && READTOC
  1339. {
  1340. int trk;
  1341. for (trk = 0;
  1342.      trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
  1343.      trk++)
  1344. xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
  1345.        "  %02x:%02x.%02x  %02x:%02x.%02xn",
  1346.        trk + stuffp->di.n_first,
  1347.        stuffp->toc[trk].control,
  1348.        stuffp->toc[trk].tno,
  1349.        stuffp->toc[trk].index,
  1350.        stuffp->toc[trk].tt.minute,
  1351.        stuffp->toc[trk].tt.second,
  1352.        stuffp->toc[trk].tt.frame,
  1353.        stuffp->toc[trk].dt.minute,
  1354.        stuffp->toc[trk].dt.second,
  1355.        stuffp->toc[trk].dt.frame);
  1356. }
  1357. #endif
  1358. return 0;
  1359. }
  1360. static int
  1361. mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
  1362. {
  1363. unsigned char cmd[7] = {
  1364. 0, 0, 0, 0, 0, 0, 0
  1365. };
  1366. if (!stuffp->readcmd) {
  1367. xinfo("Can't play from missing disk.n");
  1368. return -1;
  1369. }
  1370. cmd[0] = stuffp->playcmd;
  1371. cmd[1] = msf->cdmsf_min0;
  1372. cmd[2] = msf->cdmsf_sec0;
  1373. cmd[3] = msf->cdmsf_frame0;
  1374. cmd[4] = msf->cdmsf_min1;
  1375. cmd[5] = msf->cdmsf_sec1;
  1376. cmd[6] = msf->cdmsf_frame1;
  1377. xtrace(PLAYMSF, "ioctl(): play %x "
  1378.        "%02x:%02x:%02x -- %02x:%02x:%02xn",
  1379.        cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
  1380. outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
  1381. if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
  1382. xwarn("playmsf() timeoutn");
  1383. return -1;
  1384. }
  1385. stuffp->audiostatus = CDROM_AUDIO_PLAY;
  1386. return 0;
  1387. }
  1388. static int
  1389. mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
  1390. {
  1391. struct s_subqcode *p;
  1392. struct cdrom_msf msf;
  1393. if (-1 == mcdx_readtoc(stuffp))
  1394. return -1;
  1395. if (ti)
  1396. p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
  1397. else
  1398. p = &stuffp->start;
  1399. msf.cdmsf_min0 = p->dt.minute;
  1400. msf.cdmsf_sec0 = p->dt.second;
  1401. msf.cdmsf_frame0 = p->dt.frame;
  1402. if (ti) {
  1403. p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
  1404. stuffp->stop = *p;
  1405. } else
  1406. p = &stuffp->stop;
  1407. msf.cdmsf_min1 = p->dt.minute;
  1408. msf.cdmsf_sec1 = p->dt.second;
  1409. msf.cdmsf_frame1 = p->dt.frame;
  1410. return mcdx_playmsf(stuffp, &msf);
  1411. }
  1412. /* Drive functions ************************************************/
  1413. static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
  1414. {
  1415. struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  1416. if (!stuffp->present)
  1417. return -ENXIO;
  1418. if (!(stuffp->present & DOOR))
  1419. return -ENOSYS;
  1420. if (position) /* 1: eject */
  1421. return mcdx_talk(stuffp, "xf6", 1, NULL, 1, 5 * HZ, 3);
  1422. else /* 0: close */
  1423. return mcdx_talk(stuffp, "xf8", 1, NULL, 1, 5 * HZ, 3);
  1424. return 1;
  1425. }
  1426. static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
  1427. {
  1428. return mcdx_talk(stuffp, "xf0", 1, NULL, 1, 2 * HZ, tries);
  1429. }
  1430. static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
  1431. {
  1432. return mcdx_talk(stuffp, "x70", 1, NULL, 1, 2 * HZ, tries);
  1433. }
  1434. static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
  1435.      struct s_subqcode *sub, int tries)
  1436. {
  1437. char buf[11];
  1438. int ans;
  1439. if (-1 == (ans = mcdx_talk(stuffp, "x20", 1, buf, sizeof(buf),
  1440.    2 * HZ, tries)))
  1441. return -1;
  1442. sub->control = buf[1];
  1443. sub->tno = buf[2];
  1444. sub->index = buf[3];
  1445. sub->tt.minute = buf[4];
  1446. sub->tt.second = buf[5];
  1447. sub->tt.frame = buf[6];
  1448. sub->dt.minute = buf[8];
  1449. sub->dt.second = buf[9];
  1450. sub->dt.frame = buf[10];
  1451. return ans;
  1452. }
  1453. static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
  1454.   struct s_multi *multi, int tries)
  1455. {
  1456. char buf[5];
  1457. int ans;
  1458. if (stuffp->present & MULTI) {
  1459. ans =
  1460.     mcdx_talk(stuffp, "x11", 1, buf, sizeof(buf), 2 * HZ,
  1461.       tries);
  1462. multi->multi = buf[1];
  1463. multi->msf_last.minute = buf[2];
  1464. multi->msf_last.second = buf[3];
  1465. multi->msf_last.frame = buf[4];
  1466. return ans;
  1467. } else {
  1468. multi->multi = 0;
  1469. return 0;
  1470. }
  1471. }
  1472. static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
  1473.     int tries)
  1474. {
  1475. char buf[9];
  1476. int ans;
  1477. ans =
  1478.     mcdx_talk(stuffp, "x10", 1, buf, sizeof(buf), 2 * HZ, tries);
  1479. if (ans == -1) {
  1480. info->n_first = 0;
  1481. info->n_last = 0;
  1482. } else {
  1483. info->n_first = bcd2uint(buf[1]);
  1484. info->n_last = bcd2uint(buf[2]);
  1485. info->msf_leadout.minute = buf[3];
  1486. info->msf_leadout.second = buf[4];
  1487. info->msf_leadout.frame = buf[5];
  1488. info->msf_first.minute = buf[6];
  1489. info->msf_first.second = buf[7];
  1490. info->msf_first.frame = buf[8];
  1491. }
  1492. return ans;
  1493. }
  1494. static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
  1495.   int tries)
  1496. {
  1497. char cmd[2];
  1498. int ans;
  1499. xtrace(HW, "setdrivemode() %dn", mode);
  1500. if (-1 == (ans = mcdx_talk(stuffp, "xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
  1501. return -1;
  1502. switch (mode) {
  1503. case TOC:
  1504. cmd[1] |= 0x04;
  1505. break;
  1506. case DATA:
  1507. cmd[1] &= ~0x04;
  1508. break;
  1509. case RAW:
  1510. cmd[1] |= 0x40;
  1511. break;
  1512. case COOKED:
  1513. cmd[1] &= ~0x40;
  1514. break;
  1515. default:
  1516. break;
  1517. }
  1518. cmd[0] = 0x50;
  1519. return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
  1520. }
  1521. static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
  1522.  int tries)
  1523. {
  1524. unsigned char cmd[2] = { 0xa0 };
  1525. xtrace(HW, "setdatamode() %dn", mode);
  1526. switch (mode) {
  1527. case MODE0:
  1528. cmd[1] = 0x00;
  1529. break;
  1530. case MODE1:
  1531. cmd[1] = 0x01;
  1532. break;
  1533. case MODE2:
  1534. cmd[1] = 0x02;
  1535. break;
  1536. default:
  1537. return -EINVAL;
  1538. }
  1539. return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
  1540. }
  1541. static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
  1542. {
  1543. char cmd[4];
  1544. xtrace(HW, "config()n");
  1545. cmd[0] = 0x90;
  1546. cmd[1] = 0x10; /* irq enable */
  1547. cmd[2] = 0x05; /* pre, err irq enable */
  1548. if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
  1549. return -1;
  1550. cmd[1] = 0x02; /* dma select */
  1551. cmd[2] = 0x00; /* no dma */
  1552. return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
  1553. }
  1554. static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
  1555.     int tries)
  1556. {
  1557. char buf[3];
  1558. int ans;
  1559. if (-1 == (ans = mcdx_talk(stuffp, "xdc",
  1560.    1, buf, sizeof(buf), 2 * HZ, tries)))
  1561. return ans;
  1562. ver->code = buf[1];
  1563. ver->ver = buf[2];
  1564. return ans;
  1565. }
  1566. static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
  1567. {
  1568. if (mode == HARD) {
  1569. outb(0, (unsigned int) stuffp->wreg_chn); /* no dma, no irq -> hardware */
  1570. outb(0, (unsigned int) stuffp->wreg_reset); /* hw reset */
  1571. return 0;
  1572. } else
  1573. return mcdx_talk(stuffp, "x60", 1, NULL, 1, 5 * HZ, tries);
  1574. }
  1575. static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
  1576. {
  1577. struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
  1578. char cmd[2] = { 0xfe };
  1579. if (!(stuffp->present & DOOR))
  1580. return -ENOSYS;
  1581. if (stuffp->present & DOOR) {
  1582. cmd[1] = lock ? 0x01 : 0x00;
  1583. return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
  1584. } else
  1585. return 0;
  1586. }
  1587. static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
  1588. {
  1589. return mcdx_talk(stuffp, "x40", 1, NULL, 1, 5 * HZ, tries);
  1590. }
  1591. static int
  1592. mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
  1593. {
  1594. unsigned long timeout = to + jiffies;
  1595. char c;
  1596. if (!buf)
  1597. buf = &c;
  1598. while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
  1599. if (time_after(jiffies, timeout))
  1600. return -1;
  1601. mcdx_delay(stuffp, delay);
  1602. }
  1603. *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff;
  1604. return 0;
  1605. }
  1606. static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
  1607.     struct cdrom_volctrl *vol, int tries)
  1608. {
  1609. char cmd[5];
  1610. cmd[0] = 0xae;
  1611. cmd[1] = vol->channel0;
  1612. cmd[2] = 0;
  1613. cmd[3] = vol->channel1;
  1614. cmd[4] = 0;
  1615. return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
  1616. }
  1617. MODULE_LICENSE("GPL");