root/drivers/block/aztcd.c

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

DEFINITIONS

This source file includes following definitions.
  1. op_ok
  2. pa_ok
  3. sten_low
  4. dten_low
  5. statusAzt
  6. aztStatTimer
  7. aztcd_setup
  8. aztCloseDoor
  9. aztLockDoor
  10. aztUnlockDoor
  11. aztSendCmd
  12. sendAztCmd
  13. aztSetDiskType
  14. check_aztcd_media_change
  15. aztStatus
  16. getAztStatus
  17. aztPlay
  18. azt_msf2hsg
  19. aztcd_ioctl
  20. azt_transfer
  21. do_aztcd_request
  22. azt_poll
  23. azt_invalidate_buffers
  24. aztcd_open
  25. aztcd_release
  26. aztcd_init
  27. azt_hsg2msf
  28. azt_bin2bcd
  29. azt_bcd2bin
  30. aztGetValue
  31. aztGetQChannelInfo
  32. aztUpdateToc
  33. aztGetDiskInfo
  34. aztGetToc
  35. cleanup_module

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

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