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

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