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

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