MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / cdrom / aztcd.c
blobb6a14c80e237912464ce0eb7c6c9fe9a038c788f
1 #define AZT_VERSION "2.60"
3 /* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $
4 linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver
6 Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de)
8 based on Mitsumi CDROM driver by Martin Hariss and preworks by
9 Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby
10 Schirmer.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 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.
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.
26 HISTORY
27 V0.0 Adaption to Aztech CD268-01A Version 1.3
28 Version is PRE_ALPHA, unresolved points:
29 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW
30 thus driver causes CPU overhead and is very slow
31 2. could not find a way to stop the drive, when it is
32 in data read mode, therefore I had to set
33 msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one
34 frame can be read in sequence, this is also the reason for
35 3. getting 'timeout in state 4' messages, but nevertheless
36 it works
37 W.Zimmermann, Oct. 31, 1994
38 V0.1 Version is ALPHA, problems #2 and #3 resolved.
39 W.Zimmermann, Nov. 3, 1994
40 V0.2 Modification to some comments, debugging aids for partial test
41 with Borland C under DOS eliminated. Timer interrupt wait
42 STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented;
43 use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_
44 SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy
45 waiting seems better to me than interrupt rescheduling.
46 Besides that, when used in the wrong place, STEN_LOW_WAIT causes
47 kernel panic.
48 In function aztPlay command ACMD_PLAY_AUDIO added, should make
49 audio functions work. The Aztech drive needs different commands
50 to read data tracks and play audio tracks.
51 W.Zimmermann, Nov. 8, 1994
52 V0.3 Recognition of missing drive during boot up improved (speeded up).
53 W.Zimmermann, Nov. 13, 1994
54 V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll)
55 including removal of all 'goto' commands. :-);
56 J. Nardone, Nov. 14, 1994
57 V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had
58 to make some "compatibility" defines in azt.h; please note,
59 that the source file was renamed to azt.c, the include file to
60 azt.h
61 Speeded up drive recognition during init (will be a little bit
62 slower than before if no drive is installed!); suggested by
63 Robby Schirmer.
64 read_count declared volatile and set to AZT_BUF_SIZ to make
65 drive faster (now 300kB/sec, was 60kB/sec before, measured
66 by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096';
67 different AZT_BUF_SIZes were test, above 16 no further im-
68 provement seems to be possible; suggested by E.Moenkeberg.
69 W.Zimmermann, Nov. 18, 1994
70 V0.42 Included getAztStatus command in GetQChannelInfo() to allow
71 reading Q-channel info on audio disks, if drive is stopped,
72 and some other bug fixes in the audio stuff, suggested by
73 Robby Schirmer.
74 Added more ioctls (reading data in mode 1 and mode 2).
75 Completely removed the old azt_poll() routine.
76 Detection of ORCHID CDS-3110 in aztcd_init implemented.
77 Additional debugging aids (see the readme file).
78 W.Zimmermann, Dec. 9, 1994
79 V0.50 Autodetection of drives implemented.
80 W.Zimmermann, Dec. 12, 1994
81 V0.52 Prepared for including in the standard kernel, renamed most
82 variables to contain 'azt', included autoconf.h
83 W.Zimmermann, Dec. 16, 1994
84 V0.6 Version for being included in the standard Linux kernel.
85 Renamed source and header file to aztcd.c and aztcd.h
86 W.Zimmermann, Dec. 24, 1994
87 V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case
88 CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl,
89 which causes kernel crashes when playing audio, changed
90 include-files (config.h instead of autoconf.h, removed
91 delay.h)
92 W.Zimmermann, Jan. 8, 1995
93 V0.72 Some more modifications for adaption to the standard kernel.
94 W.Zimmermann, Jan. 16, 1995
95 V0.80 aztcd is now part of the standard kernel since version 1.1.83.
96 Modified the SET_TIMER and CLEAR_TIMER macros to comply with
97 the new timer scheme.
98 W.Zimmermann, Jan. 21, 1995
99 V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn
100 the channels on and off. If it works better with your drive,
101 please mail me. Also implemented ACMD_CLOSE for CDROMSTART.
102 W.Zimmermann, Jan. 24, 1995
103 V1.00 Implemented close and lock tray commands. Patches supplied by
104 Frank Racis
105 Added support for loadable MODULEs, so aztcd can now also be
106 loaded by insmod and removed by rmmod during run time
107 Werner Zimmermann, Mar. 24, 95
108 V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives
109 connected to Soundwave32 cards. Release for LST 2.1.
110 (still experimental)
111 Werner Zimmermann, May 8, 95
112 V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but
113 sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver-
114 sion needs an update of Dosemu0.60's cdrom.c, which will come with the
115 next revision of Dosemu.
116 Also Soundwave32 support now works.
117 Werner Zimmermann, May 22, 95
118 V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
119 Werner Zimmermann, July 4, 95
120 V1.40 Started multisession support. Implementation copied from mcdx.c
121 by Heiko Schlittermann. Not tested yet.
122 Werner Zimmermann, July 15, 95
123 V1.50 Implementation of ioctl CDROMRESET, continued multisession, began
124 XA, but still untested. Heavy modifications to drive status de-
125 tection.
126 Werner Zimmermann, July 25, 95
127 V1.60 XA support now should work. Speeded up drive recognition in cases,
128 where no drive is installed.
129 Werner Zimmermann, August 8, 1995
130 V1.70 Multisession support now is completed, but there is still not
131 enough testing done. If you can test it, please contact me. For
132 details please read Documentation/cdrom/aztcd
133 Werner Zimmermann, August 19, 1995
134 V1.80 Modification to suit the new kernel boot procedure introduced
135 with kernel 1.3.33. Will definitely not work with older kernels.
136 Programming done by Linus himself.
137 Werner Zimmermann, October 11, 1995
138 V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza.
139 Werner Zimmermann, October 21, 1995
140 V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory
141 structure was changed. README.aztcd is now /usr/src/docu-
142 mentation/cdrom/aztcd
143 Werner Zimmermann, November 10, 95
144 V2.10 Started to modify azt_poll to prevent reading beyond end of
145 tracks.
146 Werner Zimmermann, December 3, 95
147 V2.20 Changed some comments
148 Werner Zimmermann, April 1, 96
149 V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520
150 delivered by H.Berger with preworks by E.Moenkeberg.
151 Werner Zimmermann, April 29, 96
152 V2.40 Reorganized the placement of functions in the source code file
153 to reflect the layered approach; did not actually change code
154 Werner Zimmermann, May 1, 96
155 V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in
156 aztcd_ioctl; check_aztcd_media_change modified
157 Werner Zimmermann, May 16, 96
158 V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize
159 Adaption to linux kernel > 2.1.0
160 Werner Zimmermann, Nov 29, 97
162 November 1999 -- Make kernel-parameter implementation work with 2.3.x
163 Removed init_module & cleanup_module in favor of
164 module_init & module_exit.
165 Torben Mathiasen <tmm@image.dk>
168 #include <linux/version.h>
169 #include <linux/blkdev.h>
170 #include "aztcd.h"
172 #include <linux/module.h>
173 #include <linux/errno.h>
174 #include <linux/sched.h>
175 #include <linux/mm.h>
176 #include <linux/timer.h>
177 #include <linux/fs.h>
178 #include <linux/kernel.h>
179 #include <linux/cdrom.h>
180 #include <linux/ioport.h>
181 #include <linux/string.h>
182 #include <linux/major.h>
184 #include <linux/init.h>
186 #include <asm/system.h>
187 #include <asm/io.h>
189 #include <asm/uaccess.h>
191 /*###########################################################################
192 Defines
193 ###########################################################################
196 #define MAJOR_NR AZTECH_CDROM_MAJOR
197 #define QUEUE (azt_queue)
198 #define CURRENT elv_next_request(azt_queue)
199 #define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
200 delay_timer.function = (void *) (func); \
201 add_timer(&delay_timer);
203 #define CLEAR_TIMER del_timer(&delay_timer);
205 #define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
206 return value;}
207 #define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
208 return;}
210 /* Macros to switch the IDE-interface to the slave device and back to the master*/
211 #define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
212 outb_p(0x10,azt_port+6); \
213 outb_p(0x00,azt_port+7); \
214 outb_p(0x10,azt_port+6);
215 #define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
218 #if 0
219 #define AZT_TEST
220 #define AZT_TEST1 /* <int-..> */
221 #define AZT_TEST2 /* do_aztcd_request */
222 #define AZT_TEST3 /* AZT_S_state */
223 #define AZT_TEST4 /* QUICK_LOOP-counter */
224 #define AZT_TEST5 /* port(1) state */
225 #define AZT_DEBUG
226 #define AZT_DEBUG_MULTISESSION
227 #endif
229 static struct request_queue *azt_queue;
231 static int current_valid(void)
233 return CURRENT &&
234 CURRENT->cmd == READ &&
235 CURRENT->sector != -1;
238 #define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
239 #define AZT_BUF_SIZ 16
241 #define READ_TIMEOUT 3000
243 #define azt_port aztcd /*needed for the modutils */
245 /*##########################################################################
246 Type Definitions
247 ##########################################################################
249 enum azt_state_e { AZT_S_IDLE, /* 0 */
250 AZT_S_START, /* 1 */
251 AZT_S_MODE, /* 2 */
252 AZT_S_READ, /* 3 */
253 AZT_S_DATA, /* 4 */
254 AZT_S_STOP, /* 5 */
255 AZT_S_STOPPING /* 6 */
257 enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */
258 AZT_MODE_1, /*read mode for normal CD-ROMs */
259 AZT_MODE_2 /*read mode for XA CD-ROMs */
262 /*##########################################################################
263 Global Variables
264 ##########################################################################
266 static int aztPresent = 0;
268 static volatile int azt_transfer_is_active = 0;
270 static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */
271 #if AZT_PRIVATE_IOCTLS
272 static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */
273 #endif
275 static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
276 static volatile int azt_buf_in, azt_buf_out = -1;
277 static volatile int azt_error = 0;
278 static int azt_open_count = 0;
279 static volatile enum azt_state_e azt_state = AZT_S_IDLE;
280 #ifdef AZT_TEST3
281 static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
282 static volatile int azt_st_old = 0;
283 #endif
284 static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
286 static int azt_mode = -1;
287 static volatile int azt_read_count = 1;
289 static int azt_port = AZT_BASE_ADDR;
291 MODULE_PARM(azt_port, "i");
293 static int azt_port_auto[16] = AZT_BASE_AUTO;
295 static char azt_cont = 0;
296 static char azt_init_end = 0;
297 static char azt_auto_eject = AZT_AUTO_EJECT;
299 static int AztTimeout, AztTries;
300 static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
301 static struct timer_list delay_timer = TIMER_INITIALIZER(NULL, 0, 0);
303 static struct azt_DiskInfo DiskInfo;
304 static struct azt_Toc Toc[MAX_TRACKS];
305 static struct azt_Play_msf azt_Play;
307 static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
308 static char aztDiskChanged = 1;
309 static char aztTocUpToDate = 0;
311 static unsigned char aztIndatum;
312 static unsigned long aztTimeOutCount;
313 static int aztCmd = 0;
315 static spinlock_t aztSpin = SPIN_LOCK_UNLOCKED;
317 /*###########################################################################
318 Function Prototypes
319 ###########################################################################
321 /* CDROM Drive Low Level I/O Functions */
322 static void aztStatTimer(void);
324 /* CDROM Drive Command Functions */
325 static int aztGetDiskInfo(void);
326 #if AZT_MULTISESSION
327 static int aztGetMultiDiskInfo(void);
328 #endif
329 static int aztGetToc(int multi);
331 /* Kernel Interface Functions */
332 static int check_aztcd_media_change(struct gendisk *disk);
333 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
334 unsigned long arg);
335 static int aztcd_open(struct inode *ip, struct file *fp);
336 static int aztcd_release(struct inode *inode, struct file *file);
338 static struct block_device_operations azt_fops = {
339 .owner = THIS_MODULE,
340 .open = aztcd_open,
341 .release = aztcd_release,
342 .ioctl = aztcd_ioctl,
343 .media_changed = check_aztcd_media_change,
346 /* Aztcd State Machine: Controls Drive Operating State */
347 static void azt_poll(void);
349 /* Miscellaneous support functions */
350 static void azt_hsg2msf(long hsg, struct msf *msf);
351 static long azt_msf2hsg(struct msf *mp);
352 static void azt_bin2bcd(unsigned char *p);
353 static int azt_bcd2bin(unsigned char bcd);
355 /*##########################################################################
356 CDROM Drive Low Level I/O Functions
357 ##########################################################################
359 /* Macros for the drive hardware interface handshake, these macros use
360 busy waiting */
361 /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
362 # define OP_OK op_ok()
363 static void op_ok(void)
365 aztTimeOutCount = 0;
366 do {
367 aztIndatum = inb(DATA_PORT);
368 aztTimeOutCount++;
369 if (aztTimeOutCount >= AZT_TIMEOUT) {
370 printk("aztcd: Error Wait OP_OK\n");
371 break;
373 } while (aztIndatum != AFL_OP_OK);
376 /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
377 #if 0
378 # define PA_OK pa_ok()
379 static void pa_ok(void)
381 aztTimeOutCount = 0;
382 do {
383 aztIndatum = inb(DATA_PORT);
384 aztTimeOutCount++;
385 if (aztTimeOutCount >= AZT_TIMEOUT) {
386 printk("aztcd: Error Wait PA_OK\n");
387 break;
389 } while (aztIndatum != AFL_PA_OK);
391 #endif
393 /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
394 # define STEN_LOW sten_low()
395 static void sten_low(void)
397 aztTimeOutCount = 0;
398 do {
399 aztIndatum = inb(STATUS_PORT);
400 aztTimeOutCount++;
401 if (aztTimeOutCount >= AZT_TIMEOUT) {
402 if (azt_init_end)
403 printk
404 ("aztcd: Error Wait STEN_LOW commands:%x\n",
405 aztCmd);
406 break;
408 } while (aztIndatum & AFL_STATUS);
411 /* Wait for DTEN=Low = handshake signal 'Data available'*/
412 # define DTEN_LOW dten_low()
413 static void dten_low(void)
415 aztTimeOutCount = 0;
416 do {
417 aztIndatum = inb(STATUS_PORT);
418 aztTimeOutCount++;
419 if (aztTimeOutCount >= AZT_TIMEOUT) {
420 printk("aztcd: Error Wait DTEN_OK\n");
421 break;
423 } while (aztIndatum & AFL_DATA);
427 * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
428 * may cause kernel panic when used in the wrong place
430 #define STEN_LOW_WAIT statusAzt()
431 static void statusAzt(void)
433 AztTimeout = AZT_STATUS_DELAY;
434 SET_TIMER(aztStatTimer, HZ / 100);
435 sleep_on(&azt_waitq);
436 if (AztTimeout <= 0)
437 printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",
438 aztCmd);
439 return;
442 static void aztStatTimer(void)
444 if (!(inb(STATUS_PORT) & AFL_STATUS)) {
445 wake_up(&azt_waitq);
446 return;
448 AztTimeout--;
449 if (AztTimeout <= 0) {
450 wake_up(&azt_waitq);
451 printk("aztcd: Error aztStatTimer: Timeout\n");
452 return;
454 SET_TIMER(aztStatTimer, HZ / 100);
457 /*##########################################################################
458 CDROM Drive Command Functions
459 ##########################################################################
462 * Send a single command, return -1 on error, else 0
464 static int aztSendCmd(int cmd)
466 unsigned char data;
467 int retry;
469 #ifdef AZT_DEBUG
470 printk("aztcd: Executing command %x\n", cmd);
471 #endif
473 if ((azt_port == 0x1f0) || (azt_port == 0x170))
474 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
476 aztCmd = cmd;
477 outb(POLLED, MODE_PORT);
478 do {
479 if (inb(STATUS_PORT) & AFL_STATUS)
480 break;
481 inb(DATA_PORT); /* if status left from last command, read and */
482 } while (1); /* discard it */
483 do {
484 if (inb(STATUS_PORT) & AFL_DATA)
485 break;
486 inb(DATA_PORT); /* if data left from last command, read and */
487 } while (1); /* discard it */
488 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
489 outb((unsigned char) cmd, CMD_PORT);
490 STEN_LOW;
491 data = inb(DATA_PORT);
492 if (data == AFL_OP_OK) {
493 return 0;
494 } /*OP_OK? */
495 if (data == AFL_OP_ERR) {
496 STEN_LOW;
497 data = inb(DATA_PORT);
498 printk
499 ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",
500 cmd, data);
503 if (retry >= AZT_RETRY_ATTEMPTS) {
504 printk("### Error 2 aztcd: aztSendCmd %x \n", cmd);
505 azt_error = 0xA5;
507 RETURNM("aztSendCmd", -1);
511 * Send a play or read command to the drive, return -1 on error, else 0
513 static int sendAztCmd(int cmd, struct azt_Play_msf *params)
515 unsigned char data;
516 int retry;
518 #ifdef AZT_DEBUG
519 printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n",
520 params->start.min, params->start.sec, params->start.frame,
521 params->end.min, params->end.sec, params->end.frame);
522 #endif
523 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
524 aztSendCmd(cmd);
525 outb(params->start.min, CMD_PORT);
526 outb(params->start.sec, CMD_PORT);
527 outb(params->start.frame, CMD_PORT);
528 outb(params->end.min, CMD_PORT);
529 outb(params->end.sec, CMD_PORT);
530 outb(params->end.frame, CMD_PORT);
531 STEN_LOW;
532 data = inb(DATA_PORT);
533 if (data == AFL_PA_OK) {
534 return 0;
535 } /*PA_OK ? */
536 if (data == AFL_PA_ERR) {
537 STEN_LOW;
538 data = inb(DATA_PORT);
539 printk
540 ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",
541 cmd, data);
544 if (retry >= AZT_RETRY_ATTEMPTS) {
545 printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd);
546 azt_error = 0xA5;
548 RETURNM("sendAztCmd", -1);
552 * Send a seek command to the drive, return -1 on error, else 0
554 static int aztSeek(struct azt_Play_msf *params)
556 unsigned char data;
557 int retry;
559 #ifdef AZT_DEBUG
560 printk("aztcd: aztSeek %02x:%02x:%02x\n",
561 params->start.min, params->start.sec, params->start.frame);
562 #endif
563 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
564 aztSendCmd(ACMD_SEEK);
565 outb(params->start.min, CMD_PORT);
566 outb(params->start.sec, CMD_PORT);
567 outb(params->start.frame, CMD_PORT);
568 STEN_LOW;
569 data = inb(DATA_PORT);
570 if (data == AFL_PA_OK) {
571 return 0;
572 } /*PA_OK ? */
573 if (data == AFL_PA_ERR) {
574 STEN_LOW;
575 data = inb(DATA_PORT);
576 printk("### Error 1 aztcd: aztSeek\n");
579 if (retry >= AZT_RETRY_ATTEMPTS) {
580 printk("### Error 2 aztcd: aztSeek\n ");
581 azt_error = 0xA5;
583 RETURNM("aztSeek", -1);
586 /* Send a Set Disk Type command
587 does not seem to work with Aztech drives, behavior is completely indepen-
588 dent on which mode is set ???
590 static int aztSetDiskType(int type)
592 unsigned char data;
593 int retry;
595 #ifdef AZT_DEBUG
596 printk("aztcd: set disk type command: type= %i\n", type);
597 #endif
598 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) {
599 aztSendCmd(ACMD_SET_DISK_TYPE);
600 outb(type, CMD_PORT);
601 STEN_LOW;
602 data = inb(DATA_PORT);
603 if (data == AFL_PA_OK) { /*PA_OK ? */
604 azt_read_mode = type;
605 return 0;
607 if (data == AFL_PA_ERR) {
608 STEN_LOW;
609 data = inb(DATA_PORT);
610 printk
611 ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",
612 type, data);
615 if (retry >= AZT_RETRY_ATTEMPTS) {
616 printk("### Error 2 aztcd: aztSetDiskType %x\n ", type);
617 azt_error = 0xA5;
619 RETURNM("aztSetDiskType", -1);
623 /* used in azt_poll to poll the status, expects another program to issue a
624 * ACMD_GET_STATUS directly before
626 static int aztStatus(void)
628 int st;
629 /* int i;
631 i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
632 if (!i)
633 */ STEN_LOW;
634 if (aztTimeOutCount < AZT_TIMEOUT) {
635 st = inb(DATA_PORT) & 0xFF;
636 return st;
637 } else
638 RETURNM("aztStatus", -1);
642 * Get the drive status
644 static int getAztStatus(void)
646 int st;
648 if (aztSendCmd(ACMD_GET_STATUS))
649 RETURNM("getAztStatus 1", -1);
650 STEN_LOW;
651 st = inb(DATA_PORT) & 0xFF;
652 #ifdef AZT_DEBUG
653 printk("aztcd: Status = %x\n", st);
654 #endif
655 if ((st == 0xFF) || (st & AST_CMD_CHECK)) {
656 printk
657 ("aztcd: AST_CMD_CHECK error or no status available\n");
658 return -1;
661 if (((st & AST_MODE_BITS) != AST_BUSY)
662 && (aztAudioStatus == CDROM_AUDIO_PLAY))
663 /* XXX might be an error? look at q-channel? */
664 aztAudioStatus = CDROM_AUDIO_COMPLETED;
666 if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) {
667 aztDiskChanged = 1;
668 aztTocUpToDate = 0;
669 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
671 return st;
676 * Send a 'Play' command and get the status. Use only from the top half.
678 static int aztPlay(struct azt_Play_msf *arg)
680 if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0)
681 RETURNM("aztPlay", -1);
682 return 0;
686 * Subroutines to automatically close the door (tray) and
687 * lock it closed when the cd is mounted. Leave the tray
688 * locking as an option
690 static void aztCloseDoor(void)
692 aztSendCmd(ACMD_CLOSE);
693 STEN_LOW;
694 return;
697 static void aztLockDoor(void)
699 #if AZT_ALLOW_TRAY_LOCK
700 aztSendCmd(ACMD_LOCK);
701 STEN_LOW;
702 #endif
703 return;
706 static void aztUnlockDoor(void)
708 #if AZT_ALLOW_TRAY_LOCK
709 aztSendCmd(ACMD_UNLOCK);
710 STEN_LOW;
711 #endif
712 return;
716 * Read a value from the drive. Should return quickly, so a busy wait
717 * is used to avoid excessive rescheduling. The read command itself must
718 * be issued with aztSendCmd() directly before
720 static int aztGetValue(unsigned char *result)
722 int s;
724 STEN_LOW;
725 if (aztTimeOutCount >= AZT_TIMEOUT) {
726 printk("aztcd: aztGetValue timeout\n");
727 return -1;
729 s = inb(DATA_PORT) & 0xFF;
730 *result = (unsigned char) s;
731 return 0;
735 * Read the current Q-channel info. Also used for reading the
736 * table of contents.
738 static int aztGetQChannelInfo(struct azt_Toc *qp)
740 unsigned char notUsed;
741 int st;
743 #ifdef AZT_DEBUG
744 printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies);
745 #endif
746 if ((st = getAztStatus()) == -1)
747 RETURNM("aztGetQChannelInfo 1", -1);
748 if (aztSendCmd(ACMD_GET_Q_CHANNEL))
749 RETURNM("aztGetQChannelInfo 2", -1);
750 /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */
751 if (aztGetValue(&notUsed))
752 RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */
753 if ((st & AST_MODE_BITS) == AST_INITIAL) {
754 qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
755 qp->track = 0; /* only one byte with Aztech drives */
756 qp->pointIndex = 0;
757 qp->trackTime.min = 0;
758 qp->trackTime.sec = 0;
759 qp->trackTime.frame = 0;
760 qp->diskTime.min = 0;
761 qp->diskTime.sec = 0;
762 qp->diskTime.frame = 0;
763 return 0;
764 } else {
765 if (aztGetValue(&qp->ctrl_addr) < 0)
766 RETURNM("aztGetQChannelInfo 4", -1);
767 if (aztGetValue(&qp->track) < 0)
768 RETURNM("aztGetQChannelInfo 4", -1);
769 if (aztGetValue(&qp->pointIndex) < 0)
770 RETURNM("aztGetQChannelInfo 4", -1);
771 if (aztGetValue(&qp->trackTime.min) < 0)
772 RETURNM("aztGetQChannelInfo 4", -1);
773 if (aztGetValue(&qp->trackTime.sec) < 0)
774 RETURNM("aztGetQChannelInfo 4", -1);
775 if (aztGetValue(&qp->trackTime.frame) < 0)
776 RETURNM("aztGetQChannelInfo 4", -1);
777 if (aztGetValue(&notUsed) < 0)
778 RETURNM("aztGetQChannelInfo 4", -1);
779 if (aztGetValue(&qp->diskTime.min) < 0)
780 RETURNM("aztGetQChannelInfo 4", -1);
781 if (aztGetValue(&qp->diskTime.sec) < 0)
782 RETURNM("aztGetQChannelInfo 4", -1);
783 if (aztGetValue(&qp->diskTime.frame) < 0)
784 RETURNM("aztGetQChannelInfo 4", -1);
786 #ifdef AZT_DEBUG
787 printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies);
788 #endif
789 return 0;
793 * Read the table of contents (TOC) and TOC header if necessary
795 static int aztUpdateToc(void)
797 int st;
799 #ifdef AZT_DEBUG
800 printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies);
801 #endif
802 if (aztTocUpToDate)
803 return 0;
805 if (aztGetDiskInfo() < 0)
806 return -EIO;
808 if (aztGetToc(0) < 0)
809 return -EIO;
811 /*audio disk detection
812 with my Aztech drive there is no audio status bit, so I use the copy
813 protection bit of the first track. If this track is copy protected
814 (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
815 if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
816 DiskInfo.audio = 1;
817 else
818 DiskInfo.audio = 0;
820 /* XA detection */
821 if (!DiskInfo.audio) {
822 azt_Play.start.min = 0; /*XA detection only seems to work */
823 azt_Play.start.sec = 2; /*when we play a track */
824 azt_Play.start.frame = 0;
825 azt_Play.end.min = 0;
826 azt_Play.end.sec = 0;
827 azt_Play.end.frame = 1;
828 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
829 return -1;
830 DTEN_LOW;
831 for (st = 0; st < CD_FRAMESIZE; st++)
832 inb(DATA_PORT);
834 DiskInfo.xa = getAztStatus() & AST_MODE;
835 if (DiskInfo.xa) {
836 printk
837 ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
840 /*multisession detection
841 support for multisession CDs is done automatically with Aztech drives,
842 we don't have to take care about TOC redirection; if we want the isofs
843 to take care about redirection, we have to set AZT_MULTISESSION to 1 */
844 DiskInfo.multi = 0;
845 #if AZT_MULTISESSION
846 if (DiskInfo.xa) {
847 aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */
849 #endif
850 if (DiskInfo.multi) {
851 DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
852 DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
853 DiskInfo.lastSession.frame =
854 Toc[DiskInfo.next].diskTime.frame;
855 printk("aztcd: Multisession support experimental\n");
856 } else {
857 DiskInfo.lastSession.min =
858 Toc[DiskInfo.first].diskTime.min;
859 DiskInfo.lastSession.sec =
860 Toc[DiskInfo.first].diskTime.sec;
861 DiskInfo.lastSession.frame =
862 Toc[DiskInfo.first].diskTime.frame;
865 aztTocUpToDate = 1;
866 #ifdef AZT_DEBUG
867 printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies);
868 #endif
869 return 0;
873 /* Read the table of contents header, i.e. no. of tracks and start of first
874 * track
876 static int aztGetDiskInfo(void)
878 int limit;
879 unsigned char test;
880 struct azt_Toc qInfo;
882 #ifdef AZT_DEBUG
883 printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies);
884 #endif
885 if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
886 RETURNM("aztGetDiskInfo 1", -1);
887 STEN_LOW_WAIT;
888 test = 0;
889 for (limit = 300; limit > 0; limit--) {
890 if (aztGetQChannelInfo(&qInfo) < 0)
891 RETURNM("aztGetDiskInfo 2", -1);
892 if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */
893 DiskInfo.first = qInfo.diskTime.min;
894 DiskInfo.first = azt_bcd2bin(DiskInfo.first);
895 test = test | 0x01;
897 if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
898 DiskInfo.last = qInfo.diskTime.min;
899 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
900 test = test | 0x02;
902 if (qInfo.pointIndex == 0xA2) { /*DiskLength */
903 DiskInfo.diskLength.min = qInfo.diskTime.min;
904 DiskInfo.diskLength.sec = qInfo.diskTime.sec;
905 DiskInfo.diskLength.frame = qInfo.diskTime.frame;
906 test = test | 0x04;
908 if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */
909 DiskInfo.firstTrack.min = qInfo.diskTime.min;
910 DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
911 DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
912 test = test | 0x08;
914 if (test == 0x0F)
915 break;
917 #ifdef AZT_DEBUG
918 printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies);
919 printk
920 ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
921 DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
922 DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
923 DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
924 DiskInfo.firstTrack.frame);
925 #endif
926 if (test != 0x0F)
927 return -1;
928 return 0;
931 #if AZT_MULTISESSION
933 * Get Multisession Disk Info
935 static int aztGetMultiDiskInfo(void)
937 int limit, k = 5;
938 unsigned char test;
939 struct azt_Toc qInfo;
941 #ifdef AZT_DEBUG
942 printk("aztcd: starting aztGetMultiDiskInfo\n");
943 #endif
945 do {
946 azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min;
947 azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec;
948 azt_Play.start.frame =
949 Toc[DiskInfo.last + 1].diskTime.frame;
950 test = 0;
952 for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */
953 if (aztSeek(&azt_Play))
954 RETURNM("aztGetMultiDiskInfo 1", -1);
955 if (aztGetQChannelInfo(&qInfo) < 0)
956 RETURNM("aztGetMultiDiskInfo 2", -1);
957 if ((qInfo.track == 0) && (qInfo.pointIndex))
958 break; /*LeadIn found */
959 if ((azt_Play.start.sec += 10) > 59) {
960 azt_Play.start.sec = 0;
961 azt_Play.start.min++;
964 if (!limit)
965 break; /*Check, if a leadin track was found, if not we're
966 at the end of the disk */
967 #ifdef AZT_DEBUG_MULTISESSION
968 printk("leadin found track %d pointIndex %x limit %d\n",
969 qInfo.track, qInfo.pointIndex, limit);
970 #endif
971 for (limit = 300; limit > 0; limit--) {
972 if (++azt_Play.start.frame > 74) {
973 azt_Play.start.frame = 0;
974 if (azt_Play.start.sec > 59) {
975 azt_Play.start.sec = 0;
976 azt_Play.start.min++;
979 if (aztSeek(&azt_Play))
980 RETURNM("aztGetMultiDiskInfo 3", -1);
981 if (aztGetQChannelInfo(&qInfo) < 0)
982 RETURNM("aztGetMultiDiskInfo 4", -1);
983 if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */
984 DiskInfo.next = qInfo.diskTime.min;
985 DiskInfo.next = azt_bcd2bin(DiskInfo.next);
986 test = test | 0x01;
988 if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */
989 DiskInfo.last = qInfo.diskTime.min;
990 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
991 test = test | 0x02;
993 if (qInfo.pointIndex == 0xA2) { /*DiskLength */
994 DiskInfo.diskLength.min =
995 qInfo.diskTime.min;
996 DiskInfo.diskLength.sec =
997 qInfo.diskTime.sec;
998 DiskInfo.diskLength.frame =
999 qInfo.diskTime.frame;
1000 test = test | 0x04;
1002 if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */
1003 DiskInfo.nextSession.min =
1004 qInfo.diskTime.min;
1005 DiskInfo.nextSession.sec =
1006 qInfo.diskTime.sec;
1007 DiskInfo.nextSession.frame =
1008 qInfo.diskTime.frame;
1009 test = test | 0x08;
1011 if (test == 0x0F)
1012 break;
1014 #ifdef AZT_DEBUG_MULTISESSION
1015 printk
1016 ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n",
1017 DiskInfo.first, DiskInfo.next, DiskInfo.last,
1018 DiskInfo.diskLength.min, DiskInfo.diskLength.sec,
1019 DiskInfo.diskLength.frame, DiskInfo.firstTrack.min,
1020 DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame,
1021 DiskInfo.nextSession.min, DiskInfo.nextSession.sec,
1022 DiskInfo.nextSession.frame);
1023 #endif
1024 if (test != 0x0F)
1025 break;
1026 else
1027 DiskInfo.multi = 1; /*found TOC of more than one session */
1028 aztGetToc(1);
1029 } while (--k);
1031 #ifdef AZT_DEBUG
1032 printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies);
1033 #endif
1034 return 0;
1036 #endif
1039 * Read the table of contents (TOC)
1041 static int aztGetToc(int multi)
1043 int i, px;
1044 int limit;
1045 struct azt_Toc qInfo;
1047 #ifdef AZT_DEBUG
1048 printk("aztcd: starting aztGetToc Time:%li\n", jiffies);
1049 #endif
1050 if (!multi) {
1051 for (i = 0; i < MAX_TRACKS; i++)
1052 Toc[i].pointIndex = 0;
1053 i = DiskInfo.last + 3;
1054 } else {
1055 for (i = DiskInfo.next; i < MAX_TRACKS; i++)
1056 Toc[i].pointIndex = 0;
1057 i = DiskInfo.last + 4 - DiskInfo.next;
1060 /*Is there a good reason to stop motor before TOC read?
1061 if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
1062 STEN_LOW_WAIT;
1065 if (!multi) {
1066 azt_mode = 0x05;
1067 if (aztSendCmd(ACMD_SEEK_TO_LEADIN))
1068 RETURNM("aztGetToc 2", -1);
1069 STEN_LOW_WAIT;
1071 for (limit = 300; limit > 0; limit--) {
1072 if (multi) {
1073 if (++azt_Play.start.sec > 59) {
1074 azt_Play.start.sec = 0;
1075 azt_Play.start.min++;
1077 if (aztSeek(&azt_Play))
1078 RETURNM("aztGetToc 3", -1);
1080 if (aztGetQChannelInfo(&qInfo) < 0)
1081 break;
1083 px = azt_bcd2bin(qInfo.pointIndex);
1085 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1086 if (Toc[px].pointIndex == 0) {
1087 Toc[px] = qInfo;
1088 i--;
1091 if (i <= 0)
1092 break;
1095 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1096 Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
1098 #ifdef AZT_DEBUG_MULTISESSION
1099 printk("aztcd: exiting aztGetToc\n");
1100 for (i = 1; i <= DiskInfo.last + 1; i++)
1101 printk
1102 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1103 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1104 Toc[i].trackTime.min, Toc[i].trackTime.sec,
1105 Toc[i].trackTime.frame, Toc[i].diskTime.min,
1106 Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1107 for (i = 100; i < 103; i++)
1108 printk
1109 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1110 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1111 Toc[i].trackTime.min, Toc[i].trackTime.sec,
1112 Toc[i].trackTime.frame, Toc[i].diskTime.min,
1113 Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1114 #endif
1116 return limit > 0 ? 0 : -1;
1120 /*##########################################################################
1121 Kernel Interface Functions
1122 ##########################################################################
1125 #ifndef MODULE
1126 static int __init aztcd_setup(char *str)
1128 int ints[4];
1130 (void) get_options(str, ARRAY_SIZE(ints), ints);
1132 if (ints[0] > 0)
1133 azt_port = ints[1];
1134 if (ints[1] > 1)
1135 azt_cont = ints[2];
1136 return 1;
1139 __setup("aztcd=", aztcd_setup);
1141 #endif /* !MODULE */
1144 * Checking if the media has been changed
1146 static int check_aztcd_media_change(struct gendisk *disk)
1148 if (aztDiskChanged) { /* disk changed */
1149 aztDiskChanged = 0;
1150 return 1;
1151 } else
1152 return 0; /* no change */
1156 * Kernel IO-controls
1158 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
1159 unsigned long arg)
1161 int i;
1162 struct azt_Toc qInfo;
1163 struct cdrom_ti ti;
1164 struct cdrom_tochdr tocHdr;
1165 struct cdrom_msf msf;
1166 struct cdrom_tocentry entry;
1167 struct azt_Toc *tocPtr;
1168 struct cdrom_subchnl subchnl;
1169 struct cdrom_volctrl volctrl;
1170 void __user *argp = (void __user *)arg;
1172 #ifdef AZT_DEBUG
1173 printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",
1174 cmd, jiffies);
1175 printk("aztcd Status %x\n", getAztStatus());
1176 #endif
1177 if (!ip)
1178 RETURNM("aztcd_ioctl 1", -EINVAL);
1179 if (getAztStatus() < 0)
1180 RETURNM("aztcd_ioctl 2", -EIO);
1181 if ((!aztTocUpToDate) || (aztDiskChanged)) {
1182 if ((i = aztUpdateToc()) < 0)
1183 RETURNM("aztcd_ioctl 3", i); /* error reading TOC */
1186 switch (cmd) {
1187 case CDROMSTART: /* Spin up the drive. Don't know, what to do,
1188 at least close the tray */
1189 #if AZT_PRIVATE_IOCTLS
1190 if (aztSendCmd(ACMD_CLOSE))
1191 RETURNM("aztcd_ioctl 4", -1);
1192 STEN_LOW_WAIT;
1193 #endif
1194 break;
1195 case CDROMSTOP: /* Spin down the drive */
1196 if (aztSendCmd(ACMD_STOP))
1197 RETURNM("aztcd_ioctl 5", -1);
1198 STEN_LOW_WAIT;
1199 /* should we do anything if it fails? */
1200 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1201 break;
1202 case CDROMPAUSE: /* Pause the drive */
1203 if (aztAudioStatus != CDROM_AUDIO_PLAY)
1204 return -EINVAL;
1206 if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */
1207 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1208 RETURNM("aztcd_ioctl 7", 0);
1210 azt_Play.start = qInfo.diskTime; /* remember restart point */
1212 if (aztSendCmd(ACMD_PAUSE))
1213 RETURNM("aztcd_ioctl 8", -1);
1214 STEN_LOW_WAIT;
1215 aztAudioStatus = CDROM_AUDIO_PAUSED;
1216 break;
1217 case CDROMRESUME: /* Play it again, Sam */
1218 if (aztAudioStatus != CDROM_AUDIO_PAUSED)
1219 return -EINVAL;
1220 /* restart the drive at the saved position. */
1221 i = aztPlay(&azt_Play);
1222 if (i < 0) {
1223 aztAudioStatus = CDROM_AUDIO_ERROR;
1224 return -EIO;
1226 aztAudioStatus = CDROM_AUDIO_PLAY;
1227 break;
1228 case CDROMMULTISESSION: /*multisession support -- experimental */
1230 struct cdrom_multisession ms;
1231 #ifdef AZT_DEBUG
1232 printk("aztcd ioctl MULTISESSION\n");
1233 #endif
1234 if (copy_from_user(&ms, argp,
1235 sizeof(struct cdrom_multisession)))
1236 return -EFAULT;
1237 if (ms.addr_format == CDROM_MSF) {
1238 ms.addr.msf.minute =
1239 azt_bcd2bin(DiskInfo.lastSession.min);
1240 ms.addr.msf.second =
1241 azt_bcd2bin(DiskInfo.lastSession.sec);
1242 ms.addr.msf.frame =
1243 azt_bcd2bin(DiskInfo.lastSession.
1244 frame);
1245 } else if (ms.addr_format == CDROM_LBA)
1246 ms.addr.lba =
1247 azt_msf2hsg(&DiskInfo.lastSession);
1248 else
1249 return -EINVAL;
1250 ms.xa_flag = DiskInfo.xa;
1251 if (copy_to_user(argp, &ms,
1252 sizeof(struct cdrom_multisession)))
1253 return -EFAULT;
1254 #ifdef AZT_DEBUG
1255 if (ms.addr_format == CDROM_MSF)
1256 printk
1257 ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
1258 ms.xa_flag, ms.addr.msf.minute,
1259 ms.addr.msf.second, ms.addr.msf.frame,
1260 DiskInfo.lastSession.min,
1261 DiskInfo.lastSession.sec,
1262 DiskInfo.lastSession.frame);
1263 else
1264 printk
1265 ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
1266 ms.xa_flag, ms.addr.lba,
1267 DiskInfo.lastSession.min,
1268 DiskInfo.lastSession.sec,
1269 DiskInfo.lastSession.frame);
1270 #endif
1271 return 0;
1273 case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
1274 if (copy_from_user(&ti, argp, sizeof ti))
1275 return -EFAULT;
1276 if (ti.cdti_trk0 < DiskInfo.first
1277 || ti.cdti_trk0 > DiskInfo.last
1278 || ti.cdti_trk1 < ti.cdti_trk0) {
1279 return -EINVAL;
1281 if (ti.cdti_trk1 > DiskInfo.last)
1282 ti.cdti_trk1 = DiskInfo.last;
1283 azt_Play.start = Toc[ti.cdti_trk0].diskTime;
1284 azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
1285 #ifdef AZT_DEBUG
1286 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
1287 azt_Play.start.min, azt_Play.start.sec,
1288 azt_Play.start.frame, azt_Play.end.min,
1289 azt_Play.end.sec, azt_Play.end.frame);
1290 #endif
1291 i = aztPlay(&azt_Play);
1292 if (i < 0) {
1293 aztAudioStatus = CDROM_AUDIO_ERROR;
1294 return -EIO;
1296 aztAudioStatus = CDROM_AUDIO_PLAY;
1297 break;
1298 case CDROMPLAYMSF: /* Play starting at the given MSF address. */
1299 /* if (aztAudioStatus == CDROM_AUDIO_PLAY)
1300 { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
1301 STEN_LOW;
1302 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1305 if (copy_from_user(&msf, argp, sizeof msf))
1306 return -EFAULT;
1307 /* convert to bcd */
1308 azt_bin2bcd(&msf.cdmsf_min0);
1309 azt_bin2bcd(&msf.cdmsf_sec0);
1310 azt_bin2bcd(&msf.cdmsf_frame0);
1311 azt_bin2bcd(&msf.cdmsf_min1);
1312 azt_bin2bcd(&msf.cdmsf_sec1);
1313 azt_bin2bcd(&msf.cdmsf_frame1);
1314 azt_Play.start.min = msf.cdmsf_min0;
1315 azt_Play.start.sec = msf.cdmsf_sec0;
1316 azt_Play.start.frame = msf.cdmsf_frame0;
1317 azt_Play.end.min = msf.cdmsf_min1;
1318 azt_Play.end.sec = msf.cdmsf_sec1;
1319 azt_Play.end.frame = msf.cdmsf_frame1;
1320 #ifdef AZT_DEBUG
1321 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
1322 azt_Play.start.min, azt_Play.start.sec,
1323 azt_Play.start.frame, azt_Play.end.min,
1324 azt_Play.end.sec, azt_Play.end.frame);
1325 #endif
1326 i = aztPlay(&azt_Play);
1327 if (i < 0) {
1328 aztAudioStatus = CDROM_AUDIO_ERROR;
1329 return -EIO;
1331 aztAudioStatus = CDROM_AUDIO_PLAY;
1332 break;
1334 case CDROMREADTOCHDR: /* Read the table of contents header */
1335 tocHdr.cdth_trk0 = DiskInfo.first;
1336 tocHdr.cdth_trk1 = DiskInfo.last;
1337 if (copy_to_user(argp, &tocHdr, sizeof tocHdr))
1338 return -EFAULT;
1339 break;
1340 case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
1341 if (copy_from_user(&entry, argp, sizeof entry))
1342 return -EFAULT;
1343 if ((!aztTocUpToDate) || aztDiskChanged)
1344 aztUpdateToc();
1345 if (entry.cdte_track == CDROM_LEADOUT)
1346 tocPtr = &Toc[DiskInfo.last + 1];
1347 else if (entry.cdte_track > DiskInfo.last
1348 || entry.cdte_track < DiskInfo.first) {
1349 return -EINVAL;
1350 } else
1351 tocPtr = &Toc[entry.cdte_track];
1352 entry.cdte_adr = tocPtr->ctrl_addr;
1353 entry.cdte_ctrl = tocPtr->ctrl_addr >> 4;
1354 if (entry.cdte_format == CDROM_LBA)
1355 entry.cdte_addr.lba =
1356 azt_msf2hsg(&tocPtr->diskTime);
1357 else if (entry.cdte_format == CDROM_MSF) {
1358 entry.cdte_addr.msf.minute =
1359 azt_bcd2bin(tocPtr->diskTime.min);
1360 entry.cdte_addr.msf.second =
1361 azt_bcd2bin(tocPtr->diskTime.sec);
1362 entry.cdte_addr.msf.frame =
1363 azt_bcd2bin(tocPtr->diskTime.frame);
1364 } else {
1365 return -EINVAL;
1367 if (copy_to_user(argp, &entry, sizeof entry))
1368 return -EFAULT;
1369 break;
1370 case CDROMSUBCHNL: /* Get subchannel info */
1371 if (copy_from_user
1372 (&subchnl, argp, sizeof(struct cdrom_subchnl)))
1373 return -EFAULT;
1374 if (aztGetQChannelInfo(&qInfo) < 0) {
1375 #ifdef AZT_DEBUG
1376 printk
1377 ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",
1378 cmd);
1379 #endif
1380 return -EIO;
1382 subchnl.cdsc_audiostatus = aztAudioStatus;
1383 subchnl.cdsc_adr = qInfo.ctrl_addr;
1384 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
1385 subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
1386 subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
1387 if (subchnl.cdsc_format == CDROM_LBA) {
1388 subchnl.cdsc_absaddr.lba =
1389 azt_msf2hsg(&qInfo.diskTime);
1390 subchnl.cdsc_reladdr.lba =
1391 azt_msf2hsg(&qInfo.trackTime);
1392 } else { /*default */
1393 subchnl.cdsc_format = CDROM_MSF;
1394 subchnl.cdsc_absaddr.msf.minute =
1395 azt_bcd2bin(qInfo.diskTime.min);
1396 subchnl.cdsc_absaddr.msf.second =
1397 azt_bcd2bin(qInfo.diskTime.sec);
1398 subchnl.cdsc_absaddr.msf.frame =
1399 azt_bcd2bin(qInfo.diskTime.frame);
1400 subchnl.cdsc_reladdr.msf.minute =
1401 azt_bcd2bin(qInfo.trackTime.min);
1402 subchnl.cdsc_reladdr.msf.second =
1403 azt_bcd2bin(qInfo.trackTime.sec);
1404 subchnl.cdsc_reladdr.msf.frame =
1405 azt_bcd2bin(qInfo.trackTime.frame);
1407 if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl)))
1408 return -EFAULT;
1409 break;
1410 case CDROMVOLCTRL: /* Volume control
1411 * With my Aztech CD268-01A volume control does not work, I can only
1412 turn the channels on (any value !=0) or off (value==0). Maybe it
1413 works better with your drive */
1414 if (copy_from_user(&volctrl, argp, sizeof(volctrl)))
1415 return -EFAULT;
1416 azt_Play.start.min = 0x21;
1417 azt_Play.start.sec = 0x84;
1418 azt_Play.start.frame = volctrl.channel0;
1419 azt_Play.end.min = volctrl.channel1;
1420 azt_Play.end.sec = volctrl.channel2;
1421 azt_Play.end.frame = volctrl.channel3;
1422 sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
1423 STEN_LOW_WAIT;
1424 break;
1425 case CDROMEJECT:
1426 aztUnlockDoor(); /* Assume user knows what they're doing */
1427 /* all drives can at least stop! */
1428 if (aztAudioStatus == CDROM_AUDIO_PLAY) {
1429 if (aztSendCmd(ACMD_STOP))
1430 RETURNM("azt_ioctl 10", -1);
1431 STEN_LOW_WAIT;
1433 if (aztSendCmd(ACMD_EJECT))
1434 RETURNM("azt_ioctl 11", -1);
1435 STEN_LOW_WAIT;
1436 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1437 break;
1438 case CDROMEJECT_SW:
1439 azt_auto_eject = (char) arg;
1440 break;
1441 case CDROMRESET:
1442 outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
1443 STEN_LOW;
1444 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
1445 printk
1446 ("aztcd: AZTECH CD-ROM drive does not respond\n");
1448 break;
1449 /*Take care, the following code is not compatible with other CD-ROM drivers,
1450 use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
1451 if you do not want to use it!
1453 #if AZT_PRIVATE_IOCTLS
1454 case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */
1455 case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */
1457 if (copy_from_user(&msf, argp, sizeof msf))
1458 return -EFAULT;
1459 /* convert to bcd */
1460 azt_bin2bcd(&msf.cdmsf_min0);
1461 azt_bin2bcd(&msf.cdmsf_sec0);
1462 azt_bin2bcd(&msf.cdmsf_frame0);
1463 msf.cdmsf_min1 = 0;
1464 msf.cdmsf_sec1 = 0;
1465 msf.cdmsf_frame1 = 1; /*read only one frame */
1466 azt_Play.start.min = msf.cdmsf_min0;
1467 azt_Play.start.sec = msf.cdmsf_sec0;
1468 azt_Play.start.frame = msf.cdmsf_frame0;
1469 azt_Play.end.min = msf.cdmsf_min1;
1470 azt_Play.end.sec = msf.cdmsf_sec1;
1471 azt_Play.end.frame = msf.cdmsf_frame1;
1472 if (cmd == CDROMREADRAW) {
1473 if (DiskInfo.xa) {
1474 return -1; /*XA Disks can't be read raw */
1475 } else {
1476 if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play))
1477 return -1;
1478 DTEN_LOW;
1479 insb(DATA_PORT, buf, CD_FRAMESIZE_RAW);
1480 if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW))
1481 return -EFAULT;
1483 } else
1484 /*CDROMREADCOOKED*/ {
1485 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play))
1486 return -1;
1487 DTEN_LOW;
1488 insb(DATA_PORT, buf, CD_FRAMESIZE);
1489 if (copy_to_user(argp, &buf, CD_FRAMESIZE))
1490 return -EFAULT;
1493 break;
1494 case CDROMSEEK: /*seek msf address */
1495 if (copy_from_user(&msf, argp, sizeof msf))
1496 return -EFAULT;
1497 /* convert to bcd */
1498 azt_bin2bcd(&msf.cdmsf_min0);
1499 azt_bin2bcd(&msf.cdmsf_sec0);
1500 azt_bin2bcd(&msf.cdmsf_frame0);
1501 azt_Play.start.min = msf.cdmsf_min0;
1502 azt_Play.start.sec = msf.cdmsf_sec0;
1503 azt_Play.start.frame = msf.cdmsf_frame0;
1504 if (aztSeek(&azt_Play))
1505 return -1;
1506 break;
1507 #endif /*end of incompatible code */
1508 case CDROMREADMODE1: /*set read data in mode 1 */
1509 return aztSetDiskType(AZT_MODE_1);
1510 case CDROMREADMODE2: /*set read data in mode 2 */
1511 return aztSetDiskType(AZT_MODE_2);
1512 default:
1513 return -EINVAL;
1515 #ifdef AZT_DEBUG
1516 printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd,
1517 jiffies);
1518 #endif
1519 return 0;
1523 * Take care of the different block sizes between cdrom and Linux.
1524 * When Linux gets variable block sizes this will probably go away.
1526 static void azt_transfer(void)
1528 #ifdef AZT_TEST
1529 printk("aztcd: executing azt_transfer Time:%li\n", jiffies);
1530 #endif
1531 if (!current_valid())
1532 return;
1534 while (CURRENT->nr_sectors) {
1535 int bn = CURRENT->sector / 4;
1536 int i;
1537 for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i);
1538 if (i < AZT_BUF_SIZ) {
1539 int offs = (i * 4 + (CURRENT->sector & 3)) * 512;
1540 int nr_sectors = 4 - (CURRENT->sector & 3);
1541 if (azt_buf_out != i) {
1542 azt_buf_out = i;
1543 if (azt_buf_bn[i] != bn) {
1544 azt_buf_out = -1;
1545 continue;
1548 if (nr_sectors > CURRENT->nr_sectors)
1549 nr_sectors = CURRENT->nr_sectors;
1550 memcpy(CURRENT->buffer, azt_buf + offs,
1551 nr_sectors * 512);
1552 CURRENT->nr_sectors -= nr_sectors;
1553 CURRENT->sector += nr_sectors;
1554 CURRENT->buffer += nr_sectors * 512;
1555 } else {
1556 azt_buf_out = -1;
1557 break;
1562 static void do_aztcd_request(request_queue_t * q)
1564 #ifdef AZT_TEST
1565 printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector,
1566 CURRENT->nr_sectors, jiffies);
1567 #endif
1568 if (DiskInfo.audio) {
1569 printk("aztcd: Error, tried to mount an Audio CD\n");
1570 end_request(CURRENT, 0);
1571 return;
1573 azt_transfer_is_active = 1;
1574 while (current_valid()) {
1575 azt_transfer();
1576 if (CURRENT->nr_sectors == 0) {
1577 end_request(CURRENT, 1);
1578 } else {
1579 azt_buf_out = -1; /* Want to read a block not in buffer */
1580 if (azt_state == AZT_S_IDLE) {
1581 if ((!aztTocUpToDate) || aztDiskChanged) {
1582 if (aztUpdateToc() < 0) {
1583 while (current_valid())
1584 end_request(CURRENT, 0);
1585 break;
1588 azt_state = AZT_S_START;
1589 AztTries = 5;
1590 SET_TIMER(azt_poll, HZ / 100);
1592 break;
1595 azt_transfer_is_active = 0;
1596 #ifdef AZT_TEST2
1597 printk
1598 ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
1599 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
1600 printk(" do_aztcd_request ends Time:%li\n", jiffies);
1601 #endif
1605 static void azt_invalidate_buffers(void)
1607 int i;
1609 #ifdef AZT_DEBUG
1610 printk("aztcd: executing azt_invalidate_buffers\n");
1611 #endif
1612 for (i = 0; i < AZT_BUF_SIZ; ++i)
1613 azt_buf_bn[i] = -1;
1614 azt_buf_out = -1;
1618 * Open the device special file. Check that a disk is in.
1620 static int aztcd_open(struct inode *ip, struct file *fp)
1622 int st;
1624 #ifdef AZT_DEBUG
1625 printk("aztcd: starting aztcd_open\n");
1626 #endif
1628 if (aztPresent == 0)
1629 return -ENXIO; /* no hardware */
1631 if (!azt_open_count && azt_state == AZT_S_IDLE) {
1632 azt_invalidate_buffers();
1634 st = getAztStatus(); /* check drive status */
1635 if (st == -1)
1636 goto err_out; /* drive doesn't respond */
1638 if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */
1639 printk("aztcd: Door Open?\n");
1640 aztCloseDoor();
1641 st = getAztStatus();
1644 if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */
1645 printk
1646 ("aztcd: Disk Changed or No Disk in Drive?\n");
1647 aztTocUpToDate = 0;
1649 if (aztUpdateToc())
1650 goto err_out;
1653 ++azt_open_count;
1654 aztLockDoor();
1656 #ifdef AZT_DEBUG
1657 printk("aztcd: exiting aztcd_open\n");
1658 #endif
1659 return 0;
1661 err_out:
1662 return -EIO;
1667 * On close, we flush all azt blocks from the buffer cache.
1669 static int aztcd_release(struct inode *inode, struct file *file)
1671 #ifdef AZT_DEBUG
1672 printk("aztcd: executing aztcd_release\n");
1673 printk("inode: %p, device: %s file: %p\n", inode,
1674 inode->i_bdev->bd_disk->disk_name, file);
1675 #endif
1676 if (!--azt_open_count) {
1677 azt_invalidate_buffers();
1678 aztUnlockDoor();
1679 if (azt_auto_eject)
1680 aztSendCmd(ACMD_EJECT);
1681 CLEAR_TIMER;
1683 return 0;
1686 static struct gendisk *azt_disk;
1689 * Test for presence of drive and initialize it. Called at boot time.
1692 static int __init aztcd_init(void)
1694 long int count, max_count;
1695 unsigned char result[50];
1696 int st;
1697 void* status = NULL;
1698 int i = 0;
1699 int ret = 0;
1701 if (azt_port == 0) {
1702 printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization");
1703 return -EIO;
1706 printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM "
1707 "CD-ROM Driver\n");
1708 printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n");
1709 if (azt_port == -1) {
1710 printk
1711 ("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",
1712 UTS_RELEASE, AZT_VERSION);
1713 } else
1714 printk
1715 ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",
1716 AZT_VERSION, azt_port);
1717 printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/"
1718 "Documentation/cdrom/aztcd\n");
1721 #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */
1722 if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) {
1723 printk
1724 ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
1725 AZT_SW32_BASE_ADDR, AZT_SW32_INIT,
1726 AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG);
1727 return -EIO;
1728 } else {
1729 printk(KERN_INFO
1730 "aztcd: Soundwave32 card detected at %x Version %x\n",
1731 AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
1732 outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG);
1733 for (count = 0; count < 10000; count++); /*delay a bit */
1735 #endif
1737 /* check for presence of drive */
1739 if (azt_port == -1) { /* autoprobing for proprietary interface */
1740 for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) {
1741 azt_port = azt_port_auto[i];
1742 printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x"
1743 "\n", azt_port);
1744 /*proprietary interfaces need 4 bytes */
1745 if (!request_region(azt_port, 4, "aztcd")) {
1746 continue;
1748 outb(POLLED, MODE_PORT);
1749 inb(CMD_PORT);
1750 inb(CMD_PORT);
1751 outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
1753 aztTimeOutCount = 0;
1754 do {
1755 aztIndatum = inb(STATUS_PORT);
1756 aztTimeOutCount++;
1757 if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
1758 break;
1759 } while (aztIndatum & AFL_STATUS);
1760 if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */
1761 break;
1763 else { /* Drive not found on this port - try next one */
1764 release_region(azt_port, 4);
1767 if ((azt_port_auto[i] == 0) || (i == 16)) {
1768 printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n");
1769 return -EIO;
1771 } else { /* no autoprobing */
1772 if ((azt_port == 0x1f0) || (azt_port == 0x170))
1773 status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */
1774 else
1775 status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */
1776 if (!status) {
1777 printk(KERN_WARNING "aztcd: conflict, I/O port (%X) "
1778 "already used\n", azt_port);
1779 return -EIO;
1782 if ((azt_port == 0x1f0) || (azt_port == 0x170))
1783 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */
1785 outb(POLLED, MODE_PORT);
1786 inb(CMD_PORT);
1787 inb(CMD_PORT);
1788 outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */
1790 aztTimeOutCount = 0;
1791 do {
1792 aztIndatum = inb(STATUS_PORT);
1793 aztTimeOutCount++;
1794 if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
1795 break;
1796 } while (aztIndatum & AFL_STATUS);
1798 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */
1799 #ifndef MODULE
1800 if (azt_cont != 0x79) {
1801 printk(KERN_WARNING "aztcd: no AZTECH CD-ROM "
1802 "drive found-Try boot parameter aztcd="
1803 "<BaseAddress>,0x79\n");
1804 ret = -EIO;
1805 goto err_out;
1807 #else
1808 if (0) {
1810 #endif
1811 else {
1812 printk(KERN_INFO "aztcd: drive reset - "
1813 "please wait\n");
1814 for (count = 0; count < 50; count++) {
1815 inb(STATUS_PORT); /*removing all data from earlier tries */
1816 inb(DATA_PORT);
1818 outb(POLLED, MODE_PORT);
1819 inb(CMD_PORT);
1820 inb(CMD_PORT);
1821 getAztStatus(); /*trap errors */
1822 outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */
1823 STEN_LOW;
1824 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */
1825 printk(KERN_WARNING "aztcd: no AZTECH "
1826 "CD-ROM drive found\n");
1827 ret = -EIO;
1828 goto err_out;
1831 for (count = 0; count < AZT_TIMEOUT;
1832 count++)
1833 barrier(); /* Stop gcc 2.96 being smart */
1834 /* use udelay(), damnit -- AV */
1836 if ((st = getAztStatus()) == -1) {
1837 printk(KERN_WARNING "aztcd: Drive Status"
1838 " Error Status=%x\n", st);
1839 ret = -EIO;
1840 goto err_out;
1842 #ifdef AZT_DEBUG
1843 printk(KERN_DEBUG "aztcd: Status = %x\n", st);
1844 #endif
1845 outb(POLLED, MODE_PORT);
1846 inb(CMD_PORT);
1847 inb(CMD_PORT);
1848 outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */
1849 STEN_LOW;
1850 OP_OK;
1855 azt_init_end = 1;
1856 STEN_LOW;
1857 result[0] = inb(DATA_PORT); /*reading in a null byte??? */
1858 for (count = 1; count < 50; count++) { /*Reading version string */
1859 aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */
1860 do {
1861 aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */
1862 aztTimeOutCount++;
1863 if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
1864 break;
1865 } while (aztIndatum & AFL_STATUS);
1866 if (aztTimeOutCount >= AZT_FAST_TIMEOUT)
1867 break; /*all chars read? */
1868 result[count] = inb(DATA_PORT);
1870 if (count > 30)
1871 max_count = 30; /*print max.30 chars of the version string */
1872 else
1873 max_count = count;
1874 printk(KERN_INFO "aztcd: FirmwareVersion=");
1875 for (count = 1; count < max_count; count++)
1876 printk("%c", result[count]);
1877 printk("<<>> ");
1879 if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) {
1880 printk("AZTECH drive detected\n");
1881 /*AZTECH*/}
1882 else if ((result[2] == 'C') && (result[3] == 'D')
1883 && (result[4] == 'D')) {
1884 printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */
1885 } else if ((result[1] == 0x03) && (result[2] == '5')) {
1886 printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */
1887 } else { /*OTHERS or none */
1888 printk("\nunknown drive or firmware version detected\n");
1889 printk
1890 ("aztcd may not run stable, if you want to try anyhow,\n");
1891 printk("boot with: aztcd=<BaseAddress>,0x79\n");
1892 if ((azt_cont != 0x79)) {
1893 printk("aztcd: FirmwareVersion=");
1894 for (count = 1; count < 5; count++)
1895 printk("%c", result[count]);
1896 printk("<<>> ");
1897 printk("Aborted\n");
1898 ret = -EIO;
1899 goto err_out;
1902 azt_disk = alloc_disk(1);
1903 if (!azt_disk)
1904 goto err_out;
1906 if (register_blkdev(MAJOR_NR, "aztcd")) {
1907 ret = -EIO;
1908 goto err_out2;
1911 azt_queue = blk_init_queue(do_aztcd_request, &aztSpin);
1912 if (!azt_queue) {
1913 ret = -ENOMEM;
1914 goto err_out3;
1917 blk_queue_hardsect_size(azt_queue, 2048);
1918 azt_disk->major = MAJOR_NR;
1919 azt_disk->first_minor = 0;
1920 azt_disk->fops = &azt_fops;
1921 sprintf(azt_disk->disk_name, "aztcd");
1922 sprintf(azt_disk->devfs_name, "aztcd");
1923 azt_disk->queue = azt_queue;
1924 add_disk(azt_disk);
1925 azt_invalidate_buffers();
1926 aztPresent = 1;
1927 aztCloseDoor();
1928 return 0;
1929 err_out3:
1930 unregister_blkdev(MAJOR_NR, "aztcd");
1931 err_out2:
1932 put_disk(azt_disk);
1933 err_out:
1934 if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
1935 SWITCH_IDE_MASTER;
1936 release_region(azt_port, 8); /*IDE-interface */
1937 } else
1938 release_region(azt_port, 4); /*proprietary interface */
1939 return ret;
1943 static void __exit aztcd_exit(void)
1945 del_gendisk(azt_disk);
1946 put_disk(azt_disk);
1947 if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
1948 printk("What's that: can't unregister aztcd\n");
1949 return;
1951 blk_cleanup_queue(azt_queue);
1952 if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
1953 SWITCH_IDE_MASTER;
1954 release_region(azt_port, 8); /*IDE-interface */
1955 } else
1956 release_region(azt_port, 4); /*proprietary interface */
1957 printk(KERN_INFO "aztcd module released.\n");
1960 module_init(aztcd_init);
1961 module_exit(aztcd_exit);
1963 /*##########################################################################
1964 Aztcd State Machine: Controls Drive Operating State
1965 ##########################################################################
1967 static void azt_poll(void)
1969 int st = 0;
1970 int loop_ctl = 1;
1971 int skip = 0;
1973 if (azt_error) {
1974 if (aztSendCmd(ACMD_GET_ERROR))
1975 RETURN("azt_poll 1");
1976 STEN_LOW;
1977 azt_error = inb(DATA_PORT) & 0xFF;
1978 printk("aztcd: I/O error 0x%02x\n", azt_error);
1979 azt_invalidate_buffers();
1980 #ifdef WARN_IF_READ_FAILURE
1981 if (AztTries == 5)
1982 printk
1983 ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n",
1984 azt_next_bn);
1985 #endif
1986 if (!AztTries--) {
1987 printk
1988 ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n",
1989 azt_next_bn);
1990 if (azt_transfer_is_active) {
1991 AztTries = 0;
1992 loop_ctl = 0;
1994 if (current_valid())
1995 end_request(CURRENT, 0);
1996 AztTries = 5;
1998 azt_error = 0;
1999 azt_state = AZT_S_STOP;
2002 while (loop_ctl) {
2003 loop_ctl = 0; /* each case must flip this back to 1 if we want
2004 to come back up here */
2005 switch (azt_state) {
2007 case AZT_S_IDLE:
2008 #ifdef AZT_TEST3
2009 if (azt_state != azt_state_old) {
2010 azt_state_old = azt_state;
2011 printk("AZT_S_IDLE\n");
2013 #endif
2014 return;
2016 case AZT_S_START:
2017 #ifdef AZT_TEST3
2018 if (azt_state != azt_state_old) {
2019 azt_state_old = azt_state;
2020 printk("AZT_S_START\n");
2022 #endif
2023 if (aztSendCmd(ACMD_GET_STATUS))
2024 RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
2025 azt_state =
2026 azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
2027 AztTimeout = 3000;
2028 break;
2030 case AZT_S_MODE:
2031 #ifdef AZT_TEST3
2032 if (azt_state != azt_state_old) {
2033 azt_state_old = azt_state;
2034 printk("AZT_S_MODE\n");
2036 #endif
2037 if (!skip) {
2038 if ((st = aztStatus()) != -1) {
2039 if ((st & AST_DSK_CHG)
2040 || (st & AST_NOT_READY)) {
2041 aztDiskChanged = 1;
2042 aztTocUpToDate = 0;
2043 azt_invalidate_buffers();
2044 end_request(CURRENT, 0);
2045 printk
2046 ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
2048 } else
2049 break;
2051 skip = 0;
2053 if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
2054 aztDiskChanged = 1;
2055 aztTocUpToDate = 0;
2056 printk
2057 ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
2058 end_request(CURRENT, 0);
2059 printk((st & AST_DOOR_OPEN) ?
2060 "aztcd: door open\n" :
2061 "aztcd: disk removed\n");
2062 if (azt_transfer_is_active) {
2063 azt_state = AZT_S_START;
2064 loop_ctl = 1; /* goto immediately */
2065 break;
2067 azt_state = AZT_S_IDLE;
2068 while (current_valid())
2069 end_request(CURRENT, 0);
2070 return;
2073 /* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
2074 outb(0x01, DATA_PORT);
2075 PA_OK;
2076 STEN_LOW;
2078 if (aztSendCmd(ACMD_GET_STATUS))
2079 RETURN("azt_poll 4");
2080 STEN_LOW;
2081 azt_mode = 1;
2082 azt_state = AZT_S_READ;
2083 AztTimeout = 3000;
2085 break;
2088 case AZT_S_READ:
2089 #ifdef AZT_TEST3
2090 if (azt_state != azt_state_old) {
2091 azt_state_old = azt_state;
2092 printk("AZT_S_READ\n");
2094 #endif
2095 if (!skip) {
2096 if ((st = aztStatus()) != -1) {
2097 if ((st & AST_DSK_CHG)
2098 || (st & AST_NOT_READY)) {
2099 aztDiskChanged = 1;
2100 aztTocUpToDate = 0;
2101 azt_invalidate_buffers();
2102 printk
2103 ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
2104 end_request(CURRENT, 0);
2106 } else
2107 break;
2110 skip = 0;
2111 if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) {
2112 aztDiskChanged = 1;
2113 aztTocUpToDate = 0;
2114 printk((st & AST_DOOR_OPEN) ?
2115 "aztcd: door open\n" :
2116 "aztcd: disk removed\n");
2117 if (azt_transfer_is_active) {
2118 azt_state = AZT_S_START;
2119 loop_ctl = 1;
2120 break;
2122 azt_state = AZT_S_IDLE;
2123 while (current_valid())
2124 end_request(CURRENT, 0);
2125 return;
2128 if (current_valid()) {
2129 struct azt_Play_msf msf;
2130 int i;
2131 azt_next_bn = CURRENT->sector / 4;
2132 azt_hsg2msf(azt_next_bn, &msf.start);
2133 i = 0;
2134 /* find out in which track we are */
2135 while (azt_msf2hsg(&msf.start) >
2136 azt_msf2hsg(&Toc[++i].trackTime)) {
2138 if (azt_msf2hsg(&msf.start) <
2139 azt_msf2hsg(&Toc[i].trackTime) -
2140 AZT_BUF_SIZ) {
2141 azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */
2142 /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */
2143 } else /* don't read beyond end of track */
2144 #if AZT_MULTISESSION
2146 azt_read_count =
2147 (azt_msf2hsg(&Toc[i].trackTime)
2148 / 4) * 4 -
2149 azt_msf2hsg(&msf.start);
2150 if (azt_read_count < 0)
2151 azt_read_count = 0;
2152 if (azt_read_count > AZT_BUF_SIZ)
2153 azt_read_count =
2154 AZT_BUF_SIZ;
2155 printk
2156 ("aztcd: warning - trying to read beyond end of track\n");
2157 /* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
2158 */ }
2159 #else
2161 azt_read_count = AZT_BUF_SIZ;
2163 #endif
2164 msf.end.min = 0;
2165 msf.end.sec = 0;
2166 msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */
2167 #ifdef AZT_TEST3
2168 printk
2169 ("---reading msf-address %x:%x:%x %x:%x:%x\n",
2170 msf.start.min, msf.start.sec,
2171 msf.start.frame, msf.end.min,
2172 msf.end.sec, msf.end.frame);
2173 printk
2174 ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n",
2175 azt_next_bn, azt_buf_in, azt_buf_out,
2176 azt_buf_bn[azt_buf_in]);
2177 #endif
2178 if (azt_read_mode == AZT_MODE_2) {
2179 sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */
2180 } else {
2181 sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */
2183 azt_state = AZT_S_DATA;
2184 AztTimeout = READ_TIMEOUT;
2185 } else {
2186 azt_state = AZT_S_STOP;
2187 loop_ctl = 1;
2188 break;
2191 break;
2194 case AZT_S_DATA:
2195 #ifdef AZT_TEST3
2196 if (azt_state != azt_state_old) {
2197 azt_state_old = azt_state;
2198 printk("AZT_S_DATA\n");
2200 #endif
2202 st = inb(STATUS_PORT) & AFL_STATUSorDATA;
2204 switch (st) {
2206 case AFL_DATA:
2207 #ifdef AZT_TEST3
2208 if (st != azt_st_old) {
2209 azt_st_old = st;
2210 printk("---AFL_DATA st:%x\n", st);
2212 #endif
2213 if (!AztTries--) {
2214 printk
2215 ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n",
2216 azt_next_bn);
2217 if (azt_transfer_is_active) {
2218 AztTries = 0;
2219 break;
2221 if (current_valid())
2222 end_request(CURRENT, 0);
2223 AztTries = 5;
2225 azt_state = AZT_S_START;
2226 AztTimeout = READ_TIMEOUT;
2227 loop_ctl = 1;
2228 break;
2230 case AFL_STATUSorDATA:
2231 #ifdef AZT_TEST3
2232 if (st != azt_st_old) {
2233 azt_st_old = st;
2234 printk
2235 ("---AFL_STATUSorDATA st:%x\n",
2236 st);
2238 #endif
2239 break;
2241 default:
2242 #ifdef AZT_TEST3
2243 if (st != azt_st_old) {
2244 azt_st_old = st;
2245 printk("---default: st:%x\n", st);
2247 #endif
2248 AztTries = 5;
2249 if (!current_valid() && azt_buf_in == azt_buf_out) {
2250 azt_state = AZT_S_STOP;
2251 loop_ctl = 1;
2252 break;
2254 if (azt_read_count <= 0)
2255 printk
2256 ("aztcd: warning - try to read 0 frames\n");
2257 while (azt_read_count) { /*??? fast read ahead loop */
2258 azt_buf_bn[azt_buf_in] = -1;
2259 DTEN_LOW; /*??? unsolved problem, very
2260 seldom we get timeouts
2261 here, don't now the real
2262 reason. With my drive this
2263 sometimes also happens with
2264 Aztech's original driver under
2265 DOS. Is it a hardware bug?
2266 I tried to recover from such
2267 situations here. Zimmermann */
2268 if (aztTimeOutCount >= AZT_TIMEOUT) {
2269 printk
2270 ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n",
2271 azt_read_count,
2272 CURRENT->nr_sectors,
2273 azt_buf_in);
2274 printk
2275 ("azt_transfer_is_active:%x\n",
2276 azt_transfer_is_active);
2277 azt_read_count = 0;
2278 azt_state = AZT_S_STOP;
2279 loop_ctl = 1;
2280 end_request(CURRENT, 1); /*should we have here (1) or (0)? */
2281 } else {
2282 if (azt_read_mode ==
2283 AZT_MODE_2) {
2284 insb(DATA_PORT,
2285 azt_buf +
2286 CD_FRAMESIZE_RAW
2287 * azt_buf_in,
2288 CD_FRAMESIZE_RAW);
2289 } else {
2290 insb(DATA_PORT,
2291 azt_buf +
2292 CD_FRAMESIZE *
2293 azt_buf_in,
2294 CD_FRAMESIZE);
2296 azt_read_count--;
2297 #ifdef AZT_TEST3
2298 printk
2299 ("AZT_S_DATA; ---I've read data- read_count: %d\n",
2300 azt_read_count);
2301 printk
2302 ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n",
2303 azt_next_bn,
2304 azt_buf_in,
2305 azt_buf_out,
2306 azt_buf_bn
2307 [azt_buf_in]);
2308 #endif
2309 azt_buf_bn[azt_buf_in] =
2310 azt_next_bn++;
2311 if (azt_buf_out == -1)
2312 azt_buf_out =
2313 azt_buf_in;
2314 azt_buf_in =
2315 azt_buf_in + 1 ==
2316 AZT_BUF_SIZ ? 0 :
2317 azt_buf_in + 1;
2320 if (!azt_transfer_is_active) {
2321 while (current_valid()) {
2322 azt_transfer();
2323 if (CURRENT->nr_sectors ==
2325 end_request(CURRENT, 1);
2326 else
2327 break;
2331 if (current_valid()
2332 && (CURRENT->sector / 4 < azt_next_bn
2333 || CURRENT->sector / 4 >
2334 azt_next_bn + AZT_BUF_SIZ)) {
2335 azt_state = AZT_S_STOP;
2336 loop_ctl = 1;
2337 break;
2339 AztTimeout = READ_TIMEOUT;
2340 if (azt_read_count == 0) {
2341 azt_state = AZT_S_STOP;
2342 loop_ctl = 1;
2343 break;
2345 break;
2347 break;
2350 case AZT_S_STOP:
2351 #ifdef AZT_TEST3
2352 if (azt_state != azt_state_old) {
2353 azt_state_old = azt_state;
2354 printk("AZT_S_STOP\n");
2356 #endif
2357 if (azt_read_count != 0)
2358 printk("aztcd: discard data=%x frames\n",
2359 azt_read_count);
2360 while (azt_read_count != 0) {
2361 int i;
2362 if (!(inb(STATUS_PORT) & AFL_DATA)) {
2363 if (azt_read_mode == AZT_MODE_2)
2364 for (i = 0;
2365 i < CD_FRAMESIZE_RAW;
2366 i++)
2367 inb(DATA_PORT);
2368 else
2369 for (i = 0;
2370 i < CD_FRAMESIZE; i++)
2371 inb(DATA_PORT);
2373 azt_read_count--;
2375 if (aztSendCmd(ACMD_GET_STATUS))
2376 RETURN("azt_poll 5");
2377 azt_state = AZT_S_STOPPING;
2378 AztTimeout = 1000;
2379 break;
2381 case AZT_S_STOPPING:
2382 #ifdef AZT_TEST3
2383 if (azt_state != azt_state_old) {
2384 azt_state_old = azt_state;
2385 printk("AZT_S_STOPPING\n");
2387 #endif
2389 if ((st = aztStatus()) == -1 && AztTimeout)
2390 break;
2392 if ((st != -1)
2393 && ((st & AST_DSK_CHG)
2394 || (st & AST_NOT_READY))) {
2395 aztDiskChanged = 1;
2396 aztTocUpToDate = 0;
2397 azt_invalidate_buffers();
2398 printk
2399 ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
2400 end_request(CURRENT, 0);
2403 #ifdef AZT_TEST3
2404 printk("CURRENT_VALID %d azt_mode %d\n",
2405 current_valid(), azt_mode);
2406 #endif
2408 if (current_valid()) {
2409 if (st != -1) {
2410 if (azt_mode == 1) {
2411 azt_state = AZT_S_READ;
2412 loop_ctl = 1;
2413 skip = 1;
2414 break;
2415 } else {
2416 azt_state = AZT_S_MODE;
2417 loop_ctl = 1;
2418 skip = 1;
2419 break;
2421 } else {
2422 azt_state = AZT_S_START;
2423 AztTimeout = 1;
2425 } else {
2426 azt_state = AZT_S_IDLE;
2427 return;
2429 break;
2431 default:
2432 printk("aztcd: invalid state %d\n", azt_state);
2433 return;
2434 } /* case */
2435 } /* while */
2438 if (!AztTimeout--) {
2439 printk("aztcd: timeout in state %d\n", azt_state);
2440 azt_state = AZT_S_STOP;
2441 if (aztSendCmd(ACMD_STOP))
2442 RETURN("azt_poll 6");
2443 STEN_LOW_WAIT;
2446 SET_TIMER(azt_poll, HZ / 100);
2450 /*###########################################################################
2451 * Miscellaneous support functions
2452 ###########################################################################
2454 static void azt_hsg2msf(long hsg, struct msf *msf)
2456 hsg += 150;
2457 msf->min = hsg / 4500;
2458 hsg %= 4500;
2459 msf->sec = hsg / 75;
2460 msf->frame = hsg % 75;
2461 #ifdef AZT_DEBUG
2462 if (msf->min >= 70)
2463 printk("aztcd: Error hsg2msf address Minutes\n");
2464 if (msf->sec >= 60)
2465 printk("aztcd: Error hsg2msf address Seconds\n");
2466 if (msf->frame >= 75)
2467 printk("aztcd: Error hsg2msf address Frames\n");
2468 #endif
2469 azt_bin2bcd(&msf->min); /* convert to BCD */
2470 azt_bin2bcd(&msf->sec);
2471 azt_bin2bcd(&msf->frame);
2474 static long azt_msf2hsg(struct msf *mp)
2476 return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75
2477 + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET;
2480 static void azt_bin2bcd(unsigned char *p)
2482 int u, t;
2484 u = *p % 10;
2485 t = *p / 10;
2486 *p = u | (t << 4);
2489 static int azt_bcd2bin(unsigned char bcd)
2491 return (bcd >> 4) * 10 + (bcd & 0xF);
2494 MODULE_LICENSE("GPL");
2495 MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);