Revert last change. Bug noticed by Linus.
[linux-2.6/linux-mips.git] / drivers / cdrom / aztcd.c
blob8b551a99daa4a8589fa16d737d18902ec5c1bfdb
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 /usr/src/linux/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>
170 #define MAJOR_NR AZTECH_CDROM_MAJOR
172 #include <linux/blk.h>
173 #include "aztcd.h"
175 #include <linux/module.h>
176 #include <linux/errno.h>
177 #include <linux/sched.h>
178 #include <linux/mm.h>
179 #include <linux/timer.h>
180 #include <linux/fs.h>
181 #include <linux/kernel.h>
182 #include <linux/cdrom.h>
183 #include <linux/ioport.h>
184 #include <linux/string.h>
185 #include <linux/major.h>
186 #include <linux/devfs_fs_kernel.h>
188 #ifndef AZT_KERNEL_PRIOR_2_1
189 #include <linux/init.h>
190 #endif
192 #include <asm/system.h>
193 #include <asm/io.h>
195 #ifdef AZT_KERNEL_PRIOR_2_1
196 #include <asm/segment.h>
197 #else
198 #include <asm/uaccess.h>
199 static int aztcd_blocksizes[1] = {2048};
200 #endif
203 /*###########################################################################
204 Defines
205 ###########################################################################
207 #define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
208 delay_timer.function = (void *) (func); \
209 add_timer(&delay_timer);
211 #define CLEAR_TIMER del_timer(&delay_timer);
213 #define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
214 return value;}
215 #define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
216 return;}
218 /* Macros to switch the IDE-interface to the slave device and back to the master*/
219 #define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
220 outb_p(0x10,azt_port+6); \
221 outb_p(0x00,azt_port+7); \
222 outb_p(0x10,azt_port+6);
223 #define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
226 #if 0
227 #define AZT_TEST
228 #define AZT_TEST1 /* <int-..> */
229 #define AZT_TEST2 /* do_aztcd_request */
230 #define AZT_TEST3 /* AZT_S_state */
231 #define AZT_TEST4 /* QUICK_LOOP-counter */
232 #define AZT_TEST5 /* port(1) state */
233 #define AZT_DEBUG
234 #define AZT_DEBUG_MULTISESSION
235 #endif
237 #define CURRENT_VALID \
238 (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
239 && CURRENT -> sector != -1)
241 #define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
242 #define AZT_BUF_SIZ 16
244 #define READ_TIMEOUT 3000
246 #define azt_port aztcd /*needed for the modutils*/
248 #ifndef AZT_KERNEL_PRIOR_2_1
249 #define memcpy_fromfs copy_from_user
250 #define memcpy_tofs copy_to_user
251 #endif
253 /*##########################################################################
254 Type Definitions
255 ##########################################################################
257 enum azt_state_e
258 { AZT_S_IDLE, /* 0 */
259 AZT_S_START, /* 1 */
260 AZT_S_MODE, /* 2 */
261 AZT_S_READ, /* 3 */
262 AZT_S_DATA, /* 4 */
263 AZT_S_STOP, /* 5 */
264 AZT_S_STOPPING /* 6 */
266 enum azt_read_modes
267 { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware*/
268 AZT_MODE_1, /*read mode for normal CD-ROMs*/
269 AZT_MODE_2 /*read mode for XA CD-ROMs*/
272 /*##########################################################################
273 Global Variables
274 ##########################################################################
276 static int aztPresent = 0;
278 static volatile int azt_transfer_is_active=0;
280 static char azt_buf[CD_FRAMESIZE_RAW*AZT_BUF_SIZ];/*buffer for block size conversion*/
281 #if AZT_PRIVATE_IOCTLS
282 static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls*/
283 #endif
285 static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
286 static volatile int azt_buf_in, azt_buf_out = -1;
287 static volatile int azt_error=0;
288 static int azt_open_count=0;
289 static volatile enum azt_state_e azt_state = AZT_S_IDLE;
290 #ifdef AZT_TEST3
291 static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
292 static volatile int azt_st_old = 0;
293 #endif
294 static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
296 static int azt_mode = -1;
297 static volatile int azt_read_count = 1;
299 static int azt_port = AZT_BASE_ADDR;
301 #ifndef AZT_KERNEL_PRIOR_2_1
302 MODULE_PARM(azt_port, "i");
303 #endif
305 static int azt_port_auto[16] = AZT_BASE_AUTO;
307 static char azt_cont = 0;
308 static char azt_init_end = 0;
309 static char azt_auto_eject = AZT_AUTO_EJECT;
311 static int AztTimeout, AztTries;
312 static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
313 static struct timer_list delay_timer = { {NULL, NULL}, 0, 0, NULL };
315 static struct azt_DiskInfo DiskInfo;
316 static struct azt_Toc Toc[MAX_TRACKS];
317 static struct azt_Play_msf azt_Play;
319 static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
320 static char aztDiskChanged = 1;
321 static char aztTocUpToDate = 0;
323 static unsigned char aztIndatum;
324 static unsigned long aztTimeOutCount;
325 static int aztCmd = 0;
327 /*###########################################################################
328 Function Prototypes
329 ###########################################################################
331 /* CDROM Drive Low Level I/O Functions */
332 void op_ok(void);
333 void pa_ok(void);
334 void sten_low(void);
335 void dten_low(void);
336 void statusAzt(void);
337 static void aztStatTimer(void);
339 /* CDROM Drive Command Functions */
340 static int aztSendCmd(int cmd);
341 static int sendAztCmd(int cmd, struct azt_Play_msf *params);
342 static int aztSeek(struct azt_Play_msf *params);
343 static int aztSetDiskType(int type);
344 static int aztStatus(void);
345 static int getAztStatus(void);
346 static int aztPlay(struct azt_Play_msf *arg);
347 static void aztCloseDoor(void);
348 static void aztLockDoor(void);
349 static void aztUnlockDoor(void);
350 static int aztGetValue(unsigned char *result);
351 static int aztGetQChannelInfo(struct azt_Toc *qp);
352 static int aztUpdateToc(void);
353 static int aztGetDiskInfo(void);
354 #if AZT_MULTISESSION
355 static int aztGetMultiDiskInfo(void);
356 #endif
357 static int aztGetToc(int multi);
359 /* Kernel Interface Functions */
360 static int check_aztcd_media_change(kdev_t full_dev);
361 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
362 static void azt_transfer(void);
363 static void do_aztcd_request(request_queue_t *);
364 static void azt_invalidate_buffers(void);
365 int aztcd_open(struct inode *ip, struct file *fp);
367 #ifdef AZT_KERNEL_PRIOR_2_1
368 static void aztcd_release(struct inode * inode, struct file * file);
369 #else
370 static int aztcd_release(struct inode * inode, struct file * file);
371 #endif
373 int aztcd_init(void);
375 static struct block_device_operations azt_fops = {
376 open: aztcd_open,
377 release: aztcd_release,
378 ioctl: aztcd_ioctl,
379 check_media_change: check_aztcd_media_change,
382 /* Aztcd State Machine: Controls Drive Operating State */
383 static void azt_poll(void);
385 /* Miscellaneous support functions */
386 static void azt_hsg2msf(long hsg, struct msf *msf);
387 static long azt_msf2hsg(struct msf *mp);
388 static void azt_bin2bcd(unsigned char *p);
389 static int azt_bcd2bin(unsigned char bcd);
391 /*##########################################################################
392 CDROM Drive Low Level I/O Functions
393 ##########################################################################
395 /* Macros for the drive hardware interface handshake, these macros use
396 busy waiting */
397 /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
398 # define OP_OK op_ok()
399 void op_ok(void)
400 { aztTimeOutCount=0;
401 do { aztIndatum=inb(DATA_PORT);
402 aztTimeOutCount++;
403 if (aztTimeOutCount>=AZT_TIMEOUT)
404 { printk("aztcd: Error Wait OP_OK\n");
405 break;
407 } while (aztIndatum!=AFL_OP_OK);
410 /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
411 # define PA_OK pa_ok()
412 void pa_ok(void)
413 { aztTimeOutCount=0;
414 do { aztIndatum=inb(DATA_PORT);
415 aztTimeOutCount++;
416 if (aztTimeOutCount>=AZT_TIMEOUT)
417 { printk("aztcd: Error Wait PA_OK\n");
418 break;
420 } while (aztIndatum!=AFL_PA_OK);
423 /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
424 # define STEN_LOW sten_low()
425 void sten_low(void)
426 { aztTimeOutCount=0;
427 do { aztIndatum=inb(STATUS_PORT);
428 aztTimeOutCount++;
429 if (aztTimeOutCount>=AZT_TIMEOUT)
430 { if (azt_init_end) printk("aztcd: Error Wait STEN_LOW commands:%x\n",aztCmd);
431 break;
433 } while (aztIndatum&AFL_STATUS);
436 /* Wait for DTEN=Low = handshake signal 'Data available'*/
437 # define DTEN_LOW dten_low()
438 void dten_low(void)
439 { aztTimeOutCount=0;
440 do { aztIndatum=inb(STATUS_PORT);
441 aztTimeOutCount++;
442 if (aztTimeOutCount>=AZT_TIMEOUT)
443 { printk("aztcd: Error Wait DTEN_OK\n");
444 break;
446 } while (aztIndatum&AFL_DATA);
450 * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
451 * may cause kernel panic when used in the wrong place
453 #define STEN_LOW_WAIT statusAzt()
454 void statusAzt(void)
455 { AztTimeout = AZT_STATUS_DELAY;
456 SET_TIMER(aztStatTimer, HZ/100);
457 sleep_on(&azt_waitq);
458 if (AztTimeout <= 0) printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",aztCmd);
459 return;
462 static void aztStatTimer(void)
463 { if (!(inb(STATUS_PORT) & AFL_STATUS))
464 { wake_up(&azt_waitq);
465 return;
467 AztTimeout--;
468 if (AztTimeout <= 0)
469 { wake_up(&azt_waitq);
470 printk("aztcd: Error aztStatTimer: Timeout\n");
471 return;
473 SET_TIMER(aztStatTimer, HZ/100);
476 /*##########################################################################
477 CDROM Drive Command Functions
478 ##########################################################################
481 * Send a single command, return -1 on error, else 0
483 static int aztSendCmd(int cmd)
484 { unsigned char data;
485 int retry;
487 #ifdef AZT_DEBUG
488 printk("aztcd: Executing command %x\n",cmd);
489 #endif
491 if ((azt_port==0x1f0)||(azt_port==0x170))
492 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/
494 aztCmd=cmd;
495 outb(POLLED,MODE_PORT);
496 do { if (inb(STATUS_PORT)&AFL_STATUS) break;
497 inb(DATA_PORT); /* if status left from last command, read and */
498 } while (1); /* discard it */
499 do { if (inb(STATUS_PORT)&AFL_DATA) break;
500 inb(DATA_PORT); /* if data left from last command, read and */
501 } while (1); /* discard it */
502 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
503 { outb((unsigned char) cmd,CMD_PORT);
504 STEN_LOW;
505 data=inb(DATA_PORT);
506 if (data==AFL_OP_OK)
507 { return 0;} /*OP_OK?*/
508 if (data==AFL_OP_ERR)
509 { STEN_LOW;
510 data=inb(DATA_PORT);
511 printk("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",cmd,data);
514 if (retry>=AZT_RETRY_ATTEMPTS)
515 { printk("### Error 2 aztcd: aztSendCmd %x \n",cmd);
516 azt_error=0xA5;
518 RETURNM("aztSendCmd",-1);
522 * Send a play or read command to the drive, return -1 on error, else 0
524 static int sendAztCmd(int cmd, struct azt_Play_msf *params)
525 { unsigned char data;
526 int retry;
528 #ifdef AZT_DEBUG
529 printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", \
530 params->start.min, params->start.sec, params->start.frame, \
531 params->end.min, params->end.sec, params->end.frame);
532 #endif
533 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
534 { aztSendCmd(cmd);
535 outb(params -> start.min,CMD_PORT);
536 outb(params -> start.sec,CMD_PORT);
537 outb(params -> start.frame,CMD_PORT);
538 outb(params -> end.min,CMD_PORT);
539 outb(params -> end.sec,CMD_PORT);
540 outb(params -> end.frame,CMD_PORT);
541 STEN_LOW;
542 data=inb(DATA_PORT);
543 if (data==AFL_PA_OK)
544 { return 0;} /*PA_OK ?*/
545 if (data==AFL_PA_ERR)
546 { STEN_LOW;
547 data=inb(DATA_PORT);
548 printk("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",cmd,data);
551 if (retry>=AZT_RETRY_ATTEMPTS)
552 { printk("### Error 2 aztcd: sendAztCmd %x\n ",cmd);
553 azt_error=0xA5;
555 RETURNM("sendAztCmd",-1);
559 * Send a seek command to the drive, return -1 on error, else 0
561 static int aztSeek(struct azt_Play_msf *params)
562 { unsigned char data;
563 int retry;
565 #ifdef AZT_DEBUG
566 printk("aztcd: aztSeek %02x:%02x:%02x\n", \
567 params->start.min, params->start.sec, params->start.frame);
568 #endif
569 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
570 { aztSendCmd(ACMD_SEEK);
571 outb(params -> start.min,CMD_PORT);
572 outb(params -> start.sec,CMD_PORT);
573 outb(params -> start.frame,CMD_PORT);
574 STEN_LOW;
575 data=inb(DATA_PORT);
576 if (data==AFL_PA_OK)
577 { return 0;} /*PA_OK ?*/
578 if (data==AFL_PA_ERR)
579 { STEN_LOW;
580 data=inb(DATA_PORT);
581 printk("### Error 1 aztcd: aztSeek\n");
584 if (retry>=AZT_RETRY_ATTEMPTS)
585 { printk("### Error 2 aztcd: aztSeek\n ");
586 azt_error=0xA5;
588 RETURNM("aztSeek",-1);
591 /* Send a Set Disk Type command
592 does not seem to work with Aztech drives, behavior is completely indepen-
593 dent on which mode is set ???
595 static int aztSetDiskType(int type)
596 { unsigned char data;
597 int retry;
599 #ifdef AZT_DEBUG
600 printk("aztcd: set disk type command: type= %i\n",type);
601 #endif
602 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
603 { aztSendCmd(ACMD_SET_DISK_TYPE);
604 outb(type,CMD_PORT);
605 STEN_LOW;
606 data=inb(DATA_PORT);
607 if (data==AFL_PA_OK) /*PA_OK ?*/
608 { azt_read_mode=type;
609 return 0;
611 if (data==AFL_PA_ERR)
612 { STEN_LOW;
613 data=inb(DATA_PORT);
614 printk("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",type,data);
617 if (retry>=AZT_RETRY_ATTEMPTS)
618 { printk("### Error 2 aztcd: aztSetDiskType %x\n ",type);
619 azt_error=0xA5;
621 RETURNM("aztSetDiskType",-1);
625 /* used in azt_poll to poll the status, expects another program to issue a
626 * ACMD_GET_STATUS directly before
628 static int aztStatus(void)
629 { int st;
630 /* int i;
632 i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
633 if (!i)
634 */ STEN_LOW;
635 if (aztTimeOutCount<AZT_TIMEOUT)
636 { st = inb(DATA_PORT) & 0xFF;
637 return st;
639 else
640 RETURNM("aztStatus",-1);
644 * Get the drive status
646 static int getAztStatus(void)
647 { int st;
649 if (aztSendCmd(ACMD_GET_STATUS)) 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("aztcd: AST_CMD_CHECK error or no status available\n");
657 return -1;
660 if (((st&AST_MODE_BITS)!=AST_BUSY) && (aztAudioStatus == CDROM_AUDIO_PLAY))
661 /* XXX might be an error? look at q-channel? */
662 aztAudioStatus = CDROM_AUDIO_COMPLETED;
664 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY))
665 { aztDiskChanged = 1;
666 aztTocUpToDate = 0;
667 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
669 return st;
674 * Send a 'Play' command and get the status. Use only from the top half.
676 static int aztPlay(struct azt_Play_msf *arg)
677 { if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0) RETURNM("aztPlay",-1);
678 return 0;
682 * Subroutines to automatically close the door (tray) and
683 * lock it closed when the cd is mounted. Leave the tray
684 * locking as an option
686 static void aztCloseDoor(void)
688 aztSendCmd(ACMD_CLOSE);
689 STEN_LOW;
690 return;
693 static void aztLockDoor(void)
695 #if AZT_ALLOW_TRAY_LOCK
696 aztSendCmd(ACMD_LOCK);
697 STEN_LOW;
698 #endif
699 return;
702 static void aztUnlockDoor(void)
704 #if AZT_ALLOW_TRAY_LOCK
705 aztSendCmd(ACMD_UNLOCK);
706 STEN_LOW;
707 #endif
708 return;
712 * Read a value from the drive. Should return quickly, so a busy wait
713 * is used to avoid excessive rescheduling. The read command itself must
714 * be issued with aztSendCmd() directly before
716 static int aztGetValue(unsigned char *result)
717 { int s;
719 STEN_LOW;
720 if (aztTimeOutCount>=AZT_TIMEOUT)
721 { printk("aztcd: aztGetValue timeout\n");
722 return -1;
724 s = inb(DATA_PORT) & 0xFF;
725 *result = (unsigned char) s;
726 return 0;
730 * Read the current Q-channel info. Also used for reading the
731 * table of contents.
733 int aztGetQChannelInfo(struct azt_Toc *qp)
734 { unsigned char notUsed;
735 int st;
737 #ifdef AZT_DEBUG
738 printk("aztcd: starting aztGetQChannelInfo Time:%li\n",jiffies);
739 #endif
740 if ((st=getAztStatus())==-1) RETURNM("aztGetQChannelInfo 1",-1);
741 if (aztSendCmd(ACMD_GET_Q_CHANNEL)) RETURNM("aztGetQChannelInfo 2",-1);
742 /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here*/
743 if (aztGetValue(&notUsed)) RETURNM("aztGetQChannelInfo 3",-1); /*??? Nullbyte einlesen*/
744 if ((st&AST_MODE_BITS)==AST_INITIAL)
745 { qp->ctrl_addr=0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
746 qp->track=0; /* only one byte with Aztech drives */
747 qp->pointIndex=0;
748 qp->trackTime.min=0;
749 qp->trackTime.sec=0;
750 qp->trackTime.frame=0;
751 qp->diskTime.min=0;
752 qp->diskTime.sec=0;
753 qp->diskTime.frame=0;
754 return 0;
756 else
757 { if (aztGetValue(&qp -> ctrl_addr) < 0) RETURNM("aztGetQChannelInfo 4",-1);
758 if (aztGetValue(&qp -> track) < 0) RETURNM("aztGetQChannelInfo 4",-1);
759 if (aztGetValue(&qp -> pointIndex) < 0) RETURNM("aztGetQChannelInfo 4",-1);
760 if (aztGetValue(&qp -> trackTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1);
761 if (aztGetValue(&qp -> trackTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1);
762 if (aztGetValue(&qp -> trackTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1);
763 if (aztGetValue(&notUsed) < 0) RETURNM("aztGetQChannelInfo 4",-1);
764 if (aztGetValue(&qp -> diskTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1);
765 if (aztGetValue(&qp -> diskTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1);
766 if (aztGetValue(&qp -> diskTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1);
768 #ifdef AZT_DEBUG
769 printk("aztcd: exiting aztGetQChannelInfo Time:%li\n",jiffies);
770 #endif
771 return 0;
775 * Read the table of contents (TOC) and TOC header if necessary
777 static int aztUpdateToc()
778 { int st;
780 #ifdef AZT_DEBUG
781 printk("aztcd: starting aztUpdateToc Time:%li\n",jiffies);
782 #endif
783 if (aztTocUpToDate)
784 return 0;
786 if (aztGetDiskInfo() < 0)
787 return -EIO;
789 if (aztGetToc(0) < 0)
790 return -EIO;
792 /*audio disk detection
793 with my Aztech drive there is no audio status bit, so I use the copy
794 protection bit of the first track. If this track is copy protected
795 (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
796 if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
797 DiskInfo.audio=1;
798 else
799 DiskInfo.audio=0;
801 /* XA detection */
802 if (! DiskInfo.audio)
803 { azt_Play.start.min = 0; /*XA detection only seems to work*/
804 azt_Play.start.sec = 2; /*when we play a track*/
805 azt_Play.start.frame = 0;
806 azt_Play.end.min = 0;
807 azt_Play.end.sec = 0;
808 azt_Play.end.frame = 1;
809 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
810 DTEN_LOW;
811 for (st=0;st<CD_FRAMESIZE;st++) inb(DATA_PORT);
813 DiskInfo.xa = getAztStatus() & AST_MODE;
814 if (DiskInfo.xa)
815 { printk("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
818 /*multisession detection
819 support for multisession CDs is done automatically with Aztech drives,
820 we don't have to take care about TOC redirection; if we want the isofs
821 to take care about redirection, we have to set AZT_MULTISESSION to 1*/
822 DiskInfo.multi=0;
823 #if AZT_MULTISESSION
824 if (DiskInfo.xa)
825 { aztGetMultiDiskInfo(); /*here Disk.Info.multi is set*/
827 #endif
828 if (DiskInfo.multi)
829 { DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
830 DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
831 DiskInfo.lastSession.frame= Toc[DiskInfo.next].diskTime.frame;
832 printk("aztcd: Multisession support experimental\n");
834 else
835 { DiskInfo.lastSession.min = Toc[DiskInfo.first].diskTime.min;
836 DiskInfo.lastSession.sec = Toc[DiskInfo.first].diskTime.sec;
837 DiskInfo.lastSession.frame= Toc[DiskInfo.first].diskTime.frame;
840 aztTocUpToDate = 1;
841 #ifdef AZT_DEBUG
842 printk("aztcd: exiting aztUpdateToc Time:%li\n",jiffies);
843 #endif
844 return 0;
848 /* Read the table of contents header, i.e. no. of tracks and start of first
849 * track
851 static int aztGetDiskInfo()
852 { int limit;
853 unsigned char test;
854 struct azt_Toc qInfo;
856 #ifdef AZT_DEBUG
857 printk("aztcd: starting aztGetDiskInfo Time:%li\n",jiffies);
858 #endif
859 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetDiskInfo 1",-1);
860 STEN_LOW_WAIT;
861 test=0;
862 for (limit=300;limit>0;limit--)
863 { if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetDiskInfo 2",-1);
864 if (qInfo.pointIndex==0xA0) /*Number of FirstTrack*/
865 { DiskInfo.first = qInfo.diskTime.min;
866 DiskInfo.first = azt_bcd2bin(DiskInfo.first);
867 test=test|0x01;
869 if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/
870 { DiskInfo.last = qInfo.diskTime.min;
871 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
872 test=test|0x02;
874 if (qInfo.pointIndex==0xA2) /*DiskLength*/
875 { DiskInfo.diskLength.min=qInfo.diskTime.min;
876 DiskInfo.diskLength.sec=qInfo.diskTime.sec;
877 DiskInfo.diskLength.frame=qInfo.diskTime.frame;
878 test=test|0x04;
880 if ((qInfo.pointIndex==DiskInfo.first)&&(test&0x01)) /*StartTime of First Track*/
881 { DiskInfo.firstTrack.min=qInfo.diskTime.min;
882 DiskInfo.firstTrack.sec=qInfo.diskTime.sec;
883 DiskInfo.firstTrack.frame=qInfo.diskTime.frame;
884 test=test|0x08;
886 if (test==0x0F) break;
888 #ifdef AZT_DEBUG
889 printk ("aztcd: exiting aztGetDiskInfo Time:%li\n",jiffies);
890 printk("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
891 DiskInfo.first,
892 DiskInfo.last,
893 DiskInfo.diskLength.min,
894 DiskInfo.diskLength.sec,
895 DiskInfo.diskLength.frame,
896 DiskInfo.firstTrack.min,
897 DiskInfo.firstTrack.sec,
898 DiskInfo.firstTrack.frame);
899 #endif
900 if (test!=0x0F) return -1;
901 return 0;
904 #if AZT_MULTISESSION
906 * Get Multisession Disk Info
908 static int aztGetMultiDiskInfo(void)
909 { int limit, k=5;
910 unsigned char test;
911 struct azt_Toc qInfo;
913 #ifdef AZT_DEBUG
914 printk("aztcd: starting aztGetMultiDiskInfo\n");
915 #endif
917 do { azt_Play.start.min = Toc[DiskInfo.last+1].diskTime.min;
918 azt_Play.start.sec = Toc[DiskInfo.last+1].diskTime.sec;
919 azt_Play.start.frame = Toc[DiskInfo.last+1].diskTime.frame;
920 test=0;
922 for (limit=30;limit>0;limit--) /*Seek for LeadIn of next session*/
923 { if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 1",-1);
924 if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 2",-1);
925 if ((qInfo.track==0)&&(qInfo.pointIndex)) break; /*LeadIn found*/
926 if ((azt_Play.start.sec+=10) > 59)
927 { azt_Play.start.sec=0;
928 azt_Play.start.min++;
931 if (!limit) break; /*Check, if a leadin track was found, if not we're
932 at the end of the disk*/
933 #ifdef AZT_DEBUG_MULTISESSION
934 printk("leadin found track %d pointIndex %x limit %d\n",qInfo.track,qInfo.pointIndex,limit);
935 #endif
936 for (limit=300;limit>0;limit--)
937 { if (++azt_Play.start.frame>74)
938 { azt_Play.start.frame=0;
939 if (azt_Play.start.sec > 59)
940 { azt_Play.start.sec=0;
941 azt_Play.start.min++;
944 if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 3",-1);
945 if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 4",-1);
946 if (qInfo.pointIndex==0xA0) /*Number of NextTrack*/
947 { DiskInfo.next = qInfo.diskTime.min;
948 DiskInfo.next = azt_bcd2bin(DiskInfo.next);
949 test=test|0x01;
951 if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/
952 { DiskInfo.last = qInfo.diskTime.min;
953 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
954 test=test|0x02;
956 if (qInfo.pointIndex==0xA2) /*DiskLength*/
957 { DiskInfo.diskLength.min =qInfo.diskTime.min;
958 DiskInfo.diskLength.sec =qInfo.diskTime.sec;
959 DiskInfo.diskLength.frame=qInfo.diskTime.frame;
960 test=test|0x04;
962 if ((qInfo.pointIndex==DiskInfo.next)&&(test&0x01)) /*StartTime of Next Track*/
963 { DiskInfo.nextSession.min=qInfo.diskTime.min;
964 DiskInfo.nextSession.sec=qInfo.diskTime.sec;
965 DiskInfo.nextSession.frame=qInfo.diskTime.frame;
966 test=test|0x08;
968 if (test==0x0F) break;
970 #ifdef AZT_DEBUG_MULTISESSION
971 printk ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n",
972 DiskInfo.first,
973 DiskInfo.next,
974 DiskInfo.last,
975 DiskInfo.diskLength.min,
976 DiskInfo.diskLength.sec,
977 DiskInfo.diskLength.frame,
978 DiskInfo.firstTrack.min,
979 DiskInfo.firstTrack.sec,
980 DiskInfo.firstTrack.frame,
981 DiskInfo.nextSession.min,
982 DiskInfo.nextSession.sec,
983 DiskInfo.nextSession.frame);
984 #endif
985 if (test!=0x0F)
986 break;
987 else
988 DiskInfo.multi=1; /*found TOC of more than one session*/
989 aztGetToc(1);
990 } while(--k);
992 #ifdef AZT_DEBUG
993 printk ("aztcd: exiting aztGetMultiDiskInfo Time:%li\n",jiffies);
994 #endif
995 return 0;
997 #endif
1000 * Read the table of contents (TOC)
1002 static int aztGetToc(int multi)
1003 { int i, px;
1004 int limit;
1005 struct azt_Toc qInfo;
1007 #ifdef AZT_DEBUG
1008 printk("aztcd: starting aztGetToc Time:%li\n",jiffies);
1009 #endif
1010 if (!multi)
1011 { for (i = 0; i < MAX_TRACKS; i++)
1012 Toc[i].pointIndex = 0;
1013 i = DiskInfo.last + 3;
1015 else
1016 { for (i = DiskInfo.next; i < MAX_TRACKS; i++)
1017 Toc[i].pointIndex = 0;
1018 i = DiskInfo.last + 4 - DiskInfo.next;
1021 /*Is there a good reason to stop motor before TOC read?
1022 if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
1023 STEN_LOW_WAIT;
1026 if (!multi)
1027 { azt_mode = 0x05;
1028 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1);
1029 STEN_LOW_WAIT;
1031 for (limit = 300; limit > 0; limit--)
1032 { if (multi)
1033 { if (++azt_Play.start.sec > 59)
1034 { azt_Play.start.sec=0;
1035 azt_Play.start.min++;
1037 if (aztSeek(&azt_Play)) RETURNM("aztGetToc 3",-1);
1039 if (aztGetQChannelInfo(&qInfo) < 0)
1040 break;
1042 px = azt_bcd2bin(qInfo.pointIndex);
1044 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1045 if (Toc[px].pointIndex == 0)
1046 { Toc[px] = qInfo;
1047 i--;
1050 if (i <= 0)
1051 break;
1054 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1055 Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
1057 #ifdef AZT_DEBUG_MULTISESSION
1058 printk("aztcd: exiting aztGetToc\n");
1059 for (i = 1; i <= DiskInfo.last+1; i++)
1060 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1061 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1062 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1063 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1064 for (i = 100; i < 103; i++)
1065 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1066 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1067 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1068 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1069 #endif
1071 return limit > 0 ? 0 : -1;
1075 /*##########################################################################
1076 Kernel Interface Functions
1077 ##########################################################################
1080 #ifndef MODULE
1081 static int __init aztcd_setup(char *str)
1083 int ints[4];
1085 (void)get_options(str, ARRAY_SIZE(ints), ints);
1087 if (ints[0] > 0)
1088 azt_port = ints[1];
1089 if (ints[1] > 1)
1090 azt_cont = ints[2];
1091 return 1;
1094 __setup("aztcd=", aztcd_setup);
1096 #endif /* !MODULE */
1099 * Checking if the media has been changed
1101 static int check_aztcd_media_change(kdev_t full_dev)
1102 { if (aztDiskChanged) /* disk changed */
1103 { aztDiskChanged=0;
1104 return 1;
1106 else
1107 return 0; /* no change */
1111 * Kernel IO-controls
1113 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
1114 { int i, st;
1115 struct azt_Toc qInfo;
1116 struct cdrom_ti ti;
1117 struct cdrom_tochdr tocHdr;
1118 struct cdrom_msf msf;
1119 struct cdrom_tocentry entry;
1120 struct azt_Toc *tocPtr;
1121 struct cdrom_subchnl subchnl;
1122 struct cdrom_volctrl volctrl;
1124 #ifdef AZT_DEBUG
1125 printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n",cmd, jiffies);
1126 printk("aztcd Status %x\n", getAztStatus());
1127 #endif
1128 if (!ip) RETURNM("aztcd_ioctl 1",-EINVAL);
1129 if (getAztStatus()<0) RETURNM("aztcd_ioctl 2", -EIO);
1130 if ((!aztTocUpToDate)||(aztDiskChanged))
1131 { if ((i=aztUpdateToc())<0) RETURNM("aztcd_ioctl 3", i); /* error reading TOC */
1134 switch (cmd)
1136 case CDROMSTART: /* Spin up the drive. Don't know, what to do,
1137 at least close the tray */
1138 #if AZT_PRIVATE_IOCTLS
1139 if (aztSendCmd(ACMD_CLOSE)) RETURNM("aztcd_ioctl 4",-1);
1140 STEN_LOW_WAIT;
1141 #endif
1142 break;
1143 case CDROMSTOP: /* Spin down the drive */
1144 if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 5",-1);
1145 STEN_LOW_WAIT;
1146 /* should we do anything if it fails? */
1147 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1148 break;
1149 case CDROMPAUSE: /* Pause the drive */
1150 if (aztAudioStatus != CDROM_AUDIO_PLAY) return -EINVAL;
1152 if (aztGetQChannelInfo(&qInfo) < 0)
1153 { /* didn't get q channel info */
1154 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1155 RETURNM("aztcd_ioctl 7",0);
1157 azt_Play.start = qInfo.diskTime; /* remember restart point */
1159 if (aztSendCmd(ACMD_PAUSE)) RETURNM("aztcd_ioctl 8",-1);
1160 STEN_LOW_WAIT;
1161 aztAudioStatus = CDROM_AUDIO_PAUSED;
1162 break;
1163 case CDROMRESUME: /* Play it again, Sam */
1164 if (aztAudioStatus != CDROM_AUDIO_PAUSED) return -EINVAL;
1165 /* restart the drive at the saved position. */
1166 i = aztPlay(&azt_Play);
1167 if (i < 0)
1168 { aztAudioStatus = CDROM_AUDIO_ERROR;
1169 return -EIO;
1171 aztAudioStatus = CDROM_AUDIO_PLAY;
1172 break;
1173 case CDROMMULTISESSION: /*multisession support -- experimental*/
1174 { struct cdrom_multisession ms;
1175 #ifdef AZT_DEBUG
1176 printk("aztcd ioctl MULTISESSION\n");
1177 #endif
1178 st = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct cdrom_multisession));
1179 if (st) return st;
1180 memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession));
1181 if (ms.addr_format == CDROM_MSF)
1182 { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min);
1183 ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec);
1184 ms.addr.msf.frame = azt_bcd2bin(DiskInfo.lastSession.frame);
1186 else if (ms.addr_format == CDROM_LBA)
1187 ms.addr.lba = azt_msf2hsg(&DiskInfo.lastSession);
1188 else
1189 return -EINVAL;
1190 ms.xa_flag = DiskInfo.xa;
1191 memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));
1192 #ifdef AZT_DEBUG
1193 if (ms.addr_format == CDROM_MSF)
1194 printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
1195 ms.xa_flag, ms.addr.msf.minute, ms.addr.msf.second,
1196 ms.addr.msf.frame, DiskInfo.lastSession.min,
1197 DiskInfo.lastSession.sec, DiskInfo.lastSession.frame);
1198 else
1199 printk("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
1200 ms.xa_flag, ms.addr.lba, DiskInfo.lastSession.min,
1201 DiskInfo.lastSession.sec, DiskInfo.lastSession.frame);
1202 #endif
1203 return 0;
1205 case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
1206 st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
1207 if (st) return st;
1208 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
1209 if (ti.cdti_trk0 < DiskInfo.first
1210 || ti.cdti_trk0 > DiskInfo.last
1211 || ti.cdti_trk1 < ti.cdti_trk0)
1212 { return -EINVAL;
1214 if (ti.cdti_trk1 > DiskInfo.last)
1215 ti.cdti_trk1 = DiskInfo.last;
1216 azt_Play.start = Toc[ti.cdti_trk0].diskTime;
1217 azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
1218 #ifdef AZT_DEBUG
1219 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
1220 azt_Play.start.min, azt_Play.start.sec, azt_Play.start.frame,
1221 azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
1222 #endif
1223 i = aztPlay(&azt_Play);
1224 if (i < 0)
1225 { aztAudioStatus = CDROM_AUDIO_ERROR;
1226 return -EIO;
1228 aztAudioStatus = CDROM_AUDIO_PLAY;
1229 break;
1230 case CDROMPLAYMSF: /* Play starting at the given MSF address. */
1231 /* if (aztAudioStatus == CDROM_AUDIO_PLAY)
1232 { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1);
1233 STEN_LOW;
1234 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1237 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1238 if (st) return st;
1239 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1240 /* convert to bcd */
1241 azt_bin2bcd(&msf.cdmsf_min0);
1242 azt_bin2bcd(&msf.cdmsf_sec0);
1243 azt_bin2bcd(&msf.cdmsf_frame0);
1244 azt_bin2bcd(&msf.cdmsf_min1);
1245 azt_bin2bcd(&msf.cdmsf_sec1);
1246 azt_bin2bcd(&msf.cdmsf_frame1);
1247 azt_Play.start.min = msf.cdmsf_min0;
1248 azt_Play.start.sec = msf.cdmsf_sec0;
1249 azt_Play.start.frame = msf.cdmsf_frame0;
1250 azt_Play.end.min = msf.cdmsf_min1;
1251 azt_Play.end.sec = msf.cdmsf_sec1;
1252 azt_Play.end.frame = msf.cdmsf_frame1;
1253 #ifdef AZT_DEBUG
1254 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n",
1255 azt_Play.start.min, azt_Play.start.sec, azt_Play.start.frame,
1256 azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
1257 #endif
1258 i = aztPlay(&azt_Play);
1259 if (i < 0)
1260 { aztAudioStatus = CDROM_AUDIO_ERROR;
1261 return -EIO;
1263 aztAudioStatus = CDROM_AUDIO_PLAY;
1264 break;
1266 case CDROMREADTOCHDR: /* Read the table of contents header */
1267 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
1268 if (st) return st;
1269 tocHdr.cdth_trk0 = DiskInfo.first;
1270 tocHdr.cdth_trk1 = DiskInfo.last;
1271 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
1272 break;
1273 case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
1274 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
1275 if (st) return st;
1276 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
1277 if ((!aztTocUpToDate)||aztDiskChanged) aztUpdateToc();
1278 if (entry.cdte_track == CDROM_LEADOUT)
1279 tocPtr = &Toc[DiskInfo.last + 1];
1280 else if (entry.cdte_track > DiskInfo.last
1281 || entry.cdte_track < DiskInfo.first)
1282 { return -EINVAL;
1284 else
1285 tocPtr = &Toc[entry.cdte_track];
1286 entry.cdte_adr = tocPtr -> ctrl_addr;
1287 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
1288 if (entry.cdte_format == CDROM_LBA)
1289 entry.cdte_addr.lba = azt_msf2hsg(&tocPtr -> diskTime);
1290 else if (entry.cdte_format == CDROM_MSF)
1291 { entry.cdte_addr.msf.minute = azt_bcd2bin(tocPtr -> diskTime.min);
1292 entry.cdte_addr.msf.second = azt_bcd2bin(tocPtr -> diskTime.sec);
1293 entry.cdte_addr.msf.frame = azt_bcd2bin(tocPtr -> diskTime.frame);
1295 else
1296 { return -EINVAL;
1298 memcpy_tofs((void *) arg, &entry, sizeof entry);
1299 break;
1300 case CDROMSUBCHNL: /* Get subchannel info */
1301 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
1302 if (st) {
1303 #ifdef AZT_DEBUG
1304 printk("aztcd: exiting aztcd_ioctl - Error 1 - Command:%x\n",cmd);
1305 #endif
1306 return st;
1308 memcpy_fromfs(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl));
1309 if (aztGetQChannelInfo(&qInfo) < 0)
1310 if (st) {
1311 #ifdef AZT_DEBUG
1312 printk("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n",cmd);
1313 #endif
1314 return -EIO;
1316 subchnl.cdsc_audiostatus = aztAudioStatus;
1317 subchnl.cdsc_adr = qInfo.ctrl_addr;
1318 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
1319 subchnl.cdsc_trk = azt_bcd2bin(qInfo.track);
1320 subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex);
1321 if (subchnl.cdsc_format == CDROM_LBA)
1322 { subchnl.cdsc_absaddr.lba = azt_msf2hsg(&qInfo.diskTime);
1323 subchnl.cdsc_reladdr.lba = azt_msf2hsg(&qInfo.trackTime);
1325 else /*default*/
1326 { subchnl.cdsc_format = CDROM_MSF;
1327 subchnl.cdsc_absaddr.msf.minute = azt_bcd2bin(qInfo.diskTime.min);
1328 subchnl.cdsc_absaddr.msf.second = azt_bcd2bin(qInfo.diskTime.sec);
1329 subchnl.cdsc_absaddr.msf.frame = azt_bcd2bin(qInfo.diskTime.frame);
1330 subchnl.cdsc_reladdr.msf.minute = azt_bcd2bin(qInfo.trackTime.min);
1331 subchnl.cdsc_reladdr.msf.second = azt_bcd2bin(qInfo.trackTime.sec);
1332 subchnl.cdsc_reladdr.msf.frame = azt_bcd2bin(qInfo.trackTime.frame);
1334 memcpy_tofs((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
1335 break;
1336 case CDROMVOLCTRL: /* Volume control
1337 * With my Aztech CD268-01A volume control does not work, I can only
1338 turn the channels on (any value !=0) or off (value==0). Maybe it
1339 works better with your drive */
1340 st=verify_area(VERIFY_READ,(void *) arg, sizeof(volctrl));
1341 if (st) return (st);
1342 memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
1343 azt_Play.start.min = 0x21;
1344 azt_Play.start.sec = 0x84;
1345 azt_Play.start.frame = volctrl.channel0;
1346 azt_Play.end.min = volctrl.channel1;
1347 azt_Play.end.sec = volctrl.channel2;
1348 azt_Play.end.frame = volctrl.channel3;
1349 sendAztCmd(ACMD_SET_VOLUME, &azt_Play);
1350 STEN_LOW_WAIT;
1351 break;
1352 case CDROMEJECT:
1353 aztUnlockDoor(); /* Assume user knows what they're doing */
1354 /* all drives can at least stop! */
1355 if (aztAudioStatus == CDROM_AUDIO_PLAY)
1356 { if (aztSendCmd(ACMD_STOP)) RETURNM("azt_ioctl 10",-1);
1357 STEN_LOW_WAIT;
1359 if (aztSendCmd(ACMD_EJECT)) RETURNM("azt_ioctl 11",-1);
1360 STEN_LOW_WAIT;
1361 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
1362 break;
1363 case CDROMEJECT_SW:
1364 azt_auto_eject = (char) arg;
1365 break;
1366 case CDROMRESET:
1367 outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
1368 STEN_LOW;
1369 if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
1370 { printk("aztcd: AZTECH CD-ROM drive does not respond\n");
1372 break;
1373 /*Take care, the following code is not compatible with other CD-ROM drivers,
1374 use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h,
1375 if you do not want to use it!
1377 #if AZT_PRIVATE_IOCTLS
1378 case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes)*/
1379 case CDROMREADRAW: /*read data in mode 2 (2336 Bytes)*/
1380 { st = verify_area(VERIFY_WRITE, (void *) arg, sizeof buf);
1381 if (st) return st;
1382 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1383 /* convert to bcd */
1384 azt_bin2bcd(&msf.cdmsf_min0);
1385 azt_bin2bcd(&msf.cdmsf_sec0);
1386 azt_bin2bcd(&msf.cdmsf_frame0);
1387 msf.cdmsf_min1=0;
1388 msf.cdmsf_sec1=0;
1389 msf.cdmsf_frame1=1; /*read only one frame*/
1390 azt_Play.start.min = msf.cdmsf_min0;
1391 azt_Play.start.sec = msf.cdmsf_sec0;
1392 azt_Play.start.frame = msf.cdmsf_frame0;
1393 azt_Play.end.min = msf.cdmsf_min1;
1394 azt_Play.end.sec = msf.cdmsf_sec1;
1395 azt_Play.end.frame = msf.cdmsf_frame1;
1396 if (cmd==CDROMREADRAW)
1397 { if (DiskInfo.xa)
1398 { return -1; /*XA Disks can't be read raw*/
1400 else
1401 { if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) return -1;
1402 DTEN_LOW;
1403 insb(DATA_PORT,buf,CD_FRAMESIZE_RAW);
1404 memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW);
1407 else /*CDROMREADCOOKED*/
1408 { if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
1409 DTEN_LOW;
1410 insb(DATA_PORT,buf,CD_FRAMESIZE);
1411 memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE);
1414 break;
1415 case CDROMSEEK: /*seek msf address*/
1416 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1417 if (st) return st;
1418 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1419 /* convert to bcd */
1420 azt_bin2bcd(&msf.cdmsf_min0);
1421 azt_bin2bcd(&msf.cdmsf_sec0);
1422 azt_bin2bcd(&msf.cdmsf_frame0);
1423 azt_Play.start.min = msf.cdmsf_min0;
1424 azt_Play.start.sec = msf.cdmsf_sec0;
1425 azt_Play.start.frame = msf.cdmsf_frame0;
1426 if (aztSeek(&azt_Play)) return -1;
1427 break;
1428 #endif /*end of incompatible code*/
1429 case CDROMREADMODE1: /*set read data in mode 1*/
1430 return aztSetDiskType(AZT_MODE_1);
1431 case CDROMREADMODE2: /*set read data in mode 2*/
1432 return aztSetDiskType(AZT_MODE_2);
1433 default:
1434 return -EINVAL;
1436 #ifdef AZT_DEBUG
1437 printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n",cmd,jiffies);
1438 #endif
1439 return 0;
1443 * Take care of the different block sizes between cdrom and Linux.
1444 * When Linux gets variable block sizes this will probably go away.
1446 static void azt_transfer(void)
1448 #ifdef AZT_TEST
1449 printk("aztcd: executing azt_transfer Time:%li\n",jiffies);
1450 #endif
1451 if (CURRENT_VALID) {
1452 while (CURRENT -> nr_sectors) {
1453 int bn = CURRENT -> sector / 4;
1454 int i;
1455 for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i)
1457 if (i < AZT_BUF_SIZ) {
1458 int offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
1459 int nr_sectors = 4 - (CURRENT -> sector & 3);
1460 if (azt_buf_out != i) {
1461 azt_buf_out = i;
1462 if (azt_buf_bn[i] != bn) {
1463 azt_buf_out = -1;
1464 continue;
1467 if (nr_sectors > CURRENT -> nr_sectors)
1468 nr_sectors = CURRENT -> nr_sectors;
1469 memcpy(CURRENT -> buffer, azt_buf + offs, nr_sectors * 512);
1470 CURRENT -> nr_sectors -= nr_sectors;
1471 CURRENT -> sector += nr_sectors;
1472 CURRENT -> buffer += nr_sectors * 512;
1473 } else {
1474 azt_buf_out = -1;
1475 break;
1481 static void do_aztcd_request(request_queue_t * q)
1483 #ifdef AZT_TEST
1484 printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT -> sector, CURRENT -> nr_sectors,jiffies);
1485 #endif
1486 if (DiskInfo.audio)
1487 { printk("aztcd: Error, tried to mount an Audio CD\n");
1488 end_request(0);
1489 return;
1491 azt_transfer_is_active = 1;
1492 while (CURRENT_VALID) {
1493 if (CURRENT->bh) {
1494 if (!buffer_locked(CURRENT->bh))
1495 panic(DEVICE_NAME ": block not locked");
1497 azt_transfer();
1498 if (CURRENT -> nr_sectors == 0) {
1499 end_request(1);
1500 } else {
1501 azt_buf_out = -1; /* Want to read a block not in buffer */
1502 if (azt_state == AZT_S_IDLE) {
1503 if ((!aztTocUpToDate)||aztDiskChanged) {
1504 if (aztUpdateToc() < 0) {
1505 while (CURRENT_VALID)
1506 end_request(0);
1507 break;
1510 azt_state = AZT_S_START;
1511 AztTries = 5;
1512 SET_TIMER(azt_poll, HZ/100);
1514 break;
1517 azt_transfer_is_active = 0;
1518 #ifdef AZT_TEST2
1519 printk("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", \
1520 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
1521 printk(" do_aztcd_request ends Time:%li\n",jiffies);
1522 #endif
1526 static void azt_invalidate_buffers(void)
1527 { int i;
1529 #ifdef AZT_DEBUG
1530 printk("aztcd: executing azt_invalidate_buffers\n");
1531 #endif
1532 for (i = 0; i < AZT_BUF_SIZ; ++i)
1533 azt_buf_bn[i] = -1;
1534 azt_buf_out = -1;
1538 * Open the device special file. Check that a disk is in.
1540 int aztcd_open(struct inode *ip, struct file *fp)
1541 { int st;
1543 #ifdef AZT_DEBUG
1544 printk("aztcd: starting aztcd_open\n");
1545 #endif
1547 if (aztPresent == 0)
1548 return -ENXIO; /* no hardware */
1550 MOD_INC_USE_COUNT;
1552 if (!azt_open_count && azt_state == AZT_S_IDLE)
1553 { azt_invalidate_buffers();
1555 st = getAztStatus(); /* check drive status */
1556 if (st == -1) goto err_out; /* drive doesn't respond */
1558 if (st & AST_DOOR_OPEN)
1559 { /* close door, then get the status again. */
1560 printk("aztcd: Door Open?\n");
1561 aztCloseDoor();
1562 st = getAztStatus();
1565 if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) /*no disk in drive or changed*/
1566 { printk("aztcd: Disk Changed or No Disk in Drive?\n");
1567 aztTocUpToDate=0;
1569 if (aztUpdateToc()) goto err_out;
1572 ++azt_open_count;
1573 aztLockDoor();
1575 #ifdef AZT_DEBUG
1576 printk("aztcd: exiting aztcd_open\n");
1577 #endif
1578 return 0;
1580 err_out:
1581 MOD_DEC_USE_COUNT;
1582 return -EIO;
1587 * On close, we flush all azt blocks from the buffer cache.
1589 #ifdef AZT_KERNEL_PRIOR_2_1
1590 static void aztcd_release(struct inode * inode, struct file * file)
1591 #else
1592 static int aztcd_release(struct inode * inode, struct file * file)
1593 #endif
1595 #ifdef AZT_DEBUG
1596 printk("aztcd: executing aztcd_release\n");
1597 printk("inode: %p, inode->i_rdev: %x file: %p\n",inode,inode->i_rdev,file);
1598 #endif
1599 MOD_DEC_USE_COUNT;
1600 if (!--azt_open_count) {
1601 azt_invalidate_buffers();
1602 aztUnlockDoor();
1603 if (azt_auto_eject)
1604 aztSendCmd(ACMD_EJECT);
1605 CLEAR_TIMER;
1607 #ifdef AZT_KERNEL_PRIOR_2_1
1608 return;
1609 #else
1610 return 0;
1611 #endif
1617 * Test for presence of drive and initialize it. Called at boot time.
1620 int __init aztcd_init(void)
1621 { long int count, max_count;
1622 unsigned char result[50];
1623 int st;
1624 int i = 0;
1626 if (azt_port == 0)
1627 { printk("aztcd: no Aztech CD-ROM Initialization");
1628 return -EIO;
1631 printk("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n");
1632 printk("aztcd: (C) 1994-98 W.Zimmermann\n");
1633 if (azt_port == -1)
1634 { printk("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",UTS_RELEASE,AZT_VERSION);
1636 else
1637 printk("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port);
1638 printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
1641 #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card*/
1642 if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500)
1643 { printk("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
1644 AZT_SW32_BASE_ADDR,AZT_SW32_INIT,AZT_SW32_CONFIG_REG,AZT_SW32_ID_REG);
1645 return -EIO;
1647 else
1648 { printk(KERN_INFO "aztcd: Soundwave32 card detected at %x Version %x\n",
1649 AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
1650 outw(AZT_SW32_INIT,AZT_SW32_CONFIG_REG);
1651 for (count=0;count<10000;count++); /*delay a bit*/
1653 #endif
1655 /* check for presence of drive */
1657 if (azt_port == -1) /* autoprobing */
1658 { for (i=0;(azt_port_auto[i]!=0)&&(i<16);i++)
1659 { azt_port = azt_port_auto[i];
1660 printk("aztcd: Autoprobing BaseAddress=0x%x \n",azt_port);
1661 st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
1662 if (st) continue;
1664 outb(POLLED,MODE_PORT);
1665 inb(CMD_PORT);
1666 inb(CMD_PORT);
1667 outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
1669 aztTimeOutCount=0;
1670 do { aztIndatum=inb(STATUS_PORT);
1671 aztTimeOutCount++;
1672 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1673 } while (aztIndatum&AFL_STATUS);
1674 if (inb(DATA_PORT)==AFL_OP_OK)
1675 break;
1677 if ((azt_port_auto[i]==0)||(i==16))
1678 { printk("aztcd: no AZTECH CD-ROM drive found\n");
1679 return -EIO;
1682 else /* no autoprobing */
1683 { if ((azt_port==0x1f0)||(azt_port==0x170))
1684 st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes*/
1685 else
1686 st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
1687 if (st)
1688 { printk("aztcd: conflict, I/O port (%X) already used\n",azt_port);
1689 return -EIO;
1692 if ((azt_port==0x1f0)||(azt_port==0x170))
1693 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/
1695 outb(POLLED,MODE_PORT);
1696 inb(CMD_PORT);
1697 inb(CMD_PORT);
1698 outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
1700 aztTimeOutCount=0;
1701 do { aztIndatum=inb(STATUS_PORT);
1702 aztTimeOutCount++;
1703 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1704 } while (aztIndatum&AFL_STATUS);
1706 if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
1708 #ifndef MODULE
1709 if (azt_cont!=0x79)
1710 { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=<BaseAddress>,0x79\n");
1711 return -EIO;
1713 #else
1714 if (0)
1717 #endif
1718 else
1719 { printk("aztcd: drive reset - please wait\n");
1720 for (count=0;count<50;count++)
1721 { inb(STATUS_PORT); /*removing all data from earlier tries*/
1722 inb(DATA_PORT);
1724 outb(POLLED,MODE_PORT);
1725 inb(CMD_PORT);
1726 inb(CMD_PORT);
1727 getAztStatus(); /*trap errors*/
1728 outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
1729 STEN_LOW;
1730 if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
1731 { printk("aztcd: no AZTECH CD-ROM drive found\n");
1732 return -EIO;
1735 for (count = 0; count < AZT_TIMEOUT; count++)
1736 barrier(); /* Stop gcc 2.96 being smart */
1738 if ((st=getAztStatus())==-1)
1739 { printk("aztcd: Drive Status Error Status=%x\n",st);
1740 return -EIO;
1742 #ifdef AZT_DEBUG
1743 printk("aztcd: Status = %x\n",st);
1744 #endif
1745 outb(POLLED,MODE_PORT);
1746 inb(CMD_PORT);
1747 inb(CMD_PORT);
1748 outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
1749 STEN_LOW;
1750 OP_OK;
1755 azt_init_end=1;
1756 STEN_LOW;
1757 result[0]=inb(DATA_PORT); /*reading in a null byte???*/
1758 for (count=1;count<50;count++) /*Reading version string*/
1759 { aztTimeOutCount=0; /*here we must implement STEN_LOW differently*/
1760 do { aztIndatum=inb(STATUS_PORT);/*because we want to exit by timeout*/
1761 aztTimeOutCount++;
1762 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1763 } while (aztIndatum&AFL_STATUS);
1764 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; /*all chars read?*/
1765 result[count]=inb(DATA_PORT);
1767 if (count>30) max_count=30; /*print max.30 chars of the version string*/
1768 else max_count=count;
1769 printk(KERN_INFO "aztcd: FirmwareVersion=");
1770 for (count=1;count<max_count;count++) printk("%c",result[count]);
1771 printk("<<>> ");
1773 if ((result[1]=='A')&&(result[2]=='Z')&&(result[3]=='T'))
1774 { printk("AZTECH drive detected\n"); /*AZTECH*/
1776 else if ((result[2]=='C')&&(result[3]=='D')&&(result[4]=='D'))
1777 { printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES*/
1779 else if ((result[1]==0x03)&&(result[2]=='5'))
1780 { printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM*/
1782 else /*OTHERS or none*/
1783 { printk("\nunknown drive or firmware version detected\n");
1784 printk("aztcd may not run stable, if you want to try anyhow,\n");
1785 printk("boot with: aztcd=<BaseAddress>,0x79\n");
1786 if ((azt_cont!=0x79))
1787 { printk("aztcd: FirmwareVersion=");
1788 for (count=1;count<5;count++) printk("%c",result[count]);
1789 printk("<<>> ");
1790 printk("Aborted\n");
1791 return -EIO;
1794 devfs_register (NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
1795 S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL);
1796 if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0)
1798 printk("aztcd: Unable to get major %d for Aztech CD-ROM\n",
1799 MAJOR_NR);
1800 return -EIO;
1802 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1803 #ifndef AZT_KERNEL_PRIOR_2_1
1804 blksize_size[MAJOR_NR] = aztcd_blocksizes;
1805 #endif
1806 read_ahead[MAJOR_NR] = 4;
1807 register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &azt_fops, 0);
1809 if ((azt_port==0x1f0)||(azt_port==0x170))
1810 request_region(azt_port, 8, "aztcd"); /*IDE-interface*/
1811 else
1812 request_region(azt_port, 4, "aztcd"); /*proprietary interface*/
1814 azt_invalidate_buffers();
1815 aztPresent = 1;
1816 aztCloseDoor();
1817 return (0);
1820 void __exit aztcd_exit(void)
1822 devfs_unregister(devfs_find_handle(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK,
1823 0));
1824 if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL))
1825 { printk("What's that: can't unregister aztcd\n");
1826 return;
1828 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1829 if ((azt_port==0x1f0)||(azt_port==0x170))
1830 { SWITCH_IDE_MASTER;
1831 release_region(azt_port,8); /*IDE-interface*/
1833 else
1834 release_region(azt_port,4); /*proprietary interface*/
1835 printk(KERN_INFO "aztcd module released.\n");
1838 #ifdef MODULE
1839 module_init(aztcd_init);
1840 #endif
1841 module_exit(aztcd_exit);
1843 /*##########################################################################
1844 Aztcd State Machine: Controls Drive Operating State
1845 ##########################################################################
1847 static void azt_poll(void)
1849 int st = 0;
1850 int loop_ctl = 1;
1851 int skip = 0;
1853 if (azt_error) {
1854 if (aztSendCmd(ACMD_GET_ERROR)) RETURN("azt_poll 1");
1855 STEN_LOW;
1856 azt_error=inb(DATA_PORT)&0xFF;
1857 printk("aztcd: I/O error 0x%02x\n", azt_error);
1858 azt_invalidate_buffers();
1859 #ifdef WARN_IF_READ_FAILURE
1860 if (AztTries == 5)
1861 printk("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", azt_next_bn);
1862 #endif
1863 if (!AztTries--) {
1864 printk("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", azt_next_bn);
1865 if (azt_transfer_is_active) {
1866 AztTries = 0;
1867 loop_ctl = 0;
1869 if (CURRENT_VALID)
1870 end_request(0);
1871 AztTries = 5;
1873 azt_error = 0;
1874 azt_state = AZT_S_STOP;
1877 while (loop_ctl)
1879 loop_ctl = 0; /* each case must flip this back to 1 if we want
1880 to come back up here */
1881 switch (azt_state) {
1883 case AZT_S_IDLE:
1884 #ifdef AZT_TEST3
1885 if (azt_state!=azt_state_old) {
1886 azt_state_old=azt_state;
1887 printk("AZT_S_IDLE\n");
1889 #endif
1890 return;
1892 case AZT_S_START:
1893 #ifdef AZT_TEST3
1894 if (azt_state!=azt_state_old) {
1895 azt_state_old=azt_state;
1896 printk("AZT_S_START\n");
1898 #endif
1899 if(aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
1900 azt_state = azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
1901 AztTimeout = 3000;
1902 break;
1904 case AZT_S_MODE:
1905 #ifdef AZT_TEST3
1906 if (azt_state!=azt_state_old) {
1907 azt_state_old=azt_state;
1908 printk("AZT_S_MODE\n");
1910 #endif
1911 if (!skip) {
1912 if ((st = aztStatus()) != -1) {
1913 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) {
1914 aztDiskChanged = 1;
1915 aztTocUpToDate = 0;
1916 azt_invalidate_buffers();
1917 end_request(0);
1918 printk("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
1920 } else break;
1922 skip = 0;
1924 if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) {
1925 aztDiskChanged = 1;
1926 aztTocUpToDate = 0;
1927 printk("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
1928 end_request(0);
1929 printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n");
1930 if (azt_transfer_is_active) {
1931 azt_state = AZT_S_START;
1932 loop_ctl = 1; /* goto immediately */
1933 break;
1935 azt_state = AZT_S_IDLE;
1936 while (CURRENT_VALID)
1937 end_request(0);
1938 return;
1941 /* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
1942 outb(0x01, DATA_PORT);
1943 PA_OK;
1944 STEN_LOW;
1945 */ if (aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 4");
1946 STEN_LOW;
1947 azt_mode = 1;
1948 azt_state = AZT_S_READ;
1949 AztTimeout = 3000;
1951 break;
1954 case AZT_S_READ:
1955 #ifdef AZT_TEST3
1956 if (azt_state!=azt_state_old) {
1957 azt_state_old=azt_state;
1958 printk("AZT_S_READ\n");
1960 #endif
1961 if (!skip) {
1962 if ((st = aztStatus()) != -1) {
1963 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) {
1964 aztDiskChanged = 1;
1965 aztTocUpToDate = 0;
1966 azt_invalidate_buffers();
1967 printk("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
1968 end_request(0);
1970 } else break;
1973 skip = 0;
1974 if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) {
1975 aztDiskChanged = 1;
1976 aztTocUpToDate = 0;
1977 printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n");
1978 if (azt_transfer_is_active) {
1979 azt_state = AZT_S_START;
1980 loop_ctl = 1;
1981 break;
1983 azt_state = AZT_S_IDLE;
1984 while (CURRENT_VALID)
1985 end_request(0);
1986 return;
1989 if (CURRENT_VALID) {
1990 struct azt_Play_msf msf;
1991 int i;
1992 azt_next_bn = CURRENT -> sector / 4;
1993 azt_hsg2msf(azt_next_bn, &msf.start);
1994 i = 0;
1995 /* find out in which track we are */
1996 while (azt_msf2hsg(&msf.start)>azt_msf2hsg(&Toc[++i].trackTime)) {};
1997 if (azt_msf2hsg(&msf.start)<azt_msf2hsg(&Toc[i].trackTime)-AZT_BUF_SIZ)
1998 { azt_read_count=AZT_BUF_SIZ; /*fast, because we read ahead*/
1999 /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead*/
2001 else /* don't read beyond end of track */
2002 #if AZT_MULTISESSION
2003 { azt_read_count=(azt_msf2hsg(&Toc[i].trackTime)/4)*4-azt_msf2hsg(&msf.start);
2004 if (azt_read_count < 0) azt_read_count=0;
2005 if (azt_read_count > AZT_BUF_SIZ) azt_read_count=AZT_BUF_SIZ;
2006 printk("aztcd: warning - trying to read beyond end of track\n");
2007 /* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
2008 */ }
2009 #else
2010 { azt_read_count=AZT_BUF_SIZ;
2012 #endif
2013 msf.end.min = 0;
2014 msf.end.sec = 0;
2015 msf.end.frame = azt_read_count ;/*Mitsumi here reads 0xffffff sectors*/
2016 #ifdef AZT_TEST3
2017 printk("---reading msf-address %x:%x:%x %x:%x:%x\n",msf.start.min,msf.start.sec,msf.start.frame,msf.end.min,msf.end.sec,msf.end.frame);
2018 printk("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", \
2019 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
2020 #endif
2021 if (azt_read_mode==AZT_MODE_2)
2022 { sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode*/
2024 else
2025 { sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode*/
2027 azt_state = AZT_S_DATA;
2028 AztTimeout = READ_TIMEOUT;
2029 } else {
2030 azt_state = AZT_S_STOP;
2031 loop_ctl = 1;
2032 break;
2035 break;
2038 case AZT_S_DATA:
2039 #ifdef AZT_TEST3
2040 if (azt_state!=azt_state_old) {
2041 azt_state_old=azt_state;
2042 printk("AZT_S_DATA\n");
2044 #endif
2046 st = inb(STATUS_PORT) & AFL_STATUSorDATA;
2048 switch (st) {
2050 case AFL_DATA:
2051 #ifdef AZT_TEST3
2052 if (st!=azt_st_old) {
2053 azt_st_old=st;
2054 printk("---AFL_DATA st:%x\n",st);
2056 #endif
2057 if (!AztTries--) {
2058 printk("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", azt_next_bn);
2059 if (azt_transfer_is_active) {
2060 AztTries = 0;
2061 break;
2063 if (CURRENT_VALID)
2064 end_request(0);
2065 AztTries = 5;
2067 azt_state = AZT_S_START;
2068 AztTimeout = READ_TIMEOUT;
2069 loop_ctl = 1;
2070 break;
2072 case AFL_STATUSorDATA:
2073 #ifdef AZT_TEST3
2074 if (st!=azt_st_old) {
2075 azt_st_old=st;
2076 printk("---AFL_STATUSorDATA st:%x\n",st);
2078 #endif
2079 break;
2081 default:
2082 #ifdef AZT_TEST3
2083 if (st!=azt_st_old) {
2084 azt_st_old=st;
2085 printk("---default: st:%x\n",st);
2087 #endif
2088 AztTries = 5;
2089 if (!CURRENT_VALID && azt_buf_in == azt_buf_out) {
2090 azt_state = AZT_S_STOP;
2091 loop_ctl = 1;
2092 break;
2094 if (azt_read_count<=0)
2095 printk("aztcd: warning - try to read 0 frames\n");
2096 while (azt_read_count) /*??? fast read ahead loop*/
2097 { azt_buf_bn[azt_buf_in] = -1;
2098 DTEN_LOW; /*??? unsolved problem, very
2099 seldom we get timeouts
2100 here, don't now the real
2101 reason. With my drive this
2102 sometimes also happens with
2103 Aztech's original driver under
2104 DOS. Is it a hardware bug?
2105 I tried to recover from such
2106 situations here. Zimmermann*/
2107 if (aztTimeOutCount>=AZT_TIMEOUT)
2108 { printk("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", azt_read_count,CURRENT->nr_sectors,azt_buf_in);
2109 printk("azt_transfer_is_active:%x\n",azt_transfer_is_active);
2110 azt_read_count=0;
2111 azt_state = AZT_S_STOP;
2112 loop_ctl = 1;
2113 end_request(1); /*should we have here (1) or (0)? */
2115 else
2116 { if (azt_read_mode==AZT_MODE_2)
2117 { insb(DATA_PORT, azt_buf + CD_FRAMESIZE_RAW * azt_buf_in, CD_FRAMESIZE_RAW);
2119 else
2120 { insb(DATA_PORT, azt_buf + CD_FRAMESIZE * azt_buf_in, CD_FRAMESIZE);
2122 azt_read_count--;
2123 #ifdef AZT_TEST3
2124 printk("AZT_S_DATA; ---I've read data- read_count: %d\n",azt_read_count);
2125 printk("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", \
2126 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
2127 #endif
2128 azt_buf_bn[azt_buf_in] = azt_next_bn++;
2129 if (azt_buf_out == -1)
2130 azt_buf_out = azt_buf_in;
2131 azt_buf_in = azt_buf_in + 1 == AZT_BUF_SIZ ? 0 : azt_buf_in + 1;
2134 if (!azt_transfer_is_active) {
2135 while (CURRENT_VALID) {
2136 azt_transfer();
2137 if (CURRENT -> nr_sectors == 0)
2138 end_request(1);
2139 else
2140 break;
2144 if (CURRENT_VALID
2145 && (CURRENT -> sector / 4 < azt_next_bn ||
2146 CURRENT -> sector / 4 > azt_next_bn + AZT_BUF_SIZ)) {
2147 azt_state = AZT_S_STOP;
2148 loop_ctl = 1;
2149 break;
2151 AztTimeout = READ_TIMEOUT;
2152 if (azt_read_count==0) {
2153 azt_state = AZT_S_STOP;
2154 loop_ctl = 1;
2155 break;
2157 break;
2159 break;
2162 case AZT_S_STOP:
2163 #ifdef AZT_TEST3
2164 if (azt_state!=azt_state_old) {
2165 azt_state_old=azt_state;
2166 printk("AZT_S_STOP\n");
2168 #endif
2169 if (azt_read_count!=0) printk("aztcd: discard data=%x frames\n",azt_read_count);
2170 while (azt_read_count!=0) {
2171 int i;
2172 if ( !(inb(STATUS_PORT) & AFL_DATA) ) {
2173 if (azt_read_mode==AZT_MODE_2)
2174 for (i=0; i<CD_FRAMESIZE_RAW; i++) inb(DATA_PORT);
2175 else
2176 for (i=0; i<CD_FRAMESIZE; i++) inb(DATA_PORT);
2178 azt_read_count--;
2180 if (aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 5");
2181 azt_state = AZT_S_STOPPING;
2182 AztTimeout = 1000;
2183 break;
2185 case AZT_S_STOPPING:
2186 #ifdef AZT_TEST3
2187 if (azt_state!=azt_state_old) {
2188 azt_state_old=azt_state;
2189 printk("AZT_S_STOPPING\n");
2191 #endif
2193 if ((st = aztStatus()) == -1 && AztTimeout)
2194 break;
2196 if ((st != -1) && ((st & AST_DSK_CHG)||(st & AST_NOT_READY))) {
2197 aztDiskChanged = 1;
2198 aztTocUpToDate = 0;
2199 azt_invalidate_buffers();
2200 printk("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
2201 end_request(0);
2205 #ifdef AZT_TEST3
2206 printk("CURRENT_VALID %d azt_mode %d\n",
2207 CURRENT_VALID, azt_mode);
2208 #endif
2210 if (CURRENT_VALID) {
2211 if (st != -1) {
2212 if (azt_mode == 1) {
2213 azt_state = AZT_S_READ;
2214 loop_ctl = 1;
2215 skip = 1;
2216 break;
2217 } else {
2218 azt_state = AZT_S_MODE;
2219 loop_ctl = 1;
2220 skip = 1;
2221 break;
2223 } else {
2224 azt_state = AZT_S_START;
2225 AztTimeout = 1;
2227 } else {
2228 azt_state = AZT_S_IDLE;
2229 return;
2231 break;
2233 default:
2234 printk("aztcd: invalid state %d\n", azt_state);
2235 return;
2236 } /* case */
2237 } /* while */
2240 if (!AztTimeout--)
2241 { printk("aztcd: timeout in state %d\n", azt_state);
2242 azt_state = AZT_S_STOP;
2243 if (aztSendCmd(ACMD_STOP)) RETURN("azt_poll 6");
2244 STEN_LOW_WAIT;
2247 SET_TIMER(azt_poll, HZ/100);
2251 /*###########################################################################
2252 * Miscellaneous support functions
2253 ###########################################################################
2255 static void azt_hsg2msf(long hsg, struct msf *msf)
2256 { hsg += 150;
2257 msf -> min = hsg / 4500;
2258 hsg %= 4500;
2259 msf -> sec = hsg / 75;
2260 msf -> frame = hsg % 75;
2261 #ifdef AZT_DEBUG
2262 if (msf->min >=70) printk("aztcd: Error hsg2msf address Minutes\n");
2263 if (msf->sec >=60) printk("aztcd: Error hsg2msf address Seconds\n");
2264 if (msf->frame>=75) printk("aztcd: Error hsg2msf address Frames\n");
2265 #endif
2266 azt_bin2bcd(&msf -> min); /* convert to BCD */
2267 azt_bin2bcd(&msf -> sec);
2268 azt_bin2bcd(&msf -> frame);
2271 static long azt_msf2hsg(struct msf *mp)
2272 { return azt_bcd2bin(mp -> frame) + azt_bcd2bin(mp -> sec) * 75
2273 + azt_bcd2bin(mp -> min) * 4500 - CD_MSF_OFFSET;
2276 static void azt_bin2bcd(unsigned char *p)
2277 { int u, t;
2279 u = *p % 10;
2280 t = *p / 10;
2281 *p = u | (t << 4);
2284 static int azt_bcd2bin(unsigned char bcd)
2285 { return (bcd >> 4) * 10 + (bcd & 0xF);