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