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

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