at v2.6.19-rc2 1816 lines 43 kB view raw
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 74#include <asm/system.h> 75#include <asm/io.h> 76#include <asm/uaccess.h> 77#include <linux/blkdev.h> 78#include "sjcd.h" 79 80static int sjcd_present = 0; 81static struct request_queue *sjcd_queue; 82 83#define MAJOR_NR SANYO_CDROM_MAJOR 84#define QUEUE (sjcd_queue) 85#define CURRENT elv_next_request(sjcd_queue) 86 87#define SJCD_BUF_SIZ 32 /* cdr-h94a has internal 64K buffer */ 88 89/* 90 * buffer for block size conversion 91 */ 92static char sjcd_buf[2048 * SJCD_BUF_SIZ]; 93static volatile int sjcd_buf_bn[SJCD_BUF_SIZ], sjcd_next_bn; 94static volatile int sjcd_buf_in, sjcd_buf_out = -1; 95 96/* 97 * Status. 98 */ 99static unsigned short sjcd_status_valid = 0; 100static unsigned short sjcd_door_closed; 101static unsigned short sjcd_door_was_open; 102static unsigned short sjcd_media_is_available; 103static unsigned short sjcd_media_is_changed; 104static unsigned short sjcd_toc_uptodate = 0; 105static unsigned short sjcd_command_failed; 106static volatile unsigned char sjcd_completion_status = 0; 107static volatile unsigned char sjcd_completion_error = 0; 108static unsigned short sjcd_command_is_in_progress = 0; 109static unsigned short sjcd_error_reported = 0; 110static DEFINE_SPINLOCK(sjcd_lock); 111 112static int sjcd_open_count; 113 114static int sjcd_audio_status; 115static struct sjcd_play_msf sjcd_playing; 116 117static int sjcd_base = SJCD_BASE_ADDR; 118 119module_param(sjcd_base, int, 0); 120 121static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq); 122 123/* 124 * Data transfer. 125 */ 126static volatile unsigned short sjcd_transfer_is_active = 0; 127 128enum sjcd_transfer_state { 129 SJCD_S_IDLE = 0, 130 SJCD_S_START = 1, 131 SJCD_S_MODE = 2, 132 SJCD_S_READ = 3, 133 SJCD_S_DATA = 4, 134 SJCD_S_STOP = 5, 135 SJCD_S_STOPPING = 6 136}; 137static enum sjcd_transfer_state sjcd_transfer_state = SJCD_S_IDLE; 138static long sjcd_transfer_timeout = 0; 139static int sjcd_read_count = 0; 140static unsigned char sjcd_mode = 0; 141 142#define SJCD_READ_TIMEOUT 5000 143 144#if defined( SJCD_GATHER_STAT ) 145/* 146 * Statistic. 147 */ 148static struct sjcd_stat statistic; 149#endif 150 151/* 152 * Timer. 153 */ 154static DEFINE_TIMER(sjcd_delay_timer, NULL, 0, 0); 155 156#define SJCD_SET_TIMER( func, tmout ) \ 157 ( sjcd_delay_timer.expires = jiffies+tmout, \ 158 sjcd_delay_timer.function = ( void * )func, \ 159 add_timer( &sjcd_delay_timer ) ) 160 161#define CLEAR_TIMER del_timer( &sjcd_delay_timer ) 162 163/* 164 * Set up device, i.e., use command line data to set 165 * base address. 166 */ 167#ifndef MODULE 168static int __init sjcd_setup(char *str) 169{ 170 int ints[2]; 171 (void) get_options(str, ARRAY_SIZE(ints), ints); 172 if (ints[0] > 0) 173 sjcd_base = ints[1]; 174 175 return 1; 176} 177 178__setup("sjcd=", sjcd_setup); 179 180#endif 181 182/* 183 * Special converters. 184 */ 185static unsigned char bin2bcd(int bin) 186{ 187 int u, v; 188 189 u = bin % 10; 190 v = bin / 10; 191 return (u | (v << 4)); 192} 193 194static int bcd2bin(unsigned char bcd) 195{ 196 return ((bcd >> 4) * 10 + (bcd & 0x0F)); 197} 198 199static long msf2hsg(struct msf *mp) 200{ 201 return (bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 202 + bcd2bin(mp->min) * 4500 - 150); 203} 204 205static void hsg2msf(long hsg, struct msf *msf) 206{ 207 hsg += 150; 208 msf->min = hsg / 4500; 209 hsg %= 4500; 210 msf->sec = hsg / 75; 211 msf->frame = hsg % 75; 212 msf->min = bin2bcd(msf->min); /* convert to BCD */ 213 msf->sec = bin2bcd(msf->sec); 214 msf->frame = bin2bcd(msf->frame); 215} 216 217/* 218 * Send a command to cdrom. Invalidate status. 219 */ 220static void sjcd_send_cmd(unsigned char cmd) 221{ 222#if defined( SJCD_TRACE ) 223 printk("SJCD: send_cmd( 0x%x )\n", cmd); 224#endif 225 outb(cmd, SJCDPORT(0)); 226 sjcd_command_is_in_progress = 1; 227 sjcd_status_valid = 0; 228 sjcd_command_failed = 0; 229} 230 231/* 232 * Send a command with one arg to cdrom. Invalidate status. 233 */ 234static void sjcd_send_1_cmd(unsigned char cmd, unsigned char a) 235{ 236#if defined( SJCD_TRACE ) 237 printk("SJCD: send_1_cmd( 0x%x, 0x%x )\n", cmd, a); 238#endif 239 outb(cmd, SJCDPORT(0)); 240 outb(a, SJCDPORT(0)); 241 sjcd_command_is_in_progress = 1; 242 sjcd_status_valid = 0; 243 sjcd_command_failed = 0; 244} 245 246/* 247 * Send a command with four args to cdrom. Invalidate status. 248 */ 249static void sjcd_send_4_cmd(unsigned char cmd, unsigned char a, 250 unsigned char b, unsigned char c, 251 unsigned char d) 252{ 253#if defined( SJCD_TRACE ) 254 printk("SJCD: send_4_cmd( 0x%x )\n", cmd); 255#endif 256 outb(cmd, SJCDPORT(0)); 257 outb(a, SJCDPORT(0)); 258 outb(b, SJCDPORT(0)); 259 outb(c, SJCDPORT(0)); 260 outb(d, SJCDPORT(0)); 261 sjcd_command_is_in_progress = 1; 262 sjcd_status_valid = 0; 263 sjcd_command_failed = 0; 264} 265 266/* 267 * Send a play or read command to cdrom. Invalidate Status. 268 */ 269static void sjcd_send_6_cmd(unsigned char cmd, struct sjcd_play_msf *pms) 270{ 271#if defined( SJCD_TRACE ) 272 printk("SJCD: send_long_cmd( 0x%x )\n", cmd); 273#endif 274 outb(cmd, SJCDPORT(0)); 275 outb(pms->start.min, SJCDPORT(0)); 276 outb(pms->start.sec, SJCDPORT(0)); 277 outb(pms->start.frame, SJCDPORT(0)); 278 outb(pms->end.min, SJCDPORT(0)); 279 outb(pms->end.sec, SJCDPORT(0)); 280 outb(pms->end.frame, SJCDPORT(0)); 281 sjcd_command_is_in_progress = 1; 282 sjcd_status_valid = 0; 283 sjcd_command_failed = 0; 284} 285 286/* 287 * Get a value from the data port. Should not block, so we use a little 288 * wait for a while. Returns 0 if OK. 289 */ 290static int sjcd_load_response(void *buf, int len) 291{ 292 unsigned char *resp = (unsigned char *) buf; 293 294 for (; len; --len) { 295 int i; 296 for (i = 200; 297 i-- && !SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)));); 298 if (i > 0) 299 *resp++ = (unsigned char) inb(SJCDPORT(0)); 300 else 301 break; 302 } 303 return (len); 304} 305 306/* 307 * Load and parse command completion status (drive info byte and maybe error). 308 * Sorry, no error classification yet. 309 */ 310static void sjcd_load_status(void) 311{ 312 sjcd_media_is_changed = 0; 313 sjcd_completion_error = 0; 314 sjcd_completion_status = inb(SJCDPORT(0)); 315 if (sjcd_completion_status & SST_DOOR_OPENED) { 316 sjcd_door_closed = sjcd_media_is_available = 0; 317 } else { 318 sjcd_door_closed = 1; 319 if (sjcd_completion_status & SST_MEDIA_CHANGED) 320 sjcd_media_is_available = sjcd_media_is_changed = 321 1; 322 else if (sjcd_completion_status & 0x0F) { 323 /* 324 * OK, we seem to catch an error ... 325 */ 326 while (!SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))); 327 sjcd_completion_error = inb(SJCDPORT(0)); 328 if ((sjcd_completion_status & 0x08) && 329 (sjcd_completion_error & 0x40)) 330 sjcd_media_is_available = 0; 331 else 332 sjcd_command_failed = 1; 333 } else 334 sjcd_media_is_available = 1; 335 } 336 /* 337 * Ok, status loaded successfully. 338 */ 339 sjcd_status_valid = 1, sjcd_error_reported = 0; 340 sjcd_command_is_in_progress = 0; 341 342 /* 343 * If the disk is changed, the TOC is not valid. 344 */ 345 if (sjcd_media_is_changed) 346 sjcd_toc_uptodate = 0; 347#if defined( SJCD_TRACE ) 348 printk("SJCD: status %02x.%02x loaded.\n", 349 (int) sjcd_completion_status, (int) sjcd_completion_error); 350#endif 351} 352 353/* 354 * Read status from cdrom. Check to see if the status is available. 355 */ 356static int sjcd_check_status(void) 357{ 358 /* 359 * Try to load the response from cdrom into buffer. 360 */ 361 if (SJCD_STATUS_AVAILABLE(inb(SJCDPORT(1)))) { 362 sjcd_load_status(); 363 return (1); 364 } else { 365 /* 366 * No status is available. 367 */ 368 return (0); 369 } 370} 371 372/* 373 * This is just timeout counter, and nothing more. Surprised ? :-) 374 */ 375static volatile long sjcd_status_timeout; 376 377/* 378 * We need about 10 seconds to wait. The longest command takes about 5 seconds 379 * to probe the disk (usually after tray closed or drive reset). Other values 380 * should be thought of for other commands. 381 */ 382#define SJCD_WAIT_FOR_STATUS_TIMEOUT 1000 383 384static void sjcd_status_timer(void) 385{ 386 if (sjcd_check_status()) { 387 /* 388 * The command completed and status is loaded, stop waiting. 389 */ 390 wake_up(&sjcd_waitq); 391 } else if (--sjcd_status_timeout <= 0) { 392 /* 393 * We are timed out. 394 */ 395 wake_up(&sjcd_waitq); 396 } else { 397 /* 398 * We have still some time to wait. Try again. 399 */ 400 SJCD_SET_TIMER(sjcd_status_timer, 1); 401 } 402} 403 404/* 405 * Wait for status for 10 sec approx. Returns non-positive when timed out. 406 * Should not be used while reading data CDs. 407 */ 408static int sjcd_wait_for_status(void) 409{ 410 sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT; 411 SJCD_SET_TIMER(sjcd_status_timer, 1); 412 sleep_on(&sjcd_waitq); 413#if defined( SJCD_DIAGNOSTIC ) || defined ( SJCD_TRACE ) 414 if (sjcd_status_timeout <= 0) 415 printk("SJCD: Error Wait For Status.\n"); 416#endif 417 return (sjcd_status_timeout); 418} 419 420static int sjcd_receive_status(void) 421{ 422 int i; 423#if defined( SJCD_TRACE ) 424 printk("SJCD: receive_status\n"); 425#endif 426 /* 427 * Wait a bit for status available. 428 */ 429 for (i = 200; i-- && (sjcd_check_status() == 0);); 430 if (i < 0) { 431#if defined( SJCD_TRACE ) 432 printk("SJCD: long wait for status\n"); 433#endif 434 if (sjcd_wait_for_status() <= 0) 435 printk("SJCD: Timeout when read status.\n"); 436 else 437 i = 0; 438 } 439 return (i); 440} 441 442/* 443 * Load the status. Issue get status command and wait for status available. 444 */ 445static void sjcd_get_status(void) 446{ 447#if defined( SJCD_TRACE ) 448 printk("SJCD: get_status\n"); 449#endif 450 sjcd_send_cmd(SCMD_GET_STATUS); 451 sjcd_receive_status(); 452} 453 454/* 455 * Check the drive if the disk is changed. Should be revised. 456 */ 457static int sjcd_disk_change(struct gendisk *disk) 458{ 459#if 0 460 printk("SJCD: sjcd_disk_change(%s)\n", disk->disk_name); 461#endif 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 void __user *argp = (void __user *)arg; 720#if defined( SJCD_TRACE ) 721 printk("SJCD:ioctl\n"); 722#endif 723 724 sjcd_get_status(); 725 if (!sjcd_status_valid) 726 return (-EIO); 727 if (sjcd_update_toc() < 0) 728 return (-EIO); 729 730 switch (cmd) { 731 case CDROMSTART:{ 732#if defined( SJCD_TRACE ) 733 printk("SJCD: ioctl: start\n"); 734#endif 735 return (0); 736 } 737 738 case CDROMSTOP:{ 739#if defined( SJCD_TRACE ) 740 printk("SJCD: ioctl: stop\n"); 741#endif 742 sjcd_send_cmd(SCMD_PAUSE); 743 (void) sjcd_receive_status(); 744 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 745 return (0); 746 } 747 748 case CDROMPAUSE:{ 749 struct sjcd_hw_qinfo q_info; 750#if defined( SJCD_TRACE ) 751 printk("SJCD: ioctl: pause\n"); 752#endif 753 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 754 sjcd_send_cmd(SCMD_PAUSE); 755 (void) sjcd_receive_status(); 756 if (sjcd_get_q_info(&q_info) < 0) { 757 sjcd_audio_status = 758 CDROM_AUDIO_NO_STATUS; 759 } else { 760 sjcd_audio_status = 761 CDROM_AUDIO_PAUSED; 762 sjcd_playing.start = q_info.abs; 763 } 764 return (0); 765 } else 766 return (-EINVAL); 767 } 768 769 case CDROMRESUME:{ 770#if defined( SJCD_TRACE ) 771 printk("SJCD: ioctl: resume\n"); 772#endif 773 if (sjcd_audio_status == CDROM_AUDIO_PAUSED) { 774 /* 775 * continue play starting at saved location 776 */ 777 if (sjcd_play(&sjcd_playing) < 0) { 778 sjcd_audio_status = 779 CDROM_AUDIO_ERROR; 780 return (-EIO); 781 } else { 782 sjcd_audio_status = 783 CDROM_AUDIO_PLAY; 784 return (0); 785 } 786 } else 787 return (-EINVAL); 788 } 789 790 case CDROMPLAYTRKIND:{ 791 struct cdrom_ti ti; 792 int s = -EFAULT; 793#if defined( SJCD_TRACE ) 794 printk("SJCD: ioctl: playtrkind\n"); 795#endif 796 if (!copy_from_user(&ti, argp, sizeof(ti))) { 797 s = 0; 798 if (ti.cdti_trk0 < sjcd_first_track_no) 799 return (-EINVAL); 800 if (ti.cdti_trk1 > sjcd_last_track_no) 801 ti.cdti_trk1 = sjcd_last_track_no; 802 if (ti.cdti_trk0 > ti.cdti_trk1) 803 return (-EINVAL); 804 805 sjcd_playing.start = 806 sjcd_table_of_contents[ti.cdti_trk0]. 807 un.track_msf; 808 sjcd_playing.end = 809 (ti.cdti_trk1 < 810 sjcd_last_track_no) ? 811 sjcd_table_of_contents[ti.cdti_trk1 + 812 1].un. 813 track_msf : sjcd_table_of_contents[0]. 814 un.track_msf; 815 816 if (sjcd_play(&sjcd_playing) < 0) { 817 sjcd_audio_status = 818 CDROM_AUDIO_ERROR; 819 return (-EIO); 820 } else 821 sjcd_audio_status = 822 CDROM_AUDIO_PLAY; 823 } 824 return (s); 825 } 826 827 case CDROMPLAYMSF:{ 828 struct cdrom_msf sjcd_msf; 829 int s; 830#if defined( SJCD_TRACE ) 831 printk("SJCD: ioctl: playmsf\n"); 832#endif 833 if ((s = 834 access_ok(VERIFY_READ, argp, sizeof(sjcd_msf)) 835 ? 0 : -EFAULT) == 0) { 836 if (sjcd_audio_status == CDROM_AUDIO_PLAY) { 837 sjcd_send_cmd(SCMD_PAUSE); 838 (void) sjcd_receive_status(); 839 sjcd_audio_status = 840 CDROM_AUDIO_NO_STATUS; 841 } 842 843 if (copy_from_user(&sjcd_msf, argp, 844 sizeof(sjcd_msf))) 845 return (-EFAULT); 846 847 sjcd_playing.start.min = 848 bin2bcd(sjcd_msf.cdmsf_min0); 849 sjcd_playing.start.sec = 850 bin2bcd(sjcd_msf.cdmsf_sec0); 851 sjcd_playing.start.frame = 852 bin2bcd(sjcd_msf.cdmsf_frame0); 853 sjcd_playing.end.min = 854 bin2bcd(sjcd_msf.cdmsf_min1); 855 sjcd_playing.end.sec = 856 bin2bcd(sjcd_msf.cdmsf_sec1); 857 sjcd_playing.end.frame = 858 bin2bcd(sjcd_msf.cdmsf_frame1); 859 860 if (sjcd_play(&sjcd_playing) < 0) { 861 sjcd_audio_status = 862 CDROM_AUDIO_ERROR; 863 return (-EIO); 864 } else 865 sjcd_audio_status = 866 CDROM_AUDIO_PLAY; 867 } 868 return (s); 869 } 870 871 case CDROMREADTOCHDR:{ 872 struct cdrom_tochdr toc_header; 873#if defined (SJCD_TRACE ) 874 printk("SJCD: ioctl: readtocheader\n"); 875#endif 876 toc_header.cdth_trk0 = sjcd_first_track_no; 877 toc_header.cdth_trk1 = sjcd_last_track_no; 878 if (copy_to_user(argp, &toc_header, 879 sizeof(toc_header))) 880 return -EFAULT; 881 return 0; 882 } 883 884 case CDROMREADTOCENTRY:{ 885 struct cdrom_tocentry toc_entry; 886 int s; 887#if defined( SJCD_TRACE ) 888 printk("SJCD: ioctl: readtocentry\n"); 889#endif 890 if ((s = 891 access_ok(VERIFY_WRITE, argp, sizeof(toc_entry)) 892 ? 0 : -EFAULT) == 0) { 893 struct sjcd_hw_disk_info *tp; 894 895 if (copy_from_user(&toc_entry, argp, 896 sizeof(toc_entry))) 897 return (-EFAULT); 898 if (toc_entry.cdte_track == CDROM_LEADOUT) 899 tp = &sjcd_table_of_contents[0]; 900 else if (toc_entry.cdte_track < 901 sjcd_first_track_no) 902 return (-EINVAL); 903 else if (toc_entry.cdte_track > 904 sjcd_last_track_no) 905 return (-EINVAL); 906 else 907 tp = &sjcd_table_of_contents 908 [toc_entry.cdte_track]; 909 910 toc_entry.cdte_adr = 911 tp->track_control & 0x0F; 912 toc_entry.cdte_ctrl = 913 tp->track_control >> 4; 914 915 switch (toc_entry.cdte_format) { 916 case CDROM_LBA: 917 toc_entry.cdte_addr.lba = 918 msf2hsg(&(tp->un.track_msf)); 919 break; 920 case CDROM_MSF: 921 toc_entry.cdte_addr.msf.minute = 922 bcd2bin(tp->un.track_msf.min); 923 toc_entry.cdte_addr.msf.second = 924 bcd2bin(tp->un.track_msf.sec); 925 toc_entry.cdte_addr.msf.frame = 926 bcd2bin(tp->un.track_msf. 927 frame); 928 break; 929 default: 930 return (-EINVAL); 931 } 932 if (copy_to_user(argp, &toc_entry, 933 sizeof(toc_entry))) 934 s = -EFAULT; 935 } 936 return (s); 937 } 938 939 case CDROMSUBCHNL:{ 940 struct cdrom_subchnl subchnl; 941 int s; 942#if defined( SJCD_TRACE ) 943 printk("SJCD: ioctl: subchnl\n"); 944#endif 945 if ((s = 946 access_ok(VERIFY_WRITE, argp, sizeof(subchnl)) 947 ? 0 : -EFAULT) == 0) { 948 struct sjcd_hw_qinfo q_info; 949 950 if (copy_from_user(&subchnl, argp, 951 sizeof(subchnl))) 952 return (-EFAULT); 953 954 if (sjcd_get_q_info(&q_info) < 0) 955 return (-EIO); 956 957 subchnl.cdsc_audiostatus = 958 sjcd_audio_status; 959 subchnl.cdsc_adr = 960 q_info.track_control & 0x0F; 961 subchnl.cdsc_ctrl = 962 q_info.track_control >> 4; 963 subchnl.cdsc_trk = 964 bcd2bin(q_info.track_no); 965 subchnl.cdsc_ind = bcd2bin(q_info.x); 966 967 switch (subchnl.cdsc_format) { 968 case CDROM_LBA: 969 subchnl.cdsc_absaddr.lba = 970 msf2hsg(&(q_info.abs)); 971 subchnl.cdsc_reladdr.lba = 972 msf2hsg(&(q_info.rel)); 973 break; 974 case CDROM_MSF: 975 subchnl.cdsc_absaddr.msf.minute = 976 bcd2bin(q_info.abs.min); 977 subchnl.cdsc_absaddr.msf.second = 978 bcd2bin(q_info.abs.sec); 979 subchnl.cdsc_absaddr.msf.frame = 980 bcd2bin(q_info.abs.frame); 981 subchnl.cdsc_reladdr.msf.minute = 982 bcd2bin(q_info.rel.min); 983 subchnl.cdsc_reladdr.msf.second = 984 bcd2bin(q_info.rel.sec); 985 subchnl.cdsc_reladdr.msf.frame = 986 bcd2bin(q_info.rel.frame); 987 break; 988 default: 989 return (-EINVAL); 990 } 991 if (copy_to_user(argp, &subchnl, 992 sizeof(subchnl))) 993 s = -EFAULT; 994 } 995 return (s); 996 } 997 998 case CDROMVOLCTRL:{ 999 struct cdrom_volctrl vol_ctrl; 1000 int s; 1001#if defined( SJCD_TRACE ) 1002 printk("SJCD: ioctl: volctrl\n"); 1003#endif 1004 if ((s = 1005 access_ok(VERIFY_READ, argp, sizeof(vol_ctrl)) 1006 ? 0 : -EFAULT) == 0) { 1007 unsigned char dummy[4]; 1008 1009 if (copy_from_user(&vol_ctrl, argp, 1010 sizeof(vol_ctrl))) 1011 return (-EFAULT); 1012 sjcd_send_4_cmd(SCMD_SET_VOLUME, 1013 vol_ctrl.channel0, 0xFF, 1014 vol_ctrl.channel1, 0xFF); 1015 if (sjcd_receive_status() < 0) 1016 return (-EIO); 1017 (void) sjcd_load_response(dummy, 4); 1018 } 1019 return (s); 1020 } 1021 1022 case CDROMEJECT:{ 1023#if defined( SJCD_TRACE ) 1024 printk("SJCD: ioctl: eject\n"); 1025#endif 1026 if (!sjcd_command_is_in_progress) { 1027 sjcd_tray_unlock(); 1028 sjcd_send_cmd(SCMD_EJECT_TRAY); 1029 (void) sjcd_receive_status(); 1030 } 1031 return (0); 1032 } 1033 1034#if defined( SJCD_GATHER_STAT ) 1035 case 0xABCD:{ 1036#if defined( SJCD_TRACE ) 1037 printk("SJCD: ioctl: statistic\n"); 1038#endif 1039 if (copy_to_user(argp, &statistic, sizeof(statistic))) 1040 return -EFAULT; 1041 return 0; 1042 } 1043#endif 1044 1045 default: 1046 return (-EINVAL); 1047 } 1048} 1049 1050/* 1051 * Invalidate internal buffers of the driver. 1052 */ 1053static void sjcd_invalidate_buffers(void) 1054{ 1055 int i; 1056 for (i = 0; i < SJCD_BUF_SIZ; sjcd_buf_bn[i++] = -1); 1057 sjcd_buf_out = -1; 1058} 1059 1060/* 1061 * Take care of the different block sizes between cdrom and Linux. 1062 * When Linux gets variable block sizes this will probably go away. 1063 */ 1064 1065static int current_valid(void) 1066{ 1067 return CURRENT && 1068 CURRENT->cmd == READ && 1069 CURRENT->sector != -1; 1070} 1071 1072static void sjcd_transfer(void) 1073{ 1074#if defined( SJCD_TRACE ) 1075 printk("SJCD: transfer:\n"); 1076#endif 1077 if (current_valid()) { 1078 while (CURRENT->nr_sectors) { 1079 int i, bn = CURRENT->sector / 4; 1080 for (i = 0; 1081 i < SJCD_BUF_SIZ && sjcd_buf_bn[i] != bn; 1082 i++); 1083 if (i < SJCD_BUF_SIZ) { 1084 int offs = 1085 (i * 4 + (CURRENT->sector & 3)) * 512; 1086 int nr_sectors = 4 - (CURRENT->sector & 3); 1087 if (sjcd_buf_out != i) { 1088 sjcd_buf_out = i; 1089 if (sjcd_buf_bn[i] != bn) { 1090 sjcd_buf_out = -1; 1091 continue; 1092 } 1093 } 1094 if (nr_sectors > CURRENT->nr_sectors) 1095 nr_sectors = CURRENT->nr_sectors; 1096#if defined( SJCD_TRACE ) 1097 printk("SJCD: copy out\n"); 1098#endif 1099 memcpy(CURRENT->buffer, sjcd_buf + offs, 1100 nr_sectors * 512); 1101 CURRENT->nr_sectors -= nr_sectors; 1102 CURRENT->sector += nr_sectors; 1103 CURRENT->buffer += nr_sectors * 512; 1104 } else { 1105 sjcd_buf_out = -1; 1106 break; 1107 } 1108 } 1109 } 1110#if defined( SJCD_TRACE ) 1111 printk("SJCD: transfer: done\n"); 1112#endif 1113} 1114 1115static void sjcd_poll(void) 1116{ 1117#if defined( SJCD_GATHER_STAT ) 1118 /* 1119 * Update total number of ticks. 1120 */ 1121 statistic.ticks++; 1122 statistic.tticks[sjcd_transfer_state]++; 1123#endif 1124 1125 ReSwitch:switch (sjcd_transfer_state) { 1126 1127 case SJCD_S_IDLE:{ 1128#if defined( SJCD_GATHER_STAT ) 1129 statistic.idle_ticks++; 1130#endif 1131#if defined( SJCD_TRACE ) 1132 printk("SJCD_S_IDLE\n"); 1133#endif 1134 return; 1135 } 1136 1137 case SJCD_S_START:{ 1138#if defined( SJCD_GATHER_STAT ) 1139 statistic.start_ticks++; 1140#endif 1141 sjcd_send_cmd(SCMD_GET_STATUS); 1142 sjcd_transfer_state = 1143 sjcd_mode == 1144 SCMD_MODE_COOKED ? SJCD_S_READ : SJCD_S_MODE; 1145 sjcd_transfer_timeout = 500; 1146#if defined( SJCD_TRACE ) 1147 printk("SJCD_S_START: goto SJCD_S_%s mode\n", 1148 sjcd_transfer_state == 1149 SJCD_S_READ ? "READ" : "MODE"); 1150#endif 1151 break; 1152 } 1153 1154 case SJCD_S_MODE:{ 1155 if (sjcd_check_status()) { 1156 /* 1157 * Previous command is completed. 1158 */ 1159 if (!sjcd_status_valid 1160 || sjcd_command_failed) { 1161#if defined( SJCD_TRACE ) 1162 printk 1163 ("SJCD_S_MODE: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1164#endif 1165 sjcd_transfer_state = SJCD_S_STOP; 1166 goto ReSwitch; 1167 } 1168 1169 sjcd_mode = 0; /* unknown mode; should not be valid when failed */ 1170 sjcd_send_1_cmd(SCMD_SET_MODE, 1171 SCMD_MODE_COOKED); 1172 sjcd_transfer_state = SJCD_S_READ; 1173 sjcd_transfer_timeout = 1000; 1174#if defined( SJCD_TRACE ) 1175 printk 1176 ("SJCD_S_MODE: goto SJCD_S_READ mode\n"); 1177#endif 1178 } 1179#if defined( SJCD_GATHER_STAT ) 1180 else 1181 statistic.mode_ticks++; 1182#endif 1183 break; 1184 } 1185 1186 case SJCD_S_READ:{ 1187 if (sjcd_status_valid ? 1 : sjcd_check_status()) { 1188 /* 1189 * Previous command is completed. 1190 */ 1191 if (!sjcd_status_valid 1192 || sjcd_command_failed) { 1193#if defined( SJCD_TRACE ) 1194 printk 1195 ("SJCD_S_READ: pre-cmd failed: goto to SJCD_S_STOP mode\n"); 1196#endif 1197 sjcd_transfer_state = SJCD_S_STOP; 1198 goto ReSwitch; 1199 } 1200 if (!sjcd_media_is_available) { 1201#if defined( SJCD_TRACE ) 1202 printk 1203 ("SJCD_S_READ: no disk: goto to SJCD_S_STOP mode\n"); 1204#endif 1205 sjcd_transfer_state = SJCD_S_STOP; 1206 goto ReSwitch; 1207 } 1208 if (sjcd_mode != SCMD_MODE_COOKED) { 1209 /* 1210 * We seem to come from set mode. So discard one byte of result. 1211 */ 1212 if (sjcd_load_response 1213 (&sjcd_mode, 1) != 0) { 1214#if defined( SJCD_TRACE ) 1215 printk 1216 ("SJCD_S_READ: load failed: goto to SJCD_S_STOP mode\n"); 1217#endif 1218 sjcd_transfer_state = 1219 SJCD_S_STOP; 1220 goto ReSwitch; 1221 } 1222 if (sjcd_mode != SCMD_MODE_COOKED) { 1223#if defined( SJCD_TRACE ) 1224 printk 1225 ("SJCD_S_READ: mode failed: goto to SJCD_S_STOP mode\n"); 1226#endif 1227 sjcd_transfer_state = 1228 SJCD_S_STOP; 1229 goto ReSwitch; 1230 } 1231 } 1232 1233 if (current_valid()) { 1234 struct sjcd_play_msf msf; 1235 1236 sjcd_next_bn = CURRENT->sector / 4; 1237 hsg2msf(sjcd_next_bn, &msf.start); 1238 msf.end.min = 0; 1239 msf.end.sec = 0; 1240 msf.end.frame = sjcd_read_count = 1241 SJCD_BUF_SIZ; 1242#if defined( SJCD_TRACE ) 1243 printk 1244 ("SJCD: ---reading msf-address %x:%x:%x %x:%x:%x\n", 1245 msf.start.min, msf.start.sec, 1246 msf.start.frame, msf.end.min, 1247 msf.end.sec, msf.end.frame); 1248 printk 1249 ("sjcd_next_bn:%x buf_in:%x buf_out:%x buf_bn:%x\n", 1250 sjcd_next_bn, sjcd_buf_in, 1251 sjcd_buf_out, 1252 sjcd_buf_bn[sjcd_buf_in]); 1253#endif 1254 sjcd_send_6_cmd(SCMD_DATA_READ, 1255 &msf); 1256 sjcd_transfer_state = SJCD_S_DATA; 1257 sjcd_transfer_timeout = 500; 1258#if defined( SJCD_TRACE ) 1259 printk 1260 ("SJCD_S_READ: go to SJCD_S_DATA mode\n"); 1261#endif 1262 } else { 1263#if defined( SJCD_TRACE ) 1264 printk 1265 ("SJCD_S_READ: nothing to read: go to SJCD_S_STOP mode\n"); 1266#endif 1267 sjcd_transfer_state = SJCD_S_STOP; 1268 goto ReSwitch; 1269 } 1270 } 1271#if defined( SJCD_GATHER_STAT ) 1272 else 1273 statistic.read_ticks++; 1274#endif 1275 break; 1276 } 1277 1278 case SJCD_S_DATA:{ 1279 unsigned char stat; 1280 1281 sjcd_s_data:stat = 1282 inb(SJCDPORT 1283 (1)); 1284#if defined( SJCD_TRACE ) 1285 printk("SJCD_S_DATA: status = 0x%02x\n", stat); 1286#endif 1287 if (SJCD_STATUS_AVAILABLE(stat)) { 1288 /* 1289 * No data is waiting for us in the drive buffer. Status of operation 1290 * completion is available. Read and parse it. 1291 */ 1292 sjcd_load_status(); 1293 1294 if (!sjcd_status_valid 1295 || sjcd_command_failed) { 1296#if defined( SJCD_TRACE ) 1297 printk 1298 ("SJCD: read block %d failed, maybe audio disk? Giving up\n", 1299 sjcd_next_bn); 1300#endif 1301 if (current_valid()) 1302 end_request(CURRENT, 0); 1303#if defined( SJCD_TRACE ) 1304 printk 1305 ("SJCD_S_DATA: pre-cmd failed: go to SJCD_S_STOP mode\n"); 1306#endif 1307 sjcd_transfer_state = SJCD_S_STOP; 1308 goto ReSwitch; 1309 } 1310 1311 if (!sjcd_media_is_available) { 1312 printk 1313 ("SJCD_S_DATA: no disk: go to SJCD_S_STOP mode\n"); 1314 sjcd_transfer_state = SJCD_S_STOP; 1315 goto ReSwitch; 1316 } 1317 1318 sjcd_transfer_state = SJCD_S_READ; 1319 goto ReSwitch; 1320 } else if (SJCD_DATA_AVAILABLE(stat)) { 1321 /* 1322 * One frame is read into device buffer. We must copy it to our memory. 1323 * Otherwise cdrom hangs up. Check to see if we have something to copy 1324 * to. 1325 */ 1326 if (!current_valid() 1327 && sjcd_buf_in == sjcd_buf_out) { 1328#if defined( SJCD_TRACE ) 1329 printk 1330 ("SJCD_S_DATA: nothing to read: go to SJCD_S_STOP mode\n"); 1331 printk 1332 (" ... all the date would be discarded\n"); 1333#endif 1334 sjcd_transfer_state = SJCD_S_STOP; 1335 goto ReSwitch; 1336 } 1337 1338 /* 1339 * Everything seems to be OK. Just read the frame and recalculate 1340 * indices. 1341 */ 1342 sjcd_buf_bn[sjcd_buf_in] = -1; /* ??? */ 1343 insb(SJCDPORT(2), 1344 sjcd_buf + 2048 * sjcd_buf_in, 2048); 1345#if defined( SJCD_TRACE ) 1346 printk 1347 ("SJCD_S_DATA: next_bn=%d, buf_in=%d, buf_out=%d, buf_bn=%d\n", 1348 sjcd_next_bn, sjcd_buf_in, 1349 sjcd_buf_out, 1350 sjcd_buf_bn[sjcd_buf_in]); 1351#endif 1352 sjcd_buf_bn[sjcd_buf_in] = sjcd_next_bn++; 1353 if (sjcd_buf_out == -1) 1354 sjcd_buf_out = sjcd_buf_in; 1355 if (++sjcd_buf_in == SJCD_BUF_SIZ) 1356 sjcd_buf_in = 0; 1357 1358 /* 1359 * Only one frame is ready at time. So we should turn over to wait for 1360 * another frame. If we need that, of course. 1361 */ 1362 if (--sjcd_read_count == 0) { 1363 /* 1364 * OK, request seems to be precessed. Continue transferring... 1365 */ 1366 if (!sjcd_transfer_is_active) { 1367 while (current_valid()) { 1368 /* 1369 * Continue transferring. 1370 */ 1371 sjcd_transfer(); 1372 if (CURRENT-> 1373 nr_sectors == 1374 0) 1375 end_request 1376 (CURRENT, 1); 1377 else 1378 break; 1379 } 1380 } 1381 if (current_valid() && 1382 (CURRENT->sector / 4 < 1383 sjcd_next_bn 1384 || CURRENT->sector / 4 > 1385 sjcd_next_bn + 1386 SJCD_BUF_SIZ)) { 1387#if defined( SJCD_TRACE ) 1388 printk 1389 ("SJCD_S_DATA: can't read: go to SJCD_S_STOP mode\n"); 1390#endif 1391 sjcd_transfer_state = 1392 SJCD_S_STOP; 1393 goto ReSwitch; 1394 } 1395 } 1396 /* 1397 * Now we should turn around rather than wait for while. 1398 */ 1399 goto sjcd_s_data; 1400 } 1401#if defined( SJCD_GATHER_STAT ) 1402 else 1403 statistic.data_ticks++; 1404#endif 1405 break; 1406 } 1407 1408 case SJCD_S_STOP:{ 1409 sjcd_read_count = 0; 1410 sjcd_send_cmd(SCMD_STOP); 1411 sjcd_transfer_state = SJCD_S_STOPPING; 1412 sjcd_transfer_timeout = 500; 1413#if defined( SJCD_GATHER_STAT ) 1414 statistic.stop_ticks++; 1415#endif 1416 break; 1417 } 1418 1419 case SJCD_S_STOPPING:{ 1420 unsigned char stat; 1421 1422 stat = inb(SJCDPORT(1)); 1423#if defined( SJCD_TRACE ) 1424 printk("SJCD_S_STOP: status = 0x%02x\n", stat); 1425#endif 1426 if (SJCD_DATA_AVAILABLE(stat)) { 1427 int i; 1428#if defined( SJCD_TRACE ) 1429 printk("SJCD_S_STOP: discard data\n"); 1430#endif 1431 /* 1432 * Discard all the data from the pipe. Foolish method. 1433 */ 1434 for (i = 2048; i--; 1435 (void) inb(SJCDPORT(2))); 1436 sjcd_transfer_timeout = 500; 1437 } else if (SJCD_STATUS_AVAILABLE(stat)) { 1438 sjcd_load_status(); 1439 if (sjcd_status_valid 1440 && sjcd_media_is_changed) { 1441 sjcd_toc_uptodate = 0; 1442 sjcd_invalidate_buffers(); 1443 } 1444 if (current_valid()) { 1445 if (sjcd_status_valid) 1446 sjcd_transfer_state = 1447 SJCD_S_READ; 1448 else 1449 sjcd_transfer_state = 1450 SJCD_S_START; 1451 } else 1452 sjcd_transfer_state = SJCD_S_IDLE; 1453 goto ReSwitch; 1454 } 1455#if defined( SJCD_GATHER_STAT ) 1456 else 1457 statistic.stopping_ticks++; 1458#endif 1459 break; 1460 } 1461 1462 default: 1463 printk("SJCD: poll: invalid state %d\n", 1464 sjcd_transfer_state); 1465 return; 1466 } 1467 1468 if (--sjcd_transfer_timeout == 0) { 1469 printk("SJCD: timeout in state %d\n", sjcd_transfer_state); 1470 while (current_valid()) 1471 end_request(CURRENT, 0); 1472 sjcd_send_cmd(SCMD_STOP); 1473 sjcd_transfer_state = SJCD_S_IDLE; 1474 goto ReSwitch; 1475 } 1476 1477 /* 1478 * Get back in some time. 1 should be replaced with count variable to 1479 * avoid unnecessary testings. 1480 */ 1481 SJCD_SET_TIMER(sjcd_poll, 1); 1482} 1483 1484static void do_sjcd_request(request_queue_t * q) 1485{ 1486#if defined( SJCD_TRACE ) 1487 printk("SJCD: do_sjcd_request(%ld+%ld)\n", 1488 CURRENT->sector, CURRENT->nr_sectors); 1489#endif 1490 sjcd_transfer_is_active = 1; 1491 while (current_valid()) { 1492 sjcd_transfer(); 1493 if (CURRENT->nr_sectors == 0) 1494 end_request(CURRENT, 1); 1495 else { 1496 sjcd_buf_out = -1; /* Want to read a block not in buffer */ 1497 if (sjcd_transfer_state == SJCD_S_IDLE) { 1498 if (!sjcd_toc_uptodate) { 1499 if (sjcd_update_toc() < 0) { 1500 printk 1501 ("SJCD: transfer: discard\n"); 1502 while (current_valid()) 1503 end_request(CURRENT, 0); 1504 break; 1505 } 1506 } 1507 sjcd_transfer_state = SJCD_S_START; 1508 SJCD_SET_TIMER(sjcd_poll, HZ / 100); 1509 } 1510 break; 1511 } 1512 } 1513 sjcd_transfer_is_active = 0; 1514#if defined( SJCD_TRACE ) 1515 printk 1516 ("sjcd_next_bn:%x sjcd_buf_in:%x sjcd_buf_out:%x sjcd_buf_bn:%x\n", 1517 sjcd_next_bn, sjcd_buf_in, sjcd_buf_out, 1518 sjcd_buf_bn[sjcd_buf_in]); 1519 printk("do_sjcd_request ends\n"); 1520#endif 1521} 1522 1523/* 1524 * Open the device special file. Check disk is in. 1525 */ 1526static int sjcd_open(struct inode *ip, struct file *fp) 1527{ 1528 /* 1529 * Check the presence of device. 1530 */ 1531 if (!sjcd_present) 1532 return (-ENXIO); 1533 1534 /* 1535 * Only read operations are allowed. Really? (:-) 1536 */ 1537 if (fp->f_mode & 2) 1538 return (-EROFS); 1539 1540 if (sjcd_open_count == 0) { 1541 int s, sjcd_open_tries; 1542/* We don't know that, do we? */ 1543/* 1544 sjcd_audio_status = CDROM_AUDIO_NO_STATUS; 1545*/ 1546 sjcd_mode = 0; 1547 sjcd_door_was_open = 0; 1548 sjcd_transfer_state = SJCD_S_IDLE; 1549 sjcd_invalidate_buffers(); 1550 sjcd_status_valid = 0; 1551 1552 /* 1553 * Strict status checking. 1554 */ 1555 for (sjcd_open_tries = 4; --sjcd_open_tries;) { 1556 if (!sjcd_status_valid) 1557 sjcd_get_status(); 1558 if (!sjcd_status_valid) { 1559#if defined( SJCD_DIAGNOSTIC ) 1560 printk 1561 ("SJCD: open: timed out when check status.\n"); 1562#endif 1563 goto err_out; 1564 } else if (!sjcd_media_is_available) { 1565#if defined( SJCD_DIAGNOSTIC ) 1566 printk("SJCD: open: no disk in drive\n"); 1567#endif 1568 if (!sjcd_door_closed) { 1569 sjcd_door_was_open = 1; 1570#if defined( SJCD_TRACE ) 1571 printk 1572 ("SJCD: open: close the tray\n"); 1573#endif 1574 s = sjcd_tray_close(); 1575 if (s < 0 || !sjcd_status_valid 1576 || sjcd_command_failed) { 1577#if defined( SJCD_DIAGNOSTIC ) 1578 printk 1579 ("SJCD: open: tray close attempt failed\n"); 1580#endif 1581 goto err_out; 1582 } 1583 continue; 1584 } else 1585 goto err_out; 1586 } 1587 break; 1588 } 1589 s = sjcd_tray_lock(); 1590 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1591#if defined( SJCD_DIAGNOSTIC ) 1592 printk("SJCD: open: tray lock attempt failed\n"); 1593#endif 1594 goto err_out; 1595 } 1596#if defined( SJCD_TRACE ) 1597 printk("SJCD: open: done\n"); 1598#endif 1599 } 1600 1601 ++sjcd_open_count; 1602 return (0); 1603 1604 err_out: 1605 return (-EIO); 1606} 1607 1608/* 1609 * On close, we flush all sjcd blocks from the buffer cache. 1610 */ 1611static int sjcd_release(struct inode *inode, struct file *file) 1612{ 1613 int s; 1614 1615#if defined( SJCD_TRACE ) 1616 printk("SJCD: release\n"); 1617#endif 1618 if (--sjcd_open_count == 0) { 1619 sjcd_invalidate_buffers(); 1620 s = sjcd_tray_unlock(); 1621 if (s < 0 || !sjcd_status_valid || sjcd_command_failed) { 1622#if defined( SJCD_DIAGNOSTIC ) 1623 printk 1624 ("SJCD: release: tray unlock attempt failed.\n"); 1625#endif 1626 } 1627 if (sjcd_door_was_open) { 1628 s = sjcd_tray_open(); 1629 if (s < 0 || !sjcd_status_valid 1630 || sjcd_command_failed) { 1631#if defined( SJCD_DIAGNOSTIC ) 1632 printk 1633 ("SJCD: release: tray unload attempt failed.\n"); 1634#endif 1635 } 1636 } 1637 } 1638 return 0; 1639} 1640 1641/* 1642 * A list of file operations allowed for this cdrom. 1643 */ 1644static struct block_device_operations sjcd_fops = { 1645 .owner = THIS_MODULE, 1646 .open = sjcd_open, 1647 .release = sjcd_release, 1648 .ioctl = sjcd_ioctl, 1649 .media_changed = sjcd_disk_change, 1650}; 1651 1652/* 1653 * Following stuff is intended for initialization of the cdrom. It 1654 * first looks for presence of device. If the device is present, it 1655 * will be reset. Then read the version of the drive and load status. 1656 * The version is two BCD-coded bytes. 1657 */ 1658static struct { 1659 unsigned char major, minor; 1660} sjcd_version; 1661 1662static struct gendisk *sjcd_disk; 1663 1664/* 1665 * Test for presence of drive and initialize it. Called at boot time. 1666 * Probe cdrom, find out version and status. 1667 */ 1668static int __init sjcd_init(void) 1669{ 1670 int i; 1671 1672 printk(KERN_INFO 1673 "SJCD: Sanyo CDR-H94A cdrom driver version %d.%d.\n", 1674 SJCD_VERSION_MAJOR, SJCD_VERSION_MINOR); 1675 1676#if defined( SJCD_TRACE ) 1677 printk("SJCD: sjcd=0x%x: ", sjcd_base); 1678#endif 1679 1680 if (register_blkdev(MAJOR_NR, "sjcd")) 1681 return -EIO; 1682 1683 sjcd_queue = blk_init_queue(do_sjcd_request, &sjcd_lock); 1684 if (!sjcd_queue) 1685 goto out0; 1686 1687 blk_queue_hardsect_size(sjcd_queue, 2048); 1688 1689 sjcd_disk = alloc_disk(1); 1690 if (!sjcd_disk) { 1691 printk(KERN_ERR "SJCD: can't allocate disk"); 1692 goto out1; 1693 } 1694 sjcd_disk->major = MAJOR_NR, 1695 sjcd_disk->first_minor = 0, 1696 sjcd_disk->fops = &sjcd_fops, 1697 sprintf(sjcd_disk->disk_name, "sjcd"); 1698 1699 if (!request_region(sjcd_base, 4,"sjcd")) { 1700 printk 1701 ("SJCD: Init failed, I/O port (%X) is already in use\n", 1702 sjcd_base); 1703 goto out2; 1704 } 1705 1706 /* 1707 * Check for card. Since we are booting now, we can't use standard 1708 * wait algorithm. 1709 */ 1710 printk(KERN_INFO "SJCD: Resetting: "); 1711 sjcd_send_cmd(SCMD_RESET); 1712 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1713 unsigned long timer; 1714 1715 /* 1716 * Wait 10ms approx. 1717 */ 1718 for (timer = jiffies; time_before_eq(jiffies, timer);); 1719 if ((i % 100) == 0) 1720 printk("."); 1721 (void) sjcd_check_status(); 1722 } 1723 if (i == 0 || sjcd_command_failed) { 1724 printk(" reset failed, no drive found.\n"); 1725 goto out3; 1726 } else 1727 printk("\n"); 1728 1729 /* 1730 * Get and print out cdrom version. 1731 */ 1732 printk(KERN_INFO "SJCD: Getting version: "); 1733 sjcd_send_cmd(SCMD_GET_VERSION); 1734 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1735 unsigned long timer; 1736 1737 /* 1738 * Wait 10ms approx. 1739 */ 1740 for (timer = jiffies; time_before_eq(jiffies, timer);); 1741 if ((i % 100) == 0) 1742 printk("."); 1743 (void) sjcd_check_status(); 1744 } 1745 if (i == 0 || sjcd_command_failed) { 1746 printk(" get version failed, no drive found.\n"); 1747 goto out3; 1748 } 1749 1750 if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { 1751 printk(" %1x.%02x\n", (int) sjcd_version.major, 1752 (int) sjcd_version.minor); 1753 } else { 1754 printk(" read version failed, no drive found.\n"); 1755 goto out3; 1756 } 1757 1758 /* 1759 * Check and print out the tray state. (if it is needed?). 1760 */ 1761 if (!sjcd_status_valid) { 1762 printk(KERN_INFO "SJCD: Getting status: "); 1763 sjcd_send_cmd(SCMD_GET_STATUS); 1764 for (i = 1000; i > 0 && !sjcd_status_valid; --i) { 1765 unsigned long timer; 1766 1767 /* 1768 * Wait 10ms approx. 1769 */ 1770 for (timer = jiffies; 1771 time_before_eq(jiffies, timer);); 1772 if ((i % 100) == 0) 1773 printk("."); 1774 (void) sjcd_check_status(); 1775 } 1776 if (i == 0 || sjcd_command_failed) { 1777 printk(" get status failed, no drive found.\n"); 1778 goto out3; 1779 } else 1780 printk("\n"); 1781 } 1782 1783 printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); 1784 sjcd_disk->queue = sjcd_queue; 1785 add_disk(sjcd_disk); 1786 1787 sjcd_present++; 1788 return (0); 1789out3: 1790 release_region(sjcd_base, 4); 1791out2: 1792 put_disk(sjcd_disk); 1793out1: 1794 blk_cleanup_queue(sjcd_queue); 1795out0: 1796 if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) 1797 printk("SJCD: cannot unregister device.\n"); 1798 return (-EIO); 1799} 1800 1801static void __exit sjcd_exit(void) 1802{ 1803 del_gendisk(sjcd_disk); 1804 put_disk(sjcd_disk); 1805 release_region(sjcd_base, 4); 1806 blk_cleanup_queue(sjcd_queue); 1807 if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) 1808 printk("SJCD: cannot unregister device.\n"); 1809 printk(KERN_INFO "SJCD: module: removed.\n"); 1810} 1811 1812module_init(sjcd_init); 1813module_exit(sjcd_exit); 1814 1815MODULE_LICENSE("GPL"); 1816MODULE_ALIAS_BLOCKDEV_MAJOR(SANYO_CDROM_MAJOR);