1/* -- sjcd.c 2 * 3 * Sanyo CD-ROM device driver implementation, Version 1.6 4 * Copyright (C) 1995 Vadim V. Model 5 * 6 * model@cecmow.enet.dec.com 7 * vadim@rbrf.ru 8 * vadim@ipsun.ras.ru 9 * 10 * 11 * This driver is based on pre-works by Eberhard Moenkeberg (emoenke@gwdg.de); 12 * it was developed under use of mcd.c from Martin Harriss, with help of 13 * Eric van der Maarel (H.T.M.v.d.Maarel@marin.nl). 14 * 15 * It is planned to include these routines into sbpcd.c later - to make 16 * a "mixed use" on one cable possible for all kinds of drives which use 17 * the SoundBlaster/Panasonic style CDROM interface. But today, the 18 * ability to install directly from CDROM is more important than flexibility. 19 * 20 * This program is free software; you can redistribute it and/or modify 21 * it under the terms of the GNU General Public License as published by 22 * the Free Software Foundation; either version 2 of the License, or 23 * (at your option) any later version. 24 * 25 * This program is distributed in the hope that it will be useful, 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * GNU General Public License for more details. 29 * 30 * You should have received a copy of the GNU General Public License 31 * along with this program; if not, write to the Free Software 32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 33 * 34 * History: 35 * 1.1 First public release with kernel version 1.3.7. 36 * Written by Vadim Model. 37 * 1.2 Added detection and configuration of cdrom interface 38 * on ISP16 soundcard. 39 * Allow for command line options: sjcd=<io_base>,<irq>,<dma> 40 * 1.3 Some minor changes to README.sjcd. 41 * 1.4 MSS Sound support!! Listen to a CD through the speakers. 42 * 1.5 Module support and bugfixes. 43 * Tray locking. 44 * 1.6 Removed ISP16 code from this driver. 45 * Allow only to set io base address on command line: sjcd=<io_base> 46 * Changes to Documentation/cdrom/sjcd 47 * Added cleanup after any error in the initialisation. 48 * 1.7 Added code to set the sector size tables to prevent the bug present in 49 * the previous version of this driver. Coded added by Anthony Barbachan 50 * from bugfix tip originally suggested by Alan Cox. 51 * 52 * November 1999 -- Make kernel-parameter implementation work with 2.3.x 53 * Removed init_module & cleanup_module in favor of 54 * module_init & module_exit. 55 * Torben Mathiasen <tmm@image.dk> 56 */ 57 58#define SJCD_VERSION_MAJOR 1 59#define SJCD_VERSION_MINOR 7 60 61#include <linux/module.h> 62#include <linux/errno.h> 63#include <linux/mm.h> 64#include <linux/timer.h> 65#include <linux/fs.h> 66#include <linux/kernel.h> 67#include <linux/cdrom.h> 68#include <linux/ioport.h> 69#include <linux/string.h> 70#include <linux/major.h> 71#include <linux/init.h> 72 73#include <asm/system.h> 74#include <asm/io.h> 75#include <asm/uaccess.h> 76#include <linux/blkdev.h> 77#include "sjcd.h" 78 79static int sjcd_present = 0; 80static struct request_queue *sjcd_queue; 81 82#define MAJOR_NR SANYO_CDROM_MAJOR 83#define QUEUE (sjcd_queue) 84#define CURRENT elv_next_request(sjcd_queue) 85 86#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ 87 88/* 89 * buffer for block size conversion 90 */ 91static char sjcd_buf[2048 * SJCD_BUF_SIZ]; 92static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn; 93static volatile int sjcd_buf_in, sjcd_buf_out = -1; 94 95/* 96 * Status. 97 */ 98static unsigned short sjcd_status_valid = 0; 99static unsigned short sjcd_door_closed; 100static unsigned short sjcd_door_was_open; 101static unsigned short sjcd_media_is_available; 102static unsigned short sjcd_media_is_changed; 103static unsigned short sjcd_toc_uptodate = 0; 104static unsigned short sjcd_command_failed; 105static volatile unsigned char sjcd_completion_status = 0; 106static volatile unsigned char sjcd_completion_error = 0; 107static unsigned short sjcd_command_is_in_progress = 0; 108static unsigned short sjcd_error_reported = 0; 109static DEFINE_SPINLOCK(sjcd_lock); 110 111static int sjcd_open_count; 112 113static int sjcd_audio_status; 114static struct sjcd_play_msf sjcd_playing; 115 116static int sjcd_base = SJCD_BASE_ADDR; 117 118module_param(sjcd_base, int, 0); 119 120static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq); 121 122/* 123 * Data transfer. 124 */ 125static volatile unsigned short sjcd_transfer_is_active = 0; 126 127enum sjcd_transfer_state { 128 SJCD_S_IDLE = 0, 129 SJCD_S_START = 1, 130 SJCD_S_MODE = 2, 131 SJCD_S_READ = 3, 132 SJCD_S_DATA = 4, 133 SJCD_S_STOP = 5, 134 SJCD_S_STOPPING = 6 135}; 136static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE; 137static long sjcd_transfer_timeout = 0; 138static int sjcd_read_count = 0; 139static unsigned char sjcd_mode = 0; 140 141#define SJCD_READ_TIMEOUT 5000 142 143#if defined(SJCD_GATHER_STAT) 144/* 145 * Statistic. 146 */ 147static struct sjcd_stat statistic; 148#endif 149 150/* 151 * Timer. 152 */ 153static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0); 154 155#define SJCD_SET_TIMER( func, tmout ) \ 156 ( sjcd_delay_timer.expires = jiffies+tmout, \ 157 sjcd_delay_timer.function = ( void * )func, \ 158 add_timer( &sjcd_delay_timer ) ) 159 160#define CLEAR_TIMER del_timer( &sjcd_delay_timer ) 161 162/* 163 * Set up device, i.e., use command line data to set 164 * base address. 165 */ 166#ifndef MODULE 167static int __init sjcd_setup(char *str) 168{ 169 int ints[2]; 170 (void) get_options(str, ARRAY_SIZE(ints), ints); 171 if (ints[0] > 0) 172 sjcd_base = ints[1]; 173 174 return 1; 175} 176 177__setup("sjcd=", sjcd_setup); 178 179#endif 180 181/* 182 * Special converters. 183 */ 184static unsigned char bin2bcd(int bin) 185{ 186 int u, v; 187 188 u = bin % 10; 189 v = bin / 10; 190 return (u | (v << 4)); 191} 192 193static int bcd2bin(unsigned char bcd) 194{ 195 return ((bcd >> 4) * 10 + (bcd & 0x0F)); 196} 197 198static long msf2hsg(struct msf *mp) 199{ 200 return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 201 + bcd2bin(mp->min) * 4500 - 150); 202} 203 204static void hsg2msf(long hsg, struct msf *msf) 205{ 206 hsg += 150; 207 msf->min = hsg / 4500; 208 hsg %= 4500; 209 msf->sec = hsg / 75; 210 msf->frame = hsg % 75; 211 msf->min = bin2bcd(msf->min); /* convert to BCD */ 212 msf->sec = bin2bcd(msf->sec); 213 msf->frame = bin2bcd(msf->frame); 214} 215 216/* 217 * Send a command to cdrom. Invalidate status. 218 */ 219static void sjcd_send_cmd(unsigned char cmd) 220{ 221#if defined(SJCD_TRACE) 222 printk("SJCD: send_cmd( 0x%x )\n", cmd); 223#endif 224 outb(cmd, SJCDPORT(0)); 225 sjcd_command_is_in_progress = 1; 226 sjcd_status_valid = 0; 227 sjcd_command_failed = 0; 228} 229 230/* 231 * Send a command with one arg to cdrom. Invalidate status. 232 */ 233static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a) 234{ 235#if defined(SJCD_TRACE) 236 printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a); 237#endif 238 outb(cmd, SJCDPORT(0)); 239 outb(a, SJCDPORT(0)); 240 sjcd_command_is_in_progress = 1; 241 sjcd_status_valid = 0; 242 sjcd_command_failed = 0; 243} 244 245/* 246 * Send a command with four args to cdrom. Invalidate status. 247 */ 248static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a, 249 unsigned char b, unsigned char c, 250 unsigned char d) 251{ 252#if defined(SJCD_TRACE) 253 printk("SJCD: send_4_cmd( 0x%x )\n", cmd); 254#endif 255 outb(cmd, SJCDPORT(0)); 256 outb(a, SJCDPORT(0)); 257 outb(b, SJCDPORT(0)); 258 outb(c, SJCDPORT(0)); 259 outb(d, SJCDPORT(0)); 260 sjcd_command_is_in_progress = 1; 261 sjcd_status_valid = 0; 262 sjcd_command_failed = 0; 263} 264 265/* 266 * Send a play or read command to cdrom. Invalidate Status. 267 */ 268static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms) 269{ 270#if defined(SJCD_TRACE) 271 printk("SJCD: send_long_cmd( 0x%x )\n", cmd); 272#endif 273 outb(cmd, SJCDPORT(0)); 274 outb(pms->start.min, SJCDPORT(0)); 275 outb(pms->start.sec, SJCDPORT(0)); 276 outb(pms->start.frame, SJCDPORT(0)); 277 outb(pms->end.min, SJCDPORT(0)); 278 outb(pms->end.sec, SJCDPORT(0)); 279 outb(pms->end.frame, SJCDPORT(0)); 280 sjcd_command_is_in_progress = 1; 281 sjcd_status_valid = 0; 282 sjcd_command_failed = 0; 283} 284 285/* 286 * Get a value from the data port. Should not block, so we use a little 287 * wait for a while. Returns 0 if OK. 288 */ 289static int sjcd_load_response(void *buf, int len) 290{ 291 unsigned char *resp = (unsigned char *) buf; 292 293 for (; len; --len) { 294 int i; 295 for (i = 200; 296 i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)));); 297 if (i > 0) 298 *resp++ = (unsigned char) inb(SJCDPORT(0)); 299 else 300 break; 301 } 302 return (len); 303} 304 305/* 306 * Load and parse command completion status (drive info byte and maybe error). 307 * Sorry, no error classification yet. 308 */ 309static void sjcd_load_status(void) 310{ 311 sjcd_media_is_changed = 0; 312 sjcd_completion_error = 0; 313 sjcd_completion_status = inb(SJCDPORT(0)); 314 if (sjcd_completion_status & SST_DOOR_OPENED) { 315 sjcd_door_closed = sjcd_media_is_available = 0; 316 } else { 317 sjcd_door_closed = 1; 318 if (sjcd_completion_status & SST_MEDIA_CHANGED) 319 sjcd_media_is_available = sjcd_media_is_changed = 320 1; 321 else if (sjcd_completion_status & 0x0F) { 322 /* 323 * OK, we seem to catch an error ... 324 */ 325 while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))); 326 sjcd_completion_error = inb(SJCDPORT(0)); 327 if ((sjcd_completion_status & 0x08) && 328 (sjcd_completion_error & 0x40)) 329 sjcd_media_is_available = 0; 330 else 331 sjcd_command_failed = 1; 332 } else 333 sjcd_media_is_available = 1; 334 } 335 /* 336 * Ok, status loaded successfully. 337 */ 338 sjcd_status_valid = 1, sjcd_error_reported = 0; 339 sjcd_command_is_in_progress = 0; 340 341 /* 342 * If the disk is changed, the TOC is not valid. 343 */ 344 if (sjcd_media_is_changed) 345 sjcd_toc_uptodate = 0; 346#if defined(SJCD_TRACE) 347 printk("SJCD: status %02x.%02x loaded.\n", 348 (int) sjcd_completion_status, (int) sjcd_completion_error); 349#endif 350} 351 352/* 353 * Read status from cdrom. Check to see if the status is available. 354 */ 355static int sjcd_check_status(void) 356{ 357 /* 358 * Try to load the response from cdrom into buffer. 359 */ 360 if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) { 361 sjcd_load_status(); 362 return (1); 363 } else { 364 /* 365 * No status is available. 366 */ 367 return (0); 368 } 369} 370 371/* 372 * This is just timeout counter, and nothing more. Surprised ? :-) 373 */ 374static volatile long sjcd_status_timeout; 375 376/* 377 * We need about 10 seconds to wait. The longest command takes about 5 seconds 378 * to probe the disk (usually after tray closed or drive reset). Other values 379 * should be thought of for other commands. 380 */ 381#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000 382 383static void sjcd_status_timer(void) 384{ 385 if (sjcd_check_status()) { 386 /* 387 * The command completed and status is loaded, stop waiting. 388 */ 389 wake_up(&sjcd_waitq); 390 } else if (--sjcd_status_timeout <= 0) { 391 /* 392 * We are timed out. 393 */ 394 wake_up(&sjcd_waitq); 395 } else { 396 /* 397 * We have still some time to wait. Try again. 398 */ 399 SJCD_SET_TIMER(sjcd_status_timer, 1); 400 } 401} 402 403/* 404 * Wait for status for 10 sec approx. Returns non-positive when timed out. 405 * Should not be used while reading data CDs. 406 */ 407static int sjcd_wait_for_status(void) 408{ 409 sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT; 410 SJCD_SET_TIMER(sjcd_status_timer, 1); 411 sleep_on(&sjcd_waitq); 412#if defined(SJCD_DIAGNOSTIC) || defined(SJCD_TRACE) 413 if (sjcd_status_timeout <= 0) 414 printk("SJCD: Error Wait For Status.\n"); 415#endif 416 return (sjcd_status_timeout); 417} 418 419static int sjcd_receive_status(void) 420{ 421 int i; 422#if defined(SJCD_TRACE) 423 printk("SJCD: receive_status\n"); 424#endif 425 /* 426 * Wait a bit for status available. 427 */ 428 for (i = 200; i-- && (sjcd_check_status() == 0);); 429 if (i < 0) { 430#if defined(SJCD_TRACE) 431 printk("SJCD: long wait for status\n"); 432#endif 433 if (sjcd_wait_for_status() <= 0) 434 printk("SJCD: Timeout when read status.\n"); 435 else 436 i = 0; 437 } 438 return (i); 439} 440 441/* 442 * Load the status. Issue get status command and wait for status available. 443 */ 444static void sjcd_get_status(void) 445{ 446#if defined(SJCD_TRACE) 447 printk("SJCD: get_status\n"); 448#endif 449 sjcd_send_cmd(SCMD_GET_STATUS); 450 sjcd_receive_status(); 451} 452 453/* 454 * Check the drive if the disk is changed. Should be revised. 455 */ 456static int sjcd_disk_change(struct gendisk *disk) 457{ 458 if (!sjcd_command_is_in_progress) 459 sjcd_get_status(); 460 return (sjcd_status_valid ? sjcd_media_is_changed : 0); 461} 462 463/* 464 * Read the table of contents (TOC) and TOC header if necessary. 465 * We assume that the drive contains no more than 99 toc entries. 466 */ 467static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS]; 468static unsigned char sjcd_first_track_no, sjcd_last_track_no; 469#define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf 470 471static int sjcd_update_toc(void) 472{ 473 struct sjcd_hw_disk_info info; 474 int i; 475#if defined(SJCD_TRACE) 476 printk("SJCD: update toc:\n"); 477#endif 478 /* 479 * check to see if we need to do anything 480 */ 481 if (sjcd_toc_uptodate) 482 return (0); 483 484 /* 485 * Get the TOC start information. 486 */ 487 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK); 488 sjcd_receive_status(); 489 490 if (!sjcd_status_valid) { 491 printk("SJCD: cannot load status.\n"); 492 return (-1); 493 } 494 495 if (!sjcd_media_is_available) { 496 printk("SJCD: no disk in drive\n"); 497 return (-1); 498 } 499 500 if (!sjcd_command_failed) { 501 if (sjcd_load_response(&info, sizeof(info)) != 0) { 502 printk 503 ("SJCD: cannot load response about TOC start.\n"); 504 return (-1); 505 } 506 sjcd_first_track_no = bcd2bin(info.un.track_no); 507 } else { 508 printk("SJCD: get first failed\n"); 509 return (-1); 510 } 511#if defined(SJCD_TRACE) 512 printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no); 513#endif 514 /* 515 * Get the TOC finish information. 516 */ 517 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK); 518 sjcd_receive_status(); 519 520 if (!sjcd_status_valid) { 521 printk("SJCD: cannot load status.\n"); 522 return (-1); 523 } 524 525 if (!sjcd_media_is_available) { 526 printk("SJCD: no disk in drive\n"); 527 return (-1); 528 } 529 530 if (!sjcd_command_failed) { 531 if (sjcd_load_response(&info, sizeof(info)) != 0) { 532 printk 533 ("SJCD: cannot load response about TOC finish.\n"); 534 return (-1); 535 } 536 sjcd_last_track_no = bcd2bin(info.un.track_no); 537 } else { 538 printk("SJCD: get last failed\n"); 539 return (-1); 540 } 541#if defined(SJCD_TRACE) 542 printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no); 543#endif 544 for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) { 545 /* 546 * Get the first track information. 547 */ 548 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i)); 549 sjcd_receive_status(); 550 551 if (!sjcd_status_valid) { 552 printk("SJCD: cannot load status.\n"); 553 return (-1); 554 } 555 556 if (!sjcd_media_is_available) { 557 printk("SJCD: no disk in drive\n"); 558 return (-1); 559 } 560 561 if (!sjcd_command_failed) { 562 if (sjcd_load_response(&sjcd_table_of_contents[i], 563 sizeof(struct 564 sjcd_hw_disk_info)) 565 != 0) { 566 printk 567 ("SJCD: cannot load info for %d track\n", 568 i); 569 return (-1); 570 } 571 } else { 572 printk("SJCD: get info %d failed\n", i); 573 return (-1); 574 } 575 } 576 577 /* 578 * Get the disk length info. 579 */ 580 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE); 581 sjcd_receive_status(); 582 583 if (!sjcd_status_valid) { 584 printk("SJCD: cannot load status.\n"); 585 return (-1); 586 } 587 588 if (!sjcd_media_is_available) { 589 printk("SJCD: no disk in drive\n"); 590 return (-1); 591 } 592 593 if (!sjcd_command_failed) { 594 if (sjcd_load_response(&info, sizeof(info)) != 0) { 595 printk 596 ("SJCD: cannot load response about disk size.\n"); 597 return (-1); 598 } 599 sjcd_disk_length.min = info.un.track_msf.min; 600 sjcd_disk_length.sec = info.un.track_msf.sec; 601 sjcd_disk_length.frame = info.un.track_msf.frame; 602 } else { 603 printk("SJCD: get size failed\n"); 604 return (1); 605 } 606#if defined(SJCD_TRACE) 607 printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, 608 sjcd_disk_length.sec, sjcd_disk_length.frame); 609#endif 610 return (0); 611} 612 613/* 614 * Load subchannel information. 615 */ 616static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp) 617{ 618 int s; 619#if defined(SJCD_TRACE) 620 printk("SJCD: load sub q\n"); 621#endif 622 sjcd_send_cmd(SCMD_GET_QINFO); 623 s = sjcd_receive_status(); 624 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) { 625 sjcd_send_cmd(0xF2); 626 s = sjcd_receive_status(); 627 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) 628 return (-1); 629 sjcd_send_cmd(SCMD_GET_QINFO); 630 s = sjcd_receive_status(); 631 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) 632 return (-1); 633 } 634 if (sjcd_media_is_available) 635 if (sjcd_load_response(qp, sizeof(*qp)) == 0) 636 return (0); 637 return (-1); 638} 639 640/* 641 * Start playing from the specified position. 642 */ 643static int sjcd_play(struct sjcd_play_msf *mp) 644{ 645 struct sjcd_play_msf msf; 646 647 /* 648 * Turn the device to play mode. 649 */ 650 sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY); 651 if (sjcd_receive_status() < 0) 652 return (-1); 653 654 /* 655 * Seek to the starting point. 656 */ 657 msf.start = mp->start; 658 msf.end.min = msf.end.sec = msf.end.frame = 0x00; 659 sjcd_send_6_cmd(SCMD_SEEK, &msf); 660 if (sjcd_receive_status() < 0) 661 return (-1); 662 663 /* 664 * Start playing. 665 */ 666 sjcd_send_6_cmd(SCMD_PLAY, mp); 667 return (sjcd_receive_status()); 668} 669 670/* 671 * Tray control functions. 672 */ 673static int sjcd_tray_close(void) 674{ 675#if defined(SJCD_TRACE) 676 printk("SJCD: tray_close\n"); 677#endif 678 sjcd_send_cmd(SCMD_CLOSE_TRAY); 679 return (sjcd_receive_status()); 680} 681 682static int sjcd_tray_lock(void) 683{ 684#if defined(SJCD_TRACE) 685 printk("SJCD: tray_lock\n"); 686#endif 687 sjcd_send_cmd(SCMD_LOCK_TRAY); 688 return (sjcd_receive_status()); 689} 690 691static int sjcd_tray_unlock(void) 692{ 693#if defined(SJCD_TRACE) 694 printk("SJCD: tray_unlock\n"); 695#endif 696 sjcd_send_cmd(SCMD_UNLOCK_TRAY); 697 return (sjcd_receive_status()); 698} 699 700static int sjcd_tray_open(void) 701{ 702#if defined(SJCD_TRACE) 703 printk("SJCD: tray_open\n"); 704#endif 705 sjcd_send_cmd(SCMD_EJECT_TRAY); 706 return (sjcd_receive_status()); 707} 708 709/* 710 * Do some user commands. 711 */ 712static int sjcd_ioctl(struct inode *ip, struct file *fp, 713 unsigned int cmd, unsigned long arg) 714{ 715 void __user *argp = (void __user *)arg; 716#if defined(SJCD_TRACE) 717 printk("SJCD:ioctl\n"); 718#endif 719 720 sjcd_get_status(); 721 if (!sjcd_status_valid) 722 return (-EIO); 723 if (sjcd_update_toc() < 0) 724 return (-EIO); 725 726 switch (cmd) { 727 case CDROMSTART:{ 728#if defined(SJCD_TRACE) 729 printk("SJCD: ioctl: start\n"); 730#endif 731 return (0); 732 } 733 734 case CDROMSTOP:{ 735#if defined(SJCD_TRACE) 736 printk("SJCD: ioctl: stop\n"); 737#endif 738 sjcd_send_cmd(SCMD_PAUSE); 739 (void) sjcd_receive_status(); 740 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 741 return (0); 742 } 743 744 case CDROMPAUSE:{ 745 struct sjcd_hw_qinfo q_info; 746#if defined(SJCD_TRACE) 747 printk("SJCD: ioctl: pause\n"); 748#endif 749 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 750 sjcd_send_cmd(SCMD_PAUSE); 751 (void) sjcd_receive_status(); 752 if (sjcd_get_q_info(&q_info) < 0) { 753 sjcd_audio_status = 754 CDROM_AUDIO_NO_STATUS; 755 } else { 756 sjcd_audio_status = 757 CDROM_AUDIO_PAUSED; 758 sjcd_playing.start = q_info.abs; 759 } 760 return (0); 761 } else 762 return (-EINVAL); 763 } 764 765 case CDROMRESUME:{ 766#if defined(SJCD_TRACE) 767 printk("SJCD: ioctl: resume\n"); 768#endif 769 if (sjcd_audio_status == CDROM_AUDIO_PAUSED) { 770 /* 771 * continue play starting at saved location 772 */ 773 if (sjcd_play(&sjcd_playing) < 0) { 774 sjcd_audio_status = 775 CDROM_AUDIO_ERROR; 776 return (-EIO); 777 } else { 778 sjcd_audio_status = 779 CDROM_AUDIO_PLAY; 780 return (0); 781 } 782 } else 783 return (-EINVAL); 784 } 785 786 case CDROMPLAYTRKIND:{ 787 struct cdrom_ti ti; 788 int s = -EFAULT; 789#if defined(SJCD_TRACE) 790 printk("SJCD: ioctl: playtrkind\n"); 791#endif 792 if (!copy_from_user(&ti, argp, sizeof(ti))) { 793 s = 0; 794 if (ti.cdti_trk0 < sjcd_first_track_no) 795 return (-EINVAL); 796 if (ti.cdti_trk1 > sjcd_last_track_no) 797 ti.cdti_trk1 = sjcd_last_track_no; 798 if (ti.cdti_trk0 > ti.cdti_trk1) 799 return (-EINVAL); 800 801 sjcd_playing.start = 802 sjcd_table_of_contents[ti.cdti_trk0]. 803 un.track_msf; 804 sjcd_playing.end = 805 (ti.cdti_trk1 < 806 sjcd_last_track_no) ? 807 sjcd_table_of_contents[ti.cdti_trk1 + 808 1].un. 809 track_msf : sjcd_table_of_contents[0]. 810 un.track_msf; 811 812 if (sjcd_play(&sjcd_playing) < 0) { 813 sjcd_audio_status = 814 CDROM_AUDIO_ERROR; 815 return (-EIO); 816 } else 817 sjcd_audio_status = 818 CDROM_AUDIO_PLAY; 819 } 820 return (s); 821 } 822 823 case CDROMPLAYMSF:{ 824 struct cdrom_msf sjcd_msf; 825 int s; 826#if defined(SJCD_TRACE) 827 printk("SJCD: ioctl: playmsf\n"); 828#endif 829 if ((s = 830 access_ok(VERIFY_READ, argp, sizeof(sjcd_msf)) 831 ? 0 : -EFAULT) == 0) { 832 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 833 sjcd_send_cmd(SCMD_PAUSE); 834 (void) sjcd_receive_status(); 835 sjcd_audio_status = 836 CDROM_AUDIO_NO_STATUS; 837 } 838 839 if (copy_from_user(&sjcd_msf, argp, 840 sizeof(sjcd_msf))) 841 return (-EFAULT); 842 843 sjcd_playing.start.min = 844 bin2bcd(sjcd_msf.cdmsf_min0); 845 sjcd_playing.start.sec = 846 bin2bcd(sjcd_msf.cdmsf_sec0); 847 sjcd_playing.start.frame = 848 bin2bcd(sjcd_msf.cdmsf_frame0); 849 sjcd_playing.end.min = 850 bin2bcd(sjcd_msf.cdmsf_min1); 851 sjcd_playing.end.sec = 852 bin2bcd(sjcd_msf.cdmsf_sec1); 853 sjcd_playing.end.frame = 854 bin2bcd(sjcd_msf.cdmsf_frame1); 855 856 if (sjcd_play(&sjcd_playing) < 0) { 857 sjcd_audio_status = 858 CDROM_AUDIO_ERROR; 859 return (-EIO); 860 } else 861 sjcd_audio_status = 862 CDROM_AUDIO_PLAY; 863 } 864 return (s); 865 } 866 867 case CDROMREADTOCHDR:{ 868 struct cdrom_tochdr toc_header; 869#if defined(SJCD_TRACE) 870 printk("SJCD: ioctl: readtocheader\n"); 871#endif 872 toc_header.cdth_trk0 = sjcd_first_track_no; 873 toc_header.cdth_trk1 = sjcd_last_track_no; 874 if (copy_to_user(argp, &toc_header, 875 sizeof(toc_header))) 876 return -EFAULT; 877 return 0; 878 } 879 880 case CDROMREADTOCENTRY:{ 881 struct cdrom_tocentry toc_entry; 882 int s; 883#if defined(SJCD_TRACE) 884 printk("SJCD: ioctl: readtocentry\n"); 885#endif 886 if ((s = 887 access_ok(VERIFY_WRITE, argp, sizeof(toc_entry)) 888 ? 0 : -EFAULT) == 0) { 889 struct sjcd_hw_disk_info *tp; 890 891 if (copy_from_user(&toc_entry, argp, 892 sizeof(toc_entry))) 893 return (-EFAULT); 894 if (toc_entry.cdte_track == CDROM_LEADOUT) 895 tp = &sjcd_table_of_contents[0]; 896 else if (toc_entry.cdte_track < 897 sjcd_first_track_no) 898 return (-EINVAL); 899 else if (toc_entry.cdte_track > 900 sjcd_last_track_no) 901 return (-EINVAL); 902 else 903 tp = &sjcd_table_of_contents 904 [toc_entry.cdte_track]; 905 906 toc_entry.cdte_adr = 907 tp->track_control & 0x0F; 908 toc_entry.cdte_ctrl = 909 tp->track_control >> 4; 910 911 switch (toc_entry.cdte_format) { 912 case CDROM_LBA: 913 toc_entry.cdte_addr.lba = 914 msf2hsg(&(tp->un.track_msf)); 915 break; 916 case CDROM_MSF: 917 toc_entry.cdte_addr.msf.minute = 918 bcd2bin(tp->un.track_msf.min); 919 toc_entry.cdte_addr.msf.second = 920 bcd2bin(tp->un.track_msf.sec); 921 toc_entry.cdte_addr.msf.frame = 922 bcd2bin(tp->un.track_msf. 923 frame); 924 break; 925 default: 926 return (-EINVAL); 927 } 928 if (copy_to_user(argp, &toc_entry, 929 sizeof(toc_entry))) 930 s = -EFAULT; 931 } 932 return (s); 933 } 934 935 case CDROMSUBCHNL:{ 936 struct cdrom_subchnl subchnl; 937 int s; 938#if defined(SJCD_TRACE) 939 printk("SJCD: ioctl: subchnl\n"); 940#endif 941 if ((s = 942 access_ok(VERIFY_WRITE, argp, sizeof(subchnl)) 943 ? 0 : -EFAULT) == 0) { 944 struct sjcd_hw_qinfo q_info; 945 946 if (copy_from_user(&subchnl, argp, 947 sizeof(subchnl))) 948 return (-EFAULT); 949 950 if (sjcd_get_q_info(&q_info) < 0) 951 return (-EIO); 952 953 subchnl.cdsc_audiostatus = 954 sjcd_audio_status; 955 subchnl.cdsc_adr = 956 q_info.track_control & 0x0F; 957 subchnl.cdsc_ctrl = 958 q_info.track_control >> 4; 959 subchnl.cdsc_trk = 960 bcd2bin(q_info.track_no); 961 subchnl.cdsc_ind = bcd2bin(q_info.x); 962 963 switch (subchnl.cdsc_format) { 964 case CDROM_LBA: 965 subchnl.cdsc_absaddr.lba = 966 msf2hsg(&(q_info.abs)); 967 subchnl.cdsc_reladdr.lba = 968 msf2hsg(&(q_info.rel)); 969 break; 970 case CDROM_MSF: 971 subchnl.cdsc_absaddr.msf.minute = 972 bcd2bin(q_info.abs.min); 973 subchnl.cdsc_absaddr.msf.second = 974 bcd2bin(q_info.abs.sec); 975 subchnl.cdsc_absaddr.msf.frame = 976 bcd2bin(q_info.abs.frame); 977 subchnl.cdsc_reladdr.msf.minute = 978 bcd2bin(q_info.rel.min); 979 subchnl.cdsc_reladdr.msf.second = 980 bcd2bin(q_info.rel.sec); 981 subchnl.cdsc_reladdr.msf.frame = 982 bcd2bin(q_info.rel.frame); 983 break; 984 default: 985 return (-EINVAL); 986 } 987 if (copy_to_user(argp, &subchnl, 988 sizeof(subchnl))) 989 s = -EFAULT; 990 } 991 return (s); 992 } 993 994 case CDROMVOLCTRL:{ 995 struct cdrom_volctrl vol_ctrl; 996 int s; 997#if defined(SJCD_TRACE) 998 printk("SJCD: ioctl: volctrl\n"); 999#endif 1000 if ((s = 1001 access_ok(VERIFY_READ, argp, sizeof(vol_ctrl)) 1002 ? 0 : -EFAULT) == 0) { 1003 unsigned char dummy[4]; 1004 1005 if (copy_from_user(&vol_ctrl, argp, 1006 sizeof(vol_ctrl))) 1007 return (-EFAULT); 1008 sjcd_send_4_cmd(SCMD_SET_VOLUME, 1009 vol_ctrl.channel0, 0xFF, 1010 vol_ctrl.channel1, 0xFF); 1011 if (sjcd_receive_status() < 0) 1012 return (-EIO); 1013 (void) sjcd_load_response(dummy, 4); 1014 } 1015 return (s); 1016 } 1017 1018 case CDROMEJECT:{ 1019#if defined(SJCD_TRACE) 1020 printk("SJCD: ioctl: eject\n"); 1021#endif 1022 if (!sjcd_command_is_in_progress) { 1023 sjcd_tray_unlock(); 1024 sjcd_send_cmd(SCMD_EJECT_TRAY); 1025 (void) sjcd_receive_status(); 1026 } 1027 return (0); 1028 } 1029 1030#if defined(SJCD_GATHER_STAT) 1031 case 0xABCD:{ 1032#if defined(SJCD_TRACE) 1033 printk("SJCD: ioctl: statistic\n"); 1034#endif 1035 if (copy_to_user(argp, &statistic, sizeof(statistic))) 1036 return -EFAULT; 1037 return 0; 1038 } 1039#endif 1040 1041 default: 1042 return (-EINVAL); 1043 } 1044} 1045 1046/* 1047 * Invalidate internal buffers of the driver. 1048 */ 1049static void sjcd_invalidate_buffers(void) 1050{ 1051 int i; 1052 for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1); 1053 sjcd_buf_out = -1; 1054} 1055 1056/* 1057 * Take care of the different block sizes between cdrom and Linux. 1058 * When Linux gets variable block sizes this will probably go away. 1059 */ 1060 1061static int current_valid(void) 1062{ 1063 return CURRENT && 1064 CURRENT->cmd == READ && 1065 CURRENT->sector != -1; 1066} 1067 1068static void sjcd_transfer(void) 1069{ 1070#if defined(SJCD_TRACE) 1071 printk("SJCD: transfer:\n"); 1072#endif 1073 if (current_valid()) { 1074 while (CURRENT->nr_sectors) { 1075 int i, bn = CURRENT->sector / 4; 1076 for (i = 0; 1077 i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn; 1078 i++); 1079 if (i < SJCD_BUF_SIZ) { 1080 int offs = 1081 (i * 4 + (CURRENT->sector & 3)) * 512; 1082 int nr_sectors = 4 - (CURRENT->sector & 3); 1083 if (sjcd_buf_out != i) { 1084 sjcd_buf_out = i; 1085 if (sjcd_buf_bn[i] != bn) { 1086 sjcd_buf_out = -1; 1087 continue; 1088 } 1089 } 1090 if (nr_sectors > CURRENT->nr_sectors) 1091 nr_sectors = CURRENT->nr_sectors; 1092#if defined(SJCD_TRACE) 1093 printk("SJCD: copy out\n"); 1094#endif 1095 memcpy(CURRENT->buffer, sjcd_buf + offs, 1096 nr_sectors * 512); 1097 CURRENT->nr_sectors -= nr_sectors; 1098 CURRENT->sector += nr_sectors; 1099 CURRENT->buffer += nr_sectors * 512; 1100 } else { 1101 sjcd_buf_out = -1; 1102 break; 1103 } 1104 } 1105 } 1106#if defined(SJCD_TRACE) 1107 printk("SJCD: transfer: done\n"); 1108#endif 1109} 1110 1111static void sjcd_poll(void) 1112{ 1113#if defined(SJCD_GATHER_STAT) 1114 /* 1115 * Update total number of ticks. 1116 */ 1117 statistic.ticks++; 1118 statistic.tticks[sjcd_transfer_state]++; 1119#endif 1120 1121 ReSwitch:switch (sjcd_transfer_state) { 1122 1123 case SJCD_S_IDLE:{ 1124#if defined(SJCD_GATHER_STAT) 1125 statistic.idle_ticks++; 1126#endif 1127#if defined(SJCD_TRACE) 1128 printk("SJCD_S_IDLE\n"); 1129#endif 1130 return; 1131 } 1132 1133 case SJCD_S_START:{ 1134#if defined(SJCD_GATHER_STAT) 1135 statistic.start_ticks++; 1136#endif 1137 sjcd_send_cmd(SCMD_GET_STATUS); 1138 sjcd_transfer_state = 1139 sjcd_mode == 1140 SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; 1141 sjcd_transfer_timeout = 500; 1142#if defined(SJCD_TRACE) 1143 printk("SJCD_S_START: goto SJCD_S_%s mode\n", 1144 sjcd_transfer_state == 1145 SJCD_S_READ ? "READ" : "MODE"); 1146#endif 1147 break; 1148 } 1149 1150 case SJCD_S_MODE:{ 1151 if (sjcd_check_status()) { 1152 /* 1153 * Previous command is completed. 1154 */ 1155 if (!sjcd_status_valid 1156 || sjcd_command_failed) { 1157#if defined(SJCD_TRACE) 1158 printk 1159 ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1160#endif 1161 sjcd_transfer_state = SJCD_S_STOP; 1162 goto ReSwitch; 1163 } 1164 1165 sjcd_mode = 0; /* unknown mode; should not be valid when failed */ 1166 sjcd_send_1_cmd(SCMD_SET_MODE, 1167 SCMD_MODE_COOKED); 1168 sjcd_transfer_state = SJCD_S_READ; 1169 sjcd_transfer_timeout = 1000; 1170#if defined(SJCD_TRACE) 1171 printk 1172 ("SJCD_S_MODE: goto SJCD_S_READ mode\n"); 1173#endif 1174 } 1175#if defined(SJCD_GATHER_STAT) 1176 else 1177 statistic.mode_ticks++; 1178#endif 1179 break; 1180 } 1181 1182 case SJCD_S_READ:{ 1183 if (sjcd_status_valid ? 1 : sjcd_check_status()) { 1184 /* 1185 * Previous command is completed. 1186 */ 1187 if (!sjcd_status_valid 1188 || sjcd_command_failed) { 1189#if defined(SJCD_TRACE) 1190 printk 1191 ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1192#endif 1193 sjcd_transfer_state = SJCD_S_STOP; 1194 goto ReSwitch; 1195 } 1196 if (!sjcd_media_is_available) { 1197#if defined(SJCD_TRACE) 1198 printk 1199 ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n"); 1200#endif 1201 sjcd_transfer_state = SJCD_S_STOP; 1202 goto ReSwitch; 1203 } 1204 if (sjcd_mode != SCMD_MODE_COOKED) { 1205 /* 1206 * We seem to come from set mode. So discard one byte of result. 1207 */ 1208 if (sjcd_load_response 1209 (&sjcd_mode, 1) != 0) { 1210#if defined(SJCD_TRACE) 1211 printk 1212 ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n"); 1213#endif 1214 sjcd_transfer_state = 1215 SJCD_S_STOP; 1216 goto ReSwitch; 1217 } 1218 if (sjcd_mode != SCMD_MODE_COOKED) { 1219#if defined(SJCD_TRACE) 1220 printk 1221 ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n"); 1222#endif 1223 sjcd_transfer_state = 1224 SJCD_S_STOP; 1225 goto ReSwitch; 1226 } 1227 } 1228 1229 if (current_valid()) { 1230 struct sjcd_play_msf msf; 1231 1232 sjcd_next_bn = CURRENT->sector / 4; 1233 hsg2msf(sjcd_next_bn, &msf.start); 1234 msf.end.min = 0; 1235 msf.end.sec = 0; 1236 msf.end.frame = sjcd_read_count = 1237 SJCD_BUF_SIZ; 1238#if defined(SJCD_TRACE) 1239 printk 1240 ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", 1241 msf.start.min, msf.start.sec, 1242 msf.start.frame, msf.end.min, 1243 msf.end.sec, msf.end.frame); 1244 printk 1245 ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", 1246 sjcd_next_bn, sjcd_buf_in, 1247 sjcd_buf_out, 1248 sjcd_buf_bn[sjcd_buf_in]); 1249#endif 1250 sjcd_send_6_cmd(SCMD_DATA_READ, 1251 &msf); 1252 sjcd_transfer_state = SJCD_S_DATA; 1253 sjcd_transfer_timeout = 500; 1254#if defined(SJCD_TRACE) 1255 printk 1256 ("SJCD_S_READ: go to SJCD_S_DATA mode\n"); 1257#endif 1258 } else { 1259#if defined(SJCD_TRACE) 1260 printk 1261 ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n"); 1262#endif 1263 sjcd_transfer_state = SJCD_S_STOP; 1264 goto ReSwitch; 1265 } 1266 } 1267#if defined(SJCD_GATHER_STAT) 1268 else 1269 statistic.read_ticks++; 1270#endif 1271 break; 1272 } 1273 1274 case SJCD_S_DATA:{ 1275 unsigned char stat; 1276 1277 sjcd_s_data:stat = 1278 inb(SJCDPORT 1279 (1)); 1280#if defined(SJCD_TRACE) 1281 printk("SJCD_S_DATA: status = 0x%02x\n", stat); 1282#endif 1283 if (SJCD_STATUS_AVAILABLE(stat)) { 1284 /* 1285 * No data is waiting for us in the drive buffer. Status of operation 1286 * completion is available. Read and parse it. 1287 */ 1288 sjcd_load_status(); 1289 1290 if (!sjcd_status_valid 1291 || sjcd_command_failed) { 1292#if defined(SJCD_TRACE) 1293 printk 1294 ("SJCD: read block %d failed, maybe audio disk? Giving up\n", 1295 sjcd_next_bn); 1296#endif 1297 if (current_valid()) 1298 end_request(CURRENT, 0); 1299#if defined(SJCD_TRACE) 1300 printk 1301 ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n"); 1302#endif 1303 sjcd_transfer_state = SJCD_S_STOP; 1304 goto ReSwitch; 1305 } 1306 1307 if (!sjcd_media_is_available) { 1308 printk 1309 ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); 1310 sjcd_transfer_state = SJCD_S_STOP; 1311 goto ReSwitch; 1312 } 1313 1314 sjcd_transfer_state = SJCD_S_READ; 1315 goto ReSwitch; 1316 } else if (SJCD_DATA_AVAILABLE(stat)) { 1317 /* 1318 * One frame is read into device buffer. We must copy it to our memory. 1319 * Otherwise cdrom hangs up. Check to see if we have something to copy 1320 * to. 1321 */ 1322 if (!current_valid() 1323 && sjcd_buf_in == sjcd_buf_out) { 1324#if defined(SJCD_TRACE) 1325 printk 1326 ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); 1327 printk 1328 (" ... all the date would be discarded\n"); 1329#endif 1330 sjcd_transfer_state = SJCD_S_STOP; 1331 goto ReSwitch; 1332 } 1333 1334 /* 1335 * Everything seems to be OK. Just read the frame and recalculate 1336 * indices. 1337 */ 1338 sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ 1339 insb(SJCDPORT(2), 1340 sjcd_buf + 2048 * sjcd_buf_in, 2048); 1341#if defined(SJCD_TRACE) 1342 printk 1343 ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", 1344 sjcd_next_bn, sjcd_buf_in, 1345 sjcd_buf_out, 1346 sjcd_buf_bn[sjcd_buf_in]); 1347#endif 1348 sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; 1349 if (sjcd_buf_out == -1) 1350 sjcd_buf_out = sjcd_buf_in; 1351 if (++sjcd_buf_in == SJCD_BUF_SIZ) 1352 sjcd_buf_in = 0; 1353 1354 /* 1355 * Only one frame is ready at time. So we should turn over to wait for 1356 * another frame. If we need that, of course. 1357 */ 1358 if (--sjcd_read_count == 0) { 1359 /* 1360 * OK, request seems to be precessed. Continue transferring... 1361 */ 1362 if (!sjcd_transfer_is_active) { 1363 while (current_valid()) { 1364 /* 1365 * Continue transferring. 1366 */ 1367 sjcd_transfer(); 1368 if (CURRENT-> 1369 nr_sectors == 1370 0) 1371 end_request 1372 (CURRENT, 1); 1373 else 1374 break; 1375 } 1376 } 1377 if (current_valid() && 1378 (CURRENT->sector / 4 < 1379 sjcd_next_bn 1380 || CURRENT->sector / 4 > 1381 sjcd_next_bn + 1382 SJCD_BUF_SIZ)) { 1383#if defined(SJCD_TRACE) 1384 printk 1385 ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n"); 1386#endif 1387 sjcd_transfer_state = 1388 SJCD_S_STOP; 1389 goto ReSwitch; 1390 } 1391 } 1392 /* 1393 * Now we should turn around rather than wait for while. 1394 */ 1395 goto sjcd_s_data; 1396 } 1397#if defined(SJCD_GATHER_STAT) 1398 else 1399 statistic.data_ticks++; 1400#endif 1401 break; 1402 } 1403 1404 case SJCD_S_STOP:{ 1405 sjcd_read_count = 0; 1406 sjcd_send_cmd(SCMD_STOP); 1407 sjcd_transfer_state = SJCD_S_STOPPING; 1408 sjcd_transfer_timeout = 500; 1409#if defined(SJCD_GATHER_STAT) 1410 statistic.stop_ticks++; 1411#endif 1412 break; 1413 } 1414 1415 case SJCD_S_STOPPING:{ 1416 unsigned char stat; 1417 1418 stat = inb(SJCDPORT(1)); 1419#if defined(SJCD_TRACE) 1420 printk("SJCD_S_STOP: status = 0x%02x\n", stat); 1421#endif 1422 if (SJCD_DATA_AVAILABLE(stat)) { 1423 int i; 1424#if defined(SJCD_TRACE) 1425 printk("SJCD_S_STOP: discard data\n"); 1426#endif 1427 /* 1428 * Discard all the data from the pipe. Foolish method. 1429 */ 1430 for (i = 2048; i--; 1431 (void) inb(SJCDPORT(2))); 1432 sjcd_transfer_timeout = 500; 1433 } else if (SJCD_STATUS_AVAILABLE(stat)) { 1434 sjcd_load_status(); 1435 if (sjcd_status_valid 1436 && sjcd_media_is_changed) { 1437 sjcd_toc_uptodate = 0; 1438 sjcd_invalidate_buffers(); 1439 } 1440 if (current_valid()) { 1441 if (sjcd_status_valid) 1442 sjcd_transfer_state = 1443 SJCD_S_READ; 1444 else 1445 sjcd_transfer_state = 1446 SJCD_S_START; 1447 } else 1448 sjcd_transfer_state = SJCD_S_IDLE; 1449 goto ReSwitch; 1450 } 1451#if defined(SJCD_GATHER_STAT) 1452 else 1453 statistic.stopping_ticks++; 1454#endif 1455 break; 1456 } 1457 1458 default: 1459 printk("SJCD: poll: invalid state %d\n", 1460 sjcd_transfer_state); 1461 return; 1462 } 1463 1464 if (--sjcd_transfer_timeout == 0) { 1465 printk("SJCD: timeout in state %d\n", sjcd_transfer_state); 1466 while (current_valid()) 1467 end_request(CURRENT, 0); 1468 sjcd_send_cmd(SCMD_STOP); 1469 sjcd_transfer_state = SJCD_S_IDLE; 1470 goto ReSwitch; 1471 } 1472 1473 /* 1474 * Get back in some time. 1 should be replaced with count variable to 1475 * avoid unnecessary testings. 1476 */ 1477 SJCD_SET_TIMER(sjcd_poll, 1); 1478} 1479 1480static void do_sjcd_request(request_queue_t * q) 1481{ 1482#if defined(SJCD_TRACE) 1483 printk("SJCD: do_sjcd_request(%ld+%ld)\n", 1484 CURRENT->sector, CURRENT->nr_sectors); 1485#endif 1486 sjcd_transfer_is_active = 1; 1487 while (current_valid()) { 1488 sjcd_transfer(); 1489 if (CURRENT->nr_sectors == 0) 1490 end_request(CURRENT, 1); 1491 else { 1492 sjcd_buf_out = -1; /* Want to read a block not in buffer */ 1493 if (sjcd_transfer_state == SJCD_S_IDLE) { 1494 if (!sjcd_toc_uptodate) { 1495 if (sjcd_update_toc() < 0) { 1496 printk 1497 ("SJCD: transfer: discard\n"); 1498 while (current_valid()) 1499 end_request(CURRENT, 0); 1500 break; 1501 } 1502 } 1503 sjcd_transfer_state = SJCD_S_START; 1504 SJCD_SET_TIMER(sjcd_poll, HZ / 100); 1505 } 1506 break; 1507 } 1508 } 1509 sjcd_transfer_is_active = 0; 1510#if defined(SJCD_TRACE) 1511 printk 1512 ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", 1513 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, 1514 sjcd_buf_bn[sjcd_buf_in]); 1515 printk("do_sjcd_request ends\n"); 1516#endif 1517} 1518 1519/* 1520 * Open the device special file. Check disk is in. 1521 */ 1522static int sjcd_open(struct inode *ip, struct file *fp) 1523{ 1524 /* 1525 * Check the presence of device. 1526 */ 1527 if (!sjcd_present) 1528 return (-ENXIO); 1529 1530 /* 1531 * Only read operations are allowed. Really? (:-) 1532 */ 1533 if (fp->f_mode & 2) 1534 return (-EROFS); 1535 1536 if (sjcd_open_count == 0) { 1537 int s, sjcd_open_tries; 1538/* We don't know that, do we? */ 1539/* 1540 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 1541*/ 1542 sjcd_mode = 0; 1543 sjcd_door_was_open = 0; 1544 sjcd_transfer_state = SJCD_S_IDLE; 1545 sjcd_invalidate_buffers(); 1546 sjcd_status_valid = 0; 1547 1548 /* 1549 * Strict status checking. 1550 */ 1551 for (sjcd_open_tries = 4; --sjcd_open_tries;) { 1552 if (!sjcd_status_valid) 1553 sjcd_get_status(); 1554 if (!sjcd_status_valid) { 1555#if defined(SJCD_DIAGNOSTIC) 1556 printk 1557 ("SJCD: open: timed out when check status.\n"); 1558#endif 1559 goto err_out; 1560 } else if (!sjcd_media_is_available) { 1561#if defined(SJCD_DIAGNOSTIC) 1562 printk("SJCD: open: no disk in drive\n"); 1563#endif 1564 if (!sjcd_door_closed) { 1565 sjcd_door_was_open = 1; 1566#if defined(SJCD_TRACE) 1567 printk 1568 ("SJCD: open: close the tray\n"); 1569#endif 1570 s = sjcd_tray_close(); 1571 if (s < 0 || !sjcd_status_valid 1572 || sjcd_command_failed) { 1573#if defined(SJCD_DIAGNOSTIC) 1574 printk 1575 ("SJCD: open: tray close attempt failed\n"); 1576#endif 1577 goto err_out; 1578 } 1579 continue; 1580 } else 1581 goto err_out; 1582 } 1583 break; 1584 } 1585 s = sjcd_tray_lock(); 1586 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1587#if defined(SJCD_DIAGNOSTIC) 1588 printk("SJCD: open: tray lock attempt failed\n"); 1589#endif 1590 goto err_out; 1591 } 1592#if defined(SJCD_TRACE) 1593 printk("SJCD: open: done\n"); 1594#endif 1595 } 1596 1597 ++sjcd_open_count; 1598 return (0); 1599 1600 err_out: 1601 return (-EIO); 1602} 1603 1604/* 1605 * On close, we flush all sjcd blocks from the buffer cache. 1606 */ 1607static int sjcd_release(struct inode *inode, struct file *file) 1608{ 1609 int s; 1610 1611#if defined(SJCD_TRACE) 1612 printk("SJCD: release\n"); 1613#endif 1614 if (--sjcd_open_count == 0) { 1615 sjcd_invalidate_buffers(); 1616 s = sjcd_tray_unlock(); 1617 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1618#if defined(SJCD_DIAGNOSTIC) 1619 printk 1620 ("SJCD: release: tray unlock attempt failed.\n"); 1621#endif 1622 } 1623 if (sjcd_door_was_open) { 1624 s = sjcd_tray_open(); 1625 if (s < 0 || !sjcd_status_valid 1626 || sjcd_command_failed) { 1627#if defined(SJCD_DIAGNOSTIC) 1628 printk 1629 ("SJCD: release: tray unload attempt failed.\n"); 1630#endif 1631 } 1632 } 1633 } 1634 return 0; 1635} 1636 1637/* 1638 * A list of file operations allowed for this cdrom. 1639 */ 1640static struct block_device_operations sjcd_fops = { 1641 .owner = THIS_MODULE, 1642 .open = sjcd_open, 1643 .release = sjcd_release, 1644 .ioctl = sjcd_ioctl, 1645 .media_changed = sjcd_disk_change, 1646}; 1647 1648/* 1649 * Following stuff is intended for initialization of the cdrom. It 1650 * first looks for presence of device. If the device is present, it 1651 * will be reset. Then read the version of the drive and load status. 1652 * The version is two BCD-coded bytes. 1653 */ 1654static struct { 1655 unsigned char major, minor; 1656} sjcd_version; 1657 1658static struct gendisk *sjcd_disk; 1659 1660/* 1661 * Test for presence of drive and initialize it. Called at boot time. 1662 * Probe cdrom, find out version and status. 1663 */ 1664static int __init sjcd_init(void) 1665{ 1666 int i; 1667 1668 printk(KERN_INFO 1669 "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", 1670 SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR); 1671 1672#if defined(SJCD_TRACE) 1673 printk("SJCD: sjcd=0x%x: ", sjcd_base); 1674#endif 1675 1676 if (register_blkdev(MAJOR_NR, "sjcd")) 1677 return -EIO; 1678 1679 sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock); 1680 if (!sjcd_queue) 1681 goto out0; 1682 1683 blk_queue_hardsect_size(sjcd_queue, 2048); 1684 1685 sjcd_disk = alloc_disk(1); 1686 if (!sjcd_disk) { 1687 printk(KERN_ERR "SJCD: can't allocate disk"); 1688 goto out1; 1689 } 1690 sjcd_disk->major = MAJOR_NR, 1691 sjcd_disk->first_minor = 0, 1692 sjcd_disk->fops = &sjcd_fops, 1693 sprintf(sjcd_disk->disk_name, "sjcd"); 1694 1695 if (!request_region(sjcd_base, 4,"sjcd")) { 1696 printk 1697 ("SJCD: Init failed, I/O port (%X) is already in use\n", 1698 sjcd_base); 1699 goto out2; 1700 } 1701 1702 /* 1703 * Check for card. Since we are booting now, we can't use standard 1704 * wait algorithm. 1705 */ 1706 printk(KERN_INFO "SJCD: Resetting: "); 1707 sjcd_send_cmd(SCMD_RESET); 1708 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1709 unsigned long timer; 1710 1711 /* 1712 * Wait 10ms approx. 1713 */ 1714 for (timer = jiffies; time_before_eq(jiffies, timer);); 1715 if ((i % 100) == 0) 1716 printk("."); 1717 (void) sjcd_check_status(); 1718 } 1719 if (i == 0 || sjcd_command_failed) { 1720 printk(" reset failed, no drive found.\n"); 1721 goto out3; 1722 } else 1723 printk("\n"); 1724 1725 /* 1726 * Get and print out cdrom version. 1727 */ 1728 printk(KERN_INFO "SJCD: Getting version: "); 1729 sjcd_send_cmd(SCMD_GET_VERSION); 1730 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1731 unsigned long timer; 1732 1733 /* 1734 * Wait 10ms approx. 1735 */ 1736 for (timer = jiffies; time_before_eq(jiffies, timer);); 1737 if ((i % 100) == 0) 1738 printk("."); 1739 (void) sjcd_check_status(); 1740 } 1741 if (i == 0 || sjcd_command_failed) { 1742 printk(" get version failed, no drive found.\n"); 1743 goto out3; 1744 } 1745 1746 if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { 1747 printk(" %1x.%02x\n", (int) sjcd_version.major, 1748 (int) sjcd_version.minor); 1749 } else { 1750 printk(" read version failed, no drive found.\n"); 1751 goto out3; 1752 } 1753 1754 /* 1755 * Check and print out the tray state. (if it is needed?). 1756 */ 1757 if (!sjcd_status_valid) { 1758 printk(KERN_INFO "SJCD: Getting status: "); 1759 sjcd_send_cmd(SCMD_GET_STATUS); 1760 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1761 unsigned long timer; 1762 1763 /* 1764 * Wait 10ms approx. 1765 */ 1766 for (timer = jiffies; 1767 time_before_eq(jiffies, timer);); 1768 if ((i % 100) == 0) 1769 printk("."); 1770 (void) sjcd_check_status(); 1771 } 1772 if (i == 0 || sjcd_command_failed) { 1773 printk(" get status failed, no drive found.\n"); 1774 goto out3; 1775 } else 1776 printk("\n"); 1777 } 1778 1779 printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); 1780 sjcd_disk->queue = sjcd_queue; 1781 add_disk(sjcd_disk); 1782 1783 sjcd_present++; 1784 return (0); 1785out3: 1786 release_region(sjcd_base, 4); 1787out2: 1788 put_disk(sjcd_disk); 1789out1: 1790 blk_cleanup_queue(sjcd_queue); 1791out0: 1792 if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) 1793 printk("SJCD: cannot unregister device.\n"); 1794 return (-EIO); 1795} 1796 1797static void __exit sjcd_exit(void) 1798{ 1799 del_gendisk(sjcd_disk); 1800 put_disk(sjcd_disk); 1801 release_region(sjcd_base, 4); 1802 blk_cleanup_queue(sjcd_queue); 1803 if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) 1804 printk("SJCD: cannot unregister device.\n"); 1805 printk(KERN_INFO "SJCD: module: removed.\n"); 1806} 1807 1808module_init(sjcd_init); 1809module_exit(sjcd_exit); 1810 1811MODULE_LICENSE("GPL"); 1812MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR); 1813