PageRenderTime 142ms CodeModel.GetById 3ms app.highlight 123ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/cdrom/aztcd.c

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