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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
  2. /*
  3. linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
  4.         Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
  5.         based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
  6.         
  7.         For all kind of other information about the GoldStar CDROM
  8.         and this Linux device driver I installed a WWW-URL:
  9.         http://linux.rz.fh-hannover.de/~raupach        
  10.              If you are the editor of a Linux CD, you should
  11.              enable gscd.c within your boot floppy kernel and
  12.              send me one of your CDs for free.
  13.         --------------------------------------------------------------------
  14. This program is free software; you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation; either version 2, or (at your option)
  17. any later version.
  18. This program is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. GNU General Public License for more details.
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. --------------------------------------------------------------------
  26. 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
  27.                    Removed init_module & cleanup_module in favor of 
  28.        module_init & module_exit.
  29.    Torben Mathiasen <tmm@image.dk>
  30. */
  31. /* These settings are for various debug-level. Leave they untouched ... */
  32. #define  NO_GSCD_DEBUG
  33. #define  NO_IOCTL_DEBUG
  34. #define  NO_MODULE_DEBUG
  35. #define  NO_FUTURE_WORK
  36. /*------------------------*/
  37. #include <linux/module.h>
  38. #include <linux/slab.h>
  39. #include <linux/errno.h>
  40. #include <linux/signal.h>
  41. #include <linux/sched.h>
  42. #include <linux/timer.h>
  43. #include <linux/fs.h>
  44. #include <linux/mm.h>
  45. #include <linux/kernel.h>
  46. #include <linux/cdrom.h>
  47. #include <linux/ioport.h>
  48. #include <linux/major.h>
  49. #include <linux/string.h>
  50. #include <linux/init.h>
  51. #include <linux/devfs_fs_kernel.h>
  52. #include <asm/system.h>
  53. #include <asm/io.h>
  54. #include <asm/uaccess.h>
  55. #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
  56. #include <linux/blk.h>
  57. #define gscd_port gscd /* for compatible parameter passing with "insmod" */
  58. #include "gscd.h"
  59. static int gscd_blocksizes[1] = { 512 };
  60. static int gscdPresent = 0;
  61. static unsigned char gscd_buf[2048]; /* buffer for block size conversion */
  62. static int gscd_bn = -1;
  63. static short gscd_port = GSCD_BASE_ADDR;
  64. MODULE_PARM(gscd, "h");
  65. /* Kommt spaeter vielleicht noch mal dran ...
  66.  *    static DECLARE_WAIT_QUEUE_HEAD(gscd_waitq);
  67.  */
  68. static void gscd_transfer(void);
  69. static void gscd_read_cmd(void);
  70. static void gscd_hsg2msf(long hsg, struct msf *msf);
  71. static void gscd_bin2bcd(unsigned char *p);
  72. /* Schnittstellen zum Kern/FS */
  73. static void do_gscd_request(request_queue_t *);
  74. static void __do_gscd_request(unsigned long dummy);
  75. static int gscd_ioctl(struct inode *, struct file *, unsigned int,
  76.       unsigned long);
  77. static int gscd_open(struct inode *, struct file *);
  78. static int gscd_release(struct inode *, struct file *);
  79. static int check_gscd_med_chg(kdev_t);
  80. /*      GoldStar Funktionen    */
  81. static void cc_Reset(void);
  82. static int wait_drv_ready(void);
  83. static int find_drives(void);
  84. static void cmd_out(int, char *, char *, int);
  85. static void cmd_status(void);
  86. static void cc_Ident(char *);
  87. static void cc_SetSpeed(void);
  88. static void init_cd_drive(int);
  89. static int get_status(void);
  90. static void clear_Audio(void);
  91. static void cc_invalidate(void);
  92. /* some things for the next version */
  93. #ifdef FUTURE_WORK
  94. static void update_state(void);
  95. static long gscd_msf2hsg(struct msf *mp);
  96. static int gscd_bcd2bin(unsigned char bcd);
  97. #endif
  98. /*    common GoldStar Initialization    */
  99. static int my_gscd_init(void);
  100. /*      lo-level cmd-Funktionen    */
  101. static void cmd_info_in(char *, int);
  102. static void cmd_end(void);
  103. static void cmd_read_b(char *, int, int);
  104. static void cmd_read_w(char *, int, int);
  105. static int cmd_unit_alive(void);
  106. static void cmd_write_cmd(char *);
  107. /*      GoldStar Variablen     */
  108. static int curr_drv_state;
  109. static int drv_states[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  110. static int drv_mode;
  111. static int disk_state;
  112. static int speed;
  113. static int ndrives;
  114. static unsigned char drv_num_read;
  115. static unsigned char f_dsk_valid;
  116. static unsigned char current_drive;
  117. static unsigned char f_drv_ok;
  118. static char f_AudioPlay;
  119. static char f_AudioPause;
  120. static int AudioStart_m;
  121. static int AudioStart_f;
  122. static int AudioEnd_m;
  123. static int AudioEnd_f;
  124. static struct timer_list gscd_timer;
  125. static struct block_device_operations gscd_fops = {
  126. owner:THIS_MODULE,
  127. open:gscd_open,
  128. release:gscd_release,
  129. ioctl:gscd_ioctl,
  130. check_media_change:check_gscd_med_chg,
  131. };
  132. /* 
  133.  * Checking if the media has been changed
  134.  * (not yet implemented)
  135.  */
  136. static int check_gscd_med_chg(kdev_t full_dev)
  137. {
  138. int target;
  139. target = MINOR(full_dev);
  140. if (target > 0) {
  141. printk
  142.     ("GSCD: GoldStar CD-ROM request error: invalid device.n");
  143. return 0;
  144. }
  145. #ifdef GSCD_DEBUG
  146. printk("gscd: check_med_changen");
  147. #endif
  148. return 0;
  149. }
  150. #ifndef MODULE
  151. /* Using new interface for kernel-parameters */
  152. static int __init gscd_setup(char *str)
  153. {
  154. int ints[2];
  155. (void) get_options(str, ARRAY_SIZE(ints), ints);
  156. if (ints[0] > 0) {
  157. gscd_port = ints[1];
  158. }
  159. return 1;
  160. }
  161. __setup("gscd=", gscd_setup);
  162. #endif
  163. static int gscd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
  164.       unsigned long arg)
  165. {
  166. unsigned char to_do[10];
  167. unsigned char dummy;
  168. switch (cmd) {
  169. case CDROMSTART: /* Spin up the drive */
  170. /* Don't think we can do this.  Even if we could,
  171.  * I think the drive times out and stops after a while
  172.  * anyway.  For now, ignore it.
  173.  */
  174. return 0;
  175. case CDROMRESUME: /* keine Ahnung was das ist */
  176. return 0;
  177. case CDROMEJECT:
  178. cmd_status();
  179. to_do[0] = CMD_TRAY_CTL;
  180. cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
  181. return 0;
  182. default:
  183. return -EINVAL;
  184. }
  185. }
  186. /*
  187.  * Take care of the different block sizes between cdrom and Linux.
  188.  * When Linux gets variable block sizes this will probably go away.
  189.  */
  190. static void gscd_transfer(void)
  191. {
  192. long offs;
  193. while (CURRENT->nr_sectors > 0 && gscd_bn == CURRENT->sector / 4) {
  194. offs = (CURRENT->sector & 3) * 512;
  195. memcpy(CURRENT->buffer, gscd_buf + offs, 512);
  196. CURRENT->nr_sectors--;
  197. CURRENT->sector++;
  198. CURRENT->buffer += 512;
  199. }
  200. }
  201. /*
  202.  * I/O request routine called from Linux kernel.
  203.  */
  204. static void do_gscd_request(request_queue_t * q)
  205. {
  206. __do_gscd_request(0);
  207. }
  208. static void __do_gscd_request(unsigned long dummy)
  209. {
  210. unsigned int block, dev;
  211. unsigned int nsect;
  212.       repeat:
  213. if (QUEUE_EMPTY || CURRENT->rq_status == RQ_INACTIVE)
  214. goto out;
  215. INIT_REQUEST;
  216. dev = MINOR(CURRENT->rq_dev);
  217. block = CURRENT->sector;
  218. nsect = CURRENT->nr_sectors;
  219. if (QUEUE_EMPTY || CURRENT->sector == -1)
  220. goto out;
  221. if (CURRENT->cmd != READ) {
  222. printk("GSCD: bad cmd %dn", CURRENT->cmd);
  223. end_request(0);
  224. goto repeat;
  225. }
  226. if (MINOR(CURRENT->rq_dev) != 0) {
  227. printk("GSCD: this version supports only one devicen");
  228. end_request(0);
  229. goto repeat;
  230. }
  231. gscd_transfer();
  232. /* if we satisfied the request from the buffer, we're done. */
  233. if (CURRENT->nr_sectors == 0) {
  234. end_request(1);
  235. goto repeat;
  236. }
  237. #ifdef GSCD_DEBUG
  238. printk("GSCD: dev %d, block %d, nsect %dn", dev, block, nsect);
  239. #endif
  240. gscd_read_cmd();
  241.       out:
  242. return;
  243. }
  244. /*
  245.  * Check the result of the set-mode command.  On success, send the
  246.  * read-data command.
  247.  */
  248. static void gscd_read_cmd(void)
  249. {
  250. long block;
  251. struct gscd_Play_msf gscdcmd;
  252. char cmd[] = { CMD_READ, 0x80, 0, 0, 0, 0, 1 }; /* cmd mode M-S-F secth sectl */
  253. cmd_status();
  254. if (disk_state & (ST_NO_DISK | ST_DOOR_OPEN)) {
  255. printk("GSCD: no disk or door openn");
  256. end_request(0);
  257. } else {
  258. if (disk_state & ST_INVALID) {
  259. printk("GSCD: disk invalidn");
  260. end_request(0);
  261. } else {
  262. gscd_bn = -1; /* purge our buffer */
  263. block = CURRENT->sector / 4;
  264. gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
  265. cmd[2] = gscdcmd.start.min;
  266. cmd[3] = gscdcmd.start.sec;
  267. cmd[4] = gscdcmd.start.frame;
  268. #ifdef GSCD_DEBUG
  269. printk("GSCD: read msf %d:%d:%dn", cmd[2], cmd[3],
  270.        cmd[4]);
  271. #endif
  272. cmd_out(TYPE_DATA, (char *) &cmd,
  273. (char *) &gscd_buf[0], 1);
  274. gscd_bn = CURRENT->sector / 4;
  275. gscd_transfer();
  276. end_request(1);
  277. }
  278. }
  279. SET_TIMER(__do_gscd_request, 1);
  280. }
  281. /*
  282.  * Open the device special file.  Check that a disk is in.
  283.  */
  284. static int gscd_open(struct inode *ip, struct file *fp)
  285. {
  286. int st;
  287. #ifdef GSCD_DEBUG
  288. printk("GSCD: openn");
  289. #endif
  290. if (gscdPresent == 0)
  291. return -ENXIO; /* no hardware */
  292. get_status();
  293. st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
  294. if (st) {
  295. printk("GSCD: no disk or door openn");
  296. return -ENXIO;
  297. }
  298. /* if (updateToc() < 0)
  299. return -EIO;
  300. */
  301. return 0;
  302. }
  303. /*
  304.  * On close, we flush all gscd blocks from the buffer cache.
  305.  */
  306. static int gscd_release(struct inode *inode, struct file *file)
  307. {
  308. #ifdef GSCD_DEBUG
  309. printk("GSCD: releasen");
  310. #endif
  311. gscd_bn = -1;
  312. return 0;
  313. }
  314. int get_status(void)
  315. {
  316. int status;
  317. cmd_status();
  318. status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
  319. if (status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) {
  320. cc_invalidate();
  321. return 1;
  322. } else {
  323. return 0;
  324. }
  325. }
  326. void cc_invalidate(void)
  327. {
  328. drv_num_read = 0xFF;
  329. f_dsk_valid = 0xFF;
  330. current_drive = 0xFF;
  331. f_drv_ok = 0xFF;
  332. clear_Audio();
  333. }
  334. void clear_Audio(void)
  335. {
  336. f_AudioPlay = 0;
  337. f_AudioPause = 0;
  338. AudioStart_m = 0;
  339. AudioStart_f = 0;
  340. AudioEnd_m = 0;
  341. AudioEnd_f = 0;
  342. }
  343. /*
  344.  *   waiting ?  
  345.  */
  346. int wait_drv_ready(void)
  347. {
  348. int found, read;
  349. do {
  350. found = inb(GSCDPORT(0));
  351. found &= 0x0f;
  352. read = inb(GSCDPORT(0));
  353. read &= 0x0f;
  354. } while (read != found);
  355. #ifdef GSCD_DEBUG
  356. printk("Wait for: %dn", read);
  357. #endif
  358. return read;
  359. }
  360. void cc_Ident(char *respons)
  361. {
  362. char to_do[] = { CMD_IDENT, 0, 0 };
  363. cmd_out(TYPE_INFO, (char *) &to_do, (char *) respons, (int) 0x1E);
  364. }
  365. void cc_SetSpeed(void)
  366. {
  367. char to_do[] = { CMD_SETSPEED, 0, 0 };
  368. char dummy;
  369. if (speed > 0) {
  370. to_do[1] = speed & 0x0F;
  371. cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
  372. }
  373. }
  374. void cc_Reset(void)
  375. {
  376. char to_do[] = { CMD_RESET, 0 };
  377. char dummy;
  378. cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
  379. }
  380. void cmd_status(void)
  381. {
  382. char to_do[] = { CMD_STATUS, 0 };
  383. char dummy;
  384. cmd_out(TYPE_INFO, (char *) &to_do, (char *) &dummy, 0);
  385. #ifdef GSCD_DEBUG
  386. printk("GSCD: Status: %dn", disk_state);
  387. #endif
  388. }
  389. void cmd_out(int cmd_type, char *cmd, char *respo_buf, int respo_count)
  390. {
  391. int result;
  392. result = wait_drv_ready();
  393. if (result != drv_mode) {
  394. unsigned long test_loops = 0xFFFF;
  395. int i, dummy;
  396. outb(curr_drv_state, GSCDPORT(0));
  397. /* LOCLOOP_170 */
  398. do {
  399. result = wait_drv_ready();
  400. test_loops--;
  401. } while ((result != drv_mode) && (test_loops > 0));
  402. if (result != drv_mode) {
  403. disk_state = ST_x08 | ST_x04 | ST_INVALID;
  404. return;
  405. }
  406. /* ...and waiting */
  407. for (i = 1, dummy = 1; i < 0xFFFF; i++) {
  408. dummy *= i;
  409. }
  410. }
  411. /* LOC_172 */
  412. /* check the unit */
  413. /* and wake it up */
  414. if (cmd_unit_alive() != 0x08) {
  415. /* LOC_174 */
  416. /* game over for this unit */
  417. disk_state = ST_x08 | ST_x04 | ST_INVALID;
  418. return;
  419. }
  420. /* LOC_176 */
  421. #ifdef GSCD_DEBUG
  422. printk("LOC_176 ");
  423. #endif
  424. if (drv_mode == 0x09) {
  425. /* magic... */
  426. printk("GSCD: magic ...n");
  427. outb(result, GSCDPORT(2));
  428. }
  429. /* write the command to the drive */
  430. cmd_write_cmd(cmd);
  431. /* LOC_178 */
  432. for (;;) {
  433. result = wait_drv_ready();
  434. if (result != drv_mode) {
  435. /* LOC_179 */
  436. if (result == 0x04) { /* Mode 4 */
  437. /* LOC_205 */
  438. #ifdef GSCD_DEBUG
  439. printk("LOC_205 ");
  440. #endif
  441. disk_state = inb(GSCDPORT(2));
  442. do {
  443. result = wait_drv_ready();
  444. } while (result != drv_mode);
  445. return;
  446. } else {
  447. if (result == 0x06) { /* Mode 6 */
  448. /* LOC_181 */
  449. #ifdef GSCD_DEBUG
  450. printk("LOC_181 ");
  451. #endif
  452. if (cmd_type == TYPE_DATA) {
  453. /* read data */
  454. /* LOC_184 */
  455. if (drv_mode == 9) {
  456. /* read the data to the buffer (word) */
  457. /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
  458. cmd_read_w
  459.     (respo_buf,
  460.      respo_count,
  461.      CD_FRAMESIZE /
  462.      2);
  463. return;
  464. } else {
  465. /* read the data to the buffer (byte) */
  466. /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
  467. cmd_read_b
  468.     (respo_buf,
  469.      respo_count,
  470.      CD_FRAMESIZE);
  471. return;
  472. }
  473. } else {
  474. /* read the info to the buffer */
  475. cmd_info_in(respo_buf,
  476.     respo_count);
  477. return;
  478. }
  479. return;
  480. }
  481. }
  482. } else {
  483. disk_state = ST_x08 | ST_x04 | ST_INVALID;
  484. return;
  485. }
  486. } /* for (;;) */
  487. #ifdef GSCD_DEBUG
  488. printk("n");
  489. #endif
  490. }
  491. static void cmd_write_cmd(char *pstr)
  492. {
  493. int i, j;
  494. /* LOC_177 */
  495. #ifdef GSCD_DEBUG
  496. printk("LOC_177 ");
  497. #endif
  498. /* calculate the number of parameter */
  499. j = *pstr & 0x0F;
  500. /* shift it out */
  501. for (i = 0; i < j; i++) {
  502. outb(*pstr, GSCDPORT(2));
  503. pstr++;
  504. }
  505. }
  506. static int cmd_unit_alive(void)
  507. {
  508. int result;
  509. unsigned long max_test_loops;
  510. /* LOC_172 */
  511. #ifdef GSCD_DEBUG
  512. printk("LOC_172 ");
  513. #endif
  514. outb(curr_drv_state, GSCDPORT(0));
  515. max_test_loops = 0xFFFF;
  516. do {
  517. result = wait_drv_ready();
  518. max_test_loops--;
  519. } while ((result != 0x08) && (max_test_loops > 0));
  520. return result;
  521. }
  522. static void cmd_info_in(char *pb, int count)
  523. {
  524. int result;
  525. char read;
  526. /* read info */
  527. /* LOC_182 */
  528. #ifdef GSCD_DEBUG
  529. printk("LOC_182 ");
  530. #endif
  531. do {
  532. read = inb(GSCDPORT(2));
  533. if (count > 0) {
  534. *pb = read;
  535. pb++;
  536. count--;
  537. }
  538. /* LOC_183 */
  539. do {
  540. result = wait_drv_ready();
  541. } while (result == 0x0E);
  542. } while (result == 6);
  543. cmd_end();
  544. return;
  545. }
  546. static void cmd_read_b(char *pb, int count, int size)
  547. {
  548. int result;
  549. int i;
  550. /* LOC_188 */
  551. /* LOC_189 */
  552. #ifdef GSCD_DEBUG
  553. printk("LOC_189 ");
  554. #endif
  555. do {
  556. do {
  557. result = wait_drv_ready();
  558. } while (result != 6 || result == 0x0E);
  559. if (result != 6) {
  560. cmd_end();
  561. return;
  562. }
  563. #ifdef GSCD_DEBUG
  564. printk("LOC_191 ");
  565. #endif
  566. for (i = 0; i < size; i++) {
  567. *pb = inb(GSCDPORT(2));
  568. pb++;
  569. }
  570. count--;
  571. } while (count > 0);
  572. cmd_end();
  573. return;
  574. }
  575. static void cmd_end(void)
  576. {
  577. int result;
  578. /* LOC_204 */
  579. #ifdef GSCD_DEBUG
  580. printk("LOC_204 ");
  581. #endif
  582. do {
  583. result = wait_drv_ready();
  584. if (result == drv_mode) {
  585. return;
  586. }
  587. } while (result != 4);
  588. /* LOC_205 */
  589. #ifdef GSCD_DEBUG
  590. printk("LOC_205 ");
  591. #endif
  592. disk_state = inb(GSCDPORT(2));
  593. do {
  594. result = wait_drv_ready();
  595. } while (result != drv_mode);
  596. return;
  597. }
  598. static void cmd_read_w(char *pb, int count, int size)
  599. {
  600. int result;
  601. int i;
  602. #ifdef GSCD_DEBUG
  603. printk("LOC_185 ");
  604. #endif
  605. do {
  606. /* LOC_185 */
  607. do {
  608. result = wait_drv_ready();
  609. } while (result != 6 || result == 0x0E);
  610. if (result != 6) {
  611. cmd_end();
  612. return;
  613. }
  614. for (i = 0; i < size; i++) {
  615. /* na, hier muss ich noch mal drueber nachdenken */
  616. *pb = inw(GSCDPORT(2));
  617. pb++;
  618. }
  619. count--;
  620. } while (count > 0);
  621. cmd_end();
  622. return;
  623. }
  624. int __init find_drives(void)
  625. {
  626. int *pdrv;
  627. int drvnum;
  628. int subdrv;
  629. int i;
  630. speed = 0;
  631. pdrv = (int *) &drv_states;
  632. curr_drv_state = 0xFE;
  633. subdrv = 0;
  634. drvnum = 0;
  635. for (i = 0; i < 8; i++) {
  636. subdrv++;
  637. cmd_status();
  638. disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
  639. if (disk_state != (ST_x08 | ST_x04 | ST_INVALID)) {
  640. /* LOC_240 */
  641. *pdrv = curr_drv_state;
  642. init_cd_drive(drvnum);
  643. pdrv++;
  644. drvnum++;
  645. } else {
  646. if (subdrv < 2) {
  647. continue;
  648. } else {
  649. subdrv = 0;
  650. }
  651. }
  652. /*       curr_drv_state<<1;         <-- das geht irgendwie nicht */
  653. /* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
  654. curr_drv_state *= 2;
  655. curr_drv_state |= 1;
  656. #ifdef GSCD_DEBUG
  657. printk("DriveState: %dn", curr_drv_state);
  658. #endif
  659. }
  660. ndrives = drvnum;
  661. return drvnum;
  662. }
  663. void __init init_cd_drive(int num)
  664. {
  665. char resp[50];
  666. int i;
  667. printk("GSCD: init unit %dn", num);
  668. cc_Ident((char *) &resp);
  669. printk("GSCD: identification: ");
  670. for (i = 0; i < 0x1E; i++) {
  671. printk("%c", resp[i]);
  672. }
  673. printk("n");
  674. cc_SetSpeed();
  675. }
  676. #ifdef FUTURE_WORK
  677. /* return_done */
  678. static void update_state(void)
  679. {
  680. unsigned int AX;
  681. if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0) {
  682. if (disk_state == (ST_x08 | ST_x04 | ST_INVALID)) {
  683. AX = ST_INVALID;
  684. }
  685. if ((disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01))
  686.     == 0) {
  687. invalidate();
  688. f_drv_ok = 0;
  689. }
  690. AX |= 0x8000;
  691. }
  692. if (disk_state & ST_PLAYING) {
  693. AX |= 0x200;
  694. }
  695. AX |= 0x100;
  696. /* pkt_esbx = AX; */
  697. disk_state = 0;
  698. }
  699. #endif
  700. /* Init for the Module-Version */
  701. int init_gscd(void)
  702. {
  703. long err;
  704. /* call the GoldStar-init */
  705. err = my_gscd_init();
  706. if (err < 0) {
  707. return err;
  708. } else {
  709. printk(KERN_INFO "Happy GoldStar !n");
  710. return 0;
  711. }
  712. }
  713. void __exit exit_gscd(void)
  714. {
  715. CLEAR_TIMER;
  716. devfs_unregister(devfs_find_handle
  717.  (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0));
  718. if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
  719. printk("What's that: can't unregister GoldStar-modulen");
  720. return;
  721. }
  722. blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
  723. release_region(gscd_port, 4);
  724. printk(KERN_INFO "GoldStar-module released.n");
  725. }
  726. #ifdef MODULE
  727. module_init(init_gscd);
  728. #endif
  729. module_exit(exit_gscd);
  730. /* Test for presence of drive and initialize it.  Called only at boot time. */
  731. int __init gscd_init(void)
  732. {
  733. return my_gscd_init();
  734. }
  735. /* This is the common initialisation for the GoldStar drive. */
  736. /* It is called at boot time AND for module init.           */
  737. int __init my_gscd_init(void)
  738. {
  739. int i;
  740. int result;
  741. printk(KERN_INFO "GSCD: version %sn", GSCD_VERSION);
  742. printk(KERN_INFO
  743.        "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.n",
  744.        gscd_port);
  745. if (check_region(gscd_port, 4)) {
  746. printk
  747.     ("GSCD: Init failed, I/O port (%X) already in use.n",
  748.      gscd_port);
  749. return -EIO;
  750. }
  751. /* check for card */
  752. result = wait_drv_ready();
  753. if (result == 0x09) {
  754. printk("GSCD: DMA kann ich noch nicht!n");
  755. return -EIO;
  756. }
  757. if (result == 0x0b) {
  758. drv_mode = result;
  759. i = find_drives();
  760. if (i == 0) {
  761. printk
  762.     ("GSCD: GoldStar CD-ROM Drive is not found.n");
  763. return -EIO;
  764. }
  765. }
  766. if ((result != 0x0b) && (result != 0x09)) {
  767. printk
  768.     ("GSCD: GoldStar Interface Adapter does not exist or H/W errorn");
  769. return -EIO;
  770. }
  771. /* reset all drives */
  772. i = 0;
  773. while (drv_states[i] != 0) {
  774. curr_drv_state = drv_states[i];
  775. printk(KERN_INFO "GSCD: Reset unit %d ... ", i);
  776. cc_Reset();
  777. printk("donen");
  778. i++;
  779. }
  780. if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
  781. printk
  782.     ("GSCD: Unable to get major %d for GoldStar CD-ROMn",
  783.      MAJOR_NR);
  784. return -EIO;
  785. }
  786. devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
  787.        S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
  788. blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
  789. blksize_size[MAJOR_NR] = gscd_blocksizes;
  790. read_ahead[MAJOR_NR] = 4;
  791. disk_state = 0;
  792. gscdPresent = 1;
  793. request_region(gscd_port, 4, "gscd");
  794. register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &gscd_fops, 0);
  795. printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.n");
  796. return 0;
  797. }
  798. static void gscd_hsg2msf(long hsg, struct msf *msf)
  799. {
  800. hsg += CD_MSF_OFFSET;
  801. msf->min = hsg / (CD_FRAMES * CD_SECS);
  802. hsg %= CD_FRAMES * CD_SECS;
  803. msf->sec = hsg / CD_FRAMES;
  804. msf->frame = hsg % CD_FRAMES;
  805. gscd_bin2bcd(&msf->min); /* convert to BCD */
  806. gscd_bin2bcd(&msf->sec);
  807. gscd_bin2bcd(&msf->frame);
  808. }
  809. static void gscd_bin2bcd(unsigned char *p)
  810. {
  811. int u, t;
  812. u = *p % 10;
  813. t = *p / 10;
  814. *p = u | (t << 4);
  815. }
  816. #ifdef FUTURE_WORK
  817. static long gscd_msf2hsg(struct msf *mp)
  818. {
  819. return gscd_bcd2bin(mp->frame)
  820.     + gscd_bcd2bin(mp->sec) * CD_FRAMES
  821.     + gscd_bcd2bin(mp->min) * CD_FRAMES * CD_SECS - CD_MSF_OFFSET;
  822. }
  823. static int gscd_bcd2bin(unsigned char bcd)
  824. {
  825. return (bcd >> 4) * 10 + (bcd & 0xF);
  826. }
  827. #endif
  828. MODULE_AUTHOR("Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>");
  829. MODULE_LICENSE("GPL");
  830. EXPORT_NO_SYMBOLS;