gscd.c 19 KB

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