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. cleanup_module

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

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