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

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