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

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