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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -- sjcd.c
  2.  *
  3.  *   Sanyo CD-ROM device driver implementation, Version 1.6
  4.  *   Copyright (C) 1995  Vadim V. Model
  5.  *
  6.  *   model@cecmow.enet.dec.com
  7.  *   vadim@rbrf.ru
  8.  *   vadim@ipsun.ras.ru
  9.  *
  10.  *
  11.  *  This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de);
  12.  *  it was developed under use of mcd.c from Martin Harriss, with help of
  13.  *  Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl).
  14.  *
  15.  *  It is planned to include these routines into sbpcd.c later - to make
  16.  *  a "mixed use" on one cable possible for all kinds of drives which use
  17.  *  the SoundBlaster/Panasonic style CDROM interface. But today, the
  18.  *  ability to install directly from CDROM is more important than flexibility.
  19.  *
  20.  *  This program is free software; you can redistribute it and/or modify
  21.  *  it under the terms of the GNU General Public License as published by
  22.  *  the Free Software Foundation; either version 2 of the License, or
  23.  *  (at your option) any later version.
  24.  *
  25.  *  This program is distributed in the hope that it will be useful,
  26.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  27.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28.  *  GNU General Public License for more details.
  29.  *
  30.  *  You should have received a copy of the GNU General Public License
  31.  *  along with this program; if not, write to the Free Software
  32.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  33.  *
  34.  *  History:
  35.  *  1.1 First public release with kernel version 1.3.7.
  36.  *      Written by Vadim Model.
  37.  *  1.2 Added detection and configuration of cdrom interface
  38.  *      on ISP16 soundcard.
  39.  *      Allow for command line options: sjcd=<io_base>,<irq>,<dma>
  40.  *  1.3 Some minor changes to README.sjcd.
  41.  *  1.4 MSS Sound support!! Listen to a CD through the speakers.
  42.  *  1.5 Module support and bugfixes.
  43.  *      Tray locking.
  44.  *  1.6 Removed ISP16 code from this driver.
  45.  *      Allow only to set io base address on command line: sjcd=<io_base>
  46.  *      Changes to Documentation/cdrom/sjcd
  47.  *      Added cleanup after any error in the initialisation.
  48.  *  1.7 Added code to set the sector size tables to prevent the bug present in 
  49.  *      the previous version of this driver.  Coded added by Anthony Barbachan 
  50.  *      from bugfix tip originally suggested by Alan Cox.
  51.  *
  52.  *  November 1999 -- Make kernel-parameter implementation work with 2.3.x 
  53.  *              Removed init_module & cleanup_module in favor of 
  54.  *              module_init & module_exit.
  55.  *              Torben Mathiasen <tmm@image.dk>
  56.  */
  57. #define SJCD_VERSION_MAJOR 1
  58. #define SJCD_VERSION_MINOR 7
  59. #include <linux/module.h>
  60. #include <linux/errno.h>
  61. #include <linux/sched.h>
  62. #include <linux/mm.h>
  63. #include <linux/timer.h>
  64. #include <linux/fs.h>
  65. #include <linux/kernel.h>
  66. #include <linux/cdrom.h>
  67. #include <linux/ioport.h>
  68. #include <linux/string.h>
  69. #include <linux/major.h>
  70. #include <linux/init.h>
  71. #include <linux/devfs_fs_kernel.h>
  72. #include <asm/system.h>
  73. #include <asm/io.h>
  74. #include <asm/uaccess.h>
  75. #define MAJOR_NR SANYO_CDROM_MAJOR
  76. #include <linux/blk.h>
  77. #include "sjcd.h"
  78. static int sjcd_present = 0;
  79. #define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */
  80. /*
  81.  * buffer for block size conversion
  82.  */
  83. static char sjcd_buf[2048 * SJCD_BUF_SIZ];
  84. static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn;
  85. static volatile int sjcd_buf_in, sjcd_buf_out = -1;
  86. /*
  87.  * Status.
  88.  */
  89. static unsigned short sjcd_status_valid = 0;
  90. static unsigned short sjcd_door_closed;
  91. static unsigned short sjcd_door_was_open;
  92. static unsigned short sjcd_media_is_available;
  93. static unsigned short sjcd_media_is_changed;
  94. static unsigned short sjcd_toc_uptodate = 0;
  95. static unsigned short sjcd_command_failed;
  96. static volatile unsigned char sjcd_completion_status = 0;
  97. static volatile unsigned char sjcd_completion_error = 0;
  98. static unsigned short sjcd_command_is_in_progress = 0;
  99. static unsigned short sjcd_error_reported = 0;
  100. static int sjcd_open_count;
  101. static int sjcd_audio_status;
  102. static struct sjcd_play_msf sjcd_playing;
  103. static int sjcd_base = SJCD_BASE_ADDR;
  104. MODULE_PARM(sjcd_base, "i");
  105. static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
  106. /*
  107.  * Data transfer.
  108.  */
  109. static volatile unsigned short sjcd_transfer_is_active = 0;
  110. enum sjcd_transfer_state {
  111. SJCD_S_IDLE = 0,
  112. SJCD_S_START = 1,
  113. SJCD_S_MODE = 2,
  114. SJCD_S_READ = 3,
  115. SJCD_S_DATA = 4,
  116. SJCD_S_STOP = 5,
  117. SJCD_S_STOPPING = 6
  118. };
  119. static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE;
  120. static long sjcd_transfer_timeout = 0;
  121. static int sjcd_read_count = 0;
  122. static unsigned char sjcd_mode = 0;
  123. #define SJCD_READ_TIMEOUT 5000
  124. #if defined( SJCD_GATHER_STAT )
  125. /*
  126.  * Statistic.
  127.  */
  128. static struct sjcd_stat statistic;
  129. #endif
  130. /*
  131.  * Timer.
  132.  */
  133. static struct timer_list sjcd_delay_timer;
  134. #define SJCD_SET_TIMER( func, tmout )           
  135.     ( sjcd_delay_timer.expires = jiffies+tmout,         
  136.       sjcd_delay_timer.function = ( void * )func, 
  137.       add_timer( &sjcd_delay_timer ) )
  138. #define CLEAR_TIMER del_timer( &sjcd_delay_timer )
  139. static int sjcd_cleanup(void);
  140. /*
  141.  * Set up device, i.e., use command line data to set
  142.  * base address.
  143.  */
  144. #ifndef MODULE
  145. static int __init sjcd_setup(char *str)
  146. {
  147. int ints[2];
  148. (void) get_options(str, ARRAY_SIZE(ints), ints);
  149. if (ints[0] > 0)
  150. sjcd_base = ints[1];
  151. return 1;
  152. }
  153. __setup("sjcd=", sjcd_setup);
  154. #endif
  155. /*
  156.  * Special converters.
  157.  */
  158. static unsigned char bin2bcd(int bin)
  159. {
  160. int u, v;
  161. u = bin % 10;
  162. v = bin / 10;
  163. return (u | (v << 4));
  164. }
  165. static int bcd2bin(unsigned char bcd)
  166. {
  167. return ((bcd >> 4) * 10 + (bcd & 0x0F));
  168. }
  169. static long msf2hsg(struct msf *mp)
  170. {
  171. return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75
  172. + bcd2bin(mp->min) * 4500 - 150);
  173. }
  174. static void hsg2msf(long hsg, struct msf *msf)
  175. {
  176. hsg += 150;
  177. msf->min = hsg / 4500;
  178. hsg %= 4500;
  179. msf->sec = hsg / 75;
  180. msf->frame = hsg % 75;
  181. msf->min = bin2bcd(msf->min); /* convert to BCD */
  182. msf->sec = bin2bcd(msf->sec);
  183. msf->frame = bin2bcd(msf->frame);
  184. }
  185. /*
  186.  * Send a command to cdrom. Invalidate status.
  187.  */
  188. static void sjcd_send_cmd(unsigned char cmd)
  189. {
  190. #if defined( SJCD_TRACE )
  191. printk("SJCD: send_cmd( 0x%x )n", cmd);
  192. #endif
  193. outb(cmd, SJCDPORT(0));
  194. sjcd_command_is_in_progress = 1;
  195. sjcd_status_valid = 0;
  196. sjcd_command_failed = 0;
  197. }
  198. /*
  199.  * Send a command with one arg to cdrom. Invalidate status.
  200.  */
  201. static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a)
  202. {
  203. #if defined( SJCD_TRACE )
  204. printk("SJCD: send_1_cmd( 0x%x, 0x%x )n", cmd, a);
  205. #endif
  206. outb(cmd, SJCDPORT(0));
  207. outb(a, SJCDPORT(0));
  208. sjcd_command_is_in_progress = 1;
  209. sjcd_status_valid = 0;
  210. sjcd_command_failed = 0;
  211. }
  212. /*
  213.  * Send a command with four args to cdrom. Invalidate status.
  214.  */
  215. static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a,
  216.     unsigned char b, unsigned char c,
  217.     unsigned char d)
  218. {
  219. #if defined( SJCD_TRACE )
  220. printk("SJCD: send_4_cmd( 0x%x )n", cmd);
  221. #endif
  222. outb(cmd, SJCDPORT(0));
  223. outb(a, SJCDPORT(0));
  224. outb(b, SJCDPORT(0));
  225. outb(c, SJCDPORT(0));
  226. outb(d, SJCDPORT(0));
  227. sjcd_command_is_in_progress = 1;
  228. sjcd_status_valid = 0;
  229. sjcd_command_failed = 0;
  230. }
  231. /*
  232.  * Send a play or read command to cdrom. Invalidate Status.
  233.  */
  234. static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms)
  235. {
  236. #if defined( SJCD_TRACE )
  237. printk("SJCD: send_long_cmd( 0x%x )n", cmd);
  238. #endif
  239. outb(cmd, SJCDPORT(0));
  240. outb(pms->start.min, SJCDPORT(0));
  241. outb(pms->start.sec, SJCDPORT(0));
  242. outb(pms->start.frame, SJCDPORT(0));
  243. outb(pms->end.min, SJCDPORT(0));
  244. outb(pms->end.sec, SJCDPORT(0));
  245. outb(pms->end.frame, SJCDPORT(0));
  246. sjcd_command_is_in_progress = 1;
  247. sjcd_status_valid = 0;
  248. sjcd_command_failed = 0;
  249. }
  250. /*
  251.  * Get a value from the data port. Should not block, so we use a little
  252.  * wait for a while. Returns 0 if OK.
  253.  */
  254. static int sjcd_load_response(void *buf, int len)
  255. {
  256. unsigned char *resp = (unsigned char *) buf;
  257. for (; len; --len) {
  258. int i;
  259. for (i = 200;
  260.      i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))););
  261. if (i > 0)
  262. *resp++ = (unsigned char) inb(SJCDPORT(0));
  263. else
  264. break;
  265. }
  266. return (len);
  267. }
  268. /*
  269.  * Load and parse command completion status (drive info byte and maybe error).
  270.  * Sorry, no error classification yet.
  271.  */
  272. static void sjcd_load_status(void)
  273. {
  274. sjcd_media_is_changed = 0;
  275. sjcd_completion_error = 0;
  276. sjcd_completion_status = inb(SJCDPORT(0));
  277. if (sjcd_completion_status & SST_DOOR_OPENED) {
  278. sjcd_door_closed = sjcd_media_is_available = 0;
  279. } else {
  280. sjcd_door_closed = 1;
  281. if (sjcd_completion_status & SST_MEDIA_CHANGED)
  282. sjcd_media_is_available = sjcd_media_is_changed =
  283.     1;
  284. else if (sjcd_completion_status & 0x0F) {
  285. /*
  286.  * OK, we seem to catch an error ...
  287.  */
  288. while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1))));
  289. sjcd_completion_error = inb(SJCDPORT(0));
  290. if ((sjcd_completion_status & 0x08) &&
  291.     (sjcd_completion_error & 0x40))
  292. sjcd_media_is_available = 0;
  293. else
  294. sjcd_command_failed = 1;
  295. } else
  296. sjcd_media_is_available = 1;
  297. }
  298. /*
  299.  * Ok, status loaded successfully.
  300.  */
  301. sjcd_status_valid = 1, sjcd_error_reported = 0;
  302. sjcd_command_is_in_progress = 0;
  303. /*
  304.  * If the disk is changed, the TOC is not valid.
  305.  */
  306. if (sjcd_media_is_changed)
  307. sjcd_toc_uptodate = 0;
  308. #if defined( SJCD_TRACE )
  309. printk("SJCD: status %02x.%02x loaded.n",
  310.        (int) sjcd_completion_status, (int) sjcd_completion_error);
  311. #endif
  312. }
  313. /*
  314.  * Read status from cdrom. Check to see if the status is available.
  315.  */
  316. static int sjcd_check_status(void)
  317. {
  318. /*
  319.  * Try to load the response from cdrom into buffer.
  320.  */
  321. if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) {
  322. sjcd_load_status();
  323. return (1);
  324. } else {
  325. /*
  326.  * No status is available.
  327.  */
  328. return (0);
  329. }
  330. }
  331. /*
  332.  * This is just timeout counter, and nothing more. Surprised ? :-)
  333.  */
  334. static volatile long sjcd_status_timeout;
  335. /*
  336.  * We need about 10 seconds to wait. The longest command takes about 5 seconds
  337.  * to probe the disk (usually after tray closed or drive reset). Other values
  338.  * should be thought of for other commands.
  339.  */
  340. #define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000
  341. static void sjcd_status_timer(void)
  342. {
  343. if (sjcd_check_status()) {
  344. /*
  345.  * The command completed and status is loaded, stop waiting.
  346.  */
  347. wake_up(&sjcd_waitq);
  348. } else if (--sjcd_status_timeout <= 0) {
  349. /*
  350.  * We are timed out. 
  351.  */
  352. wake_up(&sjcd_waitq);
  353. } else {
  354. /*
  355.  * We have still some time to wait. Try again.
  356.  */
  357. SJCD_SET_TIMER(sjcd_status_timer, 1);
  358. }
  359. }
  360. /*
  361.  * Wait for status for 10 sec approx. Returns non-positive when timed out.
  362.  * Should not be used while reading data CDs.
  363.  */
  364. static int sjcd_wait_for_status(void)
  365. {
  366. sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
  367. SJCD_SET_TIMER(sjcd_status_timer, 1);
  368. sleep_on(&sjcd_waitq);
  369. #if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE )
  370. if (sjcd_status_timeout <= 0)
  371. printk("SJCD: Error Wait For Status.n");
  372. #endif
  373. return (sjcd_status_timeout);
  374. }
  375. static int sjcd_receive_status(void)
  376. {
  377. int i;
  378. #if defined( SJCD_TRACE )
  379. printk("SJCD: receive_statusn");
  380. #endif
  381. /*
  382.  * Wait a bit for status available.
  383.  */
  384. for (i = 200; i-- && (sjcd_check_status() == 0););
  385. if (i < 0) {
  386. #if defined( SJCD_TRACE )
  387. printk("SJCD: long wait for statusn");
  388. #endif
  389. if (sjcd_wait_for_status() <= 0)
  390. printk("SJCD: Timeout when read status.n");
  391. else
  392. i = 0;
  393. }
  394. return (i);
  395. }
  396. /*
  397.  * Load the status. Issue get status command and wait for status available.
  398.  */
  399. static void sjcd_get_status(void)
  400. {
  401. #if defined( SJCD_TRACE )
  402. printk("SJCD: get_statusn");
  403. #endif
  404. sjcd_send_cmd(SCMD_GET_STATUS);
  405. sjcd_receive_status();
  406. }
  407. /*
  408.  * Check the drive if the disk is changed. Should be revised.
  409.  */
  410. static int sjcd_disk_change(kdev_t full_dev)
  411. {
  412. #if 0
  413. printk("SJCD: sjcd_disk_change( 0x%x )n", full_dev);
  414. #endif
  415. if (MINOR(full_dev) > 0) {
  416. printk("SJCD: request error: invalid device minor.n");
  417. return 0;
  418. }
  419. if (!sjcd_command_is_in_progress)
  420. sjcd_get_status();
  421. return (sjcd_status_valid ? sjcd_media_is_changed : 0);
  422. }
  423. /*
  424.  * Read the table of contents (TOC) and TOC header if necessary.
  425.  * We assume that the drive contains no more than 99 toc entries.
  426.  */
  427. static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS];
  428. static unsigned char sjcd_first_track_no, sjcd_last_track_no;
  429. #define sjcd_disk_length  sjcd_table_of_contents[0].un.track_msf
  430. static int sjcd_update_toc(void)
  431. {
  432. struct sjcd_hw_disk_info info;
  433. int i;
  434. #if defined( SJCD_TRACE )
  435. printk("SJCD: update toc:n");
  436. #endif
  437. /*
  438.  * check to see if we need to do anything
  439.  */
  440. if (sjcd_toc_uptodate)
  441. return (0);
  442. /*
  443.  * Get the TOC start information.
  444.  */
  445. sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK);
  446. sjcd_receive_status();
  447. if (!sjcd_status_valid) {
  448. printk("SJCD: cannot load status.n");
  449. return (-1);
  450. }
  451. if (!sjcd_media_is_available) {
  452. printk("SJCD: no disk in driven");
  453. return (-1);
  454. }
  455. if (!sjcd_command_failed) {
  456. if (sjcd_load_response(&info, sizeof(info)) != 0) {
  457. printk
  458.     ("SJCD: cannot load response about TOC start.n");
  459. return (-1);
  460. }
  461. sjcd_first_track_no = bcd2bin(info.un.track_no);
  462. } else {
  463. printk("SJCD: get first failedn");
  464. return (-1);
  465. }
  466. #if defined( SJCD_TRACE )
  467. printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no);
  468. #endif
  469. /*
  470.  * Get the TOC finish information.
  471.  */
  472. sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK);
  473. sjcd_receive_status();
  474. if (!sjcd_status_valid) {
  475. printk("SJCD: cannot load status.n");
  476. return (-1);
  477. }
  478. if (!sjcd_media_is_available) {
  479. printk("SJCD: no disk in driven");
  480. return (-1);
  481. }
  482. if (!sjcd_command_failed) {
  483. if (sjcd_load_response(&info, sizeof(info)) != 0) {
  484. printk
  485.     ("SJCD: cannot load response about TOC finish.n");
  486. return (-1);
  487. }
  488. sjcd_last_track_no = bcd2bin(info.un.track_no);
  489. } else {
  490. printk("SJCD: get last failedn");
  491. return (-1);
  492. }
  493. #if defined( SJCD_TRACE )
  494. printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no);
  495. #endif
  496. for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) {
  497. /*
  498.  * Get the first track information.
  499.  */
  500. sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i));
  501. sjcd_receive_status();
  502. if (!sjcd_status_valid) {
  503. printk("SJCD: cannot load status.n");
  504. return (-1);
  505. }
  506. if (!sjcd_media_is_available) {
  507. printk("SJCD: no disk in driven");
  508. return (-1);
  509. }
  510. if (!sjcd_command_failed) {
  511. if (sjcd_load_response(&sjcd_table_of_contents[i],
  512.        sizeof(struct
  513.       sjcd_hw_disk_info))
  514.     != 0) {
  515. printk
  516.     ("SJCD: cannot load info for %d trackn",
  517.      i);
  518. return (-1);
  519. }
  520. } else {
  521. printk("SJCD: get info %d failedn", i);
  522. return (-1);
  523. }
  524. }
  525. /*
  526.  * Get the disk length info.
  527.  */
  528. sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE);
  529. sjcd_receive_status();
  530. if (!sjcd_status_valid) {
  531. printk("SJCD: cannot load status.n");
  532. return (-1);
  533. }
  534. if (!sjcd_media_is_available) {
  535. printk("SJCD: no disk in driven");
  536. return (-1);
  537. }
  538. if (!sjcd_command_failed) {
  539. if (sjcd_load_response(&info, sizeof(info)) != 0) {
  540. printk
  541.     ("SJCD: cannot load response about disk size.n");
  542. return (-1);
  543. }
  544. sjcd_disk_length.min = info.un.track_msf.min;
  545. sjcd_disk_length.sec = info.un.track_msf.sec;
  546. sjcd_disk_length.frame = info.un.track_msf.frame;
  547. } else {
  548. printk("SJCD: get size failedn");
  549. return (1);
  550. }
  551. #if defined( SJCD_TRACE )
  552. printk("SJCD: (%02x:%02x.%02x)n", sjcd_disk_length.min,
  553.        sjcd_disk_length.sec, sjcd_disk_length.frame);
  554. #endif
  555. return (0);
  556. }
  557. /*
  558.  * Load subchannel information.
  559.  */
  560. static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp)
  561. {
  562. int s;
  563. #if defined( SJCD_TRACE )
  564. printk("SJCD: load sub qn");
  565. #endif
  566. sjcd_send_cmd(SCMD_GET_QINFO);
  567. s = sjcd_receive_status();
  568. if (s < 0 || sjcd_command_failed || !sjcd_status_valid) {
  569. sjcd_send_cmd(0xF2);
  570. s = sjcd_receive_status();
  571. if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
  572. return (-1);
  573. sjcd_send_cmd(SCMD_GET_QINFO);
  574. s = sjcd_receive_status();
  575. if (s < 0 || sjcd_command_failed || !sjcd_status_valid)
  576. return (-1);
  577. }
  578. if (sjcd_media_is_available)
  579. if (sjcd_load_response(qp, sizeof(*qp)) == 0)
  580. return (0);
  581. return (-1);
  582. }
  583. /*
  584.  * Start playing from the specified position.
  585.  */
  586. static int sjcd_play(struct sjcd_play_msf *mp)
  587. {
  588. struct sjcd_play_msf msf;
  589. /*
  590.  * Turn the device to play mode.
  591.  */
  592. sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY);
  593. if (sjcd_receive_status() < 0)
  594. return (-1);
  595. /*
  596.  * Seek to the starting point.
  597.  */
  598. msf.start = mp->start;
  599. msf.end.min = msf.end.sec = msf.end.frame = 0x00;
  600. sjcd_send_6_cmd(SCMD_SEEK, &msf);
  601. if (sjcd_receive_status() < 0)
  602. return (-1);
  603. /*
  604.  * Start playing.
  605.  */
  606. sjcd_send_6_cmd(SCMD_PLAY, mp);
  607. return (sjcd_receive_status());
  608. }
  609. /*
  610.  * Tray control functions.
  611.  */
  612. static int sjcd_tray_close(void)
  613. {
  614. #if defined( SJCD_TRACE )
  615. printk("SJCD: tray_closen");
  616. #endif
  617. sjcd_send_cmd(SCMD_CLOSE_TRAY);
  618. return (sjcd_receive_status());
  619. }
  620. static int sjcd_tray_lock(void)
  621. {
  622. #if defined( SJCD_TRACE )
  623. printk("SJCD: tray_lockn");
  624. #endif
  625. sjcd_send_cmd(SCMD_LOCK_TRAY);
  626. return (sjcd_receive_status());
  627. }
  628. static int sjcd_tray_unlock(void)
  629. {
  630. #if defined( SJCD_TRACE )
  631. printk("SJCD: tray_unlockn");
  632. #endif
  633. sjcd_send_cmd(SCMD_UNLOCK_TRAY);
  634. return (sjcd_receive_status());
  635. }
  636. static int sjcd_tray_open(void)
  637. {
  638. #if defined( SJCD_TRACE )
  639. printk("SJCD: tray_openn");
  640. #endif
  641. sjcd_send_cmd(SCMD_EJECT_TRAY);
  642. return (sjcd_receive_status());
  643. }
  644. /*
  645.  * Do some user commands.
  646.  */
  647. static int sjcd_ioctl(struct inode *ip, struct file *fp,
  648.       unsigned int cmd, unsigned long arg)
  649. {
  650. #if defined( SJCD_TRACE )
  651. printk("SJCD:ioctln");
  652. #endif
  653. if (ip == NULL)
  654. return (-EINVAL);
  655. sjcd_get_status();
  656. if (!sjcd_status_valid)
  657. return (-EIO);
  658. if (sjcd_update_toc() < 0)
  659. return (-EIO);
  660. switch (cmd) {
  661. case CDROMSTART:{
  662. #if defined( SJCD_TRACE )
  663. printk("SJCD: ioctl: startn");
  664. #endif
  665. return (0);
  666. }
  667. case CDROMSTOP:{
  668. #if defined( SJCD_TRACE )
  669. printk("SJCD: ioctl: stopn");
  670. #endif
  671. sjcd_send_cmd(SCMD_PAUSE);
  672. (void) sjcd_receive_status();
  673. sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
  674. return (0);
  675. }
  676. case CDROMPAUSE:{
  677. struct sjcd_hw_qinfo q_info;
  678. #if defined( SJCD_TRACE )
  679. printk("SJCD: ioctl: pausen");
  680. #endif
  681. if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
  682. sjcd_send_cmd(SCMD_PAUSE);
  683. (void) sjcd_receive_status();
  684. if (sjcd_get_q_info(&q_info) < 0) {
  685. sjcd_audio_status =
  686.     CDROM_AUDIO_NO_STATUS;
  687. } else {
  688. sjcd_audio_status =
  689.     CDROM_AUDIO_PAUSED;
  690. sjcd_playing.start = q_info.abs;
  691. }
  692. return (0);
  693. } else
  694. return (-EINVAL);
  695. }
  696. case CDROMRESUME:{
  697. #if defined( SJCD_TRACE )
  698. printk("SJCD: ioctl: resumen");
  699. #endif
  700. if (sjcd_audio_status == CDROM_AUDIO_PAUSED) {
  701. /*
  702.  * continue play starting at saved location
  703.  */
  704. if (sjcd_play(&sjcd_playing) < 0) {
  705. sjcd_audio_status =
  706.     CDROM_AUDIO_ERROR;
  707. return (-EIO);
  708. } else {
  709. sjcd_audio_status =
  710.     CDROM_AUDIO_PLAY;
  711. return (0);
  712. }
  713. } else
  714. return (-EINVAL);
  715. }
  716. case CDROMPLAYTRKIND:{
  717. struct cdrom_ti ti;
  718. int s;
  719. #if defined( SJCD_TRACE )
  720. printk("SJCD: ioctl: playtrkindn");
  721. #endif
  722. if ((s =
  723.      verify_area(VERIFY_READ, (void *) arg,
  724.  sizeof(ti))) == 0) {
  725. copy_from_user(&ti, (void *) arg,
  726.        sizeof(ti));
  727. if (ti.cdti_trk0 < sjcd_first_track_no)
  728. return (-EINVAL);
  729. if (ti.cdti_trk1 > sjcd_last_track_no)
  730. ti.cdti_trk1 = sjcd_last_track_no;
  731. if (ti.cdti_trk0 > ti.cdti_trk1)
  732. return (-EINVAL);
  733. sjcd_playing.start =
  734.     sjcd_table_of_contents[ti.cdti_trk0].
  735.     un.track_msf;
  736. sjcd_playing.end =
  737.     (ti.cdti_trk1 <
  738.      sjcd_last_track_no) ?
  739.     sjcd_table_of_contents[ti.cdti_trk1 +
  740.    1].un.
  741.     track_msf : sjcd_table_of_contents[0].
  742.     un.track_msf;
  743. if (sjcd_play(&sjcd_playing) < 0) {
  744. sjcd_audio_status =
  745.     CDROM_AUDIO_ERROR;
  746. return (-EIO);
  747. } else
  748. sjcd_audio_status =
  749.     CDROM_AUDIO_PLAY;
  750. }
  751. return (s);
  752. }
  753. case CDROMPLAYMSF:{
  754. struct cdrom_msf sjcd_msf;
  755. int s;
  756. #if defined( SJCD_TRACE )
  757. printk("SJCD: ioctl: playmsfn");
  758. #endif
  759. if ((s =
  760.      verify_area(VERIFY_READ, (void *) arg,
  761.  sizeof(sjcd_msf))) == 0) {
  762. if (sjcd_audio_status == CDROM_AUDIO_PLAY) {
  763. sjcd_send_cmd(SCMD_PAUSE);
  764. (void) sjcd_receive_status();
  765. sjcd_audio_status =
  766.     CDROM_AUDIO_NO_STATUS;
  767. }
  768. copy_from_user(&sjcd_msf, (void *) arg,
  769.        sizeof(sjcd_msf));
  770. sjcd_playing.start.min =
  771.     bin2bcd(sjcd_msf.cdmsf_min0);
  772. sjcd_playing.start.sec =
  773.     bin2bcd(sjcd_msf.cdmsf_sec0);
  774. sjcd_playing.start.frame =
  775.     bin2bcd(sjcd_msf.cdmsf_frame0);
  776. sjcd_playing.end.min =
  777.     bin2bcd(sjcd_msf.cdmsf_min1);
  778. sjcd_playing.end.sec =
  779.     bin2bcd(sjcd_msf.cdmsf_sec1);
  780. sjcd_playing.end.frame =
  781.     bin2bcd(sjcd_msf.cdmsf_frame1);
  782. if (sjcd_play(&sjcd_playing) < 0) {
  783. sjcd_audio_status =
  784.     CDROM_AUDIO_ERROR;
  785. return (-EIO);
  786. } else
  787. sjcd_audio_status =
  788.     CDROM_AUDIO_PLAY;
  789. }
  790. return (s);
  791. }
  792. case CDROMREADTOCHDR:{
  793. struct cdrom_tochdr toc_header;
  794. int s;
  795. #if defined (SJCD_TRACE )
  796. printk("SJCD: ioctl: readtocheadern");
  797. #endif
  798. if ((s =
  799.      verify_area(VERIFY_WRITE, (void *) arg,
  800.  sizeof(toc_header))) == 0) {
  801. toc_header.cdth_trk0 = sjcd_first_track_no;
  802. toc_header.cdth_trk1 = sjcd_last_track_no;
  803. copy_to_user((void *) arg, &toc_header,
  804.      sizeof(toc_header));
  805. }
  806. return (s);
  807. }
  808. case CDROMREADTOCENTRY:{
  809. struct cdrom_tocentry toc_entry;
  810. int s;
  811. #if defined( SJCD_TRACE )
  812. printk("SJCD: ioctl: readtocentryn");
  813. #endif
  814. if ((s =
  815.      verify_area(VERIFY_WRITE, (void *) arg,
  816.  sizeof(toc_entry))) == 0) {
  817. struct sjcd_hw_disk_info *tp;
  818. copy_from_user(&toc_entry, (void *) arg,
  819.        sizeof(toc_entry));
  820. if (toc_entry.cdte_track == CDROM_LEADOUT)
  821. tp = &sjcd_table_of_contents[0];
  822. else if (toc_entry.cdte_track <
  823.  sjcd_first_track_no)
  824. return (-EINVAL);
  825. else if (toc_entry.cdte_track >
  826.  sjcd_last_track_no)
  827. return (-EINVAL);
  828. else
  829. tp = &sjcd_table_of_contents
  830.     [toc_entry.cdte_track];
  831. toc_entry.cdte_adr =
  832.     tp->track_control & 0x0F;
  833. toc_entry.cdte_ctrl =
  834.     tp->track_control >> 4;
  835. switch (toc_entry.cdte_format) {
  836. case CDROM_LBA:
  837. toc_entry.cdte_addr.lba =
  838.     msf2hsg(&(tp->un.track_msf));
  839. break;
  840. case CDROM_MSF:
  841. toc_entry.cdte_addr.msf.minute =
  842.     bcd2bin(tp->un.track_msf.min);
  843. toc_entry.cdte_addr.msf.second =
  844.     bcd2bin(tp->un.track_msf.sec);
  845. toc_entry.cdte_addr.msf.frame =
  846.     bcd2bin(tp->un.track_msf.
  847.     frame);
  848. break;
  849. default:
  850. return (-EINVAL);
  851. }
  852. copy_to_user((void *) arg, &toc_entry,
  853.      sizeof(toc_entry));
  854. }
  855. return (s);
  856. }
  857. case CDROMSUBCHNL:{
  858. struct cdrom_subchnl subchnl;
  859. int s;
  860. #if defined( SJCD_TRACE )
  861. printk("SJCD: ioctl: subchnln");
  862. #endif
  863. if ((s =
  864.      verify_area(VERIFY_WRITE, (void *) arg,
  865.  sizeof(subchnl))) == 0) {
  866. struct sjcd_hw_qinfo q_info;
  867. copy_from_user(&subchnl, (void *) arg,
  868.        sizeof(subchnl));
  869. if (sjcd_get_q_info(&q_info) < 0)
  870. return (-EIO);
  871. subchnl.cdsc_audiostatus =
  872.     sjcd_audio_status;
  873. subchnl.cdsc_adr =
  874.     q_info.track_control & 0x0F;
  875. subchnl.cdsc_ctrl =
  876.     q_info.track_control >> 4;
  877. subchnl.cdsc_trk =
  878.     bcd2bin(q_info.track_no);
  879. subchnl.cdsc_ind = bcd2bin(q_info.x);
  880. switch (subchnl.cdsc_format) {
  881. case CDROM_LBA:
  882. subchnl.cdsc_absaddr.lba =
  883.     msf2hsg(&(q_info.abs));
  884. subchnl.cdsc_reladdr.lba =
  885.     msf2hsg(&(q_info.rel));
  886. break;
  887. case CDROM_MSF:
  888. subchnl.cdsc_absaddr.msf.minute =
  889.     bcd2bin(q_info.abs.min);
  890. subchnl.cdsc_absaddr.msf.second =
  891.     bcd2bin(q_info.abs.sec);
  892. subchnl.cdsc_absaddr.msf.frame =
  893.     bcd2bin(q_info.abs.frame);
  894. subchnl.cdsc_reladdr.msf.minute =
  895.     bcd2bin(q_info.rel.min);
  896. subchnl.cdsc_reladdr.msf.second =
  897.     bcd2bin(q_info.rel.sec);
  898. subchnl.cdsc_reladdr.msf.frame =
  899.     bcd2bin(q_info.rel.frame);
  900. break;
  901. default:
  902. return (-EINVAL);
  903. }
  904. copy_to_user((void *) arg, &subchnl,
  905.      sizeof(subchnl));
  906. }
  907. return (s);
  908. }
  909. case CDROMVOLCTRL:{
  910. struct cdrom_volctrl vol_ctrl;
  911. int s;
  912. #if defined( SJCD_TRACE )
  913. printk("SJCD: ioctl: volctrln");
  914. #endif
  915. if ((s =
  916.      verify_area(VERIFY_READ, (void *) arg,
  917.  sizeof(vol_ctrl))) == 0) {
  918. unsigned char dummy[4];
  919. copy_from_user(&vol_ctrl, (void *) arg,
  920.        sizeof(vol_ctrl));
  921. sjcd_send_4_cmd(SCMD_SET_VOLUME,
  922. vol_ctrl.channel0, 0xFF,
  923. vol_ctrl.channel1, 0xFF);
  924. if (sjcd_receive_status() < 0)
  925. return (-EIO);
  926. (void) sjcd_load_response(dummy, 4);
  927. }
  928. return (s);
  929. }
  930. case CDROMEJECT:{
  931. #if defined( SJCD_TRACE )
  932. printk("SJCD: ioctl: ejectn");
  933. #endif
  934. if (!sjcd_command_is_in_progress) {
  935. sjcd_tray_unlock();
  936. sjcd_send_cmd(SCMD_EJECT_TRAY);
  937. (void) sjcd_receive_status();
  938. }
  939. return (0);
  940. }
  941. #if defined( SJCD_GATHER_STAT )
  942. case 0xABCD:{
  943. int s;
  944. #if defined( SJCD_TRACE )
  945. printk("SJCD: ioctl: statisticn");
  946. #endif
  947. if ((s =
  948.      verify_area(VERIFY_WRITE, (void *) arg,
  949.  sizeof(statistic))) == 0)
  950. copy_to_user((void *) arg, &statistic,
  951.      sizeof(statistic));
  952. return (s);
  953. }
  954. #endif
  955. default:
  956. return (-EINVAL);
  957. }
  958. }
  959. /*
  960.  * Invalidate internal buffers of the driver.
  961.  */
  962. static void sjcd_invalidate_buffers(void)
  963. {
  964. int i;
  965. for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1);
  966. sjcd_buf_out = -1;
  967. }
  968. /*
  969.  * Take care of the different block sizes between cdrom and Linux.
  970.  * When Linux gets variable block sizes this will probably go away.
  971.  */
  972. #define CURRENT_IS_VALID                                      
  973.     ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && 
  974.       CURRENT->cmd == READ && CURRENT->sector != -1 )
  975. static void sjcd_transfer(void)
  976. {
  977. #if defined( SJCD_TRACE )
  978. printk("SJCD: transfer:n");
  979. #endif
  980. if (CURRENT_IS_VALID) {
  981. while (CURRENT->nr_sectors) {
  982. int i, bn = CURRENT->sector / 4;
  983. for (i = 0;
  984.      i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn;
  985.      i++);
  986. if (i < SJCD_BUF_SIZ) {
  987. int offs =
  988.     (i * 4 + (CURRENT->sector & 3)) * 512;
  989. int nr_sectors = 4 - (CURRENT->sector & 3);
  990. if (sjcd_buf_out != i) {
  991. sjcd_buf_out = i;
  992. if (sjcd_buf_bn[i] != bn) {
  993. sjcd_buf_out = -1;
  994. continue;
  995. }
  996. }
  997. if (nr_sectors > CURRENT->nr_sectors)
  998. nr_sectors = CURRENT->nr_sectors;
  999. #if defined( SJCD_TRACE )
  1000. printk("SJCD: copy outn");
  1001. #endif
  1002. memcpy(CURRENT->buffer, sjcd_buf + offs,
  1003.        nr_sectors * 512);
  1004. CURRENT->nr_sectors -= nr_sectors;
  1005. CURRENT->sector += nr_sectors;
  1006. CURRENT->buffer += nr_sectors * 512;
  1007. } else {
  1008. sjcd_buf_out = -1;
  1009. break;
  1010. }
  1011. }
  1012. }
  1013. #if defined( SJCD_TRACE )
  1014. printk("SJCD: transfer: donen");
  1015. #endif
  1016. }
  1017. static void sjcd_poll(void)
  1018. {
  1019. #if defined( SJCD_GATHER_STAT )
  1020. /*
  1021.  * Update total number of ticks.
  1022.  */
  1023. statistic.ticks++;
  1024. statistic.tticks[sjcd_transfer_state]++;
  1025. #endif
  1026.       ReSwitch:switch (sjcd_transfer_state) {
  1027. case SJCD_S_IDLE:{
  1028. #if defined( SJCD_GATHER_STAT )
  1029. statistic.idle_ticks++;
  1030. #endif
  1031. #if defined( SJCD_TRACE )
  1032. printk("SJCD_S_IDLEn");
  1033. #endif
  1034. return;
  1035. }
  1036. case SJCD_S_START:{
  1037. #if defined( SJCD_GATHER_STAT )
  1038. statistic.start_ticks++;
  1039. #endif
  1040. sjcd_send_cmd(SCMD_GET_STATUS);
  1041. sjcd_transfer_state =
  1042.     sjcd_mode ==
  1043.     SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE;
  1044. sjcd_transfer_timeout = 500;
  1045. #if defined( SJCD_TRACE )
  1046. printk("SJCD_S_START: goto SJCD_S_%s moden",
  1047.        sjcd_transfer_state ==
  1048.        SJCD_S_READ ? "READ" : "MODE");
  1049. #endif
  1050. break;
  1051. }
  1052. case SJCD_S_MODE:{
  1053. if (sjcd_check_status()) {
  1054. /*
  1055.  * Previous command is completed.
  1056.  */
  1057. if (!sjcd_status_valid
  1058.     || sjcd_command_failed) {
  1059. #if defined( SJCD_TRACE )
  1060. printk
  1061.     ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP moden");
  1062. #endif
  1063. sjcd_transfer_state = SJCD_S_STOP;
  1064. goto ReSwitch;
  1065. }
  1066. sjcd_mode = 0; /* unknown mode; should not be valid when failed */
  1067. sjcd_send_1_cmd(SCMD_SET_MODE,
  1068. SCMD_MODE_COOKED);
  1069. sjcd_transfer_state = SJCD_S_READ;
  1070. sjcd_transfer_timeout = 1000;
  1071. #if defined( SJCD_TRACE )
  1072. printk
  1073.     ("SJCD_S_MODE: goto SJCD_S_READ moden");
  1074. #endif
  1075. }
  1076. #if defined( SJCD_GATHER_STAT )
  1077. else
  1078. statistic.mode_ticks++;
  1079. #endif
  1080. break;
  1081. }
  1082. case SJCD_S_READ:{
  1083. if (sjcd_status_valid ? 1 : sjcd_check_status()) {
  1084. /*
  1085.  * Previous command is completed.
  1086.  */
  1087. if (!sjcd_status_valid
  1088.     || sjcd_command_failed) {
  1089. #if defined( SJCD_TRACE )
  1090. printk
  1091.     ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP moden");
  1092. #endif
  1093. sjcd_transfer_state = SJCD_S_STOP;
  1094. goto ReSwitch;
  1095. }
  1096. if (!sjcd_media_is_available) {
  1097. #if defined( SJCD_TRACE )
  1098. printk
  1099.     ("SJCD_S_READ: no disk: goto to SJCD_S_STOP moden");
  1100. #endif
  1101. sjcd_transfer_state = SJCD_S_STOP;
  1102. goto ReSwitch;
  1103. }
  1104. if (sjcd_mode != SCMD_MODE_COOKED) {
  1105. /*
  1106.  * We seem to come from set mode. So discard one byte of result.
  1107.  */
  1108. if (sjcd_load_response
  1109.     (&sjcd_mode, 1) != 0) {
  1110. #if defined( SJCD_TRACE )
  1111. printk
  1112.     ("SJCD_S_READ: load failed: goto to SJCD_S_STOP moden");
  1113. #endif
  1114. sjcd_transfer_state =
  1115.     SJCD_S_STOP;
  1116. goto ReSwitch;
  1117. }
  1118. if (sjcd_mode != SCMD_MODE_COOKED) {
  1119. #if defined( SJCD_TRACE )
  1120. printk
  1121.     ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP moden");
  1122. #endif
  1123. sjcd_transfer_state =
  1124.     SJCD_S_STOP;
  1125. goto ReSwitch;
  1126. }
  1127. }
  1128. if (CURRENT_IS_VALID) {
  1129. struct sjcd_play_msf msf;
  1130. sjcd_next_bn = CURRENT->sector / 4;
  1131. hsg2msf(sjcd_next_bn, &msf.start);
  1132. msf.end.min = 0;
  1133. msf.end.sec = 0;
  1134. msf.end.frame = sjcd_read_count =
  1135.     SJCD_BUF_SIZ;
  1136. #if defined( SJCD_TRACE )
  1137. printk
  1138.     ("SJCD: ---reading msf-address %x:%x:%x  %x:%x:%xn",
  1139.      msf.start.min, msf.start.sec,
  1140.      msf.start.frame, msf.end.min,
  1141.      msf.end.sec, msf.end.frame);
  1142. printk
  1143.     ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%xn",
  1144.      sjcd_next_bn, sjcd_buf_in,
  1145.      sjcd_buf_out,
  1146.      sjcd_buf_bn[sjcd_buf_in]);
  1147. #endif
  1148. sjcd_send_6_cmd(SCMD_DATA_READ,
  1149. &msf);
  1150. sjcd_transfer_state = SJCD_S_DATA;
  1151. sjcd_transfer_timeout = 500;
  1152. #if defined( SJCD_TRACE )
  1153. printk
  1154.     ("SJCD_S_READ: go to SJCD_S_DATA moden");
  1155. #endif
  1156. } else {
  1157. #if defined( SJCD_TRACE )
  1158. printk
  1159.     ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP moden");
  1160. #endif
  1161. sjcd_transfer_state = SJCD_S_STOP;
  1162. goto ReSwitch;
  1163. }
  1164. }
  1165. #if defined( SJCD_GATHER_STAT )
  1166. else
  1167. statistic.read_ticks++;
  1168. #endif
  1169. break;
  1170. }
  1171. case SJCD_S_DATA:{
  1172. unsigned char stat;
  1173.       sjcd_s_data:stat =
  1174.     inb(SJCDPORT
  1175. (1));
  1176. #if defined( SJCD_TRACE )
  1177. printk("SJCD_S_DATA: status = 0x%02xn", stat);
  1178. #endif
  1179. if (SJCD_STATUS_AVAILABLE(stat)) {
  1180. /*
  1181.  * No data is waiting for us in the drive buffer. Status of operation
  1182.  * completion is available. Read and parse it.
  1183.  */
  1184. sjcd_load_status();
  1185. if (!sjcd_status_valid
  1186.     || sjcd_command_failed) {
  1187. #if defined( SJCD_TRACE )
  1188. printk
  1189.     ("SJCD: read block %d failed, maybe audio disk? Giving upn",
  1190.      sjcd_next_bn);
  1191. #endif
  1192. if (CURRENT_IS_VALID)
  1193. end_request(0);
  1194. #if defined( SJCD_TRACE )
  1195. printk
  1196.     ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP moden");
  1197. #endif
  1198. sjcd_transfer_state = SJCD_S_STOP;
  1199. goto ReSwitch;
  1200. }
  1201. if (!sjcd_media_is_available) {
  1202. printk
  1203.     ("SJCD_S_DATA: no disk: go to SJCD_S_STOP moden");
  1204. sjcd_transfer_state = SJCD_S_STOP;
  1205. goto ReSwitch;
  1206. }
  1207. sjcd_transfer_state = SJCD_S_READ;
  1208. goto ReSwitch;
  1209. } else if (SJCD_DATA_AVAILABLE(stat)) {
  1210. /*
  1211.  * One frame is read into device buffer. We must copy it to our memory.
  1212.  * Otherwise cdrom hangs up. Check to see if we have something to copy
  1213.  * to.
  1214.  */
  1215. if (!CURRENT_IS_VALID
  1216.     && sjcd_buf_in == sjcd_buf_out) {
  1217. #if defined( SJCD_TRACE )
  1218. printk
  1219.     ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP moden");
  1220. printk
  1221.     (" ... all the date would be discardedn");
  1222. #endif
  1223. sjcd_transfer_state = SJCD_S_STOP;
  1224. goto ReSwitch;
  1225. }
  1226. /*
  1227.  * Everything seems to be OK. Just read the frame and recalculate
  1228.  * indices.
  1229.  */
  1230. sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */
  1231. insb(SJCDPORT(2),
  1232.      sjcd_buf + 2048 * sjcd_buf_in, 2048);
  1233. #if defined( SJCD_TRACE )
  1234. printk
  1235.     ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%dn",
  1236.      sjcd_next_bn, sjcd_buf_in,
  1237.      sjcd_buf_out,
  1238.      sjcd_buf_bn[sjcd_buf_in]);
  1239. #endif
  1240. sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++;
  1241. if (sjcd_buf_out == -1)
  1242. sjcd_buf_out = sjcd_buf_in;
  1243. if (++sjcd_buf_in == SJCD_BUF_SIZ)
  1244. sjcd_buf_in = 0;
  1245. /*
  1246.  * Only one frame is ready at time. So we should turn over to wait for
  1247.  * another frame. If we need that, of course.
  1248.  */
  1249. if (--sjcd_read_count == 0) {
  1250. /*
  1251.  * OK, request seems to be precessed. Continue transferring...
  1252.  */
  1253. if (!sjcd_transfer_is_active) {
  1254. while (CURRENT_IS_VALID) {
  1255. /*
  1256.  * Continue transferring.
  1257.  */
  1258. sjcd_transfer();
  1259. if (CURRENT->
  1260.     nr_sectors ==
  1261.     0)
  1262. end_request
  1263.     (1);
  1264. else
  1265. break;
  1266. }
  1267. }
  1268. if (CURRENT_IS_VALID &&
  1269.     (CURRENT->sector / 4 <
  1270.      sjcd_next_bn
  1271.      || CURRENT->sector / 4 >
  1272.      sjcd_next_bn +
  1273.      SJCD_BUF_SIZ)) {
  1274. #if defined( SJCD_TRACE )
  1275. printk
  1276.     ("SJCD_S_DATA: can't read: go to SJCD_S_STOP moden");
  1277. #endif
  1278. sjcd_transfer_state =
  1279.     SJCD_S_STOP;
  1280. goto ReSwitch;
  1281. }
  1282. }
  1283. /*
  1284.  * Now we should turn around rather than wait for while.
  1285.  */
  1286. goto sjcd_s_data;
  1287. }
  1288. #if defined( SJCD_GATHER_STAT )
  1289. else
  1290. statistic.data_ticks++;
  1291. #endif
  1292. break;
  1293. }
  1294. case SJCD_S_STOP:{
  1295. sjcd_read_count = 0;
  1296. sjcd_send_cmd(SCMD_STOP);
  1297. sjcd_transfer_state = SJCD_S_STOPPING;
  1298. sjcd_transfer_timeout = 500;
  1299. #if defined( SJCD_GATHER_STAT )
  1300. statistic.stop_ticks++;
  1301. #endif
  1302. break;
  1303. }
  1304. case SJCD_S_STOPPING:{
  1305. unsigned char stat;
  1306. stat = inb(SJCDPORT(1));
  1307. #if defined( SJCD_TRACE )
  1308. printk("SJCD_S_STOP: status = 0x%02xn", stat);
  1309. #endif
  1310. if (SJCD_DATA_AVAILABLE(stat)) {
  1311. int i;
  1312. #if defined( SJCD_TRACE )
  1313. printk("SJCD_S_STOP: discard datan");
  1314. #endif
  1315. /*
  1316.  * Discard all the data from the pipe. Foolish method.
  1317.  */
  1318. for (i = 2048; i--;
  1319.      (void) inb(SJCDPORT(2)));
  1320. sjcd_transfer_timeout = 500;
  1321. } else if (SJCD_STATUS_AVAILABLE(stat)) {
  1322. sjcd_load_status();
  1323. if (sjcd_status_valid
  1324.     && sjcd_media_is_changed) {
  1325. sjcd_toc_uptodate = 0;
  1326. sjcd_invalidate_buffers();
  1327. }
  1328. if (CURRENT_IS_VALID) {
  1329. if (sjcd_status_valid)
  1330. sjcd_transfer_state =
  1331.     SJCD_S_READ;
  1332. else
  1333. sjcd_transfer_state =
  1334.     SJCD_S_START;
  1335. } else
  1336. sjcd_transfer_state = SJCD_S_IDLE;
  1337. goto ReSwitch;
  1338. }
  1339. #if defined( SJCD_GATHER_STAT )
  1340. else
  1341. statistic.stopping_ticks++;
  1342. #endif
  1343. break;
  1344. }
  1345. default:
  1346. printk("SJCD: poll: invalid state %dn",
  1347.        sjcd_transfer_state);
  1348. return;
  1349. }
  1350. if (--sjcd_transfer_timeout == 0) {
  1351. printk("SJCD: timeout in state %dn", sjcd_transfer_state);
  1352. while (CURRENT_IS_VALID)
  1353. end_request(0);
  1354. sjcd_send_cmd(SCMD_STOP);
  1355. sjcd_transfer_state = SJCD_S_IDLE;
  1356. goto ReSwitch;
  1357. }
  1358. /*
  1359.  * Get back in some time. 1 should be replaced with count variable to
  1360.  * avoid unnecessary testings.
  1361.  */
  1362. SJCD_SET_TIMER(sjcd_poll, 1);
  1363. }
  1364. static void do_sjcd_request(request_queue_t * q)
  1365. {
  1366. #if defined( SJCD_TRACE )
  1367. printk("SJCD: do_sjcd_request(%ld+%ld)n",
  1368.        CURRENT->sector, CURRENT->nr_sectors);
  1369. #endif
  1370. sjcd_transfer_is_active = 1;
  1371. while (CURRENT_IS_VALID) {
  1372. /*
  1373.  * Who of us are paranoiac?
  1374.  */
  1375. if (CURRENT->bh && !buffer_locked(CURRENT->bh))
  1376. panic(DEVICE_NAME ": block not locked");
  1377. sjcd_transfer();
  1378. if (CURRENT->nr_sectors == 0)
  1379. end_request(1);
  1380. else {
  1381. sjcd_buf_out = -1; /* Want to read a block not in buffer */
  1382. if (sjcd_transfer_state == SJCD_S_IDLE) {
  1383. if (!sjcd_toc_uptodate) {
  1384. if (sjcd_update_toc() < 0) {
  1385. printk
  1386.     ("SJCD: transfer: discardn");
  1387. while (CURRENT_IS_VALID)
  1388. end_request(0);
  1389. break;
  1390. }
  1391. }
  1392. sjcd_transfer_state = SJCD_S_START;
  1393. SJCD_SET_TIMER(sjcd_poll, HZ / 100);
  1394. }
  1395. break;
  1396. }
  1397. }
  1398. sjcd_transfer_is_active = 0;
  1399. #if defined( SJCD_TRACE )
  1400. printk
  1401.     ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%xn",
  1402.      sjcd_next_bn, sjcd_buf_in, sjcd_buf_out,
  1403.      sjcd_buf_bn[sjcd_buf_in]);
  1404. printk("do_sjcd_request endsn");
  1405. #endif
  1406. }
  1407. /*
  1408.  * Open the device special file. Check disk is in.
  1409.  */
  1410. int sjcd_open(struct inode *ip, struct file *fp)
  1411. {
  1412. /*
  1413.  * Check the presence of device.
  1414.  */
  1415. if (!sjcd_present)
  1416. return (-ENXIO);
  1417. /*
  1418.  * Only read operations are allowed. Really? (:-)
  1419.  */
  1420. if (fp->f_mode & 2)
  1421. return (-EROFS);
  1422. if (sjcd_open_count == 0) {
  1423. int s, sjcd_open_tries;
  1424. /* We don't know that, do we? */
  1425. /*
  1426.     sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
  1427. */
  1428. sjcd_mode = 0;
  1429. sjcd_door_was_open = 0;
  1430. sjcd_transfer_state = SJCD_S_IDLE;
  1431. sjcd_invalidate_buffers();
  1432. sjcd_status_valid = 0;
  1433. /*
  1434.  * Strict status checking.
  1435.  */
  1436. for (sjcd_open_tries = 4; --sjcd_open_tries;) {
  1437. if (!sjcd_status_valid)
  1438. sjcd_get_status();
  1439. if (!sjcd_status_valid) {
  1440. #if defined( SJCD_DIAGNOSTIC )
  1441. printk
  1442.     ("SJCD: open: timed out when check status.n");
  1443. #endif
  1444. goto err_out;
  1445. } else if (!sjcd_media_is_available) {
  1446. #if defined( SJCD_DIAGNOSTIC )
  1447. printk("SJCD: open: no disk in driven");
  1448. #endif
  1449. if (!sjcd_door_closed) {
  1450. sjcd_door_was_open = 1;
  1451. #if defined( SJCD_TRACE )
  1452. printk
  1453.     ("SJCD: open: close the trayn");
  1454. #endif
  1455. s = sjcd_tray_close();
  1456. if (s < 0 || !sjcd_status_valid
  1457.     || sjcd_command_failed) {
  1458. #if defined( SJCD_DIAGNOSTIC )
  1459. printk
  1460.     ("SJCD: open: tray close attempt failedn");
  1461. #endif
  1462. goto err_out;
  1463. }
  1464. continue;
  1465. } else
  1466. goto err_out;
  1467. }
  1468. break;
  1469. }
  1470. s = sjcd_tray_lock();
  1471. if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
  1472. #if defined( SJCD_DIAGNOSTIC )
  1473. printk("SJCD: open: tray lock attempt failedn");
  1474. #endif
  1475. goto err_out;
  1476. }
  1477. #if defined( SJCD_TRACE )
  1478. printk("SJCD: open: donen");
  1479. #endif
  1480. }
  1481. ++sjcd_open_count;
  1482. return (0);
  1483.       err_out:
  1484. return (-EIO);
  1485. }
  1486. /*
  1487.  * On close, we flush all sjcd blocks from the buffer cache.
  1488.  */
  1489. static int sjcd_release(struct inode *inode, struct file *file)
  1490. {
  1491. int s;
  1492. #if defined( SJCD_TRACE )
  1493. printk("SJCD: releasen");
  1494. #endif
  1495. if (--sjcd_open_count == 0) {
  1496. sjcd_invalidate_buffers();
  1497. s = sjcd_tray_unlock();
  1498. if (s < 0 || !sjcd_status_valid || sjcd_command_failed) {
  1499. #if defined( SJCD_DIAGNOSTIC )
  1500. printk
  1501.     ("SJCD: release: tray unlock attempt failed.n");
  1502. #endif
  1503. }
  1504. if (sjcd_door_was_open) {
  1505. s = sjcd_tray_open();
  1506. if (s < 0 || !sjcd_status_valid
  1507.     || sjcd_command_failed) {
  1508. #if defined( SJCD_DIAGNOSTIC )
  1509. printk
  1510.     ("SJCD: release: tray unload attempt failed.n");
  1511. #endif
  1512. }
  1513. }
  1514. }
  1515. return 0;
  1516. }
  1517. /*
  1518.  * A list of file operations allowed for this cdrom.
  1519.  */
  1520. static struct block_device_operations sjcd_fops = {
  1521. owner:THIS_MODULE,
  1522. open:sjcd_open,
  1523. release:sjcd_release,
  1524. ioctl:sjcd_ioctl,
  1525. check_media_change:sjcd_disk_change,
  1526. };
  1527. static int blksize = 2048;
  1528. static int secsize = 2048;
  1529. /*
  1530.  * Following stuff is intended for initialization of the cdrom. It
  1531.  * first looks for presence of device. If the device is present, it
  1532.  * will be reset. Then read the version of the drive and load status.
  1533.  * The version is two BCD-coded bytes.
  1534.  */
  1535. static struct {
  1536. unsigned char major, minor;
  1537. } sjcd_version;
  1538. /*
  1539.  * Test for presence of drive and initialize it. Called at boot time.
  1540.  * Probe cdrom, find out version and status.
  1541.  */
  1542. int __init sjcd_init(void)
  1543. {
  1544. int i;
  1545. printk(KERN_INFO
  1546.        "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.n",
  1547.        SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR);
  1548. #if defined( SJCD_TRACE )
  1549. printk("SJCD: sjcd=0x%x: ", sjcd_base);
  1550. #endif
  1551. hardsect_size[MAJOR_NR] = &secsize;
  1552. blksize_size[MAJOR_NR] = &blksize;
  1553. if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
  1554. printk("SJCD: Unable to get major %d for Sanyo CD-ROMn",
  1555.        MAJOR_NR);
  1556. return (-EIO);
  1557. }
  1558. blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
  1559. read_ahead[MAJOR_NR] = 4;
  1560. register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0);
  1561. if (check_region(sjcd_base, 4)) {
  1562. printk
  1563.     ("SJCD: Init failed, I/O port (%X) is already in usen",
  1564.      sjcd_base);
  1565. sjcd_cleanup();
  1566. return (-EIO);
  1567. }
  1568. /*
  1569.  * Check for card. Since we are booting now, we can't use standard
  1570.  * wait algorithm.
  1571.  */
  1572. printk(KERN_INFO "SJCD: Resetting: ");
  1573. sjcd_send_cmd(SCMD_RESET);
  1574. for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
  1575. unsigned long timer;
  1576. /*
  1577.  * Wait 10ms approx.
  1578.  */
  1579. for (timer = jiffies; time_before_eq(jiffies, timer););
  1580. if ((i % 100) == 0)
  1581. printk(".");
  1582. (void) sjcd_check_status();
  1583. }
  1584. if (i == 0 || sjcd_command_failed) {
  1585. printk(" reset failed, no drive found.n");
  1586. sjcd_cleanup();
  1587. return (-EIO);
  1588. } else
  1589. printk("n");
  1590. /*
  1591.  * Get and print out cdrom version.
  1592.  */
  1593. printk(KERN_INFO "SJCD: Getting version: ");
  1594. sjcd_send_cmd(SCMD_GET_VERSION);
  1595. for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
  1596. unsigned long timer;
  1597. /*
  1598.  * Wait 10ms approx.
  1599.  */
  1600. for (timer = jiffies; time_before_eq(jiffies, timer););
  1601. if ((i % 100) == 0)
  1602. printk(".");
  1603. (void) sjcd_check_status();
  1604. }
  1605. if (i == 0 || sjcd_command_failed) {
  1606. printk(" get version failed, no drive found.n");
  1607. sjcd_cleanup();
  1608. return (-EIO);
  1609. }
  1610. if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
  1611. printk(" %1x.%02xn", (int) sjcd_version.major,
  1612.        (int) sjcd_version.minor);
  1613. } else {
  1614. printk(" read version failed, no drive found.n");
  1615. sjcd_cleanup();
  1616. return (-EIO);
  1617. }
  1618. /*
  1619.  * Check and print out the tray state. (if it is needed?).
  1620.  */
  1621. if (!sjcd_status_valid) {
  1622. printk(KERN_INFO "SJCD: Getting status: ");
  1623. sjcd_send_cmd(SCMD_GET_STATUS);
  1624. for (i = 1000; i > 0 && !sjcd_status_valid; --i) {
  1625. unsigned long timer;
  1626. /*
  1627.  * Wait 10ms approx.
  1628.  */
  1629. for (timer = jiffies;
  1630.      time_before_eq(jiffies, timer););
  1631. if ((i % 100) == 0)
  1632. printk(".");
  1633. (void) sjcd_check_status();
  1634. }
  1635. if (i == 0 || sjcd_command_failed) {
  1636. printk(" get status failed, no drive found.n");
  1637. sjcd_cleanup();
  1638. return (-EIO);
  1639. } else
  1640. printk("n");
  1641. }
  1642. printk(KERN_INFO "SJCD: Status: port=0x%x.n", sjcd_base);
  1643. devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
  1644.        S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
  1645. sjcd_present++;
  1646. return (0);
  1647. }
  1648. static int sjcd_cleanup(void)
  1649. {
  1650. if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
  1651. printk("SJCD: cannot unregister device.n");
  1652. else {
  1653. release_region(sjcd_base, 4);
  1654. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  1655. }
  1656. return (0);
  1657. }
  1658. void __exit sjcd_exit(void)
  1659. {
  1660. devfs_unregister(devfs_find_handle
  1661.  (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0));
  1662. if (sjcd_cleanup())
  1663. printk("SJCD: module: cannot be removed.n");
  1664. else
  1665. printk(KERN_INFO "SJCD: module: removed.n");
  1666. }
  1667. #ifdef MODULE
  1668. module_init(sjcd_init);
  1669. #endif
  1670. module_exit(sjcd_exit);
  1671. MODULE_LICENSE("GPL");