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. check_aztcd_media_change
  14. aztStatus
  15. getAztStatus
  16. aztPlay
  17. azt_msf2hsg
  18. aztcd_ioctl
  19. azt_transfer
  20. do_aztcd_request
  21. azt_poll
  22. azt_invalidate_buffers
  23. aztcd_open
  24. aztcd_release
  25. aztcd_init
  26. azt_hsg2msf
  27. azt_bin2bcd
  28. azt_bcd2bin
  29. aztGetValue
  30. aztGetQChannelInfo
  31. aztUpdateToc
  32. aztGetDiskInfo
  33. aztGetToc
  34. cleanup_module

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

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