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

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