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. aztSendCmd
  9. sendAztCmd
  10. check_aztcd_media_change
  11. aztStatus
  12. getAztStatus
  13. aztPlay
  14. azt_msf2hsg
  15. aztcd_ioctl
  16. azt_transfer
  17. do_aztcd_request
  18. azt_poll
  19. azt_invalidate_buffers
  20. aztcd_open
  21. aztcd_release
  22. aztcd_init
  23. azt_hsg2msf
  24. azt_bin2bcd
  25. azt_bcd2bin
  26. aztGetValue
  27. aztGetQChannelInfo
  28. aztUpdateToc
  29. aztGetDiskInfo
  30. aztGetToc

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

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