Import 2.1.118
[davej-history.git] / drivers / cdrom / aztcd.c
blob0342a538150613e55fb95c85c9481a588b3c6712
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
163 #include <linux/version.h>
165 #define MAJOR_NR AZTECH_CDROM_MAJOR
167 #include <linux/blk.h>
168 #include "aztcd.h"
170 #include <linux/module.h>
171 #include <linux/errno.h>
172 #include <linux/sched.h>
173 #include <linux/mm.h>
174 #include <linux/timer.h>
175 #include <linux/fs.h>
176 #include <linux/kernel.h>
177 #include <linux/cdrom.h>
178 #include <linux/ioport.h>
179 #include <linux/string.h>
180 #include <linux/major.h>
182 #ifndef AZT_KERNEL_PRIOR_2_1
183 #include <linux/init.h>
184 #endif
186 #include <asm/system.h>
187 #include <asm/io.h>
189 #ifdef AZT_KERNEL_PRIOR_2_1
190 #include <asm/segment.h>
191 #else
192 #include <asm/uaccess.h>
193 static int aztcd_blocksizes[1] = {2048};
194 #endif
197 /*###########################################################################
198 Defines
199 ###########################################################################
201 #define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \
202 delay_timer.function = (void *) (func); \
203 add_timer(&delay_timer);
205 #define CLEAR_TIMER del_timer(&delay_timer);
207 #define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\
208 return value;}
209 #define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\
210 return;}
212 /* Macros to switch the IDE-interface to the slave device and back to the master*/
213 #define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \
214 outb_p(0x10,azt_port+6); \
215 outb_p(0x00,azt_port+7); \
216 outb_p(0x10,azt_port+6);
217 #define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6);
220 #if 0
221 #define AZT_TEST
222 #define AZT_TEST1 /* <int-..> */
223 #define AZT_TEST2 /* do_aztcd_request */
224 #define AZT_TEST3 /* AZT_S_state */
225 #define AZT_TEST4 /* QUICK_LOOP-counter */
226 #define AZT_TEST5 /* port(1) state */
227 #define AZT_DEBUG
228 #define AZT_DEBUG_MULTISESSION
229 #endif
231 #define CURRENT_VALID \
232 (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
233 && CURRENT -> sector != -1)
235 #define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA)
236 #define AZT_BUF_SIZ 16
238 #define READ_TIMEOUT 3000
240 #define azt_port aztcd /*needed for the modutils*/
242 #ifndef AZT_KERNEL_PRIOR_2_1
243 #define memcpy_fromfs copy_from_user
244 #define memcpy_tofs copy_to_user
245 #endif
247 /*##########################################################################
248 Type Definitions
249 ##########################################################################
251 enum azt_state_e
252 { AZT_S_IDLE, /* 0 */
253 AZT_S_START, /* 1 */
254 AZT_S_MODE, /* 2 */
255 AZT_S_READ, /* 3 */
256 AZT_S_DATA, /* 4 */
257 AZT_S_STOP, /* 5 */
258 AZT_S_STOPPING /* 6 */
260 enum azt_read_modes
261 { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware*/
262 AZT_MODE_1, /*read mode for normal CD-ROMs*/
263 AZT_MODE_2 /*read mode for XA CD-ROMs*/
266 /*##########################################################################
267 Global Variables
268 ##########################################################################
270 static int aztPresent = 0;
272 static volatile int azt_transfer_is_active=0;
274 static char azt_buf[CD_FRAMESIZE_RAW*AZT_BUF_SIZ];/*buffer for block size conversion*/
275 #if AZT_PRIVATE_IOCTLS
276 static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls*/
277 #endif
279 static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn;
280 static volatile int azt_buf_in, azt_buf_out = -1;
281 static volatile int azt_error=0;
282 static int azt_open_count=0;
283 static volatile enum azt_state_e azt_state = AZT_S_IDLE;
284 #ifdef AZT_TEST3
285 static volatile enum azt_state_e azt_state_old = AZT_S_STOP;
286 static volatile int azt_st_old = 0;
287 #endif
288 static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1;
290 static int azt_mode = -1;
291 static volatile int azt_read_count = 1;
293 static int azt_port = AZT_BASE_ADDR;
295 #ifndef AZT_KERNEL_PRIOR_2_1
296 MODULE_PARM(azt_port, "i");
297 #endif
299 static int azt_port_auto[16] = AZT_BASE_AUTO;
301 static char azt_cont = 0;
302 static char azt_init_end = 0;
303 static char azt_auto_eject = AZT_AUTO_EJECT;
305 static int AztTimeout, AztTries;
306 static struct wait_queue *azt_waitq = NULL;
307 static struct timer_list delay_timer = { NULL, NULL, 0, 0, NULL };
309 static struct azt_DiskInfo DiskInfo;
310 static struct azt_Toc Toc[MAX_TRACKS];
311 static struct azt_Play_msf azt_Play;
313 static int aztAudioStatus = CDROM_AUDIO_NO_STATUS;
314 static char aztDiskChanged = 1;
315 static char aztTocUpToDate = 0;
317 static unsigned char aztIndatum;
318 static unsigned long aztTimeOutCount;
319 static int aztCmd = 0;
321 /*###########################################################################
322 Function Prototypes
323 ###########################################################################
325 /* CDROM Drive Low Level I/O Functions */
326 void op_ok(void);
327 void pa_ok(void);
328 void sten_low(void);
329 void dten_low(void);
330 void statusAzt(void);
331 static void aztStatTimer(void);
333 /* CDROM Drive Command Functions */
334 static int aztSendCmd(int cmd);
335 static int sendAztCmd(int cmd, struct azt_Play_msf *params);
336 static int aztSeek(struct azt_Play_msf *params);
337 static int aztSetDiskType(int type);
338 static int aztStatus(void);
339 static int getAztStatus(void);
340 static int aztPlay(struct azt_Play_msf *arg);
341 static void aztCloseDoor(void);
342 static void aztLockDoor(void);
343 static void aztUnlockDoor(void);
344 static int aztGetValue(unsigned char *result);
345 static int aztGetQChannelInfo(struct azt_Toc *qp);
346 static int aztUpdateToc(void);
347 static int aztGetDiskInfo(void);
348 #if AZT_MULTISESSION
349 static int aztGetMultiDiskInfo(void);
350 #endif
351 static int aztGetToc(int multi);
353 /* Kernel Interface Functions */
354 void aztcd_setup(char *str, int *ints);
355 static int check_aztcd_media_change(kdev_t full_dev);
356 static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
357 static void azt_transfer(void);
358 static void do_aztcd_request(void);
359 static void azt_invalidate_buffers(void);
360 int aztcd_open(struct inode *ip, struct file *fp);
362 #ifdef AZT_KERNEL_PRIOR_2_1
363 static void aztcd_release(struct inode * inode, struct file * file);
364 #else
365 static int aztcd_release(struct inode * inode, struct file * file);
366 #endif
368 int aztcd_init(void);
369 #ifdef MODULE
370 int init_module(void);
371 void cleanup_module(void);
372 #endif MODULE
373 static struct file_operations azt_fops = {
374 NULL, /* lseek - default */
375 block_read, /* read - general block-dev read */
376 block_write, /* write - general block-dev write */
377 NULL, /* readdir - bad */
378 NULL, /* poll */
379 aztcd_ioctl, /* ioctl */
380 NULL, /* mmap */
381 aztcd_open, /* open */
382 NULL, /* flush */
383 aztcd_release, /* release */
384 NULL, /* fsync */
385 NULL, /* fasync*/
386 check_aztcd_media_change, /*media change*/
387 NULL /* revalidate*/
390 /* Aztcd State Machine: Controls Drive Operating State */
391 static void azt_poll(void);
393 /* Miscellaneous support functions */
394 static void azt_hsg2msf(long hsg, struct msf *msf);
395 static long azt_msf2hsg(struct msf *mp);
396 static void azt_bin2bcd(unsigned char *p);
397 static int azt_bcd2bin(unsigned char bcd);
399 /*##########################################################################
400 CDROM Drive Low Level I/O Functions
401 ##########################################################################
403 /* Macros for the drive hardware interface handshake, these macros use
404 busy waiting */
405 /* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/
406 # define OP_OK op_ok()
407 void op_ok(void)
408 { aztTimeOutCount=0;
409 do { aztIndatum=inb(DATA_PORT);
410 aztTimeOutCount++;
411 if (aztTimeOutCount>=AZT_TIMEOUT)
412 { printk("aztcd: Error Wait OP_OK\n");
413 break;
415 } while (aztIndatum!=AFL_OP_OK);
418 /* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/
419 # define PA_OK pa_ok()
420 void pa_ok(void)
421 { aztTimeOutCount=0;
422 do { aztIndatum=inb(DATA_PORT);
423 aztTimeOutCount++;
424 if (aztTimeOutCount>=AZT_TIMEOUT)
425 { printk("aztcd: Error Wait PA_OK\n");
426 break;
428 } while (aztIndatum!=AFL_PA_OK);
431 /* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/
432 # define STEN_LOW sten_low()
433 void sten_low(void)
434 { aztTimeOutCount=0;
435 do { aztIndatum=inb(STATUS_PORT);
436 aztTimeOutCount++;
437 if (aztTimeOutCount>=AZT_TIMEOUT)
438 { if (azt_init_end) printk("aztcd: Error Wait STEN_LOW commands:%x\n",aztCmd);
439 break;
441 } while (aztIndatum&AFL_STATUS);
444 /* Wait for DTEN=Low = handshake signal 'Data available'*/
445 # define DTEN_LOW dten_low()
446 void dten_low(void)
447 { aztTimeOutCount=0;
448 do { aztIndatum=inb(STATUS_PORT);
449 aztTimeOutCount++;
450 if (aztTimeOutCount>=AZT_TIMEOUT)
451 { printk("aztcd: Error Wait DTEN_OK\n");
452 break;
454 } while (aztIndatum&AFL_DATA);
458 * Macro for timer wait on STEN=Low, should only be used for 'slow' commands;
459 * may cause kernel panic when used in the wrong place
461 #define STEN_LOW_WAIT statusAzt()
462 void statusAzt(void)
463 { AztTimeout = AZT_STATUS_DELAY;
464 SET_TIMER(aztStatTimer, HZ/100);
465 sleep_on(&azt_waitq);
466 if (AztTimeout <= 0) printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",aztCmd);
467 return;
470 static void aztStatTimer(void)
471 { if (!(inb(STATUS_PORT) & AFL_STATUS))
472 { wake_up(&azt_waitq);
473 return;
475 AztTimeout--;
476 if (AztTimeout <= 0)
477 { wake_up(&azt_waitq);
478 printk("aztcd: Error aztStatTimer: Timeout\n");
479 return;
481 SET_TIMER(aztStatTimer, HZ/100);
484 /*##########################################################################
485 CDROM Drive Command Functions
486 ##########################################################################
489 * Send a single command, return -1 on error, else 0
491 static int aztSendCmd(int cmd)
492 { unsigned char data;
493 int retry;
495 #ifdef AZT_DEBUG
496 printk("aztcd: Executing command %x\n",cmd);
497 #endif
499 if ((azt_port==0x1f0)||(azt_port==0x170))
500 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/
502 aztCmd=cmd;
503 outb(POLLED,MODE_PORT);
504 do { if (inb(STATUS_PORT)&AFL_STATUS) break;
505 inb(DATA_PORT); /* if status left from last command, read and */
506 } while (1); /* discard it */
507 do { if (inb(STATUS_PORT)&AFL_DATA) break;
508 inb(DATA_PORT); /* if data left from last command, read and */
509 } while (1); /* discard it */
510 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
511 { outb((unsigned char) cmd,CMD_PORT);
512 STEN_LOW;
513 data=inb(DATA_PORT);
514 if (data==AFL_OP_OK)
515 { return 0;} /*OP_OK?*/
516 if (data==AFL_OP_ERR)
517 { STEN_LOW;
518 data=inb(DATA_PORT);
519 printk("### Error 1 aztcd: aztSendCmd %x Error Code %x\n",cmd,data);
522 if (retry>=AZT_RETRY_ATTEMPTS)
523 { printk("### Error 2 aztcd: aztSendCmd %x \n",cmd);
524 azt_error=0xA5;
526 RETURNM("aztSendCmd",-1);
530 * Send a play or read command to the drive, return -1 on error, else 0
532 static int sendAztCmd(int cmd, struct azt_Play_msf *params)
533 { unsigned char data;
534 int retry;
536 #ifdef AZT_DEBUG
537 printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", \
538 params->start.min, params->start.sec, params->start.frame, \
539 params->end.min, params->end.sec, params->end.frame);
540 #endif
541 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
542 { aztSendCmd(cmd);
543 outb(params -> start.min,CMD_PORT);
544 outb(params -> start.sec,CMD_PORT);
545 outb(params -> start.frame,CMD_PORT);
546 outb(params -> end.min,CMD_PORT);
547 outb(params -> end.sec,CMD_PORT);
548 outb(params -> end.frame,CMD_PORT);
549 STEN_LOW;
550 data=inb(DATA_PORT);
551 if (data==AFL_PA_OK)
552 { return 0;} /*PA_OK ?*/
553 if (data==AFL_PA_ERR)
554 { STEN_LOW;
555 data=inb(DATA_PORT);
556 printk("### Error 1 aztcd: sendAztCmd %x Error Code %x\n",cmd,data);
559 if (retry>=AZT_RETRY_ATTEMPTS)
560 { printk("### Error 2 aztcd: sendAztCmd %x\n ",cmd);
561 azt_error=0xA5;
563 RETURNM("sendAztCmd",-1);
567 * Send a seek command to the drive, return -1 on error, else 0
569 static int aztSeek(struct azt_Play_msf *params)
570 { unsigned char data;
571 int retry;
573 #ifdef AZT_DEBUG
574 printk("aztcd: aztSeek %02x:%02x:%02x\n", \
575 params->start.min, params->start.sec, params->start.frame);
576 #endif
577 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
578 { aztSendCmd(ACMD_SEEK);
579 outb(params -> start.min,CMD_PORT);
580 outb(params -> start.sec,CMD_PORT);
581 outb(params -> start.frame,CMD_PORT);
582 STEN_LOW;
583 data=inb(DATA_PORT);
584 if (data==AFL_PA_OK)
585 { return 0;} /*PA_OK ?*/
586 if (data==AFL_PA_ERR)
587 { STEN_LOW;
588 data=inb(DATA_PORT);
589 printk("### Error 1 aztcd: aztSeek\n");
592 if (retry>=AZT_RETRY_ATTEMPTS)
593 { printk("### Error 2 aztcd: aztSeek\n ");
594 azt_error=0xA5;
596 RETURNM("aztSeek",-1);
599 /* Send a Set Disk Type command
600 does not seem to work with Aztech drives, behavior is completely indepen-
601 dent on which mode is set ???
603 static int aztSetDiskType(int type)
604 { unsigned char data;
605 int retry;
607 #ifdef AZT_DEBUG
608 printk("aztcd: set disk type command: type= %i\n",type);
609 #endif
610 for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
611 { aztSendCmd(ACMD_SET_DISK_TYPE);
612 outb(type,CMD_PORT);
613 STEN_LOW;
614 data=inb(DATA_PORT);
615 if (data==AFL_PA_OK) /*PA_OK ?*/
616 { azt_read_mode=type;
617 return 0;
619 if (data==AFL_PA_ERR)
620 { STEN_LOW;
621 data=inb(DATA_PORT);
622 printk("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n",type,data);
625 if (retry>=AZT_RETRY_ATTEMPTS)
626 { printk("### Error 2 aztcd: aztSetDiskType %x\n ",type);
627 azt_error=0xA5;
629 RETURNM("aztSetDiskType",-1);
633 /* used in azt_poll to poll the status, expects another program to issue a
634 * ACMD_GET_STATUS directly before
636 static int aztStatus(void)
637 { int st;
638 /* int i;
640 i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ???
641 if (!i)
642 */ STEN_LOW;
643 if (aztTimeOutCount<AZT_TIMEOUT)
644 { st = inb(DATA_PORT) & 0xFF;
645 return st;
647 else
648 RETURNM("aztStatus",-1);
652 * Get the drive status
654 static int getAztStatus(void)
655 { int st;
657 if (aztSendCmd(ACMD_GET_STATUS)) RETURNM("getAztStatus 1",-1);
658 STEN_LOW;
659 st = inb(DATA_PORT) & 0xFF;
660 #ifdef AZT_DEBUG
661 printk("aztcd: Status = %x\n",st);
662 #endif
663 if ((st == 0xFF)||(st&AST_CMD_CHECK))
664 { printk("aztcd: AST_CMD_CHECK error or no status available\n");
665 return -1;
668 if (((st&AST_MODE_BITS)!=AST_BUSY) && (aztAudioStatus == CDROM_AUDIO_PLAY))
669 /* XXX might be an error? look at q-channel? */
670 aztAudioStatus = CDROM_AUDIO_COMPLETED;
672 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY))
673 { aztDiskChanged = 1;
674 aztTocUpToDate = 0;
675 aztAudioStatus = CDROM_AUDIO_NO_STATUS;
677 return st;
682 * Send a 'Play' command and get the status. Use only from the top half.
684 static int aztPlay(struct azt_Play_msf *arg)
685 { if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0) RETURNM("aztPlay",-1);
686 return 0;
690 * Subroutines to automatically close the door (tray) and
691 * lock it closed when the cd is mounted. Leave the tray
692 * locking as an option
694 static void aztCloseDoor(void)
696 aztSendCmd(ACMD_CLOSE);
697 STEN_LOW;
698 return;
701 static void aztLockDoor(void)
703 #if AZT_ALLOW_TRAY_LOCK
704 aztSendCmd(ACMD_LOCK);
705 STEN_LOW;
706 #endif
707 return;
710 static void aztUnlockDoor(void)
712 #if AZT_ALLOW_TRAY_LOCK
713 aztSendCmd(ACMD_UNLOCK);
714 STEN_LOW;
715 #endif
716 return;
720 * Read a value from the drive. Should return quickly, so a busy wait
721 * is used to avoid excessive rescheduling. The read command itself must
722 * be issued with aztSendCmd() directly before
724 static int aztGetValue(unsigned char *result)
725 { int s;
727 STEN_LOW;
728 if (aztTimeOutCount>=AZT_TIMEOUT)
729 { printk("aztcd: aztGetValue timeout\n");
730 return -1;
732 s = inb(DATA_PORT) & 0xFF;
733 *result = (unsigned char) s;
734 return 0;
738 * Read the current Q-channel info. Also used for reading the
739 * table of contents.
741 int aztGetQChannelInfo(struct azt_Toc *qp)
742 { unsigned char notUsed;
743 int st;
745 #ifdef AZT_DEBUG
746 printk("aztcd: starting aztGetQChannelInfo Time:%li\n",jiffies);
747 #endif
748 if ((st=getAztStatus())==-1) RETURNM("aztGetQChannelInfo 1",-1);
749 if (aztSendCmd(ACMD_GET_Q_CHANNEL)) RETURNM("aztGetQChannelInfo 2",-1);
750 /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here*/
751 if (aztGetValue(&notUsed)) RETURNM("aztGetQChannelInfo 3",-1); /*??? Nullbyte einlesen*/
752 if ((st&AST_MODE_BITS)==AST_INITIAL)
753 { qp->ctrl_addr=0; /* when audio stop ACMD_GET_Q_CHANNEL returns */
754 qp->track=0; /* only one byte with Aztech drives */
755 qp->pointIndex=0;
756 qp->trackTime.min=0;
757 qp->trackTime.sec=0;
758 qp->trackTime.frame=0;
759 qp->diskTime.min=0;
760 qp->diskTime.sec=0;
761 qp->diskTime.frame=0;
762 return 0;
764 else
765 { if (aztGetValue(&qp -> ctrl_addr) < 0) RETURNM("aztGetQChannelInfo 4",-1);
766 if (aztGetValue(&qp -> track) < 0) RETURNM("aztGetQChannelInfo 4",-1);
767 if (aztGetValue(&qp -> pointIndex) < 0) RETURNM("aztGetQChannelInfo 4",-1);
768 if (aztGetValue(&qp -> trackTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1);
769 if (aztGetValue(&qp -> trackTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1);
770 if (aztGetValue(&qp -> trackTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1);
771 if (aztGetValue(&notUsed) < 0) RETURNM("aztGetQChannelInfo 4",-1);
772 if (aztGetValue(&qp -> diskTime.min) < 0) RETURNM("aztGetQChannelInfo 4",-1);
773 if (aztGetValue(&qp -> diskTime.sec) < 0) RETURNM("aztGetQChannelInfo 4",-1);
774 if (aztGetValue(&qp -> diskTime.frame) < 0) RETURNM("aztGetQChannelInfo 4",-1);
776 #ifdef AZT_DEBUG
777 printk("aztcd: exiting aztGetQChannelInfo Time:%li\n",jiffies);
778 #endif
779 return 0;
783 * Read the table of contents (TOC) and TOC header if necessary
785 static int aztUpdateToc()
786 { int st;
788 #ifdef AZT_DEBUG
789 printk("aztcd: starting aztUpdateToc Time:%li\n",jiffies);
790 #endif
791 if (aztTocUpToDate)
792 return 0;
794 if (aztGetDiskInfo() < 0)
795 return -EIO;
797 if (aztGetToc(0) < 0)
798 return -EIO;
800 /*audio disk detection
801 with my Aztech drive there is no audio status bit, so I use the copy
802 protection bit of the first track. If this track is copy protected
803 (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */
804 if (!(Toc[DiskInfo.first].ctrl_addr & 0x40))
805 DiskInfo.audio=1;
806 else
807 DiskInfo.audio=0;
809 /* XA detection */
810 if (! DiskInfo.audio)
811 { azt_Play.start.min = 0; /*XA detection only seems to work*/
812 azt_Play.start.sec = 2; /*when we play a track*/
813 azt_Play.start.frame = 0;
814 azt_Play.end.min = 0;
815 azt_Play.end.sec = 0;
816 azt_Play.end.frame = 1;
817 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
818 DTEN_LOW;
819 for (st=0;st<CD_FRAMESIZE;st++) inb(DATA_PORT);
821 DiskInfo.xa = getAztStatus() & AST_MODE;
822 if (DiskInfo.xa)
823 { printk("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n");
826 /*multisession detection
827 support for multisession CDs is done automatically with Aztech drives,
828 we don't have to take care about TOC redirection; if we want the isofs
829 to take care about redirection, we have to set AZT_MULTISESSION to 1*/
830 DiskInfo.multi=0;
831 #if AZT_MULTISESSION
832 if (DiskInfo.xa)
833 { aztGetMultiDiskInfo(); /*here Disk.Info.multi is set*/
835 #endif
836 if (DiskInfo.multi)
837 { DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min;
838 DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec;
839 DiskInfo.lastSession.frame= Toc[DiskInfo.next].diskTime.frame;
840 printk("aztcd: Multisession support experimental\n");
842 else
843 { DiskInfo.lastSession.min = Toc[DiskInfo.first].diskTime.min;
844 DiskInfo.lastSession.sec = Toc[DiskInfo.first].diskTime.sec;
845 DiskInfo.lastSession.frame= Toc[DiskInfo.first].diskTime.frame;
848 aztTocUpToDate = 1;
849 #ifdef AZT_DEBUG
850 printk("aztcd: exiting aztUpdateToc Time:%li\n",jiffies);
851 #endif
852 return 0;
856 /* Read the table of contents header, i.e. no. of tracks and start of first
857 * track
859 static int aztGetDiskInfo()
860 { int limit;
861 unsigned char test;
862 struct azt_Toc qInfo;
864 #ifdef AZT_DEBUG
865 printk("aztcd: starting aztGetDiskInfo Time:%li\n",jiffies);
866 #endif
867 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetDiskInfo 1",-1);
868 STEN_LOW_WAIT;
869 test=0;
870 for (limit=300;limit>0;limit--)
871 { if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetDiskInfo 2",-1);
872 if (qInfo.pointIndex==0xA0) /*Number of FirstTrack*/
873 { DiskInfo.first = qInfo.diskTime.min;
874 DiskInfo.first = azt_bcd2bin(DiskInfo.first);
875 test=test|0x01;
877 if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/
878 { DiskInfo.last = qInfo.diskTime.min;
879 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
880 test=test|0x02;
882 if (qInfo.pointIndex==0xA2) /*DiskLength*/
883 { DiskInfo.diskLength.min=qInfo.diskTime.min;
884 DiskInfo.diskLength.sec=qInfo.diskTime.sec;
885 DiskInfo.diskLength.frame=qInfo.diskTime.frame;
886 test=test|0x04;
888 if ((qInfo.pointIndex==DiskInfo.first)&&(test&0x01)) /*StartTime of First Track*/
889 { DiskInfo.firstTrack.min=qInfo.diskTime.min;
890 DiskInfo.firstTrack.sec=qInfo.diskTime.sec;
891 DiskInfo.firstTrack.frame=qInfo.diskTime.frame;
892 test=test|0x08;
894 if (test==0x0F) break;
896 #ifdef AZT_DEBUG
897 printk ("aztcd: exiting aztGetDiskInfo Time:%li\n",jiffies);
898 printk("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n",
899 DiskInfo.first,
900 DiskInfo.last,
901 DiskInfo.diskLength.min,
902 DiskInfo.diskLength.sec,
903 DiskInfo.diskLength.frame,
904 DiskInfo.firstTrack.min,
905 DiskInfo.firstTrack.sec,
906 DiskInfo.firstTrack.frame);
907 #endif
908 if (test!=0x0F) return -1;
909 return 0;
912 #if AZT_MULTISESSION
914 * Get Multisession Disk Info
916 static int aztGetMultiDiskInfo(void)
917 { int limit, k=5;
918 unsigned char test;
919 struct azt_Toc qInfo;
921 #ifdef AZT_DEBUG
922 printk("aztcd: starting aztGetMultiDiskInfo\n");
923 #endif
925 do { azt_Play.start.min = Toc[DiskInfo.last+1].diskTime.min;
926 azt_Play.start.sec = Toc[DiskInfo.last+1].diskTime.sec;
927 azt_Play.start.frame = Toc[DiskInfo.last+1].diskTime.frame;
928 test=0;
930 for (limit=30;limit>0;limit--) /*Seek for LeadIn of next session*/
931 { if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 1",-1);
932 if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 2",-1);
933 if ((qInfo.track==0)&&(qInfo.pointIndex)) break; /*LeadIn found*/
934 if ((azt_Play.start.sec+=10) > 59)
935 { azt_Play.start.sec=0;
936 azt_Play.start.min++;
939 if (!limit) break; /*Check, if a leadin track was found, if not we're
940 at the end of the disk*/
941 #ifdef AZT_DEBUG_MULTISESSION
942 printk("leadin found track %d pointIndex %x limit %d\n",qInfo.track,qInfo.pointIndex,limit);
943 #endif
944 for (limit=300;limit>0;limit--)
945 { if (++azt_Play.start.frame>74)
946 { azt_Play.start.frame=0;
947 if (azt_Play.start.sec > 59)
948 { azt_Play.start.sec=0;
949 azt_Play.start.min++;
952 if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 3",-1);
953 if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 4",-1);
954 if (qInfo.pointIndex==0xA0) /*Number of NextTrack*/
955 { DiskInfo.next = qInfo.diskTime.min;
956 DiskInfo.next = azt_bcd2bin(DiskInfo.next);
957 test=test|0x01;
959 if (qInfo.pointIndex==0xA1) /*Number of LastTrack*/
960 { DiskInfo.last = qInfo.diskTime.min;
961 DiskInfo.last = azt_bcd2bin(DiskInfo.last);
962 test=test|0x02;
964 if (qInfo.pointIndex==0xA2) /*DiskLength*/
965 { DiskInfo.diskLength.min =qInfo.diskTime.min;
966 DiskInfo.diskLength.sec =qInfo.diskTime.sec;
967 DiskInfo.diskLength.frame=qInfo.diskTime.frame;
968 test=test|0x04;
970 if ((qInfo.pointIndex==DiskInfo.next)&&(test&0x01)) /*StartTime of Next Track*/
971 { DiskInfo.nextSession.min=qInfo.diskTime.min;
972 DiskInfo.nextSession.sec=qInfo.diskTime.sec;
973 DiskInfo.nextSession.frame=qInfo.diskTime.frame;
974 test=test|0x08;
976 if (test==0x0F) break;
978 #ifdef AZT_DEBUG_MULTISESSION
979 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",
980 DiskInfo.first,
981 DiskInfo.next,
982 DiskInfo.last,
983 DiskInfo.diskLength.min,
984 DiskInfo.diskLength.sec,
985 DiskInfo.diskLength.frame,
986 DiskInfo.firstTrack.min,
987 DiskInfo.firstTrack.sec,
988 DiskInfo.firstTrack.frame,
989 DiskInfo.nextSession.min,
990 DiskInfo.nextSession.sec,
991 DiskInfo.nextSession.frame);
992 #endif
993 if (test!=0x0F)
994 break;
995 else
996 DiskInfo.multi=1; /*found TOC of more than one session*/
997 aztGetToc(1);
998 } while(--k);
1000 #ifdef AZT_DEBUG
1001 printk ("aztcd: exiting aztGetMultiDiskInfo Time:%li\n",jiffies);
1002 #endif
1003 return 0;
1005 #endif
1008 * Read the table of contents (TOC)
1010 static int aztGetToc(int multi)
1011 { int i, px;
1012 int limit;
1013 struct azt_Toc qInfo;
1015 #ifdef AZT_DEBUG
1016 printk("aztcd: starting aztGetToc Time:%li\n",jiffies);
1017 #endif
1018 if (!multi)
1019 { for (i = 0; i < MAX_TRACKS; i++)
1020 Toc[i].pointIndex = 0;
1021 i = DiskInfo.last + 3;
1023 else
1024 { for (i = DiskInfo.next; i < MAX_TRACKS; i++)
1025 Toc[i].pointIndex = 0;
1026 i = DiskInfo.last + 4 - DiskInfo.next;
1029 /*Is there a good reason to stop motor before TOC read?
1030 if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
1031 STEN_LOW_WAIT;
1034 if (!multi)
1035 { azt_mode = 0x05;
1036 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1);
1037 STEN_LOW_WAIT;
1039 for (limit = 300; limit > 0; limit--)
1040 { if (multi)
1041 { if (++azt_Play.start.sec > 59)
1042 { azt_Play.start.sec=0;
1043 azt_Play.start.min++;
1045 if (aztSeek(&azt_Play)) RETURNM("aztGetToc 3",-1);
1047 if (aztGetQChannelInfo(&qInfo) < 0)
1048 break;
1050 px = azt_bcd2bin(qInfo.pointIndex);
1052 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1053 if (Toc[px].pointIndex == 0)
1054 { Toc[px] = qInfo;
1055 i--;
1058 if (i <= 0)
1059 break;
1062 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1063 Toc[DiskInfo.last].trackTime = DiskInfo.diskLength;
1065 #ifdef AZT_DEBUG_MULTISESSION
1066 printk("aztcd: exiting aztGetToc\n");
1067 for (i = 1; i <= DiskInfo.last+1; i++)
1068 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1069 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1070 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1071 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1072 for (i = 100; i < 103; i++)
1073 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n",
1074 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1075 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1076 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1077 #endif
1079 return limit > 0 ? 0 : -1;
1083 /*##########################################################################
1084 Kernel Interface Functions
1085 ##########################################################################
1087 #ifdef AZT_KERNEL_PRIOR_2_1
1088 void aztcd_setup(char *str, int *ints)
1089 #else
1090 __initfunc(void aztcd_setup(char *str, int *ints))
1091 #endif
1092 { if (ints[0] > 0)
1093 azt_port = ints[1];
1094 if (ints[0] > 1)
1095 azt_cont = ints[2];
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(void)
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
1546 if (aztPresent == 0)
1547 return -ENXIO; /* no hardware */
1549 if (!azt_open_count && azt_state == AZT_S_IDLE)
1550 { azt_invalidate_buffers();
1552 st = getAztStatus(); /* check drive status */
1553 if (st == -1) return -EIO; /* drive doesn't respond */
1555 if (st & AST_DOOR_OPEN)
1556 { /* close door, then get the status again. */
1557 printk("aztcd: Door Open?\n");
1558 aztCloseDoor();
1559 st = getAztStatus();
1562 if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) /*no disk in drive or changed*/
1563 { printk("aztcd: Disk Changed or No Disk in Drive?\n");
1564 aztTocUpToDate=0;
1566 if (aztUpdateToc()) return -EIO;
1569 ++azt_open_count;
1570 MOD_INC_USE_COUNT;
1571 aztLockDoor();
1574 #ifdef AZT_DEBUG
1575 printk("aztcd: exiting aztcd_open\n");
1576 #endif
1577 return 0;
1582 * On close, we flush all azt blocks from the buffer cache.
1584 #ifdef AZT_KERNEL_PRIOR_2_1
1585 static void aztcd_release(struct inode * inode, struct file * file)
1586 #else
1587 static int aztcd_release(struct inode * inode, struct file * file)
1588 #endif
1590 #ifdef AZT_DEBUG
1591 printk("aztcd: executing aztcd_release\n");
1592 printk("inode: %p, inode->i_rdev: %x file: %p\n",inode,inode->i_rdev,file);
1593 #endif
1594 MOD_DEC_USE_COUNT;
1595 if (!--azt_open_count) {
1596 azt_invalidate_buffers();
1597 sync_dev(inode->i_rdev); /*??? isn't it a read only dev?*/
1598 invalidate_buffers(inode -> i_rdev);
1599 aztUnlockDoor();
1600 if (azt_auto_eject)
1601 aztSendCmd(ACMD_EJECT);
1602 CLEAR_TIMER;
1604 #ifdef AZT_KERNEL_PRIOR_2_1
1605 return;
1606 #else
1607 return 0;
1608 #endif
1614 * Test for presence of drive and initialize it. Called at boot time.
1617 #ifdef AZT_KERNEL_PRIOR_2_1
1618 int aztcd_init(void)
1619 #else
1620 __initfunc(int aztcd_init(void))
1621 #endif
1622 { long int count, max_count;
1623 unsigned char result[50];
1624 int st;
1625 int i = 0;
1627 if (azt_port == 0)
1628 { printk("aztcd: no Aztech CD-ROM Initialization");
1629 return -EIO;
1632 printk("aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM CD-ROM Driver\n");
1633 printk("aztcd: (C) 1994-98 W.Zimmermann\n");
1634 if (azt_port == -1)
1635 { printk("aztcd: KernelVersion=%s DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n",UTS_RELEASE,AZT_VERSION);
1637 else
1638 printk("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port);
1639 printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
1642 #ifdef AZT_SW32 /*CDROM connected to Soundwave32 card*/
1643 if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500)
1644 { printk("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n",
1645 AZT_SW32_BASE_ADDR,AZT_SW32_INIT,AZT_SW32_CONFIG_REG,AZT_SW32_ID_REG);
1646 return -EIO;
1648 else
1649 { printk(KERN_INFO "aztcd: Soundwave32 card detected at %x Version %x\n",
1650 AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG));
1651 outw(AZT_SW32_INIT,AZT_SW32_CONFIG_REG);
1652 for (count=0;count<10000;count++); /*delay a bit*/
1654 #endif
1656 /* check for presence of drive */
1658 if (azt_port == -1) /* autoprobing */
1659 { for (i=0;(azt_port_auto[i]!=0)&&(i<16);i++)
1660 { azt_port = azt_port_auto[i];
1661 printk("aztcd: Autoprobing BaseAddress=0x%x \n",azt_port);
1662 st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
1663 if (st) continue;
1665 outb(POLLED,MODE_PORT);
1666 inb(CMD_PORT);
1667 inb(CMD_PORT);
1668 outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
1670 aztTimeOutCount=0;
1671 do { aztIndatum=inb(STATUS_PORT);
1672 aztTimeOutCount++;
1673 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1674 } while (aztIndatum&AFL_STATUS);
1675 if (inb(DATA_PORT)==AFL_OP_OK)
1676 break;
1678 if ((azt_port_auto[i]==0)||(i==16))
1679 { printk("aztcd: no AZTECH CD-ROM drive found\n");
1680 return -EIO;
1683 else /* no autoprobing */
1684 { if ((azt_port==0x1f0)||(azt_port==0x170))
1685 st = check_region(azt_port, 8); /*IDE-interfaces need 8 bytes*/
1686 else
1687 st = check_region(azt_port, 4); /*proprietary interfaces need 4 bytes*/
1688 if (st)
1689 { printk("aztcd: conflict, I/O port (%X) already used\n",azt_port);
1690 return -EIO;
1693 if ((azt_port==0x1f0)||(azt_port==0x170))
1694 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration*/
1696 outb(POLLED,MODE_PORT);
1697 inb(CMD_PORT);
1698 inb(CMD_PORT);
1699 outb(ACMD_GET_VERSION,CMD_PORT); /*Try to get version info*/
1701 aztTimeOutCount=0;
1702 do { aztIndatum=inb(STATUS_PORT);
1703 aztTimeOutCount++;
1704 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1705 } while (aztIndatum&AFL_STATUS);
1707 if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK? If not, reset and try again*/
1709 #ifndef MODULE
1710 if (azt_cont!=0x79)
1711 { printk("aztcd: no AZTECH CD-ROM drive found-Try boot parameter aztcd=<BaseAddress>,0x79\n");
1712 return -EIO;
1714 #else
1715 if (0)
1718 #endif
1719 else
1720 { printk("aztcd: drive reset - please wait\n");
1721 for (count=0;count<50;count++)
1722 { inb(STATUS_PORT); /*removing all data from earlier tries*/
1723 inb(DATA_PORT);
1725 outb(POLLED,MODE_PORT);
1726 inb(CMD_PORT);
1727 inb(CMD_PORT);
1728 getAztStatus(); /*trap errors*/
1729 outb(ACMD_SOFT_RESET,CMD_PORT); /*send reset*/
1730 STEN_LOW;
1731 if (inb(DATA_PORT)!=AFL_OP_OK) /*OP_OK?*/
1732 { printk("aztcd: no AZTECH CD-ROM drive found\n");
1733 return -EIO;
1735 for (count = 0; count < AZT_TIMEOUT; count++);
1736 { count=count*2; /* delay a bit */
1737 count=count/2;
1739 if ((st=getAztStatus())==-1)
1740 { printk("aztcd: Drive Status Error Status=%x\n",st);
1741 return -EIO;
1743 #ifdef AZT_DEBUG
1744 printk("aztcd: Status = %x\n",st);
1745 #endif
1746 outb(POLLED,MODE_PORT);
1747 inb(CMD_PORT);
1748 inb(CMD_PORT);
1749 outb(ACMD_GET_VERSION,CMD_PORT); /*GetVersion*/
1750 STEN_LOW;
1751 OP_OK;
1756 azt_init_end=1;
1757 STEN_LOW;
1758 result[0]=inb(DATA_PORT); /*reading in a null byte???*/
1759 for (count=1;count<50;count++) /*Reading version string*/
1760 { aztTimeOutCount=0; /*here we must implement STEN_LOW differently*/
1761 do { aztIndatum=inb(STATUS_PORT);/*because we want to exit by timeout*/
1762 aztTimeOutCount++;
1763 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break;
1764 } while (aztIndatum&AFL_STATUS);
1765 if (aztTimeOutCount>=AZT_FAST_TIMEOUT) break; /*all chars read?*/
1766 result[count]=inb(DATA_PORT);
1768 if (count>30) max_count=30; /*print max.30 chars of the version string*/
1769 else max_count=count;
1770 printk(KERN_INFO "aztcd: FirmwareVersion=");
1771 for (count=1;count<max_count;count++) printk("%c",result[count]);
1772 printk("<<>> ");
1774 if ((result[1]=='A')&&(result[2]=='Z')&&(result[3]=='T'))
1775 { printk("AZTECH drive detected\n"); /*AZTECH*/
1777 else if ((result[2]=='C')&&(result[3]=='D')&&(result[4]=='D'))
1778 { printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES*/
1780 else if ((result[1]==0x03)&&(result[2]=='5'))
1781 { printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM*/
1783 else /*OTHERS or none*/
1784 { printk("\nunknown drive or firmware version detected\n");
1785 printk("aztcd may not run stable, if you want to try anyhow,\n");
1786 printk("boot with: aztcd=<BaseAddress>,0x79\n");
1787 if ((azt_cont!=0x79))
1788 { printk("aztcd: FirmwareVersion=");
1789 for (count=1;count<5;count++) printk("%c",result[count]);
1790 printk("<<>> ");
1791 printk("Aborted\n");
1792 return -EIO;
1795 if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0)
1797 printk("aztcd: Unable to get major %d for Aztech CD-ROM\n",
1798 MAJOR_NR);
1799 return -EIO;
1801 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1802 #ifndef AZT_KERNEL_PRIOR_2_1
1803 blksize_size[MAJOR_NR] = aztcd_blocksizes;
1804 #endif
1805 read_ahead[MAJOR_NR] = 4;
1807 if ((azt_port==0x1f0)||(azt_port==0x170))
1808 request_region(azt_port, 8, "aztcd"); /*IDE-interface*/
1809 else
1810 request_region(azt_port, 4, "aztcd"); /*proprietary interface*/
1812 azt_invalidate_buffers();
1813 aztPresent = 1;
1814 aztCloseDoor();
1815 return (0);
1818 #ifdef MODULE
1820 int init_module(void)
1822 return aztcd_init();
1825 void cleanup_module(void)
1827 if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL))
1828 { printk("What's that: can't unregister aztcd\n");
1829 return;
1831 if ((azt_port==0x1f0)||(azt_port==0x170))
1832 { SWITCH_IDE_MASTER;
1833 release_region(azt_port,8); /*IDE-interface*/
1835 else
1836 release_region(azt_port,4); /*proprietary interface*/
1837 printk(KERN_INFO "aztcd module released.\n");
1839 #endif MODULE
1842 /*##########################################################################
1843 Aztcd State Machine: Controls Drive Operating State
1844 ##########################################################################
1846 static void azt_poll(void)
1848 int st = 0;
1849 int loop_ctl = 1;
1850 int skip = 0;
1852 if (azt_error) {
1853 if (aztSendCmd(ACMD_GET_ERROR)) RETURN("azt_poll 1");
1854 STEN_LOW;
1855 azt_error=inb(DATA_PORT)&0xFF;
1856 printk("aztcd: I/O error 0x%02x\n", azt_error);
1857 azt_invalidate_buffers();
1858 #ifdef WARN_IF_READ_FAILURE
1859 if (AztTries == 5)
1860 printk("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", azt_next_bn);
1861 #endif
1862 if (!AztTries--) {
1863 printk("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", azt_next_bn);
1864 if (azt_transfer_is_active) {
1865 AztTries = 0;
1866 loop_ctl = 0;
1868 if (CURRENT_VALID)
1869 end_request(0);
1870 AztTries = 5;
1872 azt_error = 0;
1873 azt_state = AZT_S_STOP;
1876 while (loop_ctl)
1878 loop_ctl = 0; /* each case must flip this back to 1 if we want
1879 to come back up here */
1880 switch (azt_state) {
1882 case AZT_S_IDLE:
1883 #ifdef AZT_TEST3
1884 if (azt_state!=azt_state_old) {
1885 azt_state_old=azt_state;
1886 printk("AZT_S_IDLE\n");
1888 #endif
1889 return;
1891 case AZT_S_START:
1892 #ifdef AZT_TEST3
1893 if (azt_state!=azt_state_old) {
1894 azt_state_old=azt_state;
1895 printk("AZT_S_START\n");
1897 #endif
1898 if(aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 2"); /*result will be checked by aztStatus() */
1899 azt_state = azt_mode == 1 ? AZT_S_READ : AZT_S_MODE;
1900 AztTimeout = 3000;
1901 break;
1903 case AZT_S_MODE:
1904 #ifdef AZT_TEST3
1905 if (azt_state!=azt_state_old) {
1906 azt_state_old=azt_state;
1907 printk("AZT_S_MODE\n");
1909 #endif
1910 if (!skip) {
1911 if ((st = aztStatus()) != -1) {
1912 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) {
1913 aztDiskChanged = 1;
1914 aztTocUpToDate = 0;
1915 azt_invalidate_buffers();
1916 end_request(0);
1917 printk("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n");
1919 } else break;
1921 skip = 0;
1923 if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) {
1924 aztDiskChanged = 1;
1925 aztTocUpToDate = 0;
1926 printk("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n");
1927 end_request(0);
1928 printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n");
1929 if (azt_transfer_is_active) {
1930 azt_state = AZT_S_START;
1931 loop_ctl = 1; /* goto immediately */
1932 break;
1934 azt_state = AZT_S_IDLE;
1935 while (CURRENT_VALID)
1936 end_request(0);
1937 return;
1940 /* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3");
1941 outb(0x01, DATA_PORT);
1942 PA_OK;
1943 STEN_LOW;
1944 */ if (aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 4");
1945 STEN_LOW;
1946 azt_mode = 1;
1947 azt_state = AZT_S_READ;
1948 AztTimeout = 3000;
1950 break;
1953 case AZT_S_READ:
1954 #ifdef AZT_TEST3
1955 if (azt_state!=azt_state_old) {
1956 azt_state_old=azt_state;
1957 printk("AZT_S_READ\n");
1959 #endif
1960 if (!skip) {
1961 if ((st = aztStatus()) != -1) {
1962 if ((st & AST_DSK_CHG)||(st & AST_NOT_READY)) {
1963 aztDiskChanged = 1;
1964 aztTocUpToDate = 0;
1965 azt_invalidate_buffers();
1966 printk("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n");
1967 end_request(0);
1969 } else break;
1972 skip = 0;
1973 if ((st & AST_DOOR_OPEN)||(st & AST_NOT_READY)) {
1974 aztDiskChanged = 1;
1975 aztTocUpToDate = 0;
1976 printk((st & AST_DOOR_OPEN) ? "aztcd: door open\n" : "aztcd: disk removed\n");
1977 if (azt_transfer_is_active) {
1978 azt_state = AZT_S_START;
1979 loop_ctl = 1;
1980 break;
1982 azt_state = AZT_S_IDLE;
1983 while (CURRENT_VALID)
1984 end_request(0);
1985 return;
1988 if (CURRENT_VALID) {
1989 struct azt_Play_msf msf;
1990 int i;
1991 azt_next_bn = CURRENT -> sector / 4;
1992 azt_hsg2msf(azt_next_bn, &msf.start);
1993 i = 0;
1994 /* find out in which track we are */
1995 while (azt_msf2hsg(&msf.start)>azt_msf2hsg(&Toc[++i].trackTime)) {};
1996 if (azt_msf2hsg(&msf.start)<azt_msf2hsg(&Toc[i].trackTime)-AZT_BUF_SIZ)
1997 { azt_read_count=AZT_BUF_SIZ; /*fast, because we read ahead*/
1998 /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead*/
2000 else /* don't read beyond end of track */
2001 #if AZT_MULTISESSION
2002 { azt_read_count=(azt_msf2hsg(&Toc[i].trackTime)/4)*4-azt_msf2hsg(&msf.start);
2003 if (azt_read_count < 0) azt_read_count=0;
2004 if (azt_read_count > AZT_BUF_SIZ) azt_read_count=AZT_BUF_SIZ;
2005 printk("aztcd: warning - trying to read beyond end of track\n");
2006 /* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime));
2007 */ }
2008 #else
2009 { azt_read_count=AZT_BUF_SIZ;
2011 #endif
2012 msf.end.min = 0;
2013 msf.end.sec = 0;
2014 msf.end.frame = azt_read_count ;/*Mitsumi here reads 0xffffff sectors*/
2015 #ifdef AZT_TEST3
2016 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);
2017 printk("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", \
2018 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
2019 #endif
2020 if (azt_read_mode==AZT_MODE_2)
2021 { sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode*/
2023 else
2024 { sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode*/
2026 azt_state = AZT_S_DATA;
2027 AztTimeout = READ_TIMEOUT;
2028 } else {
2029 azt_state = AZT_S_STOP;
2030 loop_ctl = 1;
2031 break;
2034 break;
2037 case AZT_S_DATA:
2038 #ifdef AZT_TEST3
2039 if (azt_state!=azt_state_old) {
2040 azt_state_old=azt_state;
2041 printk("AZT_S_DATA\n");
2043 #endif
2045 st = inb(STATUS_PORT) & AFL_STATUSorDATA;
2047 switch (st) {
2049 case AFL_DATA:
2050 #ifdef AZT_TEST3
2051 if (st!=azt_st_old) {
2052 azt_st_old=st;
2053 printk("---AFL_DATA st:%x\n",st);
2055 #endif
2056 if (!AztTries--) {
2057 printk("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", azt_next_bn);
2058 if (azt_transfer_is_active) {
2059 AztTries = 0;
2060 break;
2062 if (CURRENT_VALID)
2063 end_request(0);
2064 AztTries = 5;
2066 azt_state = AZT_S_START;
2067 AztTimeout = READ_TIMEOUT;
2068 loop_ctl = 1;
2069 break;
2071 case AFL_STATUSorDATA:
2072 #ifdef AZT_TEST3
2073 if (st!=azt_st_old) {
2074 azt_st_old=st;
2075 printk("---AFL_STATUSorDATA st:%x\n",st);
2077 #endif
2078 break;
2080 default:
2081 #ifdef AZT_TEST3
2082 if (st!=azt_st_old) {
2083 azt_st_old=st;
2084 printk("---default: st:%x\n",st);
2086 #endif
2087 AztTries = 5;
2088 if (!CURRENT_VALID && azt_buf_in == azt_buf_out) {
2089 azt_state = AZT_S_STOP;
2090 loop_ctl = 1;
2091 break;
2093 if (azt_read_count<=0)
2094 printk("aztcd: warning - try to read 0 frames\n");
2095 while (azt_read_count) /*??? fast read ahead loop*/
2096 { azt_buf_bn[azt_buf_in] = -1;
2097 DTEN_LOW; /*??? unsolved problem, very
2098 seldom we get timeouts
2099 here, don't now the real
2100 reason. With my drive this
2101 sometimes also happens with
2102 Aztech's original driver under
2103 DOS. Is it a hardware bug?
2104 I tried to recover from such
2105 situations here. Zimmermann*/
2106 if (aztTimeOutCount>=AZT_TIMEOUT)
2107 { printk("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", azt_read_count,CURRENT->nr_sectors,azt_buf_in);
2108 printk("azt_transfer_is_active:%x\n",azt_transfer_is_active);
2109 azt_read_count=0;
2110 azt_state = AZT_S_STOP;
2111 loop_ctl = 1;
2112 end_request(1); /*should we have here (1) or (0)? */
2114 else
2115 { if (azt_read_mode==AZT_MODE_2)
2116 { insb(DATA_PORT, azt_buf + CD_FRAMESIZE_RAW * azt_buf_in, CD_FRAMESIZE_RAW);
2118 else
2119 { insb(DATA_PORT, azt_buf + CD_FRAMESIZE * azt_buf_in, CD_FRAMESIZE);
2121 azt_read_count--;
2122 #ifdef AZT_TEST3
2123 printk("AZT_S_DATA; ---I've read data- read_count: %d\n",azt_read_count);
2124 printk("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", \
2125 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]);
2126 #endif
2127 azt_buf_bn[azt_buf_in] = azt_next_bn++;
2128 if (azt_buf_out == -1)
2129 azt_buf_out = azt_buf_in;
2130 azt_buf_in = azt_buf_in + 1 == AZT_BUF_SIZ ? 0 : azt_buf_in + 1;
2133 if (!azt_transfer_is_active) {
2134 while (CURRENT_VALID) {
2135 azt_transfer();
2136 if (CURRENT -> nr_sectors == 0)
2137 end_request(1);
2138 else
2139 break;
2143 if (CURRENT_VALID
2144 && (CURRENT -> sector / 4 < azt_next_bn ||
2145 CURRENT -> sector / 4 > azt_next_bn + AZT_BUF_SIZ)) {
2146 azt_state = AZT_S_STOP;
2147 loop_ctl = 1;
2148 break;
2150 AztTimeout = READ_TIMEOUT;
2151 if (azt_read_count==0) {
2152 azt_state = AZT_S_STOP;
2153 loop_ctl = 1;
2154 break;
2156 break;
2158 break;
2161 case AZT_S_STOP:
2162 #ifdef AZT_TEST3
2163 if (azt_state!=azt_state_old) {
2164 azt_state_old=azt_state;
2165 printk("AZT_S_STOP\n");
2167 #endif
2168 if (azt_read_count!=0) printk("aztcd: discard data=%x frames\n",azt_read_count);
2169 while (azt_read_count!=0) {
2170 int i;
2171 if ( !(inb(STATUS_PORT) & AFL_DATA) ) {
2172 if (azt_read_mode==AZT_MODE_2)
2173 for (i=0; i<CD_FRAMESIZE_RAW; i++) inb(DATA_PORT);
2174 else
2175 for (i=0; i<CD_FRAMESIZE; i++) inb(DATA_PORT);
2177 azt_read_count--;
2179 if (aztSendCmd(ACMD_GET_STATUS)) RETURN("azt_poll 5");
2180 azt_state = AZT_S_STOPPING;
2181 AztTimeout = 1000;
2182 break;
2184 case AZT_S_STOPPING:
2185 #ifdef AZT_TEST3
2186 if (azt_state!=azt_state_old) {
2187 azt_state_old=azt_state;
2188 printk("AZT_S_STOPPING\n");
2190 #endif
2192 if ((st = aztStatus()) == -1 && AztTimeout)
2193 break;
2195 if ((st != -1) && ((st & AST_DSK_CHG)||(st & AST_NOT_READY))) {
2196 aztDiskChanged = 1;
2197 aztTocUpToDate = 0;
2198 azt_invalidate_buffers();
2199 printk("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n");
2200 end_request(0);
2204 #ifdef AZT_TEST3
2205 printk("CURRENT_VALID %d azt_mode %d\n",
2206 CURRENT_VALID, azt_mode);
2207 #endif
2209 if (CURRENT_VALID) {
2210 if (st != -1) {
2211 if (azt_mode == 1) {
2212 azt_state = AZT_S_READ;
2213 loop_ctl = 1;
2214 skip = 1;
2215 break;
2216 } else {
2217 azt_state = AZT_S_MODE;
2218 loop_ctl = 1;
2219 skip = 1;
2220 break;
2222 } else {
2223 azt_state = AZT_S_START;
2224 AztTimeout = 1;
2226 } else {
2227 azt_state = AZT_S_IDLE;
2228 return;
2230 break;
2232 default:
2233 printk("aztcd: invalid state %d\n", azt_state);
2234 return;
2235 } /* case */
2236 } /* while */
2239 if (!AztTimeout--)
2240 { printk("aztcd: timeout in state %d\n", azt_state);
2241 azt_state = AZT_S_STOP;
2242 if (aztSendCmd(ACMD_STOP)) RETURN("azt_poll 6");
2243 STEN_LOW_WAIT;
2246 SET_TIMER(azt_poll, HZ/100);
2250 /*###########################################################################
2251 * Miscellaneous support functions
2252 ###########################################################################
2254 static void azt_hsg2msf(long hsg, struct msf *msf)
2255 { hsg += 150;
2256 msf -> min = hsg / 4500;
2257 hsg %= 4500;
2258 msf -> sec = hsg / 75;
2259 msf -> frame = hsg % 75;
2260 #ifdef AZT_DEBUG
2261 if (msf->min >=70) printk("aztcd: Error hsg2msf address Minutes\n");
2262 if (msf->sec >=60) printk("aztcd: Error hsg2msf address Seconds\n");
2263 if (msf->frame>=75) printk("aztcd: Error hsg2msf address Frames\n");
2264 #endif
2265 azt_bin2bcd(&msf -> min); /* convert to BCD */
2266 azt_bin2bcd(&msf -> sec);
2267 azt_bin2bcd(&msf -> frame);
2270 static long azt_msf2hsg(struct msf *mp)
2271 { return azt_bcd2bin(mp -> frame) + azt_bcd2bin(mp -> sec) * 75
2272 + azt_bcd2bin(mp -> min) * 4500 - CD_MSF_OFFSET;
2275 static void azt_bin2bcd(unsigned char *p)
2276 { int u, t;
2278 u = *p % 10;
2279 t = *p / 10;
2280 *p = u | (t << 4);
2283 static int azt_bcd2bin(unsigned char bcd)
2284 { return (bcd >> 4) * 10 + (bcd & 0xF);