Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.12-rc2 2494 lines 70 kB view raw
1#define AZT_VERSION "2.60" 2 3/* $Id: aztcd.c,v 2.60 1997/11/29 09:51:19 root Exp root $ 4 linux/drivers/block/aztcd.c - Aztech CD268 CDROM driver 5 6 Copyright (C) 1994-98 Werner Zimmermann(Werner.Zimmermann@fht-esslingen.de) 7 8 based on Mitsumi CDROM driver by Martin Hariss and preworks by 9 Eberhard Moenkeberg; contains contributions by Joe Nardone and Robby 10 Schirmer. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2, or (at your option) 15 any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 26 HISTORY 27 V0.0 Adaption to Aztech CD268-01A Version 1.3 28 Version is PRE_ALPHA, unresolved points: 29 1. I use busy wait instead of timer wait in STEN_LOW,DTEN_LOW 30 thus driver causes CPU overhead and is very slow 31 2. could not find a way to stop the drive, when it is 32 in data read mode, therefore I had to set 33 msf.end.min/sec/frame to 0:0:1 (in azt_poll); so only one 34 frame can be read in sequence, this is also the reason for 35 3. getting 'timeout in state 4' messages, but nevertheless 36 it works 37 W.Zimmermann, Oct. 31, 1994 38 V0.1 Version is ALPHA, problems #2 and #3 resolved. 39 W.Zimmermann, Nov. 3, 1994 40 V0.2 Modification to some comments, debugging aids for partial test 41 with Borland C under DOS eliminated. Timer interrupt wait 42 STEN_LOW_WAIT additionally to busy wait for STEN_LOW implemented; 43 use it only for the 'slow' commands (ACMD_GET_Q_CHANNEL, ACMD_ 44 SEEK_TO_LEAD_IN), all other commands are so 'fast', that busy 45 waiting seems better to me than interrupt rescheduling. 46 Besides that, when used in the wrong place, STEN_LOW_WAIT causes 47 kernel panic. 48 In function aztPlay command ACMD_PLAY_AUDIO added, should make 49 audio functions work. The Aztech drive needs different commands 50 to read data tracks and play audio tracks. 51 W.Zimmermann, Nov. 8, 1994 52 V0.3 Recognition of missing drive during boot up improved (speeded up). 53 W.Zimmermann, Nov. 13, 1994 54 V0.35 Rewrote the control mechanism in azt_poll (formerly mcd_poll) 55 including removal of all 'goto' commands. :-); 56 J. Nardone, Nov. 14, 1994 57 V0.4 Renamed variables and constants to 'azt' instead of 'mcd'; had 58 to make some "compatibility" defines in azt.h; please note, 59 that the source file was renamed to azt.c, the include file to 60 azt.h 61 Speeded up drive recognition during init (will be a little bit 62 slower than before if no drive is installed!); suggested by 63 Robby Schirmer. 64 read_count declared volatile and set to AZT_BUF_SIZ to make 65 drive faster (now 300kB/sec, was 60kB/sec before, measured 66 by 'time dd if=/dev/cdrom of=/dev/null bs=2048 count=4096'; 67 different AZT_BUF_SIZes were test, above 16 no further im- 68 provement seems to be possible; suggested by E.Moenkeberg. 69 W.Zimmermann, Nov. 18, 1994 70 V0.42 Included getAztStatus command in GetQChannelInfo() to allow 71 reading Q-channel info on audio disks, if drive is stopped, 72 and some other bug fixes in the audio stuff, suggested by 73 Robby Schirmer. 74 Added more ioctls (reading data in mode 1 and mode 2). 75 Completely removed the old azt_poll() routine. 76 Detection of ORCHID CDS-3110 in aztcd_init implemented. 77 Additional debugging aids (see the readme file). 78 W.Zimmermann, Dec. 9, 1994 79 V0.50 Autodetection of drives implemented. 80 W.Zimmermann, Dec. 12, 1994 81 V0.52 Prepared for including in the standard kernel, renamed most 82 variables to contain 'azt', included autoconf.h 83 W.Zimmermann, Dec. 16, 1994 84 V0.6 Version for being included in the standard Linux kernel. 85 Renamed source and header file to aztcd.c and aztcd.h 86 W.Zimmermann, Dec. 24, 1994 87 V0.7 Changed VERIFY_READ to VERIFY_WRITE in aztcd_ioctl, case 88 CDROMREADMODE1 and CDROMREADMODE2; bug fix in the ioctl, 89 which causes kernel crashes when playing audio, changed 90 include-files (config.h instead of autoconf.h, removed 91 delay.h) 92 W.Zimmermann, Jan. 8, 1995 93 V0.72 Some more modifications for adaption to the standard kernel. 94 W.Zimmermann, Jan. 16, 1995 95 V0.80 aztcd is now part of the standard kernel since version 1.1.83. 96 Modified the SET_TIMER and CLEAR_TIMER macros to comply with 97 the new timer scheme. 98 W.Zimmermann, Jan. 21, 1995 99 V0.90 Included CDROMVOLCTRL, but with my Aztech drive I can only turn 100 the channels on and off. If it works better with your drive, 101 please mail me. Also implemented ACMD_CLOSE for CDROMSTART. 102 W.Zimmermann, Jan. 24, 1995 103 V1.00 Implemented close and lock tray commands. Patches supplied by 104 Frank Racis 105 Added support for loadable MODULEs, so aztcd can now also be 106 loaded by insmod and removed by rmmod during run time 107 Werner Zimmermann, Mar. 24, 95 108 V1.10 Implemented soundcard configuration for Orchid CDS-3110 drives 109 connected to Soundwave32 cards. Release for LST 2.1. 110 (still experimental) 111 Werner Zimmermann, May 8, 95 112 V1.20 Implemented limited support for DOSEMU0.60's cdrom.c. Now it works, but 113 sometimes DOSEMU may hang for 30 seconds or so. A fully functional ver- 114 sion needs an update of Dosemu0.60's cdrom.c, which will come with the 115 next revision of Dosemu. 116 Also Soundwave32 support now works. 117 Werner Zimmermann, May 22, 95 118 V1.30 Auto-eject feature. Inspired by Franc Racis (racis@psu.edu) 119 Werner Zimmermann, July 4, 95 120 V1.40 Started multisession support. Implementation copied from mcdx.c 121 by Heiko Schlittermann. Not tested yet. 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 V1.70 Multisession support now is completed, but there is still not 131 enough testing done. If you can test it, please contact me. For 132 details please read Documentation/cdrom/aztcd 133 Werner Zimmermann, August 19, 1995 134 V1.80 Modification to suit the new kernel boot procedure introduced 135 with kernel 1.3.33. Will definitely not work with older kernels. 136 Programming done by Linus himself. 137 Werner Zimmermann, October 11, 1995 138 V1.90 Support for Conrad TXC drives, thank's to Jochen Kunz and Olaf Kaluza. 139 Werner Zimmermann, October 21, 1995 140 V2.00 Changed #include "blk.h" to <linux/blk.h> as the directory 141 structure was changed. README.aztcd is now /usr/src/docu- 142 mentation/cdrom/aztcd 143 Werner Zimmermann, November 10, 95 144 V2.10 Started to modify azt_poll to prevent reading beyond end of 145 tracks. 146 Werner Zimmermann, December 3, 95 147 V2.20 Changed some comments 148 Werner Zimmermann, April 1, 96 149 V2.30 Implemented support for CyCDROM CR520, CR940, Code for CR520 150 delivered by H.Berger with preworks by E.Moenkeberg. 151 Werner Zimmermann, April 29, 96 152 V2.40 Reorganized the placement of functions in the source code file 153 to reflect the layered approach; did not actually change code 154 Werner Zimmermann, May 1, 96 155 V2.50 Heiko Eissfeldt suggested to remove some VERIFY_READs in 156 aztcd_ioctl; check_aztcd_media_change modified 157 Werner Zimmermann, May 16, 96 158 V2.60 Implemented Auto-Probing; made changes for kernel's 2.1.xx blocksize 159 Adaption to linux kernel > 2.1.0 160 Werner Zimmermann, Nov 29, 97 161 162 November 1999 -- Make kernel-parameter implementation work with 2.3.x 163 Removed init_module & cleanup_module in favor of 164 module_init & module_exit. 165 Torben Mathiasen <tmm@image.dk> 166*/ 167 168#include <linux/blkdev.h> 169#include "aztcd.h" 170 171#include <linux/module.h> 172#include <linux/errno.h> 173#include <linux/sched.h> 174#include <linux/mm.h> 175#include <linux/timer.h> 176#include <linux/fs.h> 177#include <linux/kernel.h> 178#include <linux/cdrom.h> 179#include <linux/ioport.h> 180#include <linux/string.h> 181#include <linux/major.h> 182 183#include <linux/init.h> 184 185#include <asm/system.h> 186#include <asm/io.h> 187 188#include <asm/uaccess.h> 189 190/*########################################################################### 191 Defines 192 ########################################################################### 193*/ 194 195#define MAJOR_NR AZTECH_CDROM_MAJOR 196#define QUEUE (azt_queue) 197#define CURRENT elv_next_request(azt_queue) 198#define SET_TIMER(func, jifs) delay_timer.expires = jiffies + (jifs); \ 199 delay_timer.function = (void *) (func); \ 200 add_timer(&delay_timer); 201 202#define CLEAR_TIMER del_timer(&delay_timer); 203 204#define RETURNM(message,value) {printk("aztcd: Warning: %s failed\n",message);\ 205 return value;} 206#define RETURN(message) {printk("aztcd: Warning: %s failed\n",message);\ 207 return;} 208 209/* Macros to switch the IDE-interface to the slave device and back to the master*/ 210#define SWITCH_IDE_SLAVE outb_p(0xa0,azt_port+6); \ 211 outb_p(0x10,azt_port+6); \ 212 outb_p(0x00,azt_port+7); \ 213 outb_p(0x10,azt_port+6); 214#define SWITCH_IDE_MASTER outb_p(0xa0,azt_port+6); 215 216 217#if 0 218#define AZT_TEST 219#define AZT_TEST1 /* <int-..> */ 220#define AZT_TEST2 /* do_aztcd_request */ 221#define AZT_TEST3 /* AZT_S_state */ 222#define AZT_TEST4 /* QUICK_LOOP-counter */ 223#define AZT_TEST5 /* port(1) state */ 224#define AZT_DEBUG 225#define AZT_DEBUG_MULTISESSION 226#endif 227 228static struct request_queue *azt_queue; 229 230static int current_valid(void) 231{ 232 return CURRENT && 233 CURRENT->cmd == READ && 234 CURRENT->sector != -1; 235} 236 237#define AFL_STATUSorDATA (AFL_STATUS | AFL_DATA) 238#define AZT_BUF_SIZ 16 239 240#define READ_TIMEOUT 3000 241 242#define azt_port aztcd /*needed for the modutils */ 243 244/*########################################################################## 245 Type Definitions 246 ########################################################################## 247*/ 248enum azt_state_e { AZT_S_IDLE, /* 0 */ 249 AZT_S_START, /* 1 */ 250 AZT_S_MODE, /* 2 */ 251 AZT_S_READ, /* 3 */ 252 AZT_S_DATA, /* 4 */ 253 AZT_S_STOP, /* 5 */ 254 AZT_S_STOPPING /* 6 */ 255}; 256enum azt_read_modes { AZT_MODE_0, /*read mode for audio disks, not supported by Aztech firmware */ 257 AZT_MODE_1, /*read mode for normal CD-ROMs */ 258 AZT_MODE_2 /*read mode for XA CD-ROMs */ 259}; 260 261/*########################################################################## 262 Global Variables 263 ########################################################################## 264*/ 265static int aztPresent = 0; 266 267static volatile int azt_transfer_is_active = 0; 268 269static char azt_buf[CD_FRAMESIZE_RAW * AZT_BUF_SIZ]; /*buffer for block size conversion */ 270#if AZT_PRIVATE_IOCTLS 271static char buf[CD_FRAMESIZE_RAW]; /*separate buffer for the ioctls */ 272#endif 273 274static volatile int azt_buf_bn[AZT_BUF_SIZ], azt_next_bn; 275static volatile int azt_buf_in, azt_buf_out = -1; 276static volatile int azt_error = 0; 277static int azt_open_count = 0; 278static volatile enum azt_state_e azt_state = AZT_S_IDLE; 279#ifdef AZT_TEST3 280static volatile enum azt_state_e azt_state_old = AZT_S_STOP; 281static volatile int azt_st_old = 0; 282#endif 283static volatile enum azt_read_modes azt_read_mode = AZT_MODE_1; 284 285static int azt_mode = -1; 286static volatile int azt_read_count = 1; 287 288static int azt_port = AZT_BASE_ADDR; 289 290module_param(azt_port, int, 0); 291 292static int azt_port_auto[16] = AZT_BASE_AUTO; 293 294static char azt_cont = 0; 295static char azt_init_end = 0; 296static char azt_auto_eject = AZT_AUTO_EJECT; 297 298static int AztTimeout, AztTries; 299static DECLARE_WAIT_QUEUE_HEAD(azt_waitq); 300static struct timer_list delay_timer = TIMER_INITIALIZER(NULL, 0, 0); 301 302static struct azt_DiskInfo DiskInfo; 303static struct azt_Toc Toc[MAX_TRACKS]; 304static struct azt_Play_msf azt_Play; 305 306static int aztAudioStatus = CDROM_AUDIO_NO_STATUS; 307static char aztDiskChanged = 1; 308static char aztTocUpToDate = 0; 309 310static unsigned char aztIndatum; 311static unsigned long aztTimeOutCount; 312static int aztCmd = 0; 313 314static DEFINE_SPINLOCK(aztSpin); 315 316/*########################################################################### 317 Function Prototypes 318 ########################################################################### 319*/ 320/* CDROM Drive Low Level I/O Functions */ 321static void aztStatTimer(void); 322 323/* CDROM Drive Command Functions */ 324static int aztGetDiskInfo(void); 325#if AZT_MULTISESSION 326static int aztGetMultiDiskInfo(void); 327#endif 328static int aztGetToc(int multi); 329 330/* Kernel Interface Functions */ 331static int check_aztcd_media_change(struct gendisk *disk); 332static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, 333 unsigned long arg); 334static int aztcd_open(struct inode *ip, struct file *fp); 335static int aztcd_release(struct inode *inode, struct file *file); 336 337static struct block_device_operations azt_fops = { 338 .owner = THIS_MODULE, 339 .open = aztcd_open, 340 .release = aztcd_release, 341 .ioctl = aztcd_ioctl, 342 .media_changed = check_aztcd_media_change, 343}; 344 345/* Aztcd State Machine: Controls Drive Operating State */ 346static void azt_poll(void); 347 348/* Miscellaneous support functions */ 349static void azt_hsg2msf(long hsg, struct msf *msf); 350static long azt_msf2hsg(struct msf *mp); 351static void azt_bin2bcd(unsigned char *p); 352static int azt_bcd2bin(unsigned char bcd); 353 354/*########################################################################## 355 CDROM Drive Low Level I/O Functions 356 ########################################################################## 357*/ 358/* Macros for the drive hardware interface handshake, these macros use 359 busy waiting */ 360/* Wait for OP_OK = drive answers with AFL_OP_OK after receiving a command*/ 361# define OP_OK op_ok() 362static void op_ok(void) 363{ 364 aztTimeOutCount = 0; 365 do { 366 aztIndatum = inb(DATA_PORT); 367 aztTimeOutCount++; 368 if (aztTimeOutCount >= AZT_TIMEOUT) { 369 printk("aztcd: Error Wait OP_OK\n"); 370 break; 371 } 372 } while (aztIndatum != AFL_OP_OK); 373} 374 375/* Wait for PA_OK = drive answers with AFL_PA_OK after receiving parameters*/ 376#if 0 377# define PA_OK pa_ok() 378static void pa_ok(void) 379{ 380 aztTimeOutCount = 0; 381 do { 382 aztIndatum = inb(DATA_PORT); 383 aztTimeOutCount++; 384 if (aztTimeOutCount >= AZT_TIMEOUT) { 385 printk("aztcd: Error Wait PA_OK\n"); 386 break; 387 } 388 } while (aztIndatum != AFL_PA_OK); 389} 390#endif 391 392/* Wait for STEN=Low = handshake signal 'AFL_.._OK available or command executed*/ 393# define STEN_LOW sten_low() 394static void sten_low(void) 395{ 396 aztTimeOutCount = 0; 397 do { 398 aztIndatum = inb(STATUS_PORT); 399 aztTimeOutCount++; 400 if (aztTimeOutCount >= AZT_TIMEOUT) { 401 if (azt_init_end) 402 printk 403 ("aztcd: Error Wait STEN_LOW commands:%x\n", 404 aztCmd); 405 break; 406 } 407 } while (aztIndatum & AFL_STATUS); 408} 409 410/* Wait for DTEN=Low = handshake signal 'Data available'*/ 411# define DTEN_LOW dten_low() 412static void dten_low(void) 413{ 414 aztTimeOutCount = 0; 415 do { 416 aztIndatum = inb(STATUS_PORT); 417 aztTimeOutCount++; 418 if (aztTimeOutCount >= AZT_TIMEOUT) { 419 printk("aztcd: Error Wait DTEN_OK\n"); 420 break; 421 } 422 } while (aztIndatum & AFL_DATA); 423} 424 425/* 426 * Macro for timer wait on STEN=Low, should only be used for 'slow' commands; 427 * may cause kernel panic when used in the wrong place 428*/ 429#define STEN_LOW_WAIT statusAzt() 430static void statusAzt(void) 431{ 432 AztTimeout = AZT_STATUS_DELAY; 433 SET_TIMER(aztStatTimer, HZ / 100); 434 sleep_on(&azt_waitq); 435 if (AztTimeout <= 0) 436 printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n", 437 aztCmd); 438 return; 439} 440 441static void aztStatTimer(void) 442{ 443 if (!(inb(STATUS_PORT) & AFL_STATUS)) { 444 wake_up(&azt_waitq); 445 return; 446 } 447 AztTimeout--; 448 if (AztTimeout <= 0) { 449 wake_up(&azt_waitq); 450 printk("aztcd: Error aztStatTimer: Timeout\n"); 451 return; 452 } 453 SET_TIMER(aztStatTimer, HZ / 100); 454} 455 456/*########################################################################## 457 CDROM Drive Command Functions 458 ########################################################################## 459*/ 460/* 461 * Send a single command, return -1 on error, else 0 462*/ 463static int aztSendCmd(int cmd) 464{ 465 unsigned char data; 466 int retry; 467 468#ifdef AZT_DEBUG 469 printk("aztcd: Executing command %x\n", cmd); 470#endif 471 472 if ((azt_port == 0x1f0) || (azt_port == 0x170)) 473 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ 474 475 aztCmd = cmd; 476 outb(POLLED, MODE_PORT); 477 do { 478 if (inb(STATUS_PORT) & AFL_STATUS) 479 break; 480 inb(DATA_PORT); /* if status left from last command, read and */ 481 } while (1); /* discard it */ 482 do { 483 if (inb(STATUS_PORT) & AFL_DATA) 484 break; 485 inb(DATA_PORT); /* if data left from last command, read and */ 486 } while (1); /* discard it */ 487 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { 488 outb((unsigned char) cmd, CMD_PORT); 489 STEN_LOW; 490 data = inb(DATA_PORT); 491 if (data == AFL_OP_OK) { 492 return 0; 493 } /*OP_OK? */ 494 if (data == AFL_OP_ERR) { 495 STEN_LOW; 496 data = inb(DATA_PORT); 497 printk 498 ("### Error 1 aztcd: aztSendCmd %x Error Code %x\n", 499 cmd, data); 500 } 501 } 502 if (retry >= AZT_RETRY_ATTEMPTS) { 503 printk("### Error 2 aztcd: aztSendCmd %x \n", cmd); 504 azt_error = 0xA5; 505 } 506 RETURNM("aztSendCmd", -1); 507} 508 509/* 510 * Send a play or read command to the drive, return -1 on error, else 0 511*/ 512static int sendAztCmd(int cmd, struct azt_Play_msf *params) 513{ 514 unsigned char data; 515 int retry; 516 517#ifdef AZT_DEBUG 518 printk("aztcd: play start=%02x:%02x:%02x end=%02x:%02x:%02x\n", 519 params->start.min, params->start.sec, params->start.frame, 520 params->end.min, params->end.sec, params->end.frame); 521#endif 522 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { 523 aztSendCmd(cmd); 524 outb(params->start.min, CMD_PORT); 525 outb(params->start.sec, CMD_PORT); 526 outb(params->start.frame, CMD_PORT); 527 outb(params->end.min, CMD_PORT); 528 outb(params->end.sec, CMD_PORT); 529 outb(params->end.frame, CMD_PORT); 530 STEN_LOW; 531 data = inb(DATA_PORT); 532 if (data == AFL_PA_OK) { 533 return 0; 534 } /*PA_OK ? */ 535 if (data == AFL_PA_ERR) { 536 STEN_LOW; 537 data = inb(DATA_PORT); 538 printk 539 ("### Error 1 aztcd: sendAztCmd %x Error Code %x\n", 540 cmd, data); 541 } 542 } 543 if (retry >= AZT_RETRY_ATTEMPTS) { 544 printk("### Error 2 aztcd: sendAztCmd %x\n ", cmd); 545 azt_error = 0xA5; 546 } 547 RETURNM("sendAztCmd", -1); 548} 549 550/* 551 * Send a seek command to the drive, return -1 on error, else 0 552*/ 553static int aztSeek(struct azt_Play_msf *params) 554{ 555 unsigned char data; 556 int retry; 557 558#ifdef AZT_DEBUG 559 printk("aztcd: aztSeek %02x:%02x:%02x\n", 560 params->start.min, params->start.sec, params->start.frame); 561#endif 562 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { 563 aztSendCmd(ACMD_SEEK); 564 outb(params->start.min, CMD_PORT); 565 outb(params->start.sec, CMD_PORT); 566 outb(params->start.frame, CMD_PORT); 567 STEN_LOW; 568 data = inb(DATA_PORT); 569 if (data == AFL_PA_OK) { 570 return 0; 571 } /*PA_OK ? */ 572 if (data == AFL_PA_ERR) { 573 STEN_LOW; 574 data = inb(DATA_PORT); 575 printk("### Error 1 aztcd: aztSeek\n"); 576 } 577 } 578 if (retry >= AZT_RETRY_ATTEMPTS) { 579 printk("### Error 2 aztcd: aztSeek\n "); 580 azt_error = 0xA5; 581 } 582 RETURNM("aztSeek", -1); 583} 584 585/* Send a Set Disk Type command 586 does not seem to work with Aztech drives, behavior is completely indepen- 587 dent on which mode is set ??? 588*/ 589static int aztSetDiskType(int type) 590{ 591 unsigned char data; 592 int retry; 593 594#ifdef AZT_DEBUG 595 printk("aztcd: set disk type command: type= %i\n", type); 596#endif 597 for (retry = 0; retry < AZT_RETRY_ATTEMPTS; retry++) { 598 aztSendCmd(ACMD_SET_DISK_TYPE); 599 outb(type, CMD_PORT); 600 STEN_LOW; 601 data = inb(DATA_PORT); 602 if (data == AFL_PA_OK) { /*PA_OK ? */ 603 azt_read_mode = type; 604 return 0; 605 } 606 if (data == AFL_PA_ERR) { 607 STEN_LOW; 608 data = inb(DATA_PORT); 609 printk 610 ("### Error 1 aztcd: aztSetDiskType %x Error Code %x\n", 611 type, data); 612 } 613 } 614 if (retry >= AZT_RETRY_ATTEMPTS) { 615 printk("### Error 2 aztcd: aztSetDiskType %x\n ", type); 616 azt_error = 0xA5; 617 } 618 RETURNM("aztSetDiskType", -1); 619} 620 621 622/* used in azt_poll to poll the status, expects another program to issue a 623 * ACMD_GET_STATUS directly before 624 */ 625static int aztStatus(void) 626{ 627 int st; 628/* int i; 629 630 i = inb(STATUS_PORT) & AFL_STATUS; is STEN=0? ??? 631 if (!i) 632*/ STEN_LOW; 633 if (aztTimeOutCount < AZT_TIMEOUT) { 634 st = inb(DATA_PORT) & 0xFF; 635 return st; 636 } else 637 RETURNM("aztStatus", -1); 638} 639 640/* 641 * Get the drive status 642 */ 643static int getAztStatus(void) 644{ 645 int st; 646 647 if (aztSendCmd(ACMD_GET_STATUS)) 648 RETURNM("getAztStatus 1", -1); 649 STEN_LOW; 650 st = inb(DATA_PORT) & 0xFF; 651#ifdef AZT_DEBUG 652 printk("aztcd: Status = %x\n", st); 653#endif 654 if ((st == 0xFF) || (st & AST_CMD_CHECK)) { 655 printk 656 ("aztcd: AST_CMD_CHECK error or no status available\n"); 657 return -1; 658 } 659 660 if (((st & AST_MODE_BITS) != AST_BUSY) 661 && (aztAudioStatus == CDROM_AUDIO_PLAY)) 662 /* XXX might be an error? look at q-channel? */ 663 aztAudioStatus = CDROM_AUDIO_COMPLETED; 664 665 if ((st & AST_DSK_CHG) || (st & AST_NOT_READY)) { 666 aztDiskChanged = 1; 667 aztTocUpToDate = 0; 668 aztAudioStatus = CDROM_AUDIO_NO_STATUS; 669 } 670 return st; 671} 672 673 674/* 675 * Send a 'Play' command and get the status. Use only from the top half. 676 */ 677static int aztPlay(struct azt_Play_msf *arg) 678{ 679 if (sendAztCmd(ACMD_PLAY_AUDIO, arg) < 0) 680 RETURNM("aztPlay", -1); 681 return 0; 682} 683 684/* 685 * Subroutines to automatically close the door (tray) and 686 * lock it closed when the cd is mounted. Leave the tray 687 * locking as an option 688 */ 689static void aztCloseDoor(void) 690{ 691 aztSendCmd(ACMD_CLOSE); 692 STEN_LOW; 693 return; 694} 695 696static void aztLockDoor(void) 697{ 698#if AZT_ALLOW_TRAY_LOCK 699 aztSendCmd(ACMD_LOCK); 700 STEN_LOW; 701#endif 702 return; 703} 704 705static void aztUnlockDoor(void) 706{ 707#if AZT_ALLOW_TRAY_LOCK 708 aztSendCmd(ACMD_UNLOCK); 709 STEN_LOW; 710#endif 711 return; 712} 713 714/* 715 * Read a value from the drive. Should return quickly, so a busy wait 716 * is used to avoid excessive rescheduling. The read command itself must 717 * be issued with aztSendCmd() directly before 718 */ 719static int aztGetValue(unsigned char *result) 720{ 721 int s; 722 723 STEN_LOW; 724 if (aztTimeOutCount >= AZT_TIMEOUT) { 725 printk("aztcd: aztGetValue timeout\n"); 726 return -1; 727 } 728 s = inb(DATA_PORT) & 0xFF; 729 *result = (unsigned char) s; 730 return 0; 731} 732 733/* 734 * Read the current Q-channel info. Also used for reading the 735 * table of contents. 736 */ 737static int aztGetQChannelInfo(struct azt_Toc *qp) 738{ 739 unsigned char notUsed; 740 int st; 741 742#ifdef AZT_DEBUG 743 printk("aztcd: starting aztGetQChannelInfo Time:%li\n", jiffies); 744#endif 745 if ((st = getAztStatus()) == -1) 746 RETURNM("aztGetQChannelInfo 1", -1); 747 if (aztSendCmd(ACMD_GET_Q_CHANNEL)) 748 RETURNM("aztGetQChannelInfo 2", -1); 749 /*STEN_LOW_WAIT; ??? Dosemu0.60's cdrom.c does not like STEN_LOW_WAIT here */ 750 if (aztGetValue(&notUsed)) 751 RETURNM("aztGetQChannelInfo 3", -1); /*??? Nullbyte einlesen */ 752 if ((st & AST_MODE_BITS) == AST_INITIAL) { 753 qp->ctrl_addr = 0; /* when audio stop ACMD_GET_Q_CHANNEL returns */ 754 qp->track = 0; /* only one byte with Aztech drives */ 755 qp->pointIndex = 0; 756 qp->trackTime.min = 0; 757 qp->trackTime.sec = 0; 758 qp->trackTime.frame = 0; 759 qp->diskTime.min = 0; 760 qp->diskTime.sec = 0; 761 qp->diskTime.frame = 0; 762 return 0; 763 } else { 764 if (aztGetValue(&qp->ctrl_addr) < 0) 765 RETURNM("aztGetQChannelInfo 4", -1); 766 if (aztGetValue(&qp->track) < 0) 767 RETURNM("aztGetQChannelInfo 4", -1); 768 if (aztGetValue(&qp->pointIndex) < 0) 769 RETURNM("aztGetQChannelInfo 4", -1); 770 if (aztGetValue(&qp->trackTime.min) < 0) 771 RETURNM("aztGetQChannelInfo 4", -1); 772 if (aztGetValue(&qp->trackTime.sec) < 0) 773 RETURNM("aztGetQChannelInfo 4", -1); 774 if (aztGetValue(&qp->trackTime.frame) < 0) 775 RETURNM("aztGetQChannelInfo 4", -1); 776 if (aztGetValue(&notUsed) < 0) 777 RETURNM("aztGetQChannelInfo 4", -1); 778 if (aztGetValue(&qp->diskTime.min) < 0) 779 RETURNM("aztGetQChannelInfo 4", -1); 780 if (aztGetValue(&qp->diskTime.sec) < 0) 781 RETURNM("aztGetQChannelInfo 4", -1); 782 if (aztGetValue(&qp->diskTime.frame) < 0) 783 RETURNM("aztGetQChannelInfo 4", -1); 784 } 785#ifdef AZT_DEBUG 786 printk("aztcd: exiting aztGetQChannelInfo Time:%li\n", jiffies); 787#endif 788 return 0; 789} 790 791/* 792 * Read the table of contents (TOC) and TOC header if necessary 793 */ 794static int aztUpdateToc(void) 795{ 796 int st; 797 798#ifdef AZT_DEBUG 799 printk("aztcd: starting aztUpdateToc Time:%li\n", jiffies); 800#endif 801 if (aztTocUpToDate) 802 return 0; 803 804 if (aztGetDiskInfo() < 0) 805 return -EIO; 806 807 if (aztGetToc(0) < 0) 808 return -EIO; 809 810 /*audio disk detection 811 with my Aztech drive there is no audio status bit, so I use the copy 812 protection bit of the first track. If this track is copy protected 813 (copy bit = 0), I assume, it's an audio disk. Strange, but works ??? */ 814 if (!(Toc[DiskInfo.first].ctrl_addr & 0x40)) 815 DiskInfo.audio = 1; 816 else 817 DiskInfo.audio = 0; 818 819 /* XA detection */ 820 if (!DiskInfo.audio) { 821 azt_Play.start.min = 0; /*XA detection only seems to work */ 822 azt_Play.start.sec = 2; /*when we play a track */ 823 azt_Play.start.frame = 0; 824 azt_Play.end.min = 0; 825 azt_Play.end.sec = 0; 826 azt_Play.end.frame = 1; 827 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) 828 return -1; 829 DTEN_LOW; 830 for (st = 0; st < CD_FRAMESIZE; st++) 831 inb(DATA_PORT); 832 } 833 DiskInfo.xa = getAztStatus() & AST_MODE; 834 if (DiskInfo.xa) { 835 printk 836 ("aztcd: XA support experimental - mail results to Werner.Zimmermann@fht-esslingen.de\n"); 837 } 838 839 /*multisession detection 840 support for multisession CDs is done automatically with Aztech drives, 841 we don't have to take care about TOC redirection; if we want the isofs 842 to take care about redirection, we have to set AZT_MULTISESSION to 1 */ 843 DiskInfo.multi = 0; 844#if AZT_MULTISESSION 845 if (DiskInfo.xa) { 846 aztGetMultiDiskInfo(); /*here Disk.Info.multi is set */ 847 } 848#endif 849 if (DiskInfo.multi) { 850 DiskInfo.lastSession.min = Toc[DiskInfo.next].diskTime.min; 851 DiskInfo.lastSession.sec = Toc[DiskInfo.next].diskTime.sec; 852 DiskInfo.lastSession.frame = 853 Toc[DiskInfo.next].diskTime.frame; 854 printk("aztcd: Multisession support experimental\n"); 855 } else { 856 DiskInfo.lastSession.min = 857 Toc[DiskInfo.first].diskTime.min; 858 DiskInfo.lastSession.sec = 859 Toc[DiskInfo.first].diskTime.sec; 860 DiskInfo.lastSession.frame = 861 Toc[DiskInfo.first].diskTime.frame; 862 } 863 864 aztTocUpToDate = 1; 865#ifdef AZT_DEBUG 866 printk("aztcd: exiting aztUpdateToc Time:%li\n", jiffies); 867#endif 868 return 0; 869} 870 871 872/* Read the table of contents header, i.e. no. of tracks and start of first 873 * track 874 */ 875static int aztGetDiskInfo(void) 876{ 877 int limit; 878 unsigned char test; 879 struct azt_Toc qInfo; 880 881#ifdef AZT_DEBUG 882 printk("aztcd: starting aztGetDiskInfo Time:%li\n", jiffies); 883#endif 884 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) 885 RETURNM("aztGetDiskInfo 1", -1); 886 STEN_LOW_WAIT; 887 test = 0; 888 for (limit = 300; limit > 0; limit--) { 889 if (aztGetQChannelInfo(&qInfo) < 0) 890 RETURNM("aztGetDiskInfo 2", -1); 891 if (qInfo.pointIndex == 0xA0) { /*Number of FirstTrack */ 892 DiskInfo.first = qInfo.diskTime.min; 893 DiskInfo.first = azt_bcd2bin(DiskInfo.first); 894 test = test | 0x01; 895 } 896 if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ 897 DiskInfo.last = qInfo.diskTime.min; 898 DiskInfo.last = azt_bcd2bin(DiskInfo.last); 899 test = test | 0x02; 900 } 901 if (qInfo.pointIndex == 0xA2) { /*DiskLength */ 902 DiskInfo.diskLength.min = qInfo.diskTime.min; 903 DiskInfo.diskLength.sec = qInfo.diskTime.sec; 904 DiskInfo.diskLength.frame = qInfo.diskTime.frame; 905 test = test | 0x04; 906 } 907 if ((qInfo.pointIndex == DiskInfo.first) && (test & 0x01)) { /*StartTime of First Track */ 908 DiskInfo.firstTrack.min = qInfo.diskTime.min; 909 DiskInfo.firstTrack.sec = qInfo.diskTime.sec; 910 DiskInfo.firstTrack.frame = qInfo.diskTime.frame; 911 test = test | 0x08; 912 } 913 if (test == 0x0F) 914 break; 915 } 916#ifdef AZT_DEBUG 917 printk("aztcd: exiting aztGetDiskInfo Time:%li\n", jiffies); 918 printk 919 ("Disk Info: first %d last %d length %02X:%02X.%02X dez first %02X:%02X.%02X dez\n", 920 DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min, 921 DiskInfo.diskLength.sec, DiskInfo.diskLength.frame, 922 DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec, 923 DiskInfo.firstTrack.frame); 924#endif 925 if (test != 0x0F) 926 return -1; 927 return 0; 928} 929 930#if AZT_MULTISESSION 931/* 932 * Get Multisession Disk Info 933 */ 934static int aztGetMultiDiskInfo(void) 935{ 936 int limit, k = 5; 937 unsigned char test; 938 struct azt_Toc qInfo; 939 940#ifdef AZT_DEBUG 941 printk("aztcd: starting aztGetMultiDiskInfo\n"); 942#endif 943 944 do { 945 azt_Play.start.min = Toc[DiskInfo.last + 1].diskTime.min; 946 azt_Play.start.sec = Toc[DiskInfo.last + 1].diskTime.sec; 947 azt_Play.start.frame = 948 Toc[DiskInfo.last + 1].diskTime.frame; 949 test = 0; 950 951 for (limit = 30; limit > 0; limit--) { /*Seek for LeadIn of next session */ 952 if (aztSeek(&azt_Play)) 953 RETURNM("aztGetMultiDiskInfo 1", -1); 954 if (aztGetQChannelInfo(&qInfo) < 0) 955 RETURNM("aztGetMultiDiskInfo 2", -1); 956 if ((qInfo.track == 0) && (qInfo.pointIndex)) 957 break; /*LeadIn found */ 958 if ((azt_Play.start.sec += 10) > 59) { 959 azt_Play.start.sec = 0; 960 azt_Play.start.min++; 961 } 962 } 963 if (!limit) 964 break; /*Check, if a leadin track was found, if not we're 965 at the end of the disk */ 966#ifdef AZT_DEBUG_MULTISESSION 967 printk("leadin found track %d pointIndex %x limit %d\n", 968 qInfo.track, qInfo.pointIndex, limit); 969#endif 970 for (limit = 300; limit > 0; limit--) { 971 if (++azt_Play.start.frame > 74) { 972 azt_Play.start.frame = 0; 973 if (azt_Play.start.sec > 59) { 974 azt_Play.start.sec = 0; 975 azt_Play.start.min++; 976 } 977 } 978 if (aztSeek(&azt_Play)) 979 RETURNM("aztGetMultiDiskInfo 3", -1); 980 if (aztGetQChannelInfo(&qInfo) < 0) 981 RETURNM("aztGetMultiDiskInfo 4", -1); 982 if (qInfo.pointIndex == 0xA0) { /*Number of NextTrack */ 983 DiskInfo.next = qInfo.diskTime.min; 984 DiskInfo.next = azt_bcd2bin(DiskInfo.next); 985 test = test | 0x01; 986 } 987 if (qInfo.pointIndex == 0xA1) { /*Number of LastTrack */ 988 DiskInfo.last = qInfo.diskTime.min; 989 DiskInfo.last = azt_bcd2bin(DiskInfo.last); 990 test = test | 0x02; 991 } 992 if (qInfo.pointIndex == 0xA2) { /*DiskLength */ 993 DiskInfo.diskLength.min = 994 qInfo.diskTime.min; 995 DiskInfo.diskLength.sec = 996 qInfo.diskTime.sec; 997 DiskInfo.diskLength.frame = 998 qInfo.diskTime.frame; 999 test = test | 0x04; 1000 } 1001 if ((qInfo.pointIndex == DiskInfo.next) && (test & 0x01)) { /*StartTime of Next Track */ 1002 DiskInfo.nextSession.min = 1003 qInfo.diskTime.min; 1004 DiskInfo.nextSession.sec = 1005 qInfo.diskTime.sec; 1006 DiskInfo.nextSession.frame = 1007 qInfo.diskTime.frame; 1008 test = test | 0x08; 1009 } 1010 if (test == 0x0F) 1011 break; 1012 } 1013#ifdef AZT_DEBUG_MULTISESSION 1014 printk 1015 ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez first %02x:%02x.%02x dez next %02x:%02x.%02x dez\n", 1016 DiskInfo.first, DiskInfo.next, DiskInfo.last, 1017 DiskInfo.diskLength.min, DiskInfo.diskLength.sec, 1018 DiskInfo.diskLength.frame, DiskInfo.firstTrack.min, 1019 DiskInfo.firstTrack.sec, DiskInfo.firstTrack.frame, 1020 DiskInfo.nextSession.min, DiskInfo.nextSession.sec, 1021 DiskInfo.nextSession.frame); 1022#endif 1023 if (test != 0x0F) 1024 break; 1025 else 1026 DiskInfo.multi = 1; /*found TOC of more than one session */ 1027 aztGetToc(1); 1028 } while (--k); 1029 1030#ifdef AZT_DEBUG 1031 printk("aztcd: exiting aztGetMultiDiskInfo Time:%li\n", jiffies); 1032#endif 1033 return 0; 1034} 1035#endif 1036 1037/* 1038 * Read the table of contents (TOC) 1039 */ 1040static int aztGetToc(int multi) 1041{ 1042 int i, px; 1043 int limit; 1044 struct azt_Toc qInfo; 1045 1046#ifdef AZT_DEBUG 1047 printk("aztcd: starting aztGetToc Time:%li\n", jiffies); 1048#endif 1049 if (!multi) { 1050 for (i = 0; i < MAX_TRACKS; i++) 1051 Toc[i].pointIndex = 0; 1052 i = DiskInfo.last + 3; 1053 } else { 1054 for (i = DiskInfo.next; i < MAX_TRACKS; i++) 1055 Toc[i].pointIndex = 0; 1056 i = DiskInfo.last + 4 - DiskInfo.next; 1057 } 1058 1059/*Is there a good reason to stop motor before TOC read? 1060 if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1); 1061 STEN_LOW_WAIT; 1062*/ 1063 1064 if (!multi) { 1065 azt_mode = 0x05; 1066 if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) 1067 RETURNM("aztGetToc 2", -1); 1068 STEN_LOW_WAIT; 1069 } 1070 for (limit = 300; limit > 0; limit--) { 1071 if (multi) { 1072 if (++azt_Play.start.sec > 59) { 1073 azt_Play.start.sec = 0; 1074 azt_Play.start.min++; 1075 } 1076 if (aztSeek(&azt_Play)) 1077 RETURNM("aztGetToc 3", -1); 1078 } 1079 if (aztGetQChannelInfo(&qInfo) < 0) 1080 break; 1081 1082 px = azt_bcd2bin(qInfo.pointIndex); 1083 1084 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0) 1085 if (Toc[px].pointIndex == 0) { 1086 Toc[px] = qInfo; 1087 i--; 1088 } 1089 1090 if (i <= 0) 1091 break; 1092 } 1093 1094 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength; 1095 Toc[DiskInfo.last].trackTime = DiskInfo.diskLength; 1096 1097#ifdef AZT_DEBUG_MULTISESSION 1098 printk("aztcd: exiting aztGetToc\n"); 1099 for (i = 1; i <= DiskInfo.last + 1; i++) 1100 printk 1101 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", 1102 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, 1103 Toc[i].trackTime.min, Toc[i].trackTime.sec, 1104 Toc[i].trackTime.frame, Toc[i].diskTime.min, 1105 Toc[i].diskTime.sec, Toc[i].diskTime.frame); 1106 for (i = 100; i < 103; i++) 1107 printk 1108 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez %02X:%02X.%02X dez\n", 1109 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex, 1110 Toc[i].trackTime.min, Toc[i].trackTime.sec, 1111 Toc[i].trackTime.frame, Toc[i].diskTime.min, 1112 Toc[i].diskTime.sec, Toc[i].diskTime.frame); 1113#endif 1114 1115 return limit > 0 ? 0 : -1; 1116} 1117 1118 1119/*########################################################################## 1120 Kernel Interface Functions 1121 ########################################################################## 1122*/ 1123 1124#ifndef MODULE 1125static int __init aztcd_setup(char *str) 1126{ 1127 int ints[4]; 1128 1129 (void) get_options(str, ARRAY_SIZE(ints), ints); 1130 1131 if (ints[0] > 0) 1132 azt_port = ints[1]; 1133 if (ints[1] > 1) 1134 azt_cont = ints[2]; 1135 return 1; 1136} 1137 1138__setup("aztcd=", aztcd_setup); 1139 1140#endif /* !MODULE */ 1141 1142/* 1143 * Checking if the media has been changed 1144*/ 1145static int check_aztcd_media_change(struct gendisk *disk) 1146{ 1147 if (aztDiskChanged) { /* disk changed */ 1148 aztDiskChanged = 0; 1149 return 1; 1150 } else 1151 return 0; /* no change */ 1152} 1153 1154/* 1155 * Kernel IO-controls 1156*/ 1157static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, 1158 unsigned long arg) 1159{ 1160 int i; 1161 struct azt_Toc qInfo; 1162 struct cdrom_ti ti; 1163 struct cdrom_tochdr tocHdr; 1164 struct cdrom_msf msf; 1165 struct cdrom_tocentry entry; 1166 struct azt_Toc *tocPtr; 1167 struct cdrom_subchnl subchnl; 1168 struct cdrom_volctrl volctrl; 1169 void __user *argp = (void __user *)arg; 1170 1171#ifdef AZT_DEBUG 1172 printk("aztcd: starting aztcd_ioctl - Command:%x Time: %li\n", 1173 cmd, jiffies); 1174 printk("aztcd Status %x\n", getAztStatus()); 1175#endif 1176 if (!ip) 1177 RETURNM("aztcd_ioctl 1", -EINVAL); 1178 if (getAztStatus() < 0) 1179 RETURNM("aztcd_ioctl 2", -EIO); 1180 if ((!aztTocUpToDate) || (aztDiskChanged)) { 1181 if ((i = aztUpdateToc()) < 0) 1182 RETURNM("aztcd_ioctl 3", i); /* error reading TOC */ 1183 } 1184 1185 switch (cmd) { 1186 case CDROMSTART: /* Spin up the drive. Don't know, what to do, 1187 at least close the tray */ 1188#if AZT_PRIVATE_IOCTLS 1189 if (aztSendCmd(ACMD_CLOSE)) 1190 RETURNM("aztcd_ioctl 4", -1); 1191 STEN_LOW_WAIT; 1192#endif 1193 break; 1194 case CDROMSTOP: /* Spin down the drive */ 1195 if (aztSendCmd(ACMD_STOP)) 1196 RETURNM("aztcd_ioctl 5", -1); 1197 STEN_LOW_WAIT; 1198 /* should we do anything if it fails? */ 1199 aztAudioStatus = CDROM_AUDIO_NO_STATUS; 1200 break; 1201 case CDROMPAUSE: /* Pause the drive */ 1202 if (aztAudioStatus != CDROM_AUDIO_PLAY) 1203 return -EINVAL; 1204 1205 if (aztGetQChannelInfo(&qInfo) < 0) { /* didn't get q channel info */ 1206 aztAudioStatus = CDROM_AUDIO_NO_STATUS; 1207 RETURNM("aztcd_ioctl 7", 0); 1208 } 1209 azt_Play.start = qInfo.diskTime; /* remember restart point */ 1210 1211 if (aztSendCmd(ACMD_PAUSE)) 1212 RETURNM("aztcd_ioctl 8", -1); 1213 STEN_LOW_WAIT; 1214 aztAudioStatus = CDROM_AUDIO_PAUSED; 1215 break; 1216 case CDROMRESUME: /* Play it again, Sam */ 1217 if (aztAudioStatus != CDROM_AUDIO_PAUSED) 1218 return -EINVAL; 1219 /* restart the drive at the saved position. */ 1220 i = aztPlay(&azt_Play); 1221 if (i < 0) { 1222 aztAudioStatus = CDROM_AUDIO_ERROR; 1223 return -EIO; 1224 } 1225 aztAudioStatus = CDROM_AUDIO_PLAY; 1226 break; 1227 case CDROMMULTISESSION: /*multisession support -- experimental */ 1228 { 1229 struct cdrom_multisession ms; 1230#ifdef AZT_DEBUG 1231 printk("aztcd ioctl MULTISESSION\n"); 1232#endif 1233 if (copy_from_user(&ms, argp, 1234 sizeof(struct cdrom_multisession))) 1235 return -EFAULT; 1236 if (ms.addr_format == CDROM_MSF) { 1237 ms.addr.msf.minute = 1238 azt_bcd2bin(DiskInfo.lastSession.min); 1239 ms.addr.msf.second = 1240 azt_bcd2bin(DiskInfo.lastSession.sec); 1241 ms.addr.msf.frame = 1242 azt_bcd2bin(DiskInfo.lastSession. 1243 frame); 1244 } else if (ms.addr_format == CDROM_LBA) 1245 ms.addr.lba = 1246 azt_msf2hsg(&DiskInfo.lastSession); 1247 else 1248 return -EINVAL; 1249 ms.xa_flag = DiskInfo.xa; 1250 if (copy_to_user(argp, &ms, 1251 sizeof(struct cdrom_multisession))) 1252 return -EFAULT; 1253#ifdef AZT_DEBUG 1254 if (ms.addr_format == CDROM_MSF) 1255 printk 1256 ("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n", 1257 ms.xa_flag, ms.addr.msf.minute, 1258 ms.addr.msf.second, ms.addr.msf.frame, 1259 DiskInfo.lastSession.min, 1260 DiskInfo.lastSession.sec, 1261 DiskInfo.lastSession.frame); 1262 else 1263 printk 1264 ("aztcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n", 1265 ms.xa_flag, ms.addr.lba, 1266 DiskInfo.lastSession.min, 1267 DiskInfo.lastSession.sec, 1268 DiskInfo.lastSession.frame); 1269#endif 1270 return 0; 1271 } 1272 case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */ 1273 if (copy_from_user(&ti, argp, sizeof ti)) 1274 return -EFAULT; 1275 if (ti.cdti_trk0 < DiskInfo.first 1276 || ti.cdti_trk0 > DiskInfo.last 1277 || ti.cdti_trk1 < ti.cdti_trk0) { 1278 return -EINVAL; 1279 } 1280 if (ti.cdti_trk1 > DiskInfo.last) 1281 ti.cdti_trk1 = DiskInfo.last; 1282 azt_Play.start = Toc[ti.cdti_trk0].diskTime; 1283 azt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime; 1284#ifdef AZT_DEBUG 1285 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", 1286 azt_Play.start.min, azt_Play.start.sec, 1287 azt_Play.start.frame, azt_Play.end.min, 1288 azt_Play.end.sec, azt_Play.end.frame); 1289#endif 1290 i = aztPlay(&azt_Play); 1291 if (i < 0) { 1292 aztAudioStatus = CDROM_AUDIO_ERROR; 1293 return -EIO; 1294 } 1295 aztAudioStatus = CDROM_AUDIO_PLAY; 1296 break; 1297 case CDROMPLAYMSF: /* Play starting at the given MSF address. */ 1298/* if (aztAudioStatus == CDROM_AUDIO_PLAY) 1299 { if (aztSendCmd(ACMD_STOP)) RETURNM("aztcd_ioctl 9",-1); 1300 STEN_LOW; 1301 aztAudioStatus = CDROM_AUDIO_NO_STATUS; 1302 } 1303*/ 1304 if (copy_from_user(&msf, argp, sizeof msf)) 1305 return -EFAULT; 1306 /* convert to bcd */ 1307 azt_bin2bcd(&msf.cdmsf_min0); 1308 azt_bin2bcd(&msf.cdmsf_sec0); 1309 azt_bin2bcd(&msf.cdmsf_frame0); 1310 azt_bin2bcd(&msf.cdmsf_min1); 1311 azt_bin2bcd(&msf.cdmsf_sec1); 1312 azt_bin2bcd(&msf.cdmsf_frame1); 1313 azt_Play.start.min = msf.cdmsf_min0; 1314 azt_Play.start.sec = msf.cdmsf_sec0; 1315 azt_Play.start.frame = msf.cdmsf_frame0; 1316 azt_Play.end.min = msf.cdmsf_min1; 1317 azt_Play.end.sec = msf.cdmsf_sec1; 1318 azt_Play.end.frame = msf.cdmsf_frame1; 1319#ifdef AZT_DEBUG 1320 printk("aztcd play: %02x:%02x.%02x to %02x:%02x.%02x\n", 1321 azt_Play.start.min, azt_Play.start.sec, 1322 azt_Play.start.frame, azt_Play.end.min, 1323 azt_Play.end.sec, azt_Play.end.frame); 1324#endif 1325 i = aztPlay(&azt_Play); 1326 if (i < 0) { 1327 aztAudioStatus = CDROM_AUDIO_ERROR; 1328 return -EIO; 1329 } 1330 aztAudioStatus = CDROM_AUDIO_PLAY; 1331 break; 1332 1333 case CDROMREADTOCHDR: /* Read the table of contents header */ 1334 tocHdr.cdth_trk0 = DiskInfo.first; 1335 tocHdr.cdth_trk1 = DiskInfo.last; 1336 if (copy_to_user(argp, &tocHdr, sizeof tocHdr)) 1337 return -EFAULT; 1338 break; 1339 case CDROMREADTOCENTRY: /* Read an entry in the table of contents */ 1340 if (copy_from_user(&entry, argp, sizeof entry)) 1341 return -EFAULT; 1342 if ((!aztTocUpToDate) || aztDiskChanged) 1343 aztUpdateToc(); 1344 if (entry.cdte_track == CDROM_LEADOUT) 1345 tocPtr = &Toc[DiskInfo.last + 1]; 1346 else if (entry.cdte_track > DiskInfo.last 1347 || entry.cdte_track < DiskInfo.first) { 1348 return -EINVAL; 1349 } else 1350 tocPtr = &Toc[entry.cdte_track]; 1351 entry.cdte_adr = tocPtr->ctrl_addr; 1352 entry.cdte_ctrl = tocPtr->ctrl_addr >> 4; 1353 if (entry.cdte_format == CDROM_LBA) 1354 entry.cdte_addr.lba = 1355 azt_msf2hsg(&tocPtr->diskTime); 1356 else if (entry.cdte_format == CDROM_MSF) { 1357 entry.cdte_addr.msf.minute = 1358 azt_bcd2bin(tocPtr->diskTime.min); 1359 entry.cdte_addr.msf.second = 1360 azt_bcd2bin(tocPtr->diskTime.sec); 1361 entry.cdte_addr.msf.frame = 1362 azt_bcd2bin(tocPtr->diskTime.frame); 1363 } else { 1364 return -EINVAL; 1365 } 1366 if (copy_to_user(argp, &entry, sizeof entry)) 1367 return -EFAULT; 1368 break; 1369 case CDROMSUBCHNL: /* Get subchannel info */ 1370 if (copy_from_user 1371 (&subchnl, argp, sizeof(struct cdrom_subchnl))) 1372 return -EFAULT; 1373 if (aztGetQChannelInfo(&qInfo) < 0) { 1374#ifdef AZT_DEBUG 1375 printk 1376 ("aztcd: exiting aztcd_ioctl - Error 3 - Command:%x\n", 1377 cmd); 1378#endif 1379 return -EIO; 1380 } 1381 subchnl.cdsc_audiostatus = aztAudioStatus; 1382 subchnl.cdsc_adr = qInfo.ctrl_addr; 1383 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4; 1384 subchnl.cdsc_trk = azt_bcd2bin(qInfo.track); 1385 subchnl.cdsc_ind = azt_bcd2bin(qInfo.pointIndex); 1386 if (subchnl.cdsc_format == CDROM_LBA) { 1387 subchnl.cdsc_absaddr.lba = 1388 azt_msf2hsg(&qInfo.diskTime); 1389 subchnl.cdsc_reladdr.lba = 1390 azt_msf2hsg(&qInfo.trackTime); 1391 } else { /*default */ 1392 subchnl.cdsc_format = CDROM_MSF; 1393 subchnl.cdsc_absaddr.msf.minute = 1394 azt_bcd2bin(qInfo.diskTime.min); 1395 subchnl.cdsc_absaddr.msf.second = 1396 azt_bcd2bin(qInfo.diskTime.sec); 1397 subchnl.cdsc_absaddr.msf.frame = 1398 azt_bcd2bin(qInfo.diskTime.frame); 1399 subchnl.cdsc_reladdr.msf.minute = 1400 azt_bcd2bin(qInfo.trackTime.min); 1401 subchnl.cdsc_reladdr.msf.second = 1402 azt_bcd2bin(qInfo.trackTime.sec); 1403 subchnl.cdsc_reladdr.msf.frame = 1404 azt_bcd2bin(qInfo.trackTime.frame); 1405 } 1406 if (copy_to_user(argp, &subchnl, sizeof(struct cdrom_subchnl))) 1407 return -EFAULT; 1408 break; 1409 case CDROMVOLCTRL: /* Volume control 1410 * With my Aztech CD268-01A volume control does not work, I can only 1411 turn the channels on (any value !=0) or off (value==0). Maybe it 1412 works better with your drive */ 1413 if (copy_from_user(&volctrl, argp, sizeof(volctrl))) 1414 return -EFAULT; 1415 azt_Play.start.min = 0x21; 1416 azt_Play.start.sec = 0x84; 1417 azt_Play.start.frame = volctrl.channel0; 1418 azt_Play.end.min = volctrl.channel1; 1419 azt_Play.end.sec = volctrl.channel2; 1420 azt_Play.end.frame = volctrl.channel3; 1421 sendAztCmd(ACMD_SET_VOLUME, &azt_Play); 1422 STEN_LOW_WAIT; 1423 break; 1424 case CDROMEJECT: 1425 aztUnlockDoor(); /* Assume user knows what they're doing */ 1426 /* all drives can at least stop! */ 1427 if (aztAudioStatus == CDROM_AUDIO_PLAY) { 1428 if (aztSendCmd(ACMD_STOP)) 1429 RETURNM("azt_ioctl 10", -1); 1430 STEN_LOW_WAIT; 1431 } 1432 if (aztSendCmd(ACMD_EJECT)) 1433 RETURNM("azt_ioctl 11", -1); 1434 STEN_LOW_WAIT; 1435 aztAudioStatus = CDROM_AUDIO_NO_STATUS; 1436 break; 1437 case CDROMEJECT_SW: 1438 azt_auto_eject = (char) arg; 1439 break; 1440 case CDROMRESET: 1441 outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ 1442 STEN_LOW; 1443 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ 1444 printk 1445 ("aztcd: AZTECH CD-ROM drive does not respond\n"); 1446 } 1447 break; 1448/*Take care, the following code is not compatible with other CD-ROM drivers, 1449 use it at your own risk with cdplay.c. Set AZT_PRIVATE_IOCTLS to 0 in aztcd.h, 1450 if you do not want to use it! 1451*/ 1452#if AZT_PRIVATE_IOCTLS 1453 case CDROMREADCOOKED: /*read data in mode 1 (2048 Bytes) */ 1454 case CDROMREADRAW: /*read data in mode 2 (2336 Bytes) */ 1455 { 1456 if (copy_from_user(&msf, argp, sizeof msf)) 1457 return -EFAULT; 1458 /* convert to bcd */ 1459 azt_bin2bcd(&msf.cdmsf_min0); 1460 azt_bin2bcd(&msf.cdmsf_sec0); 1461 azt_bin2bcd(&msf.cdmsf_frame0); 1462 msf.cdmsf_min1 = 0; 1463 msf.cdmsf_sec1 = 0; 1464 msf.cdmsf_frame1 = 1; /*read only one frame */ 1465 azt_Play.start.min = msf.cdmsf_min0; 1466 azt_Play.start.sec = msf.cdmsf_sec0; 1467 azt_Play.start.frame = msf.cdmsf_frame0; 1468 azt_Play.end.min = msf.cdmsf_min1; 1469 azt_Play.end.sec = msf.cdmsf_sec1; 1470 azt_Play.end.frame = msf.cdmsf_frame1; 1471 if (cmd == CDROMREADRAW) { 1472 if (DiskInfo.xa) { 1473 return -1; /*XA Disks can't be read raw */ 1474 } else { 1475 if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) 1476 return -1; 1477 DTEN_LOW; 1478 insb(DATA_PORT, buf, CD_FRAMESIZE_RAW); 1479 if (copy_to_user(argp, &buf, CD_FRAMESIZE_RAW)) 1480 return -EFAULT; 1481 } 1482 } else 1483 /*CDROMREADCOOKED*/ { 1484 if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) 1485 return -1; 1486 DTEN_LOW; 1487 insb(DATA_PORT, buf, CD_FRAMESIZE); 1488 if (copy_to_user(argp, &buf, CD_FRAMESIZE)) 1489 return -EFAULT; 1490 } 1491 } 1492 break; 1493 case CDROMSEEK: /*seek msf address */ 1494 if (copy_from_user(&msf, argp, sizeof msf)) 1495 return -EFAULT; 1496 /* convert to bcd */ 1497 azt_bin2bcd(&msf.cdmsf_min0); 1498 azt_bin2bcd(&msf.cdmsf_sec0); 1499 azt_bin2bcd(&msf.cdmsf_frame0); 1500 azt_Play.start.min = msf.cdmsf_min0; 1501 azt_Play.start.sec = msf.cdmsf_sec0; 1502 azt_Play.start.frame = msf.cdmsf_frame0; 1503 if (aztSeek(&azt_Play)) 1504 return -1; 1505 break; 1506#endif /*end of incompatible code */ 1507 case CDROMREADMODE1: /*set read data in mode 1 */ 1508 return aztSetDiskType(AZT_MODE_1); 1509 case CDROMREADMODE2: /*set read data in mode 2 */ 1510 return aztSetDiskType(AZT_MODE_2); 1511 default: 1512 return -EINVAL; 1513 } 1514#ifdef AZT_DEBUG 1515 printk("aztcd: exiting aztcd_ioctl Command:%x Time:%li\n", cmd, 1516 jiffies); 1517#endif 1518 return 0; 1519} 1520 1521/* 1522 * Take care of the different block sizes between cdrom and Linux. 1523 * When Linux gets variable block sizes this will probably go away. 1524 */ 1525static void azt_transfer(void) 1526{ 1527#ifdef AZT_TEST 1528 printk("aztcd: executing azt_transfer Time:%li\n", jiffies); 1529#endif 1530 if (!current_valid()) 1531 return; 1532 1533 while (CURRENT->nr_sectors) { 1534 int bn = CURRENT->sector / 4; 1535 int i; 1536 for (i = 0; i < AZT_BUF_SIZ && azt_buf_bn[i] != bn; ++i); 1537 if (i < AZT_BUF_SIZ) { 1538 int offs = (i * 4 + (CURRENT->sector & 3)) * 512; 1539 int nr_sectors = 4 - (CURRENT->sector & 3); 1540 if (azt_buf_out != i) { 1541 azt_buf_out = i; 1542 if (azt_buf_bn[i] != bn) { 1543 azt_buf_out = -1; 1544 continue; 1545 } 1546 } 1547 if (nr_sectors > CURRENT->nr_sectors) 1548 nr_sectors = CURRENT->nr_sectors; 1549 memcpy(CURRENT->buffer, azt_buf + offs, 1550 nr_sectors * 512); 1551 CURRENT->nr_sectors -= nr_sectors; 1552 CURRENT->sector += nr_sectors; 1553 CURRENT->buffer += nr_sectors * 512; 1554 } else { 1555 azt_buf_out = -1; 1556 break; 1557 } 1558 } 1559} 1560 1561static void do_aztcd_request(request_queue_t * q) 1562{ 1563#ifdef AZT_TEST 1564 printk(" do_aztcd_request(%ld+%ld) Time:%li\n", CURRENT->sector, 1565 CURRENT->nr_sectors, jiffies); 1566#endif 1567 if (DiskInfo.audio) { 1568 printk("aztcd: Error, tried to mount an Audio CD\n"); 1569 end_request(CURRENT, 0); 1570 return; 1571 } 1572 azt_transfer_is_active = 1; 1573 while (current_valid()) { 1574 azt_transfer(); 1575 if (CURRENT->nr_sectors == 0) { 1576 end_request(CURRENT, 1); 1577 } else { 1578 azt_buf_out = -1; /* Want to read a block not in buffer */ 1579 if (azt_state == AZT_S_IDLE) { 1580 if ((!aztTocUpToDate) || aztDiskChanged) { 1581 if (aztUpdateToc() < 0) { 1582 while (current_valid()) 1583 end_request(CURRENT, 0); 1584 break; 1585 } 1586 } 1587 azt_state = AZT_S_START; 1588 AztTries = 5; 1589 SET_TIMER(azt_poll, HZ / 100); 1590 } 1591 break; 1592 } 1593 } 1594 azt_transfer_is_active = 0; 1595#ifdef AZT_TEST2 1596 printk 1597 ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", 1598 azt_next_bn, azt_buf_in, azt_buf_out, azt_buf_bn[azt_buf_in]); 1599 printk(" do_aztcd_request ends Time:%li\n", jiffies); 1600#endif 1601} 1602 1603 1604static void azt_invalidate_buffers(void) 1605{ 1606 int i; 1607 1608#ifdef AZT_DEBUG 1609 printk("aztcd: executing azt_invalidate_buffers\n"); 1610#endif 1611 for (i = 0; i < AZT_BUF_SIZ; ++i) 1612 azt_buf_bn[i] = -1; 1613 azt_buf_out = -1; 1614} 1615 1616/* 1617 * Open the device special file. Check that a disk is in. 1618 */ 1619static int aztcd_open(struct inode *ip, struct file *fp) 1620{ 1621 int st; 1622 1623#ifdef AZT_DEBUG 1624 printk("aztcd: starting aztcd_open\n"); 1625#endif 1626 1627 if (aztPresent == 0) 1628 return -ENXIO; /* no hardware */ 1629 1630 if (!azt_open_count && azt_state == AZT_S_IDLE) { 1631 azt_invalidate_buffers(); 1632 1633 st = getAztStatus(); /* check drive status */ 1634 if (st == -1) 1635 goto err_out; /* drive doesn't respond */ 1636 1637 if (st & AST_DOOR_OPEN) { /* close door, then get the status again. */ 1638 printk("aztcd: Door Open?\n"); 1639 aztCloseDoor(); 1640 st = getAztStatus(); 1641 } 1642 1643 if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) { /*no disk in drive or changed */ 1644 printk 1645 ("aztcd: Disk Changed or No Disk in Drive?\n"); 1646 aztTocUpToDate = 0; 1647 } 1648 if (aztUpdateToc()) 1649 goto err_out; 1650 1651 } 1652 ++azt_open_count; 1653 aztLockDoor(); 1654 1655#ifdef AZT_DEBUG 1656 printk("aztcd: exiting aztcd_open\n"); 1657#endif 1658 return 0; 1659 1660 err_out: 1661 return -EIO; 1662} 1663 1664 1665/* 1666 * On close, we flush all azt blocks from the buffer cache. 1667 */ 1668static int aztcd_release(struct inode *inode, struct file *file) 1669{ 1670#ifdef AZT_DEBUG 1671 printk("aztcd: executing aztcd_release\n"); 1672 printk("inode: %p, device: %s file: %p\n", inode, 1673 inode->i_bdev->bd_disk->disk_name, file); 1674#endif 1675 if (!--azt_open_count) { 1676 azt_invalidate_buffers(); 1677 aztUnlockDoor(); 1678 if (azt_auto_eject) 1679 aztSendCmd(ACMD_EJECT); 1680 CLEAR_TIMER; 1681 } 1682 return 0; 1683} 1684 1685static struct gendisk *azt_disk; 1686 1687/* 1688 * Test for presence of drive and initialize it. Called at boot time. 1689 */ 1690 1691static int __init aztcd_init(void) 1692{ 1693 long int count, max_count; 1694 unsigned char result[50]; 1695 int st; 1696 void* status = NULL; 1697 int i = 0; 1698 int ret = 0; 1699 1700 if (azt_port == 0) { 1701 printk(KERN_INFO "aztcd: no Aztech CD-ROM Initialization"); 1702 return -EIO; 1703 } 1704 1705 printk(KERN_INFO "aztcd: AZTECH, ORCHID, OKANO, WEARNES, TXC, CyDROM " 1706 "CD-ROM Driver\n"); 1707 printk(KERN_INFO "aztcd: (C) 1994-98 W.Zimmermann\n"); 1708 if (azt_port == -1) { 1709 printk 1710 ("aztcd: DriverVersion=%s For IDE/ATAPI-drives use ide-cd.c\n", 1711 AZT_VERSION); 1712 } else 1713 printk 1714 ("aztcd: DriverVersion=%s BaseAddress=0x%x For IDE/ATAPI-drives use ide-cd.c\n", 1715 AZT_VERSION, azt_port); 1716 printk(KERN_INFO "aztcd: If you have problems, read /usr/src/linux/" 1717 "Documentation/cdrom/aztcd\n"); 1718 1719 1720#ifdef AZT_SW32 /*CDROM connected to Soundwave32 card */ 1721 if ((0xFF00 & inw(AZT_SW32_ID_REG)) != 0x4500) { 1722 printk 1723 ("aztcd: no Soundwave32 card detected at base:%x init:%x config:%x id:%x\n", 1724 AZT_SW32_BASE_ADDR, AZT_SW32_INIT, 1725 AZT_SW32_CONFIG_REG, AZT_SW32_ID_REG); 1726 return -EIO; 1727 } else { 1728 printk(KERN_INFO 1729 "aztcd: Soundwave32 card detected at %x Version %x\n", 1730 AZT_SW32_BASE_ADDR, inw(AZT_SW32_ID_REG)); 1731 outw(AZT_SW32_INIT, AZT_SW32_CONFIG_REG); 1732 for (count = 0; count < 10000; count++); /*delay a bit */ 1733 } 1734#endif 1735 1736 /* check for presence of drive */ 1737 1738 if (azt_port == -1) { /* autoprobing for proprietary interface */ 1739 for (i = 0; (azt_port_auto[i] != 0) && (i < 16); i++) { 1740 azt_port = azt_port_auto[i]; 1741 printk(KERN_INFO "aztcd: Autoprobing BaseAddress=0x%x" 1742 "\n", azt_port); 1743 /*proprietary interfaces need 4 bytes */ 1744 if (!request_region(azt_port, 4, "aztcd")) { 1745 continue; 1746 } 1747 outb(POLLED, MODE_PORT); 1748 inb(CMD_PORT); 1749 inb(CMD_PORT); 1750 outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ 1751 1752 aztTimeOutCount = 0; 1753 do { 1754 aztIndatum = inb(STATUS_PORT); 1755 aztTimeOutCount++; 1756 if (aztTimeOutCount >= AZT_FAST_TIMEOUT) 1757 break; 1758 } while (aztIndatum & AFL_STATUS); 1759 if (inb(DATA_PORT) == AFL_OP_OK) { /* OK drive found */ 1760 break; 1761 } 1762 else { /* Drive not found on this port - try next one */ 1763 release_region(azt_port, 4); 1764 } 1765 } 1766 if ((azt_port_auto[i] == 0) || (i == 16)) { 1767 printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n"); 1768 return -EIO; 1769 } 1770 } else { /* no autoprobing */ 1771 if ((azt_port == 0x1f0) || (azt_port == 0x170)) 1772 status = request_region(azt_port, 8, "aztcd"); /*IDE-interfaces need 8 bytes */ 1773 else 1774 status = request_region(azt_port, 4, "aztcd"); /*proprietary interfaces need 4 bytes */ 1775 if (!status) { 1776 printk(KERN_WARNING "aztcd: conflict, I/O port (%X) " 1777 "already used\n", azt_port); 1778 return -EIO; 1779 } 1780 1781 if ((azt_port == 0x1f0) || (azt_port == 0x170)) 1782 SWITCH_IDE_SLAVE; /*switch IDE interface to slave configuration */ 1783 1784 outb(POLLED, MODE_PORT); 1785 inb(CMD_PORT); 1786 inb(CMD_PORT); 1787 outb(ACMD_GET_VERSION, CMD_PORT); /*Try to get version info */ 1788 1789 aztTimeOutCount = 0; 1790 do { 1791 aztIndatum = inb(STATUS_PORT); 1792 aztTimeOutCount++; 1793 if (aztTimeOutCount >= AZT_FAST_TIMEOUT) 1794 break; 1795 } while (aztIndatum & AFL_STATUS); 1796 1797 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? If not, reset and try again */ 1798#ifndef MODULE 1799 if (azt_cont != 0x79) { 1800 printk(KERN_WARNING "aztcd: no AZTECH CD-ROM " 1801 "drive found-Try boot parameter aztcd=" 1802 "<BaseAddress>,0x79\n"); 1803 ret = -EIO; 1804 goto err_out; 1805 } 1806#else 1807 if (0) { 1808 } 1809#endif 1810 else { 1811 printk(KERN_INFO "aztcd: drive reset - " 1812 "please wait\n"); 1813 for (count = 0; count < 50; count++) { 1814 inb(STATUS_PORT); /*removing all data from earlier tries */ 1815 inb(DATA_PORT); 1816 } 1817 outb(POLLED, MODE_PORT); 1818 inb(CMD_PORT); 1819 inb(CMD_PORT); 1820 getAztStatus(); /*trap errors */ 1821 outb(ACMD_SOFT_RESET, CMD_PORT); /*send reset */ 1822 STEN_LOW; 1823 if (inb(DATA_PORT) != AFL_OP_OK) { /*OP_OK? */ 1824 printk(KERN_WARNING "aztcd: no AZTECH " 1825 "CD-ROM drive found\n"); 1826 ret = -EIO; 1827 goto err_out; 1828 } 1829 1830 for (count = 0; count < AZT_TIMEOUT; 1831 count++) 1832 barrier(); /* Stop gcc 2.96 being smart */ 1833 /* use udelay(), damnit -- AV */ 1834 1835 if ((st = getAztStatus()) == -1) { 1836 printk(KERN_WARNING "aztcd: Drive Status" 1837 " Error Status=%x\n", st); 1838 ret = -EIO; 1839 goto err_out; 1840 } 1841#ifdef AZT_DEBUG 1842 printk(KERN_DEBUG "aztcd: Status = %x\n", st); 1843#endif 1844 outb(POLLED, MODE_PORT); 1845 inb(CMD_PORT); 1846 inb(CMD_PORT); 1847 outb(ACMD_GET_VERSION, CMD_PORT); /*GetVersion */ 1848 STEN_LOW; 1849 OP_OK; 1850 } 1851 } 1852 } 1853 1854 azt_init_end = 1; 1855 STEN_LOW; 1856 result[0] = inb(DATA_PORT); /*reading in a null byte??? */ 1857 for (count = 1; count < 50; count++) { /*Reading version string */ 1858 aztTimeOutCount = 0; /*here we must implement STEN_LOW differently */ 1859 do { 1860 aztIndatum = inb(STATUS_PORT); /*because we want to exit by timeout */ 1861 aztTimeOutCount++; 1862 if (aztTimeOutCount >= AZT_FAST_TIMEOUT) 1863 break; 1864 } while (aztIndatum & AFL_STATUS); 1865 if (aztTimeOutCount >= AZT_FAST_TIMEOUT) 1866 break; /*all chars read? */ 1867 result[count] = inb(DATA_PORT); 1868 } 1869 if (count > 30) 1870 max_count = 30; /*print max.30 chars of the version string */ 1871 else 1872 max_count = count; 1873 printk(KERN_INFO "aztcd: FirmwareVersion="); 1874 for (count = 1; count < max_count; count++) 1875 printk("%c", result[count]); 1876 printk("<<>> "); 1877 1878 if ((result[1] == 'A') && (result[2] == 'Z') && (result[3] == 'T')) { 1879 printk("AZTECH drive detected\n"); 1880 /*AZTECH*/} 1881 else if ((result[2] == 'C') && (result[3] == 'D') 1882 && (result[4] == 'D')) { 1883 printk("ORCHID or WEARNES drive detected\n"); /*ORCHID or WEARNES */ 1884 } else if ((result[1] == 0x03) && (result[2] == '5')) { 1885 printk("TXC or CyCDROM drive detected\n"); /*Conrad TXC, CyCDROM */ 1886 } else { /*OTHERS or none */ 1887 printk("\nunknown drive or firmware version detected\n"); 1888 printk 1889 ("aztcd may not run stable, if you want to try anyhow,\n"); 1890 printk("boot with: aztcd=<BaseAddress>,0x79\n"); 1891 if ((azt_cont != 0x79)) { 1892 printk("aztcd: FirmwareVersion="); 1893 for (count = 1; count < 5; count++) 1894 printk("%c", result[count]); 1895 printk("<<>> "); 1896 printk("Aborted\n"); 1897 ret = -EIO; 1898 goto err_out; 1899 } 1900 } 1901 azt_disk = alloc_disk(1); 1902 if (!azt_disk) 1903 goto err_out; 1904 1905 if (register_blkdev(MAJOR_NR, "aztcd")) { 1906 ret = -EIO; 1907 goto err_out2; 1908 } 1909 1910 azt_queue = blk_init_queue(do_aztcd_request, &aztSpin); 1911 if (!azt_queue) { 1912 ret = -ENOMEM; 1913 goto err_out3; 1914 } 1915 1916 blk_queue_hardsect_size(azt_queue, 2048); 1917 azt_disk->major = MAJOR_NR; 1918 azt_disk->first_minor = 0; 1919 azt_disk->fops = &azt_fops; 1920 sprintf(azt_disk->disk_name, "aztcd"); 1921 sprintf(azt_disk->devfs_name, "aztcd"); 1922 azt_disk->queue = azt_queue; 1923 add_disk(azt_disk); 1924 azt_invalidate_buffers(); 1925 aztPresent = 1; 1926 aztCloseDoor(); 1927 return 0; 1928err_out3: 1929 unregister_blkdev(MAJOR_NR, "aztcd"); 1930err_out2: 1931 put_disk(azt_disk); 1932err_out: 1933 if ((azt_port == 0x1f0) || (azt_port == 0x170)) { 1934 SWITCH_IDE_MASTER; 1935 release_region(azt_port, 8); /*IDE-interface */ 1936 } else 1937 release_region(azt_port, 4); /*proprietary interface */ 1938 return ret; 1939 1940} 1941 1942static void __exit aztcd_exit(void) 1943{ 1944 del_gendisk(azt_disk); 1945 put_disk(azt_disk); 1946 if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { 1947 printk("What's that: can't unregister aztcd\n"); 1948 return; 1949 } 1950 blk_cleanup_queue(azt_queue); 1951 if ((azt_port == 0x1f0) || (azt_port == 0x170)) { 1952 SWITCH_IDE_MASTER; 1953 release_region(azt_port, 8); /*IDE-interface */ 1954 } else 1955 release_region(azt_port, 4); /*proprietary interface */ 1956 printk(KERN_INFO "aztcd module released.\n"); 1957} 1958 1959module_init(aztcd_init); 1960module_exit(aztcd_exit); 1961 1962/*########################################################################## 1963 Aztcd State Machine: Controls Drive Operating State 1964 ########################################################################## 1965*/ 1966static void azt_poll(void) 1967{ 1968 int st = 0; 1969 int loop_ctl = 1; 1970 int skip = 0; 1971 1972 if (azt_error) { 1973 if (aztSendCmd(ACMD_GET_ERROR)) 1974 RETURN("azt_poll 1"); 1975 STEN_LOW; 1976 azt_error = inb(DATA_PORT) & 0xFF; 1977 printk("aztcd: I/O error 0x%02x\n", azt_error); 1978 azt_invalidate_buffers(); 1979#ifdef WARN_IF_READ_FAILURE 1980 if (AztTries == 5) 1981 printk 1982 ("aztcd: Read of Block %d Failed - Maybe Audio Disk?\n", 1983 azt_next_bn); 1984#endif 1985 if (!AztTries--) { 1986 printk 1987 ("aztcd: Read of Block %d Failed, Maybe Audio Disk? Giving up\n", 1988 azt_next_bn); 1989 if (azt_transfer_is_active) { 1990 AztTries = 0; 1991 loop_ctl = 0; 1992 } 1993 if (current_valid()) 1994 end_request(CURRENT, 0); 1995 AztTries = 5; 1996 } 1997 azt_error = 0; 1998 azt_state = AZT_S_STOP; 1999 } 2000 2001 while (loop_ctl) { 2002 loop_ctl = 0; /* each case must flip this back to 1 if we want 2003 to come back up here */ 2004 switch (azt_state) { 2005 2006 case AZT_S_IDLE: 2007#ifdef AZT_TEST3 2008 if (azt_state != azt_state_old) { 2009 azt_state_old = azt_state; 2010 printk("AZT_S_IDLE\n"); 2011 } 2012#endif 2013 return; 2014 2015 case AZT_S_START: 2016#ifdef AZT_TEST3 2017 if (azt_state != azt_state_old) { 2018 azt_state_old = azt_state; 2019 printk("AZT_S_START\n"); 2020 } 2021#endif 2022 if (aztSendCmd(ACMD_GET_STATUS)) 2023 RETURN("azt_poll 2"); /*result will be checked by aztStatus() */ 2024 azt_state = 2025 azt_mode == 1 ? AZT_S_READ : AZT_S_MODE; 2026 AztTimeout = 3000; 2027 break; 2028 2029 case AZT_S_MODE: 2030#ifdef AZT_TEST3 2031 if (azt_state != azt_state_old) { 2032 azt_state_old = azt_state; 2033 printk("AZT_S_MODE\n"); 2034 } 2035#endif 2036 if (!skip) { 2037 if ((st = aztStatus()) != -1) { 2038 if ((st & AST_DSK_CHG) 2039 || (st & AST_NOT_READY)) { 2040 aztDiskChanged = 1; 2041 aztTocUpToDate = 0; 2042 azt_invalidate_buffers(); 2043 end_request(CURRENT, 0); 2044 printk 2045 ("aztcd: Disk Changed or Not Ready 1 - Unmount Disk!\n"); 2046 } 2047 } else 2048 break; 2049 } 2050 skip = 0; 2051 2052 if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { 2053 aztDiskChanged = 1; 2054 aztTocUpToDate = 0; 2055 printk 2056 ("aztcd: Disk Changed or Not Ready 2 - Unmount Disk!\n"); 2057 end_request(CURRENT, 0); 2058 printk((st & AST_DOOR_OPEN) ? 2059 "aztcd: door open\n" : 2060 "aztcd: disk removed\n"); 2061 if (azt_transfer_is_active) { 2062 azt_state = AZT_S_START; 2063 loop_ctl = 1; /* goto immediately */ 2064 break; 2065 } 2066 azt_state = AZT_S_IDLE; 2067 while (current_valid()) 2068 end_request(CURRENT, 0); 2069 return; 2070 } 2071 2072/* if (aztSendCmd(ACMD_SET_MODE)) RETURN("azt_poll 3"); 2073 outb(0x01, DATA_PORT); 2074 PA_OK; 2075 STEN_LOW; 2076*/ 2077 if (aztSendCmd(ACMD_GET_STATUS)) 2078 RETURN("azt_poll 4"); 2079 STEN_LOW; 2080 azt_mode = 1; 2081 azt_state = AZT_S_READ; 2082 AztTimeout = 3000; 2083 2084 break; 2085 2086 2087 case AZT_S_READ: 2088#ifdef AZT_TEST3 2089 if (azt_state != azt_state_old) { 2090 azt_state_old = azt_state; 2091 printk("AZT_S_READ\n"); 2092 } 2093#endif 2094 if (!skip) { 2095 if ((st = aztStatus()) != -1) { 2096 if ((st & AST_DSK_CHG) 2097 || (st & AST_NOT_READY)) { 2098 aztDiskChanged = 1; 2099 aztTocUpToDate = 0; 2100 azt_invalidate_buffers(); 2101 printk 2102 ("aztcd: Disk Changed or Not Ready 3 - Unmount Disk!\n"); 2103 end_request(CURRENT, 0); 2104 } 2105 } else 2106 break; 2107 } 2108 2109 skip = 0; 2110 if ((st & AST_DOOR_OPEN) || (st & AST_NOT_READY)) { 2111 aztDiskChanged = 1; 2112 aztTocUpToDate = 0; 2113 printk((st & AST_DOOR_OPEN) ? 2114 "aztcd: door open\n" : 2115 "aztcd: disk removed\n"); 2116 if (azt_transfer_is_active) { 2117 azt_state = AZT_S_START; 2118 loop_ctl = 1; 2119 break; 2120 } 2121 azt_state = AZT_S_IDLE; 2122 while (current_valid()) 2123 end_request(CURRENT, 0); 2124 return; 2125 } 2126 2127 if (current_valid()) { 2128 struct azt_Play_msf msf; 2129 int i; 2130 azt_next_bn = CURRENT->sector / 4; 2131 azt_hsg2msf(azt_next_bn, &msf.start); 2132 i = 0; 2133 /* find out in which track we are */ 2134 while (azt_msf2hsg(&msf.start) > 2135 azt_msf2hsg(&Toc[++i].trackTime)) { 2136 }; 2137 if (azt_msf2hsg(&msf.start) < 2138 azt_msf2hsg(&Toc[i].trackTime) - 2139 AZT_BUF_SIZ) { 2140 azt_read_count = AZT_BUF_SIZ; /*fast, because we read ahead */ 2141 /*azt_read_count=CURRENT->nr_sectors; slow, no read ahead */ 2142 } else /* don't read beyond end of track */ 2143#if AZT_MULTISESSION 2144 { 2145 azt_read_count = 2146 (azt_msf2hsg(&Toc[i].trackTime) 2147 / 4) * 4 - 2148 azt_msf2hsg(&msf.start); 2149 if (azt_read_count < 0) 2150 azt_read_count = 0; 2151 if (azt_read_count > AZT_BUF_SIZ) 2152 azt_read_count = 2153 AZT_BUF_SIZ; 2154 printk 2155 ("aztcd: warning - trying to read beyond end of track\n"); 2156/* printk("%i %i %li %li\n",i,azt_read_count,azt_msf2hsg(&msf.start),azt_msf2hsg(&Toc[i].trackTime)); 2157*/ } 2158#else 2159 { 2160 azt_read_count = AZT_BUF_SIZ; 2161 } 2162#endif 2163 msf.end.min = 0; 2164 msf.end.sec = 0; 2165 msf.end.frame = azt_read_count; /*Mitsumi here reads 0xffffff sectors */ 2166#ifdef AZT_TEST3 2167 printk 2168 ("---reading msf-address %x:%x:%x %x:%x:%x\n", 2169 msf.start.min, msf.start.sec, 2170 msf.start.frame, msf.end.min, 2171 msf.end.sec, msf.end.frame); 2172 printk 2173 ("azt_next_bn:%x azt_buf_in:%x azt_buf_out:%x azt_buf_bn:%x\n", 2174 azt_next_bn, azt_buf_in, azt_buf_out, 2175 azt_buf_bn[azt_buf_in]); 2176#endif 2177 if (azt_read_mode == AZT_MODE_2) { 2178 sendAztCmd(ACMD_PLAY_READ_RAW, &msf); /*XA disks in raw mode */ 2179 } else { 2180 sendAztCmd(ACMD_PLAY_READ, &msf); /*others in cooked mode */ 2181 } 2182 azt_state = AZT_S_DATA; 2183 AztTimeout = READ_TIMEOUT; 2184 } else { 2185 azt_state = AZT_S_STOP; 2186 loop_ctl = 1; 2187 break; 2188 } 2189 2190 break; 2191 2192 2193 case AZT_S_DATA: 2194#ifdef AZT_TEST3 2195 if (azt_state != azt_state_old) { 2196 azt_state_old = azt_state; 2197 printk("AZT_S_DATA\n"); 2198 } 2199#endif 2200 2201 st = inb(STATUS_PORT) & AFL_STATUSorDATA; 2202 2203 switch (st) { 2204 2205 case AFL_DATA: 2206#ifdef AZT_TEST3 2207 if (st != azt_st_old) { 2208 azt_st_old = st; 2209 printk("---AFL_DATA st:%x\n", st); 2210 } 2211#endif 2212 if (!AztTries--) { 2213 printk 2214 ("aztcd: Read of Block %d Failed, Maybe Audio Disk ? Giving up\n", 2215 azt_next_bn); 2216 if (azt_transfer_is_active) { 2217 AztTries = 0; 2218 break; 2219 } 2220 if (current_valid()) 2221 end_request(CURRENT, 0); 2222 AztTries = 5; 2223 } 2224 azt_state = AZT_S_START; 2225 AztTimeout = READ_TIMEOUT; 2226 loop_ctl = 1; 2227 break; 2228 2229 case AFL_STATUSorDATA: 2230#ifdef AZT_TEST3 2231 if (st != azt_st_old) { 2232 azt_st_old = st; 2233 printk 2234 ("---AFL_STATUSorDATA st:%x\n", 2235 st); 2236 } 2237#endif 2238 break; 2239 2240 default: 2241#ifdef AZT_TEST3 2242 if (st != azt_st_old) { 2243 azt_st_old = st; 2244 printk("---default: st:%x\n", st); 2245 } 2246#endif 2247 AztTries = 5; 2248 if (!current_valid() && azt_buf_in == azt_buf_out) { 2249 azt_state = AZT_S_STOP; 2250 loop_ctl = 1; 2251 break; 2252 } 2253 if (azt_read_count <= 0) 2254 printk 2255 ("aztcd: warning - try to read 0 frames\n"); 2256 while (azt_read_count) { /*??? fast read ahead loop */ 2257 azt_buf_bn[azt_buf_in] = -1; 2258 DTEN_LOW; /*??? unsolved problem, very 2259 seldom we get timeouts 2260 here, don't now the real 2261 reason. With my drive this 2262 sometimes also happens with 2263 Aztech's original driver under 2264 DOS. Is it a hardware bug? 2265 I tried to recover from such 2266 situations here. Zimmermann */ 2267 if (aztTimeOutCount >= AZT_TIMEOUT) { 2268 printk 2269 ("read_count:%d CURRENT->nr_sectors:%ld azt_buf_in:%d\n", 2270 azt_read_count, 2271 CURRENT->nr_sectors, 2272 azt_buf_in); 2273 printk 2274 ("azt_transfer_is_active:%x\n", 2275 azt_transfer_is_active); 2276 azt_read_count = 0; 2277 azt_state = AZT_S_STOP; 2278 loop_ctl = 1; 2279 end_request(CURRENT, 1); /*should we have here (1) or (0)? */ 2280 } else { 2281 if (azt_read_mode == 2282 AZT_MODE_2) { 2283 insb(DATA_PORT, 2284 azt_buf + 2285 CD_FRAMESIZE_RAW 2286 * azt_buf_in, 2287 CD_FRAMESIZE_RAW); 2288 } else { 2289 insb(DATA_PORT, 2290 azt_buf + 2291 CD_FRAMESIZE * 2292 azt_buf_in, 2293 CD_FRAMESIZE); 2294 } 2295 azt_read_count--; 2296#ifdef AZT_TEST3 2297 printk 2298 ("AZT_S_DATA; ---I've read data- read_count: %d\n", 2299 azt_read_count); 2300 printk 2301 ("azt_next_bn:%d azt_buf_in:%d azt_buf_out:%d azt_buf_bn:%d\n", 2302 azt_next_bn, 2303 azt_buf_in, 2304 azt_buf_out, 2305 azt_buf_bn 2306 [azt_buf_in]); 2307#endif 2308 azt_buf_bn[azt_buf_in] = 2309 azt_next_bn++; 2310 if (azt_buf_out == -1) 2311 azt_buf_out = 2312 azt_buf_in; 2313 azt_buf_in = 2314 azt_buf_in + 1 == 2315 AZT_BUF_SIZ ? 0 : 2316 azt_buf_in + 1; 2317 } 2318 } 2319 if (!azt_transfer_is_active) { 2320 while (current_valid()) { 2321 azt_transfer(); 2322 if (CURRENT->nr_sectors == 2323 0) 2324 end_request(CURRENT, 1); 2325 else 2326 break; 2327 } 2328 } 2329 2330 if (current_valid() 2331 && (CURRENT->sector / 4 < azt_next_bn 2332 || CURRENT->sector / 4 > 2333 azt_next_bn + AZT_BUF_SIZ)) { 2334 azt_state = AZT_S_STOP; 2335 loop_ctl = 1; 2336 break; 2337 } 2338 AztTimeout = READ_TIMEOUT; 2339 if (azt_read_count == 0) { 2340 azt_state = AZT_S_STOP; 2341 loop_ctl = 1; 2342 break; 2343 } 2344 break; 2345 } 2346 break; 2347 2348 2349 case AZT_S_STOP: 2350#ifdef AZT_TEST3 2351 if (azt_state != azt_state_old) { 2352 azt_state_old = azt_state; 2353 printk("AZT_S_STOP\n"); 2354 } 2355#endif 2356 if (azt_read_count != 0) 2357 printk("aztcd: discard data=%x frames\n", 2358 azt_read_count); 2359 while (azt_read_count != 0) { 2360 int i; 2361 if (!(inb(STATUS_PORT) & AFL_DATA)) { 2362 if (azt_read_mode == AZT_MODE_2) 2363 for (i = 0; 2364 i < CD_FRAMESIZE_RAW; 2365 i++) 2366 inb(DATA_PORT); 2367 else 2368 for (i = 0; 2369 i < CD_FRAMESIZE; i++) 2370 inb(DATA_PORT); 2371 } 2372 azt_read_count--; 2373 } 2374 if (aztSendCmd(ACMD_GET_STATUS)) 2375 RETURN("azt_poll 5"); 2376 azt_state = AZT_S_STOPPING; 2377 AztTimeout = 1000; 2378 break; 2379 2380 case AZT_S_STOPPING: 2381#ifdef AZT_TEST3 2382 if (azt_state != azt_state_old) { 2383 azt_state_old = azt_state; 2384 printk("AZT_S_STOPPING\n"); 2385 } 2386#endif 2387 2388 if ((st = aztStatus()) == -1 && AztTimeout) 2389 break; 2390 2391 if ((st != -1) 2392 && ((st & AST_DSK_CHG) 2393 || (st & AST_NOT_READY))) { 2394 aztDiskChanged = 1; 2395 aztTocUpToDate = 0; 2396 azt_invalidate_buffers(); 2397 printk 2398 ("aztcd: Disk Changed or Not Ready 4 - Unmount Disk!\n"); 2399 end_request(CURRENT, 0); 2400 } 2401 2402#ifdef AZT_TEST3 2403 printk("CURRENT_VALID %d azt_mode %d\n", 2404 current_valid(), azt_mode); 2405#endif 2406 2407 if (current_valid()) { 2408 if (st != -1) { 2409 if (azt_mode == 1) { 2410 azt_state = AZT_S_READ; 2411 loop_ctl = 1; 2412 skip = 1; 2413 break; 2414 } else { 2415 azt_state = AZT_S_MODE; 2416 loop_ctl = 1; 2417 skip = 1; 2418 break; 2419 } 2420 } else { 2421 azt_state = AZT_S_START; 2422 AztTimeout = 1; 2423 } 2424 } else { 2425 azt_state = AZT_S_IDLE; 2426 return; 2427 } 2428 break; 2429 2430 default: 2431 printk("aztcd: invalid state %d\n", azt_state); 2432 return; 2433 } /* case */ 2434 } /* while */ 2435 2436 2437 if (!AztTimeout--) { 2438 printk("aztcd: timeout in state %d\n", azt_state); 2439 azt_state = AZT_S_STOP; 2440 if (aztSendCmd(ACMD_STOP)) 2441 RETURN("azt_poll 6"); 2442 STEN_LOW_WAIT; 2443 }; 2444 2445 SET_TIMER(azt_poll, HZ / 100); 2446} 2447 2448 2449/*########################################################################### 2450 * Miscellaneous support functions 2451 ########################################################################### 2452*/ 2453static void azt_hsg2msf(long hsg, struct msf *msf) 2454{ 2455 hsg += 150; 2456 msf->min = hsg / 4500; 2457 hsg %= 4500; 2458 msf->sec = hsg / 75; 2459 msf->frame = hsg % 75; 2460#ifdef AZT_DEBUG 2461 if (msf->min >= 70) 2462 printk("aztcd: Error hsg2msf address Minutes\n"); 2463 if (msf->sec >= 60) 2464 printk("aztcd: Error hsg2msf address Seconds\n"); 2465 if (msf->frame >= 75) 2466 printk("aztcd: Error hsg2msf address Frames\n"); 2467#endif 2468 azt_bin2bcd(&msf->min); /* convert to BCD */ 2469 azt_bin2bcd(&msf->sec); 2470 azt_bin2bcd(&msf->frame); 2471} 2472 2473static long azt_msf2hsg(struct msf *mp) 2474{ 2475 return azt_bcd2bin(mp->frame) + azt_bcd2bin(mp->sec) * 75 2476 + azt_bcd2bin(mp->min) * 4500 - CD_MSF_OFFSET; 2477} 2478 2479static void azt_bin2bcd(unsigned char *p) 2480{ 2481 int u, t; 2482 2483 u = *p % 10; 2484 t = *p / 10; 2485 *p = u | (t << 4); 2486} 2487 2488static int azt_bcd2bin(unsigned char bcd) 2489{ 2490 return (bcd >> 4) * 10 + (bcd & 0xF); 2491} 2492 2493MODULE_LICENSE("GPL"); 2494MODULE_ALIAS_BLOCKDEV_MAJOR(AZTECH_CDROM_MAJOR);