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

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