root/drivers/cdrom/aztcd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. op_ok
  2. pa_ok
  3. sten_low
  4. dten_low
  5. statusAzt
  6. aztStatTimer
  7. aztcd_setup
  8. aztCloseDoor
  9. aztLockDoor
  10. aztUnlockDoor
  11. aztSendCmd
  12. sendAztCmd
  13. aztSeek
  14. aztSetDiskType
  15. check_aztcd_media_change
  16. aztStatus
  17. getAztStatus
  18. aztPlay
  19. aztcd_ioctl
  20. azt_transfer
  21. do_aztcd_request
  22. azt_poll
  23. azt_invalidate_buffers
  24. aztcd_open
  25. aztcd_release
  26. aztcd_init
  27. azt_hsg2msf
  28. azt_msf2hsg
  29. azt_bin2bcd
  30. azt_bcd2bin
  31. aztGetValue
  32. aztGetQChannelInfo
  33. aztUpdateToc
  34. aztGetDiskInfo
  35. aztGetMultiDiskInfo
  36. aztGetToc
  37. init_module
  38. cleanup_module

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

/* [previous][next][first][last][top][bottom][index][help] */