mcdx.c 49 KB

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