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/sched.h> 64#include <linux/mm.h> 65#include <linux/timer.h> 66#include <linux/fs.h> 67#include <linux/kernel.h> 68#include <linux/cdrom.h> 69#include <linux/ioport.h> 70#include <linux/string.h> 71#include <linux/major.h> 72#include <linux/init.h> 73#include <linux/devfs_fs_kernel.h> 74 75#include <asm/system.h> 76#include <asm/io.h> 77#include <asm/uaccess.h> 78 79#define MAJOR_NR SANYO_CDROM_MAJOR 80#include <linux/blk.h> 81#include "sjcd.h" 82 83static int sjcd_present = 0; 84 85#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ 86 87/* 88 * buffer for block size conversion 89 */ 90static char sjcd_buf[2048 * SJCD_BUF_SIZ]; 91static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn; 92static volatile int sjcd_buf_in, sjcd_buf_out = -1; 93 94/* 95 * Status. 96 */ 97static unsigned short sjcd_status_valid = 0; 98static unsigned short sjcd_door_closed; 99static unsigned short sjcd_door_was_open; 100static unsigned short sjcd_media_is_available; 101static unsigned short sjcd_media_is_changed; 102static unsigned short sjcd_toc_uptodate = 0; 103static unsigned short sjcd_command_failed; 104static volatile unsigned char sjcd_completion_status = 0; 105static volatile unsigned char sjcd_completion_error = 0; 106static unsigned short sjcd_command_is_in_progress = 0; 107static unsigned short sjcd_error_reported = 0; 108 109static int sjcd_open_count; 110 111static int sjcd_audio_status; 112static struct sjcd_play_msf sjcd_playing; 113 114static int sjcd_base = SJCD_BASE_ADDR; 115 116MODULE_PARM(sjcd_base, "i"); 117 118static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq); 119 120/* 121 * Data transfer. 122 */ 123static volatile unsigned short sjcd_transfer_is_active = 0; 124 125enum sjcd_transfer_state { 126 SJCD_S_IDLE = 0, 127 SJCD_S_START = 1, 128 SJCD_S_MODE = 2, 129 SJCD_S_READ = 3, 130 SJCD_S_DATA = 4, 131 SJCD_S_STOP = 5, 132 SJCD_S_STOPPING = 6 133}; 134static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE; 135static long sjcd_transfer_timeout = 0; 136static int sjcd_read_count = 0; 137static unsigned char sjcd_mode = 0; 138 139#define SJCD_READ_TIMEOUT 5000 140 141#if defined(SJCD_GATHER_STAT) 142/* 143 * Statistic. 144 */ 145static struct sjcd_stat statistic; 146#endif 147 148/* 149 * Timer. 150 */ 151static struct timer_list sjcd_delay_timer; 152 153#define SJCD_SET_TIMER( func, tmout ) \ 154 ( sjcd_delay_timer.expires = jiffies+tmout, \ 155 sjcd_delay_timer.function = ( void * )func, \ 156 add_timer( &sjcd_delay_timer ) ) 157 158#define CLEAR_TIMER del_timer( &sjcd_delay_timer ) 159 160static int sjcd_cleanup(void); 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(kdev_t full_dev) 457{ 458 if (MINOR(full_dev) > 0) { 459 printk("SJCD: request error: invalid device minor.\n"); 460 return 0; 461 } 462 if (!sjcd_command_is_in_progress) 463 sjcd_get_status(); 464 return (sjcd_status_valid ? sjcd_media_is_changed : 0); 465} 466 467/* 468 * Read the table of contents (TOC) and TOC header if necessary. 469 * We assume that the drive contains no more than 99 toc entries. 470 */ 471static struct sjcd_hw_disk_info sjcd_table_of_contents[SJCD_MAX_TRACKS]; 472static unsigned char sjcd_first_track_no, sjcd_last_track_no; 473#define sjcd_disk_length sjcd_table_of_contents[0].un.track_msf 474 475static int sjcd_update_toc(void) 476{ 477 struct sjcd_hw_disk_info info; 478 int i; 479#if defined(SJCD_TRACE) 480 printk("SJCD: update toc:\n"); 481#endif 482 /* 483 * check to see if we need to do anything 484 */ 485 if (sjcd_toc_uptodate) 486 return (0); 487 488 /* 489 * Get the TOC start information. 490 */ 491 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_1_TRACK); 492 sjcd_receive_status(); 493 494 if (!sjcd_status_valid) { 495 printk("SJCD: cannot load status.\n"); 496 return (-1); 497 } 498 499 if (!sjcd_media_is_available) { 500 printk("SJCD: no disk in drive\n"); 501 return (-1); 502 } 503 504 if (!sjcd_command_failed) { 505 if (sjcd_load_response(&info, sizeof(info)) != 0) { 506 printk 507 ("SJCD: cannot load response about TOC start.\n"); 508 return (-1); 509 } 510 sjcd_first_track_no = bcd2bin(info.un.track_no); 511 } else { 512 printk("SJCD: get first failed\n"); 513 return (-1); 514 } 515#if defined(SJCD_TRACE) 516 printk("SJCD: TOC start 0x%02x ", sjcd_first_track_no); 517#endif 518 /* 519 * Get the TOC finish information. 520 */ 521 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_L_TRACK); 522 sjcd_receive_status(); 523 524 if (!sjcd_status_valid) { 525 printk("SJCD: cannot load status.\n"); 526 return (-1); 527 } 528 529 if (!sjcd_media_is_available) { 530 printk("SJCD: no disk in drive\n"); 531 return (-1); 532 } 533 534 if (!sjcd_command_failed) { 535 if (sjcd_load_response(&info, sizeof(info)) != 0) { 536 printk 537 ("SJCD: cannot load response about TOC finish.\n"); 538 return (-1); 539 } 540 sjcd_last_track_no = bcd2bin(info.un.track_no); 541 } else { 542 printk("SJCD: get last failed\n"); 543 return (-1); 544 } 545#if defined(SJCD_TRACE) 546 printk("SJCD: TOC finish 0x%02x ", sjcd_last_track_no); 547#endif 548 for (i = sjcd_first_track_no; i <= sjcd_last_track_no; i++) { 549 /* 550 * Get the first track information. 551 */ 552 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, bin2bcd(i)); 553 sjcd_receive_status(); 554 555 if (!sjcd_status_valid) { 556 printk("SJCD: cannot load status.\n"); 557 return (-1); 558 } 559 560 if (!sjcd_media_is_available) { 561 printk("SJCD: no disk in drive\n"); 562 return (-1); 563 } 564 565 if (!sjcd_command_failed) { 566 if (sjcd_load_response(&sjcd_table_of_contents[i], 567 sizeof(struct 568 sjcd_hw_disk_info)) 569 != 0) { 570 printk 571 ("SJCD: cannot load info for %d track\n", 572 i); 573 return (-1); 574 } 575 } else { 576 printk("SJCD: get info %d failed\n", i); 577 return (-1); 578 } 579 } 580 581 /* 582 * Get the disk length info. 583 */ 584 sjcd_send_1_cmd(SCMD_GET_DISK_INFO, SCMD_GET_D_SIZE); 585 sjcd_receive_status(); 586 587 if (!sjcd_status_valid) { 588 printk("SJCD: cannot load status.\n"); 589 return (-1); 590 } 591 592 if (!sjcd_media_is_available) { 593 printk("SJCD: no disk in drive\n"); 594 return (-1); 595 } 596 597 if (!sjcd_command_failed) { 598 if (sjcd_load_response(&info, sizeof(info)) != 0) { 599 printk 600 ("SJCD: cannot load response about disk size.\n"); 601 return (-1); 602 } 603 sjcd_disk_length.min = info.un.track_msf.min; 604 sjcd_disk_length.sec = info.un.track_msf.sec; 605 sjcd_disk_length.frame = info.un.track_msf.frame; 606 } else { 607 printk("SJCD: get size failed\n"); 608 return (1); 609 } 610#if defined(SJCD_TRACE) 611 printk("SJCD: (%02x:%02x.%02x)\n", sjcd_disk_length.min, 612 sjcd_disk_length.sec, sjcd_disk_length.frame); 613#endif 614 return (0); 615} 616 617/* 618 * Load subchannel information. 619 */ 620static int sjcd_get_q_info(struct sjcd_hw_qinfo *qp) 621{ 622 int s; 623#if defined(SJCD_TRACE) 624 printk("SJCD: load sub q\n"); 625#endif 626 sjcd_send_cmd(SCMD_GET_QINFO); 627 s = sjcd_receive_status(); 628 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) { 629 sjcd_send_cmd(0xF2); 630 s = sjcd_receive_status(); 631 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) 632 return (-1); 633 sjcd_send_cmd(SCMD_GET_QINFO); 634 s = sjcd_receive_status(); 635 if (s < 0 || sjcd_command_failed || !sjcd_status_valid) 636 return (-1); 637 } 638 if (sjcd_media_is_available) 639 if (sjcd_load_response(qp, sizeof(*qp)) == 0) 640 return (0); 641 return (-1); 642} 643 644/* 645 * Start playing from the specified position. 646 */ 647static int sjcd_play(struct sjcd_play_msf *mp) 648{ 649 struct sjcd_play_msf msf; 650 651 /* 652 * Turn the device to play mode. 653 */ 654 sjcd_send_1_cmd(SCMD_SET_MODE, SCMD_MODE_PLAY); 655 if (sjcd_receive_status() < 0) 656 return (-1); 657 658 /* 659 * Seek to the starting point. 660 */ 661 msf.start = mp->start; 662 msf.end.min = msf.end.sec = msf.end.frame = 0x00; 663 sjcd_send_6_cmd(SCMD_SEEK, &msf); 664 if (sjcd_receive_status() < 0) 665 return (-1); 666 667 /* 668 * Start playing. 669 */ 670 sjcd_send_6_cmd(SCMD_PLAY, mp); 671 return (sjcd_receive_status()); 672} 673 674/* 675 * Tray control functions. 676 */ 677static int sjcd_tray_close(void) 678{ 679#if defined(SJCD_TRACE) 680 printk("SJCD: tray_close\n"); 681#endif 682 sjcd_send_cmd(SCMD_CLOSE_TRAY); 683 return (sjcd_receive_status()); 684} 685 686static int sjcd_tray_lock(void) 687{ 688#if defined(SJCD_TRACE) 689 printk("SJCD: tray_lock\n"); 690#endif 691 sjcd_send_cmd(SCMD_LOCK_TRAY); 692 return (sjcd_receive_status()); 693} 694 695static int sjcd_tray_unlock(void) 696{ 697#if defined(SJCD_TRACE) 698 printk("SJCD: tray_unlock\n"); 699#endif 700 sjcd_send_cmd(SCMD_UNLOCK_TRAY); 701 return (sjcd_receive_status()); 702} 703 704static int sjcd_tray_open(void) 705{ 706#if defined(SJCD_TRACE) 707 printk("SJCD: tray_open\n"); 708#endif 709 sjcd_send_cmd(SCMD_EJECT_TRAY); 710 return (sjcd_receive_status()); 711} 712 713/* 714 * Do some user commands. 715 */ 716static int sjcd_ioctl(struct inode *ip, struct file *fp, 717 unsigned int cmd, unsigned long arg) 718{ 719#if defined(SJCD_TRACE) 720 printk("SJCD:ioctl\n"); 721#endif 722 723 if (ip == NULL) 724 return (-EINVAL); 725 726 sjcd_get_status(); 727 if (!sjcd_status_valid) 728 return (-EIO); 729 if (sjcd_update_toc() < 0) 730 return (-EIO); 731 732 switch (cmd) { 733 case CDROMSTART:{ 734#if defined(SJCD_TRACE) 735 printk("SJCD: ioctl: start\n"); 736#endif 737 return (0); 738 } 739 740 case CDROMSTOP:{ 741#if defined(SJCD_TRACE) 742 printk("SJCD: ioctl: stop\n"); 743#endif 744 sjcd_send_cmd(SCMD_PAUSE); 745 (void) sjcd_receive_status(); 746 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 747 return (0); 748 } 749 750 case CDROMPAUSE:{ 751 struct sjcd_hw_qinfo q_info; 752#if defined(SJCD_TRACE) 753 printk("SJCD: ioctl: pause\n"); 754#endif 755 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 756 sjcd_send_cmd(SCMD_PAUSE); 757 (void) sjcd_receive_status(); 758 if (sjcd_get_q_info(&q_info) < 0) { 759 sjcd_audio_status = 760 CDROM_AUDIO_NO_STATUS; 761 } else { 762 sjcd_audio_status = 763 CDROM_AUDIO_PAUSED; 764 sjcd_playing.start = q_info.abs; 765 } 766 return (0); 767 } else 768 return (-EINVAL); 769 } 770 771 case CDROMRESUME:{ 772#if defined(SJCD_TRACE) 773 printk("SJCD: ioctl: resume\n"); 774#endif 775 if (sjcd_audio_status == CDROM_AUDIO_PAUSED) { 776 /* 777 * continue play starting at saved location 778 */ 779 if (sjcd_play(&sjcd_playing) < 0) { 780 sjcd_audio_status = 781 CDROM_AUDIO_ERROR; 782 return (-EIO); 783 } else { 784 sjcd_audio_status = 785 CDROM_AUDIO_PLAY; 786 return (0); 787 } 788 } else 789 return (-EINVAL); 790 } 791 792 case CDROMPLAYTRKIND:{ 793 struct cdrom_ti ti; 794 int s; 795#if defined(SJCD_TRACE) 796 printk("SJCD: ioctl: playtrkind\n"); 797#endif 798 if ((s = 799 verify_area(VERIFY_READ, (void *) arg, 800 sizeof(ti))) == 0) { 801 copy_from_user(&ti, (void *) arg, 802 sizeof(ti)); 803 804 if (ti.cdti_trk0 < sjcd_first_track_no) 805 return (-EINVAL); 806 if (ti.cdti_trk1 > sjcd_last_track_no) 807 ti.cdti_trk1 = sjcd_last_track_no; 808 if (ti.cdti_trk0 > ti.cdti_trk1) 809 return (-EINVAL); 810 811 sjcd_playing.start = 812 sjcd_table_of_contents[ti.cdti_trk0]. 813 un.track_msf; 814 sjcd_playing.end = 815 (ti.cdti_trk1 < 816 sjcd_last_track_no) ? 817 sjcd_table_of_contents[ti.cdti_trk1 + 818 1].un. 819 track_msf : sjcd_table_of_contents[0]. 820 un.track_msf; 821 822 if (sjcd_play(&sjcd_playing) < 0) { 823 sjcd_audio_status = 824 CDROM_AUDIO_ERROR; 825 return (-EIO); 826 } else 827 sjcd_audio_status = 828 CDROM_AUDIO_PLAY; 829 } 830 return (s); 831 } 832 833 case CDROMPLAYMSF:{ 834 struct cdrom_msf sjcd_msf; 835 int s; 836#if defined(SJCD_TRACE) 837 printk("SJCD: ioctl: playmsf\n"); 838#endif 839 if ((s = 840 verify_area(VERIFY_READ, (void *) arg, 841 sizeof(sjcd_msf))) == 0) { 842 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 843 sjcd_send_cmd(SCMD_PAUSE); 844 (void) sjcd_receive_status(); 845 sjcd_audio_status = 846 CDROM_AUDIO_NO_STATUS; 847 } 848 849 copy_from_user(&sjcd_msf, (void *) arg, 850 sizeof(sjcd_msf)); 851 852 sjcd_playing.start.min = 853 bin2bcd(sjcd_msf.cdmsf_min0); 854 sjcd_playing.start.sec = 855 bin2bcd(sjcd_msf.cdmsf_sec0); 856 sjcd_playing.start.frame = 857 bin2bcd(sjcd_msf.cdmsf_frame0); 858 sjcd_playing.end.min = 859 bin2bcd(sjcd_msf.cdmsf_min1); 860 sjcd_playing.end.sec = 861 bin2bcd(sjcd_msf.cdmsf_sec1); 862 sjcd_playing.end.frame = 863 bin2bcd(sjcd_msf.cdmsf_frame1); 864 865 if (sjcd_play(&sjcd_playing) < 0) { 866 sjcd_audio_status = 867 CDROM_AUDIO_ERROR; 868 return (-EIO); 869 } else 870 sjcd_audio_status = 871 CDROM_AUDIO_PLAY; 872 } 873 return (s); 874 } 875 876 case CDROMREADTOCHDR:{ 877 struct cdrom_tochdr toc_header; 878 int s; 879#if defined(SJCD_TRACE) 880 printk("SJCD: ioctl: readtocheader\n"); 881#endif 882 if ((s = 883 verify_area(VERIFY_WRITE, (void *) arg, 884 sizeof(toc_header))) == 0) { 885 toc_header.cdth_trk0 = sjcd_first_track_no; 886 toc_header.cdth_trk1 = sjcd_last_track_no; 887 copy_to_user((void *) arg, &toc_header, 888 sizeof(toc_header)); 889 } 890 return (s); 891 } 892 893 case CDROMREADTOCENTRY:{ 894 struct cdrom_tocentry toc_entry; 895 int s; 896#if defined(SJCD_TRACE) 897 printk("SJCD: ioctl: readtocentry\n"); 898#endif 899 if ((s = 900 verify_area(VERIFY_WRITE, (void *) arg, 901 sizeof(toc_entry))) == 0) { 902 struct sjcd_hw_disk_info *tp; 903 904 copy_from_user(&toc_entry, (void *) arg, 905 sizeof(toc_entry)); 906 907 if (toc_entry.cdte_track == CDROM_LEADOUT) 908 tp = &sjcd_table_of_contents[0]; 909 else if (toc_entry.cdte_track < 910 sjcd_first_track_no) 911 return (-EINVAL); 912 else if (toc_entry.cdte_track > 913 sjcd_last_track_no) 914 return (-EINVAL); 915 else 916 tp = &sjcd_table_of_contents 917 [toc_entry.cdte_track]; 918 919 toc_entry.cdte_adr = 920 tp->track_control & 0x0F; 921 toc_entry.cdte_ctrl = 922 tp->track_control >> 4; 923 924 switch (toc_entry.cdte_format) { 925 case CDROM_LBA: 926 toc_entry.cdte_addr.lba = 927 msf2hsg(&(tp->un.track_msf)); 928 break; 929 case CDROM_MSF: 930 toc_entry.cdte_addr.msf.minute = 931 bcd2bin(tp->un.track_msf.min); 932 toc_entry.cdte_addr.msf.second = 933 bcd2bin(tp->un.track_msf.sec); 934 toc_entry.cdte_addr.msf.frame = 935 bcd2bin(tp->un.track_msf. 936 frame); 937 break; 938 default: 939 return (-EINVAL); 940 } 941 copy_to_user((void *) arg, &toc_entry, 942 sizeof(toc_entry)); 943 } 944 return (s); 945 } 946 947 case CDROMSUBCHNL:{ 948 struct cdrom_subchnl subchnl; 949 int s; 950#if defined(SJCD_TRACE) 951 printk("SJCD: ioctl: subchnl\n"); 952#endif 953 if ((s = 954 verify_area(VERIFY_WRITE, (void *) arg, 955 sizeof(subchnl))) == 0) { 956 struct sjcd_hw_qinfo q_info; 957 958 copy_from_user(&subchnl, (void *) arg, 959 sizeof(subchnl)); 960 if (sjcd_get_q_info(&q_info) < 0) 961 return (-EIO); 962 963 subchnl.cdsc_audiostatus = 964 sjcd_audio_status; 965 subchnl.cdsc_adr = 966 q_info.track_control & 0x0F; 967 subchnl.cdsc_ctrl = 968 q_info.track_control >> 4; 969 subchnl.cdsc_trk = 970 bcd2bin(q_info.track_no); 971 subchnl.cdsc_ind = bcd2bin(q_info.x); 972 973 switch (subchnl.cdsc_format) { 974 case CDROM_LBA: 975 subchnl.cdsc_absaddr.lba = 976 msf2hsg(&(q_info.abs)); 977 subchnl.cdsc_reladdr.lba = 978 msf2hsg(&(q_info.rel)); 979 break; 980 case CDROM_MSF: 981 subchnl.cdsc_absaddr.msf.minute = 982 bcd2bin(q_info.abs.min); 983 subchnl.cdsc_absaddr.msf.second = 984 bcd2bin(q_info.abs.sec); 985 subchnl.cdsc_absaddr.msf.frame = 986 bcd2bin(q_info.abs.frame); 987 subchnl.cdsc_reladdr.msf.minute = 988 bcd2bin(q_info.rel.min); 989 subchnl.cdsc_reladdr.msf.second = 990 bcd2bin(q_info.rel.sec); 991 subchnl.cdsc_reladdr.msf.frame = 992 bcd2bin(q_info.rel.frame); 993 break; 994 default: 995 return (-EINVAL); 996 } 997 copy_to_user((void *) arg, &subchnl, 998 sizeof(subchnl)); 999 } 1000 return (s); 1001 } 1002 1003 case CDROMVOLCTRL:{ 1004 struct cdrom_volctrl vol_ctrl; 1005 int s; 1006#if defined(SJCD_TRACE) 1007 printk("SJCD: ioctl: volctrl\n"); 1008#endif 1009 if ((s = 1010 verify_area(VERIFY_READ, (void *) arg, 1011 sizeof(vol_ctrl))) == 0) { 1012 unsigned char dummy[4]; 1013 1014 copy_from_user(&vol_ctrl, (void *) arg, 1015 sizeof(vol_ctrl)); 1016 sjcd_send_4_cmd(SCMD_SET_VOLUME, 1017 vol_ctrl.channel0, 0xFF, 1018 vol_ctrl.channel1, 0xFF); 1019 if (sjcd_receive_status() < 0) 1020 return (-EIO); 1021 (void) sjcd_load_response(dummy, 4); 1022 } 1023 return (s); 1024 } 1025 1026 case CDROMEJECT:{ 1027#if defined(SJCD_TRACE) 1028 printk("SJCD: ioctl: eject\n"); 1029#endif 1030 if (!sjcd_command_is_in_progress) { 1031 sjcd_tray_unlock(); 1032 sjcd_send_cmd(SCMD_EJECT_TRAY); 1033 (void) sjcd_receive_status(); 1034 } 1035 return (0); 1036 } 1037 1038#if defined(SJCD_GATHER_STAT) 1039 case 0xABCD:{ 1040 int s; 1041#if defined(SJCD_TRACE) 1042 printk("SJCD: ioctl: statistic\n"); 1043#endif 1044 if ((s = 1045 verify_area(VERIFY_WRITE, (void *) arg, 1046 sizeof(statistic))) == 0) 1047 copy_to_user((void *) arg, &statistic, 1048 sizeof(statistic)); 1049 return (s); 1050 } 1051#endif 1052 1053 default: 1054 return (-EINVAL); 1055 } 1056} 1057 1058/* 1059 * Invalidate internal buffers of the driver. 1060 */ 1061static void sjcd_invalidate_buffers(void) 1062{ 1063 int i; 1064 for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1); 1065 sjcd_buf_out = -1; 1066} 1067 1068/* 1069 * Take care of the different block sizes between cdrom and Linux. 1070 * When Linux gets variable block sizes this will probably go away. 1071 */ 1072 1073#define CURRENT_IS_VALID \ 1074 ( !QUEUE_EMPTY && MAJOR( CURRENT->rq_dev ) == MAJOR_NR && \ 1075 CURRENT->cmd == READ && CURRENT->sector != -1 ) 1076 1077static void sjcd_transfer(void) 1078{ 1079#if defined(SJCD_TRACE) 1080 printk("SJCD: transfer:\n"); 1081#endif 1082 if (CURRENT_IS_VALID) { 1083 while (CURRENT->nr_sectors) { 1084 int i, bn = CURRENT->sector / 4; 1085 for (i = 0; 1086 i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn; 1087 i++); 1088 if (i < SJCD_BUF_SIZ) { 1089 int offs = 1090 (i * 4 + (CURRENT->sector & 3)) * 512; 1091 int nr_sectors = 4 - (CURRENT->sector & 3); 1092 if (sjcd_buf_out != i) { 1093 sjcd_buf_out = i; 1094 if (sjcd_buf_bn[i] != bn) { 1095 sjcd_buf_out = -1; 1096 continue; 1097 } 1098 } 1099 if (nr_sectors > CURRENT->nr_sectors) 1100 nr_sectors = CURRENT->nr_sectors; 1101#if defined(SJCD_TRACE) 1102 printk("SJCD: copy out\n"); 1103#endif 1104 memcpy(CURRENT->buffer, sjcd_buf + offs, 1105 nr_sectors * 512); 1106 CURRENT->nr_sectors -= nr_sectors; 1107 CURRENT->sector += nr_sectors; 1108 CURRENT->buffer += nr_sectors * 512; 1109 } else { 1110 sjcd_buf_out = -1; 1111 break; 1112 } 1113 } 1114 } 1115#if defined(SJCD_TRACE) 1116 printk("SJCD: transfer: done\n"); 1117#endif 1118} 1119 1120static void sjcd_poll(void) 1121{ 1122#if defined(SJCD_GATHER_STAT) 1123 /* 1124 * Update total number of ticks. 1125 */ 1126 statistic.ticks++; 1127 statistic.tticks[sjcd_transfer_state]++; 1128#endif 1129 1130 ReSwitch:switch (sjcd_transfer_state) { 1131 1132 case SJCD_S_IDLE:{ 1133#if defined(SJCD_GATHER_STAT) 1134 statistic.idle_ticks++; 1135#endif 1136#if defined(SJCD_TRACE) 1137 printk("SJCD_S_IDLE\n"); 1138#endif 1139 return; 1140 } 1141 1142 case SJCD_S_START:{ 1143#if defined(SJCD_GATHER_STAT) 1144 statistic.start_ticks++; 1145#endif 1146 sjcd_send_cmd(SCMD_GET_STATUS); 1147 sjcd_transfer_state = 1148 sjcd_mode == 1149 SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; 1150 sjcd_transfer_timeout = 500; 1151#if defined(SJCD_TRACE) 1152 printk("SJCD_S_START: goto SJCD_S_%s mode\n", 1153 sjcd_transfer_state == 1154 SJCD_S_READ ? "READ" : "MODE"); 1155#endif 1156 break; 1157 } 1158 1159 case SJCD_S_MODE:{ 1160 if (sjcd_check_status()) { 1161 /* 1162 * Previous command is completed. 1163 */ 1164 if (!sjcd_status_valid 1165 || sjcd_command_failed) { 1166#if defined(SJCD_TRACE) 1167 printk 1168 ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1169#endif 1170 sjcd_transfer_state = SJCD_S_STOP; 1171 goto ReSwitch; 1172 } 1173 1174 sjcd_mode = 0; /* unknown mode; should not be valid when failed */ 1175 sjcd_send_1_cmd(SCMD_SET_MODE, 1176 SCMD_MODE_COOKED); 1177 sjcd_transfer_state = SJCD_S_READ; 1178 sjcd_transfer_timeout = 1000; 1179#if defined(SJCD_TRACE) 1180 printk 1181 ("SJCD_S_MODE: goto SJCD_S_READ mode\n"); 1182#endif 1183 } 1184#if defined(SJCD_GATHER_STAT) 1185 else 1186 statistic.mode_ticks++; 1187#endif 1188 break; 1189 } 1190 1191 case SJCD_S_READ:{ 1192 if (sjcd_status_valid ? 1 : sjcd_check_status()) { 1193 /* 1194 * Previous command is completed. 1195 */ 1196 if (!sjcd_status_valid 1197 || sjcd_command_failed) { 1198#if defined(SJCD_TRACE) 1199 printk 1200 ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1201#endif 1202 sjcd_transfer_state = SJCD_S_STOP; 1203 goto ReSwitch; 1204 } 1205 if (!sjcd_media_is_available) { 1206#if defined(SJCD_TRACE) 1207 printk 1208 ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n"); 1209#endif 1210 sjcd_transfer_state = SJCD_S_STOP; 1211 goto ReSwitch; 1212 } 1213 if (sjcd_mode != SCMD_MODE_COOKED) { 1214 /* 1215 * We seem to come from set mode. So discard one byte of result. 1216 */ 1217 if (sjcd_load_response 1218 (&sjcd_mode, 1) != 0) { 1219#if defined(SJCD_TRACE) 1220 printk 1221 ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n"); 1222#endif 1223 sjcd_transfer_state = 1224 SJCD_S_STOP; 1225 goto ReSwitch; 1226 } 1227 if (sjcd_mode != SCMD_MODE_COOKED) { 1228#if defined(SJCD_TRACE) 1229 printk 1230 ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n"); 1231#endif 1232 sjcd_transfer_state = 1233 SJCD_S_STOP; 1234 goto ReSwitch; 1235 } 1236 } 1237 1238 if (CURRENT_IS_VALID) { 1239 struct sjcd_play_msf msf; 1240 1241 sjcd_next_bn = CURRENT->sector / 4; 1242 hsg2msf(sjcd_next_bn, &msf.start); 1243 msf.end.min = 0; 1244 msf.end.sec = 0; 1245 msf.end.frame = sjcd_read_count = 1246 SJCD_BUF_SIZ; 1247#if defined(SJCD_TRACE) 1248 printk 1249 ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", 1250 msf.start.min, msf.start.sec, 1251 msf.start.frame, msf.end.min, 1252 msf.end.sec, msf.end.frame); 1253 printk 1254 ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", 1255 sjcd_next_bn, sjcd_buf_in, 1256 sjcd_buf_out, 1257 sjcd_buf_bn[sjcd_buf_in]); 1258#endif 1259 sjcd_send_6_cmd(SCMD_DATA_READ, 1260 &msf); 1261 sjcd_transfer_state = SJCD_S_DATA; 1262 sjcd_transfer_timeout = 500; 1263#if defined(SJCD_TRACE) 1264 printk 1265 ("SJCD_S_READ: go to SJCD_S_DATA mode\n"); 1266#endif 1267 } else { 1268#if defined(SJCD_TRACE) 1269 printk 1270 ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n"); 1271#endif 1272 sjcd_transfer_state = SJCD_S_STOP; 1273 goto ReSwitch; 1274 } 1275 } 1276#if defined(SJCD_GATHER_STAT) 1277 else 1278 statistic.read_ticks++; 1279#endif 1280 break; 1281 } 1282 1283 case SJCD_S_DATA:{ 1284 unsigned char stat; 1285 1286 sjcd_s_data:stat = 1287 inb(SJCDPORT 1288 (1)); 1289#if defined(SJCD_TRACE) 1290 printk("SJCD_S_DATA: status = 0x%02x\n", stat); 1291#endif 1292 if (SJCD_STATUS_AVAILABLE(stat)) { 1293 /* 1294 * No data is waiting for us in the drive buffer. Status of operation 1295 * completion is available. Read and parse it. 1296 */ 1297 sjcd_load_status(); 1298 1299 if (!sjcd_status_valid 1300 || sjcd_command_failed) { 1301#if defined(SJCD_TRACE) 1302 printk 1303 ("SJCD: read block %d failed, maybe audio disk? Giving up\n", 1304 sjcd_next_bn); 1305#endif 1306 if (CURRENT_IS_VALID) 1307 end_request(0); 1308#if defined(SJCD_TRACE) 1309 printk 1310 ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n"); 1311#endif 1312 sjcd_transfer_state = SJCD_S_STOP; 1313 goto ReSwitch; 1314 } 1315 1316 if (!sjcd_media_is_available) { 1317 printk 1318 ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); 1319 sjcd_transfer_state = SJCD_S_STOP; 1320 goto ReSwitch; 1321 } 1322 1323 sjcd_transfer_state = SJCD_S_READ; 1324 goto ReSwitch; 1325 } else if (SJCD_DATA_AVAILABLE(stat)) { 1326 /* 1327 * One frame is read into device buffer. We must copy it to our memory. 1328 * Otherwise cdrom hangs up. Check to see if we have something to copy 1329 * to. 1330 */ 1331 if (!CURRENT_IS_VALID 1332 && sjcd_buf_in == sjcd_buf_out) { 1333#if defined(SJCD_TRACE) 1334 printk 1335 ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); 1336 printk 1337 (" ... all the date would be discarded\n"); 1338#endif 1339 sjcd_transfer_state = SJCD_S_STOP; 1340 goto ReSwitch; 1341 } 1342 1343 /* 1344 * Everything seems to be OK. Just read the frame and recalculate 1345 * indices. 1346 */ 1347 sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ 1348 insb(SJCDPORT(2), 1349 sjcd_buf + 2048 * sjcd_buf_in, 2048); 1350#if defined(SJCD_TRACE) 1351 printk 1352 ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", 1353 sjcd_next_bn, sjcd_buf_in, 1354 sjcd_buf_out, 1355 sjcd_buf_bn[sjcd_buf_in]); 1356#endif 1357 sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; 1358 if (sjcd_buf_out == -1) 1359 sjcd_buf_out = sjcd_buf_in; 1360 if (++sjcd_buf_in == SJCD_BUF_SIZ) 1361 sjcd_buf_in = 0; 1362 1363 /* 1364 * Only one frame is ready at time. So we should turn over to wait for 1365 * another frame. If we need that, of course. 1366 */ 1367 if (--sjcd_read_count == 0) { 1368 /* 1369 * OK, request seems to be precessed. Continue transferring... 1370 */ 1371 if (!sjcd_transfer_is_active) { 1372 while (CURRENT_IS_VALID) { 1373 /* 1374 * Continue transferring. 1375 */ 1376 sjcd_transfer(); 1377 if (CURRENT-> 1378 nr_sectors == 1379 0) 1380 end_request 1381 (1); 1382 else 1383 break; 1384 } 1385 } 1386 if (CURRENT_IS_VALID && 1387 (CURRENT->sector / 4 < 1388 sjcd_next_bn 1389 || CURRENT->sector / 4 > 1390 sjcd_next_bn + 1391 SJCD_BUF_SIZ)) { 1392#if defined(SJCD_TRACE) 1393 printk 1394 ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n"); 1395#endif 1396 sjcd_transfer_state = 1397 SJCD_S_STOP; 1398 goto ReSwitch; 1399 } 1400 } 1401 /* 1402 * Now we should turn around rather than wait for while. 1403 */ 1404 goto sjcd_s_data; 1405 } 1406#if defined(SJCD_GATHER_STAT) 1407 else 1408 statistic.data_ticks++; 1409#endif 1410 break; 1411 } 1412 1413 case SJCD_S_STOP:{ 1414 sjcd_read_count = 0; 1415 sjcd_send_cmd(SCMD_STOP); 1416 sjcd_transfer_state = SJCD_S_STOPPING; 1417 sjcd_transfer_timeout = 500; 1418#if defined(SJCD_GATHER_STAT) 1419 statistic.stop_ticks++; 1420#endif 1421 break; 1422 } 1423 1424 case SJCD_S_STOPPING:{ 1425 unsigned char stat; 1426 1427 stat = inb(SJCDPORT(1)); 1428#if defined(SJCD_TRACE) 1429 printk("SJCD_S_STOP: status = 0x%02x\n", stat); 1430#endif 1431 if (SJCD_DATA_AVAILABLE(stat)) { 1432 int i; 1433#if defined(SJCD_TRACE) 1434 printk("SJCD_S_STOP: discard data\n"); 1435#endif 1436 /* 1437 * Discard all the data from the pipe. Foolish method. 1438 */ 1439 for (i = 2048; i--; 1440 (void) inb(SJCDPORT(2))); 1441 sjcd_transfer_timeout = 500; 1442 } else if (SJCD_STATUS_AVAILABLE(stat)) { 1443 sjcd_load_status(); 1444 if (sjcd_status_valid 1445 && sjcd_media_is_changed) { 1446 sjcd_toc_uptodate = 0; 1447 sjcd_invalidate_buffers(); 1448 } 1449 if (CURRENT_IS_VALID) { 1450 if (sjcd_status_valid) 1451 sjcd_transfer_state = 1452 SJCD_S_READ; 1453 else 1454 sjcd_transfer_state = 1455 SJCD_S_START; 1456 } else 1457 sjcd_transfer_state = SJCD_S_IDLE; 1458 goto ReSwitch; 1459 } 1460#if defined(SJCD_GATHER_STAT) 1461 else 1462 statistic.stopping_ticks++; 1463#endif 1464 break; 1465 } 1466 1467 default: 1468 printk("SJCD: poll: invalid state %d\n", 1469 sjcd_transfer_state); 1470 return; 1471 } 1472 1473 if (--sjcd_transfer_timeout == 0) { 1474 printk("SJCD: timeout in state %d\n", sjcd_transfer_state); 1475 while (CURRENT_IS_VALID) 1476 end_request(0); 1477 sjcd_send_cmd(SCMD_STOP); 1478 sjcd_transfer_state = SJCD_S_IDLE; 1479 goto ReSwitch; 1480 } 1481 1482 /* 1483 * Get back in some time. 1 should be replaced with count variable to 1484 * avoid unnecessary testings. 1485 */ 1486 SJCD_SET_TIMER(sjcd_poll, 1); 1487} 1488 1489static void do_sjcd_request(request_queue_t * q) 1490{ 1491#if defined(SJCD_TRACE) 1492 printk("SJCD: do_sjcd_request(%ld+%ld)\n", 1493 CURRENT->sector, CURRENT->nr_sectors); 1494#endif 1495 sjcd_transfer_is_active = 1; 1496 while (CURRENT_IS_VALID) { 1497 /* 1498 * Who of us are paranoiac? 1499 */ 1500 if (CURRENT->bh && !buffer_locked(CURRENT->bh)) 1501 panic(DEVICE_NAME ": block not locked"); 1502 1503 sjcd_transfer(); 1504 if (CURRENT->nr_sectors == 0) 1505 end_request(1); 1506 else { 1507 sjcd_buf_out = -1; /* Want to read a block not in buffer */ 1508 if (sjcd_transfer_state == SJCD_S_IDLE) { 1509 if (!sjcd_toc_uptodate) { 1510 if (sjcd_update_toc() < 0) { 1511 printk 1512 ("SJCD: transfer: discard\n"); 1513 while (CURRENT_IS_VALID) 1514 end_request(0); 1515 break; 1516 } 1517 } 1518 sjcd_transfer_state = SJCD_S_START; 1519 SJCD_SET_TIMER(sjcd_poll, HZ / 100); 1520 } 1521 break; 1522 } 1523 } 1524 sjcd_transfer_is_active = 0; 1525#if defined(SJCD_TRACE) 1526 printk 1527 ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", 1528 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, 1529 sjcd_buf_bn[sjcd_buf_in]); 1530 printk("do_sjcd_request ends\n"); 1531#endif 1532} 1533 1534/* 1535 * Open the device special file. Check disk is in. 1536 */ 1537int sjcd_open(struct inode *ip, struct file *fp) 1538{ 1539 /* 1540 * Check the presence of device. 1541 */ 1542 if (!sjcd_present) 1543 return (-ENXIO); 1544 1545 /* 1546 * Only read operations are allowed. Really? (:-) 1547 */ 1548 if (fp->f_mode & 2) 1549 return (-EROFS); 1550 1551 if (sjcd_open_count == 0) { 1552 int s, sjcd_open_tries; 1553/* We don't know that, do we? */ 1554/* 1555 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 1556*/ 1557 sjcd_mode = 0; 1558 sjcd_door_was_open = 0; 1559 sjcd_transfer_state = SJCD_S_IDLE; 1560 sjcd_invalidate_buffers(); 1561 sjcd_status_valid = 0; 1562 1563 /* 1564 * Strict status checking. 1565 */ 1566 for (sjcd_open_tries = 4; --sjcd_open_tries;) { 1567 if (!sjcd_status_valid) 1568 sjcd_get_status(); 1569 if (!sjcd_status_valid) { 1570#if defined(SJCD_DIAGNOSTIC) 1571 printk 1572 ("SJCD: open: timed out when check status.\n"); 1573#endif 1574 goto err_out; 1575 } else if (!sjcd_media_is_available) { 1576#if defined(SJCD_DIAGNOSTIC) 1577 printk("SJCD: open: no disk in drive\n"); 1578#endif 1579 if (!sjcd_door_closed) { 1580 sjcd_door_was_open = 1; 1581#if defined(SJCD_TRACE) 1582 printk 1583 ("SJCD: open: close the tray\n"); 1584#endif 1585 s = sjcd_tray_close(); 1586 if (s < 0 || !sjcd_status_valid 1587 || sjcd_command_failed) { 1588#if defined(SJCD_DIAGNOSTIC) 1589 printk 1590 ("SJCD: open: tray close attempt failed\n"); 1591#endif 1592 goto err_out; 1593 } 1594 continue; 1595 } else 1596 goto err_out; 1597 } 1598 break; 1599 } 1600 s = sjcd_tray_lock(); 1601 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1602#if defined(SJCD_DIAGNOSTIC) 1603 printk("SJCD: open: tray lock attempt failed\n"); 1604#endif 1605 goto err_out; 1606 } 1607#if defined(SJCD_TRACE) 1608 printk("SJCD: open: done\n"); 1609#endif 1610 } 1611 1612 ++sjcd_open_count; 1613 return (0); 1614 1615 err_out: 1616 return (-EIO); 1617} 1618 1619/* 1620 * On close, we flush all sjcd blocks from the buffer cache. 1621 */ 1622static int sjcd_release(struct inode *inode, struct file *file) 1623{ 1624 int s; 1625 1626#if defined(SJCD_TRACE) 1627 printk("SJCD: release\n"); 1628#endif 1629 if (--sjcd_open_count == 0) { 1630 sjcd_invalidate_buffers(); 1631 s = sjcd_tray_unlock(); 1632 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1633#if defined(SJCD_DIAGNOSTIC) 1634 printk 1635 ("SJCD: release: tray unlock attempt failed.\n"); 1636#endif 1637 } 1638 if (sjcd_door_was_open) { 1639 s = sjcd_tray_open(); 1640 if (s < 0 || !sjcd_status_valid 1641 || sjcd_command_failed) { 1642#if defined(SJCD_DIAGNOSTIC) 1643 printk 1644 ("SJCD: release: tray unload attempt failed.\n"); 1645#endif 1646 } 1647 } 1648 } 1649 return 0; 1650} 1651 1652/* 1653 * A list of file operations allowed for this cdrom. 1654 */ 1655static struct block_device_operations sjcd_fops = { 1656 owner:THIS_MODULE, 1657 open:sjcd_open, 1658 release:sjcd_release, 1659 ioctl:sjcd_ioctl, 1660 check_media_change:sjcd_disk_change, 1661}; 1662 1663static int blksize = 2048; 1664static int secsize = 2048; 1665 1666/* 1667 * Following stuff is intended for initialization of the cdrom. It 1668 * first looks for presence of device. If the device is present, it 1669 * will be reset. Then read the version of the drive and load status. 1670 * The version is two BCD-coded bytes. 1671 */ 1672static struct { 1673 unsigned char major, minor; 1674} sjcd_version; 1675 1676/* 1677 * Test for presence of drive and initialize it. Called at boot time. 1678 * Probe cdrom, find out version and status. 1679 */ 1680int __init sjcd_init(void) 1681{ 1682 int i; 1683 1684 printk(KERN_INFO 1685 "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", 1686 SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR); 1687 1688#if defined(SJCD_TRACE) 1689 printk("SJCD: sjcd=0x%x: ", sjcd_base); 1690#endif 1691 1692 hardsect_size[MAJOR_NR] = &secsize; 1693 blksize_size[MAJOR_NR] = &blksize; 1694 1695 if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { 1696 printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n", 1697 MAJOR_NR); 1698 return (-EIO); 1699 } 1700 1701 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); 1702 read_ahead[MAJOR_NR] = 4; 1703 register_disk(NULL, MKDEV(MAJOR_NR, 0), 1, &sjcd_fops, 0); 1704 1705 if (check_region(sjcd_base, 4)) { 1706 printk 1707 ("SJCD: Init failed, I/O port (%X) is already in use\n", 1708 sjcd_base); 1709 sjcd_cleanup(); 1710 return (-EIO); 1711 } 1712 1713 /* 1714 * Check for card. Since we are booting now, we can't use standard 1715 * wait algorithm. 1716 */ 1717 printk(KERN_INFO "SJCD: Resetting: "); 1718 sjcd_send_cmd(SCMD_RESET); 1719 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1720 unsigned long timer; 1721 1722 /* 1723 * Wait 10ms approx. 1724 */ 1725 for (timer = jiffies; time_before_eq(jiffies, timer);); 1726 if ((i % 100) == 0) 1727 printk("."); 1728 (void) sjcd_check_status(); 1729 } 1730 if (i == 0 || sjcd_command_failed) { 1731 printk(" reset failed, no drive found.\n"); 1732 sjcd_cleanup(); 1733 return (-EIO); 1734 } else 1735 printk("\n"); 1736 1737 /* 1738 * Get and print out cdrom version. 1739 */ 1740 printk(KERN_INFO "SJCD: Getting version: "); 1741 sjcd_send_cmd(SCMD_GET_VERSION); 1742 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1743 unsigned long timer; 1744 1745 /* 1746 * Wait 10ms approx. 1747 */ 1748 for (timer = jiffies; time_before_eq(jiffies, timer);); 1749 if ((i % 100) == 0) 1750 printk("."); 1751 (void) sjcd_check_status(); 1752 } 1753 if (i == 0 || sjcd_command_failed) { 1754 printk(" get version failed, no drive found.\n"); 1755 sjcd_cleanup(); 1756 return (-EIO); 1757 } 1758 1759 if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { 1760 printk(" %1x.%02x\n", (int) sjcd_version.major, 1761 (int) sjcd_version.minor); 1762 } else { 1763 printk(" read version failed, no drive found.\n"); 1764 sjcd_cleanup(); 1765 return (-EIO); 1766 } 1767 1768 /* 1769 * Check and print out the tray state. (if it is needed?). 1770 */ 1771 if (!sjcd_status_valid) { 1772 printk(KERN_INFO "SJCD: Getting status: "); 1773 sjcd_send_cmd(SCMD_GET_STATUS); 1774 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1775 unsigned long timer; 1776 1777 /* 1778 * Wait 10ms approx. 1779 */ 1780 for (timer = jiffies; 1781 time_before_eq(jiffies, timer);); 1782 if ((i % 100) == 0) 1783 printk("."); 1784 (void) sjcd_check_status(); 1785 } 1786 if (i == 0 || sjcd_command_failed) { 1787 printk(" get status failed, no drive found.\n"); 1788 sjcd_cleanup(); 1789 return (-EIO); 1790 } else 1791 printk("\n"); 1792 } 1793 1794 printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); 1795 devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, 1796 S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); 1797 1798 sjcd_present++; 1799 return (0); 1800} 1801 1802static int sjcd_cleanup(void) 1803{ 1804 if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) 1805 printk("SJCD: cannot unregister device.\n"); 1806 else { 1807 release_region(sjcd_base, 4); 1808 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); 1809 } 1810 1811 return (0); 1812} 1813 1814 1815void __exit sjcd_exit(void) 1816{ 1817 devfs_unregister(devfs_find_handle 1818 (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0)); 1819 if (sjcd_cleanup()) 1820 printk("SJCD: module: cannot be removed.\n"); 1821 else 1822 printk(KERN_INFO "SJCD: module: removed.\n"); 1823} 1824 1825#ifdef MODULE 1826module_init(sjcd_init); 1827#endif 1828module_exit(sjcd_exit); 1829 1830 1831MODULE_LICENSE("GPL"); 1832