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