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