1/* 2 * The Mitsumi CDROM interface 3 * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de> 4 * VERSION: 2.14(hs) 5 * 6 * ... anyway, I'm back again, thanks to Marcin, he adopted 7 * large portions of my code (at least the parts containing 8 * my main thoughts ...) 9 * 10 ****************** H E L P ********************************* 11 * If you ever plan to update your CD ROM drive and perhaps 12 * want to sell or simply give away your Mitsumi FX-001[DS] 13 * -- Please -- 14 * mail me (heiko@lotte.sax.de). When my last drive goes 15 * ballistic no more driver support will be available from me! 16 ************************************************************* 17 * 18 * This program is free software; you can redistribute it and/or modify 19 * it under the terms of the GNU General Public License as published by 20 * the Free Software Foundation; either version 2, or (at your option) 21 * any later version. 22 * 23 * This program is distributed in the hope that it will be useful, 24 * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 * GNU General Public License for more details. 27 * 28 * You should have received a copy of the GNU General Public License 29 * along with this program; see the file COPYING. If not, write to 30 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 31 * 32 * Thanks to 33 * The Linux Community at all and ... 34 * Martin Harriss (he wrote the first Mitsumi Driver) 35 * Eberhard Moenkeberg (he gave me much support and the initial kick) 36 * Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they 37 * improved the original driver) 38 * Jon Tombs, Bjorn Ekwall (module support) 39 * Daniel v. Mosnenck (he sent me the Technical and Programming Reference) 40 * Gerd Knorr (he lent me his PhotoCD) 41 * Nils Faerber and Roger E. Wolff (extensively tested the LU portion) 42 * Andreas Kies (testing the mysterious hang-ups) 43 * Heiko Eissfeldt (VERIFY_READ/WRITE) 44 * Marcin Dalecki (improved performance, shortened code) 45 * ... somebody forgotten? 46 * 47 * 9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 48 * Removed init_module & cleanup_module in favor of 49 * module_init & module_exit. 50 * Torben Mathiasen <tmm@image.dk> 51 */ 52 53 54#ifdef RCS 55static const char *mcdx_c_version 56 = "$Id: mcdx.c,v 1.1.1.1 2007-08-03 18:52:27 $"; 57#endif 58 59#include <linux/module.h> 60 61#include <linux/errno.h> 62#include <linux/interrupt.h> 63#include <linux/fs.h> 64#include <linux/kernel.h> 65#include <linux/cdrom.h> 66#include <linux/ioport.h> 67#include <linux/mm.h> 68#include <linux/slab.h> 69#include <linux/init.h> 70#include <asm/io.h> 71#include <asm/current.h> 72#include <asm/uaccess.h> 73 74#include <linux/major.h> 75#define MAJOR_NR MITSUMI_X_CDROM_MAJOR 76#include <linux/blkdev.h> 77 78#include "mcdx.h" 79 80#ifndef HZ 81#error HZ not defined 82#endif 83 84#define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args) 85 86#if !MCDX_QUIET 87#define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args) 88#else 89#define xinfo(fmt, args...) { ; } 90#endif 91 92#if MCDX_DEBUG 93#define xtrace(lvl, fmt, args...) \ 94 { if (lvl > 0) \ 95 { printk(KERN_DEBUG MCDX ":: " fmt, ## args); } } 96#define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args) 97#else 98#define xtrace(lvl, fmt, args...) { ; } 99#define xdebug(fmt, args...) { ; } 100#endif 101 102/* CONSTANTS *******************************************************/ 103 104/* Following are the number of sectors we _request_ from the drive 105 every time an access outside the already requested range is done. 106 The _direct_ size is the number of sectors we're allowed to skip 107 directly (performing a read instead of requesting the new sector 108 needed */ 109static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */ 110static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */ 111 112enum drivemodes { TOC, DATA, RAW, COOKED }; 113enum datamodes { MODE0, MODE1, MODE2 }; 114enum resetmodes { SOFT, HARD }; 115 116static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ 117static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ 118static const int DOOR = 0x04; /* door locking capability */ 119static const int MULTI = 0x08; /* multi session capability */ 120 121static const unsigned char READ1X = 0xc0; 122static const unsigned char READ2X = 0xc1; 123 124 125/* DECLARATIONS ****************************************************/ 126struct s_subqcode { 127 unsigned char control; 128 unsigned char tno; 129 unsigned char index; 130 struct cdrom_msf0 tt; 131 struct cdrom_msf0 dt; 132}; 133 134struct s_diskinfo { 135 unsigned int n_first; 136 unsigned int n_last; 137 struct cdrom_msf0 msf_leadout; 138 struct cdrom_msf0 msf_first; 139}; 140 141struct s_multi { 142 unsigned char multi; 143 struct cdrom_msf0 msf_last; 144}; 145 146struct s_version { 147 unsigned char code; 148 unsigned char ver; 149}; 150 151/* Per drive/controller stuff **************************************/ 152 153struct s_drive_stuff { 154 /* waitqueues */ 155 wait_queue_head_t busyq; 156 wait_queue_head_t lockq; 157 wait_queue_head_t sleepq; 158 159 /* flags */ 160 volatile int introk; /* status of last irq operation */ 161 volatile int busy; /* drive performs an operation */ 162 volatile int lock; /* exclusive usage */ 163 164 /* cd infos */ 165 struct s_diskinfo di; 166 struct s_multi multi; 167 struct s_subqcode *toc; /* first entry of the toc array */ 168 struct s_subqcode start; 169 struct s_subqcode stop; 170 int xa; /* 1 if xa disk */ 171 int audio; /* 1 if audio disk */ 172 int audiostatus; 173 174 /* `buffer' control */ 175 volatile int valid; /* pending, ..., values are valid */ 176 volatile int pending; /* next sector to be read */ 177 volatile int low_border; /* first sector not to be skipped direct */ 178 volatile int high_border; /* first sector `out of area' */ 179#ifdef AK2 180 volatile int int_err; 181#endif /* AK2 */ 182 183 /* adds and odds */ 184 unsigned wreg_data; /* w data */ 185 unsigned wreg_reset; /* w hardware reset */ 186 unsigned wreg_hcon; /* w hardware conf */ 187 unsigned wreg_chn; /* w channel */ 188 unsigned rreg_data; /* r data */ 189 unsigned rreg_status; /* r status */ 190 191 int irq; /* irq used by this drive */ 192 int present; /* drive present and its capabilities */ 193 unsigned char readcmd; /* read cmd depends on single/double speed */ 194 unsigned char playcmd; /* play should always be single speed */ 195 unsigned int xxx; /* set if changed, reset while open */ 196 unsigned int yyy; /* set if changed, reset by media_changed */ 197 int users; /* keeps track of open/close */ 198 int lastsector; /* last block accessible */ 199 int status; /* last operation's error / status */ 200 int readerrs; /* # of blocks read w/o error */ 201 struct cdrom_device_info info; 202 struct gendisk *disk; 203}; 204 205 206/* Prototypes ******************************************************/ 207 208/* The following prototypes are already declared elsewhere. They are 209 repeated here to show what's going on. And to sense, if they're 210 changed elsewhere. */ 211 212static int mcdx_init(void); 213 214static int mcdx_block_open(struct inode *inode, struct file *file) 215{ 216 struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; 217 return cdrom_open(&p->info, inode, file); 218} 219 220static int mcdx_block_release(struct inode *inode, struct file *file) 221{ 222 struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; 223 return cdrom_release(&p->info, file); 224} 225 226static int mcdx_block_ioctl(struct inode *inode, struct file *file, 227 unsigned cmd, unsigned long arg) 228{ 229 struct s_drive_stuff *p = inode->i_bdev->bd_disk->private_data; 230 return cdrom_ioctl(file, &p->info, inode, cmd, arg); 231} 232 233static int mcdx_block_media_changed(struct gendisk *disk) 234{ 235 struct s_drive_stuff *p = disk->private_data; 236 return cdrom_media_changed(&p->info); 237} 238 239static struct block_device_operations mcdx_bdops = 240{ 241 .owner = THIS_MODULE, 242 .open = mcdx_block_open, 243 .release = mcdx_block_release, 244 .ioctl = mcdx_block_ioctl, 245 .media_changed = mcdx_block_media_changed, 246}; 247 248 249/* Indirect exported functions. These functions are exported by their 250 addresses, such as mcdx_open and mcdx_close in the 251 structure mcdx_dops. */ 252 253/* exported by file_ops */ 254static int mcdx_open(struct cdrom_device_info *cdi, int purpose); 255static void mcdx_close(struct cdrom_device_info *cdi); 256static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr); 257static int mcdx_tray_move(struct cdrom_device_info *cdi, int position); 258static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock); 259static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, 260 unsigned int cmd, void *arg); 261 262/* misc internal support functions */ 263static void log2msf(unsigned int, struct cdrom_msf0 *); 264static unsigned int msf2log(const struct cdrom_msf0 *); 265static unsigned int uint2bcd(unsigned int); 266static unsigned int bcd2uint(unsigned char); 267static unsigned port(int *); 268static int irq(int *); 269static void mcdx_delay(struct s_drive_stuff *, long jifs); 270static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector, 271 int nr_sectors); 272static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector, 273 int nr_sectors); 274 275static int mcdx_config(struct s_drive_stuff *, int); 276static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *, 277 int); 278static int mcdx_stop(struct s_drive_stuff *, int); 279static int mcdx_hold(struct s_drive_stuff *, int); 280static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int); 281static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int); 282static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int); 283static int mcdx_requestsubqcode(struct s_drive_stuff *, 284 struct s_subqcode *, int); 285static int mcdx_requestmultidiskinfo(struct s_drive_stuff *, 286 struct s_multi *, int); 287static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *, 288 int); 289static int mcdx_getstatus(struct s_drive_stuff *, int); 290static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *); 291static int mcdx_talk(struct s_drive_stuff *, 292 const unsigned char *cmd, size_t, 293 void *buffer, size_t size, unsigned int timeout, int); 294static int mcdx_readtoc(struct s_drive_stuff *); 295static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *); 296static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *); 297static int mcdx_setattentuator(struct s_drive_stuff *, 298 struct cdrom_volctrl *, int); 299 300/* static variables ************************************************/ 301 302static int mcdx_drive_map[][2] = MCDX_DRIVEMAP; 303static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES]; 304static DEFINE_SPINLOCK(mcdx_lock); 305static struct request_queue *mcdx_queue; 306 307/* You can only set the first two pairs, from old MODULE_PARM code. */ 308static int mcdx_set(const char *val, struct kernel_param *kp) 309{ 310 get_options((char *)val, 4, (int *)mcdx_drive_map); 311 return 0; 312} 313module_param_call(mcdx, mcdx_set, NULL, NULL, 0); 314 315static struct cdrom_device_ops mcdx_dops = { 316 .open = mcdx_open, 317 .release = mcdx_close, 318 .media_changed = mcdx_media_changed, 319 .tray_move = mcdx_tray_move, 320 .lock_door = mcdx_lockdoor, 321 .audio_ioctl = mcdx_audio_ioctl, 322 .capability = CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED | 323 CDC_PLAY_AUDIO | CDC_DRIVE_STATUS, 324}; 325 326/* KERNEL INTERFACE FUNCTIONS **************************************/ 327 328 329static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, 330 unsigned int cmd, void *arg) 331{ 332 struct s_drive_stuff *stuffp = cdi->handle; 333 334 if (!stuffp->present) 335 return -ENXIO; 336 337 if (stuffp->xxx) { 338 if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { 339 stuffp->lastsector = -1; 340 } else { 341 stuffp->lastsector = (CD_FRAMESIZE / 512) 342 * msf2log(&stuffp->di.msf_leadout) - 1; 343 } 344 345 if (stuffp->toc) { 346 kfree(stuffp->toc); 347 stuffp->toc = NULL; 348 if (-1 == mcdx_readtoc(stuffp)) 349 return -1; 350 } 351 352 stuffp->xxx = 0; 353 } 354 355 switch (cmd) { 356 case CDROMSTART:{ 357 xtrace(IOCTL, "ioctl() START\n"); 358 /* Spin up the drive. Don't think we can do this. 359 * For now, ignore it. 360 */ 361 return 0; 362 } 363 364 case CDROMSTOP:{ 365 xtrace(IOCTL, "ioctl() STOP\n"); 366 stuffp->audiostatus = CDROM_AUDIO_INVALID; 367 if (-1 == mcdx_stop(stuffp, 1)) 368 return -EIO; 369 return 0; 370 } 371 372 case CDROMPLAYTRKIND:{ 373 struct cdrom_ti *ti = (struct cdrom_ti *) arg; 374 375 xtrace(IOCTL, "ioctl() PLAYTRKIND\n"); 376 if ((ti->cdti_trk0 < stuffp->di.n_first) 377 || (ti->cdti_trk0 > stuffp->di.n_last) 378 || (ti->cdti_trk1 < stuffp->di.n_first)) 379 return -EINVAL; 380 if (ti->cdti_trk1 > stuffp->di.n_last) 381 ti->cdti_trk1 = stuffp->di.n_last; 382 xtrace(PLAYTRK, "ioctl() track %d to %d\n", 383 ti->cdti_trk0, ti->cdti_trk1); 384 return mcdx_playtrk(stuffp, ti); 385 } 386 387 case CDROMPLAYMSF:{ 388 struct cdrom_msf *msf = (struct cdrom_msf *) arg; 389 390 xtrace(IOCTL, "ioctl() PLAYMSF\n"); 391 392 if ((stuffp->audiostatus == CDROM_AUDIO_PLAY) 393 && (-1 == mcdx_hold(stuffp, 1))) 394 return -EIO; 395 396 msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0); 397 msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0); 398 msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0); 399 400 msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1); 401 msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1); 402 msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1); 403 404 stuffp->stop.dt.minute = msf->cdmsf_min1; 405 stuffp->stop.dt.second = msf->cdmsf_sec1; 406 stuffp->stop.dt.frame = msf->cdmsf_frame1; 407 408 return mcdx_playmsf(stuffp, msf); 409 } 410 411 case CDROMRESUME:{ 412 xtrace(IOCTL, "ioctl() RESUME\n"); 413 return mcdx_playtrk(stuffp, NULL); 414 } 415 416 case CDROMREADTOCENTRY:{ 417 struct cdrom_tocentry *entry = 418 (struct cdrom_tocentry *) arg; 419 struct s_subqcode *tp = NULL; 420 xtrace(IOCTL, "ioctl() READTOCENTRY\n"); 421 422 if (-1 == mcdx_readtoc(stuffp)) 423 return -1; 424 if (entry->cdte_track == CDROM_LEADOUT) 425 tp = &stuffp->toc[stuffp->di.n_last - 426 stuffp->di.n_first + 1]; 427 else if (entry->cdte_track > stuffp->di.n_last 428 || entry->cdte_track < stuffp->di.n_first) 429 return -EINVAL; 430 else 431 tp = &stuffp->toc[entry->cdte_track - 432 stuffp->di.n_first]; 433 434 if (NULL == tp) 435 return -EIO; 436 entry->cdte_adr = tp->control; 437 entry->cdte_ctrl = tp->control >> 4; 438 /* Always return stuff in MSF, and let the Uniform cdrom driver 439 worry about what the user actually wants */ 440 entry->cdte_addr.msf.minute = 441 bcd2uint(tp->dt.minute); 442 entry->cdte_addr.msf.second = 443 bcd2uint(tp->dt.second); 444 entry->cdte_addr.msf.frame = 445 bcd2uint(tp->dt.frame); 446 return 0; 447 } 448 449 case CDROMSUBCHNL:{ 450 struct cdrom_subchnl *sub = 451 (struct cdrom_subchnl *) arg; 452 struct s_subqcode q; 453 454 xtrace(IOCTL, "ioctl() SUBCHNL\n"); 455 456 if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) 457 return -EIO; 458 459 xtrace(SUBCHNL, "audiostatus: %x\n", 460 stuffp->audiostatus); 461 sub->cdsc_audiostatus = stuffp->audiostatus; 462 sub->cdsc_adr = q.control; 463 sub->cdsc_ctrl = q.control >> 4; 464 sub->cdsc_trk = bcd2uint(q.tno); 465 sub->cdsc_ind = bcd2uint(q.index); 466 467 xtrace(SUBCHNL, "trk %d, ind %d\n", 468 sub->cdsc_trk, sub->cdsc_ind); 469 /* Always return stuff in MSF, and let the Uniform cdrom driver 470 worry about what the user actually wants */ 471 sub->cdsc_absaddr.msf.minute = 472 bcd2uint(q.dt.minute); 473 sub->cdsc_absaddr.msf.second = 474 bcd2uint(q.dt.second); 475 sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame); 476 sub->cdsc_reladdr.msf.minute = 477 bcd2uint(q.tt.minute); 478 sub->cdsc_reladdr.msf.second = 479 bcd2uint(q.tt.second); 480 sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame); 481 xtrace(SUBCHNL, 482 "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n", 483 sub->cdsc_absaddr.msf.minute, 484 sub->cdsc_absaddr.msf.second, 485 sub->cdsc_absaddr.msf.frame, 486 sub->cdsc_reladdr.msf.minute, 487 sub->cdsc_reladdr.msf.second, 488 sub->cdsc_reladdr.msf.frame); 489 490 return 0; 491 } 492 493 case CDROMREADTOCHDR:{ 494 struct cdrom_tochdr *toc = 495 (struct cdrom_tochdr *) arg; 496 497 xtrace(IOCTL, "ioctl() READTOCHDR\n"); 498 toc->cdth_trk0 = stuffp->di.n_first; 499 toc->cdth_trk1 = stuffp->di.n_last; 500 xtrace(TOCHDR, 501 "ioctl() track0 = %d, track1 = %d\n", 502 stuffp->di.n_first, stuffp->di.n_last); 503 return 0; 504 } 505 506 case CDROMPAUSE:{ 507 xtrace(IOCTL, "ioctl() PAUSE\n"); 508 if (stuffp->audiostatus != CDROM_AUDIO_PLAY) 509 return -EINVAL; 510 if (-1 == mcdx_stop(stuffp, 1)) 511 return -EIO; 512 stuffp->audiostatus = CDROM_AUDIO_PAUSED; 513 if (-1 == 514 mcdx_requestsubqcode(stuffp, &stuffp->start, 515 1)) 516 return -EIO; 517 return 0; 518 } 519 520 case CDROMMULTISESSION:{ 521 struct cdrom_multisession *ms = 522 (struct cdrom_multisession *) arg; 523 xtrace(IOCTL, "ioctl() MULTISESSION\n"); 524 /* Always return stuff in LBA, and let the Uniform cdrom driver 525 worry about what the user actually wants */ 526 ms->addr.lba = msf2log(&stuffp->multi.msf_last); 527 ms->xa_flag = !!stuffp->multi.multi; 528 xtrace(MS, 529 "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n", 530 ms->xa_flag, ms->addr.lba, 531 stuffp->multi.msf_last.minute, 532 stuffp->multi.msf_last.second, 533 stuffp->multi.msf_last.frame); 534 535 return 0; 536 } 537 538 case CDROMEJECT:{ 539 xtrace(IOCTL, "ioctl() EJECT\n"); 540 if (stuffp->users > 1) 541 return -EBUSY; 542 return (mcdx_tray_move(cdi, 1)); 543 } 544 545 case CDROMCLOSETRAY:{ 546 xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n"); 547 return (mcdx_tray_move(cdi, 0)); 548 } 549 550 case CDROMVOLCTRL:{ 551 struct cdrom_volctrl *volctrl = 552 (struct cdrom_volctrl *) arg; 553 xtrace(IOCTL, "ioctl() VOLCTRL\n"); 554 555 return mcdx_setattentuator(stuffp, volctrl, 2); 556 } 557 558 default: 559 return -EINVAL; 560 } 561} 562 563static void do_mcdx_request(request_queue_t * q) 564{ 565 struct s_drive_stuff *stuffp; 566 struct request *req; 567 568 again: 569 570 req = elv_next_request(q); 571 if (!req) 572 return; 573 574 stuffp = req->rq_disk->private_data; 575 576 if (!stuffp->present) { 577 xwarn("do_request(): bad device: %s\n",req->rq_disk->disk_name); 578 xtrace(REQUEST, "end_request(0): bad device\n"); 579 end_request(req, 0); 580 return; 581 } 582 583 if (stuffp->audio) { 584 xwarn("do_request() attempt to read from audio cd\n"); 585 xtrace(REQUEST, "end_request(0): read from audio\n"); 586 end_request(req, 0); 587 return; 588 } 589 590 xtrace(REQUEST, "do_request() (%lu + %lu)\n", 591 req->sector, req->nr_sectors); 592 593 if (req->cmd != READ) { 594 xwarn("do_request(): non-read command to cd!!\n"); 595 xtrace(REQUEST, "end_request(0): write\n"); 596 end_request(req, 0); 597 return; 598 } 599 else { 600 stuffp->status = 0; 601 while (req->nr_sectors) { 602 int i; 603 604 i = mcdx_transfer(stuffp, 605 req->buffer, 606 req->sector, 607 req->nr_sectors); 608 609 if (i == -1) { 610 end_request(req, 0); 611 goto again; 612 } 613 req->sector += i; 614 req->nr_sectors -= i; 615 req->buffer += (i * 512); 616 } 617 end_request(req, 1); 618 goto again; 619 620 xtrace(REQUEST, "end_request(1)\n"); 621 end_request(req, 1); 622 } 623 624 goto again; 625} 626 627static int mcdx_open(struct cdrom_device_info *cdi, int purpose) 628{ 629 struct s_drive_stuff *stuffp; 630 xtrace(OPENCLOSE, "open()\n"); 631 stuffp = cdi->handle; 632 if (!stuffp->present) 633 return -ENXIO; 634 635 /* Make the modules looking used ... (thanx bjorn). 636 * But we shouldn't forget to decrement the module counter 637 * on error return */ 638 639 /* this is only done to test if the drive talks with us */ 640 if (-1 == mcdx_getstatus(stuffp, 1)) 641 return -EIO; 642 643 if (stuffp->xxx) { 644 645 xtrace(OPENCLOSE, "open() media changed\n"); 646 stuffp->audiostatus = CDROM_AUDIO_INVALID; 647 stuffp->readcmd = 0; 648 xtrace(OPENCLOSE, "open() Request multisession info\n"); 649 if (-1 == 650 mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6)) 651 xinfo("No multidiskinfo\n"); 652 } else { 653 /* multisession ? */ 654 if (!stuffp->multi.multi) 655 stuffp->multi.msf_last.second = 2; 656 657 xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n", 658 stuffp->multi.multi, 659 stuffp->multi.msf_last.minute, 660 stuffp->multi.msf_last.second, 661 stuffp->multi.msf_last.frame); 662 663 {; 664 } /* got multisession information */ 665 /* request the disks table of contents (aka diskinfo) */ 666 if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) { 667 668 stuffp->lastsector = -1; 669 670 } else { 671 672 stuffp->lastsector = (CD_FRAMESIZE / 512) 673 * msf2log(&stuffp->di.msf_leadout) - 1; 674 675 xtrace(OPENCLOSE, 676 "open() start %d (%02x:%02x.%02x) %d\n", 677 stuffp->di.n_first, 678 stuffp->di.msf_first.minute, 679 stuffp->di.msf_first.second, 680 stuffp->di.msf_first.frame, 681 msf2log(&stuffp->di.msf_first)); 682 xtrace(OPENCLOSE, 683 "open() last %d (%02x:%02x.%02x) %d\n", 684 stuffp->di.n_last, 685 stuffp->di.msf_leadout.minute, 686 stuffp->di.msf_leadout.second, 687 stuffp->di.msf_leadout.frame, 688 msf2log(&stuffp->di.msf_leadout)); 689 } 690 691 if (stuffp->toc) { 692 xtrace(MALLOC, "open() free old toc @ %p\n", 693 stuffp->toc); 694 kfree(stuffp->toc); 695 696 stuffp->toc = NULL; 697 } 698 699 xtrace(OPENCLOSE, "open() init irq generation\n"); 700 if (-1 == mcdx_config(stuffp, 1)) 701 return -EIO; 702#ifdef FALLBACK 703 /* Set the read speed */ 704 xwarn("AAA %x AAA\n", stuffp->readcmd); 705 if (stuffp->readerrs) 706 stuffp->readcmd = READ1X; 707 else 708 stuffp->readcmd = 709 stuffp->present | SINGLE ? READ1X : READ2X; 710 xwarn("XXX %x XXX\n", stuffp->readcmd); 711#else 712 stuffp->readcmd = 713 stuffp->present | SINGLE ? READ1X : READ2X; 714#endif 715 716 /* try to get the first sector, iff any ... */ 717 if (stuffp->lastsector >= 0) { 718 char buf[512]; 719 int ans; 720 int tries; 721 722 stuffp->xa = 0; 723 stuffp->audio = 0; 724 725 for (tries = 6; tries; tries--) { 726 727 stuffp->introk = 1; 728 729 xtrace(OPENCLOSE, "open() try as %s\n", 730 stuffp->xa ? "XA" : "normal"); 731 /* set data mode */ 732 if (-1 == (ans = mcdx_setdatamode(stuffp, 733 stuffp-> 734 xa ? 735 MODE2 : 736 MODE1, 737 1))) { 738 /* return -EIO; */ 739 stuffp->xa = 0; 740 break; 741 } 742 743 if ((stuffp->audio = e_audio(ans))) 744 break; 745 746 while (0 == 747 (ans = 748 mcdx_transfer(stuffp, buf, 0, 1))); 749 750 if (ans == 1) 751 break; 752 stuffp->xa = !stuffp->xa; 753 } 754 } 755 /* xa disks will be read in raw mode, others not */ 756 if (-1 == mcdx_setdrivemode(stuffp, 757 stuffp->xa ? RAW : COOKED, 758 1)) 759 return -EIO; 760 if (stuffp->audio) { 761 xinfo("open() audio disk found\n"); 762 } else if (stuffp->lastsector >= 0) { 763 xinfo("open() %s%s disk found\n", 764 stuffp->xa ? "XA / " : "", 765 stuffp->multi. 766 multi ? "Multi Session" : "Single Session"); 767 } 768 } 769 stuffp->xxx = 0; 770 stuffp->users++; 771 return 0; 772} 773 774static void mcdx_close(struct cdrom_device_info *cdi) 775{ 776 struct s_drive_stuff *stuffp; 777 778 xtrace(OPENCLOSE, "close()\n"); 779 780 stuffp = cdi->handle; 781 782 --stuffp->users; 783} 784 785static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr) 786/* Return: 1 if media changed since last call to this function 787 0 otherwise */ 788{ 789 struct s_drive_stuff *stuffp; 790 791 xinfo("mcdx_media_changed called for device %s\n", cdi->name); 792 793 stuffp = cdi->handle; 794 mcdx_getstatus(stuffp, 1); 795 796 if (stuffp->yyy == 0) 797 return 0; 798 799 stuffp->yyy = 0; 800 return 1; 801} 802 803#ifndef MODULE 804static int __init mcdx_setup(char *str) 805{ 806 int pi[4]; 807 (void) get_options(str, ARRAY_SIZE(pi), pi); 808 809 if (pi[0] > 0) 810 mcdx_drive_map[0][0] = pi[1]; 811 if (pi[0] > 1) 812 mcdx_drive_map[0][1] = pi[2]; 813 return 1; 814} 815 816__setup("mcdx=", mcdx_setup); 817 818#endif 819 820/* DIRTY PART ******************************************************/ 821 822static void mcdx_delay(struct s_drive_stuff *stuff, long jifs) 823/* This routine is used for sleeping. 824 * A jifs value <0 means NO sleeping, 825 * =0 means minimal sleeping (let the kernel 826 * run for other processes) 827 * >0 means at least sleep for that amount. 828 * May be we could use a simple count loop w/ jumps to itself, but 829 * I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */ 830{ 831 if (jifs < 0) 832 return; 833 834 xtrace(SLEEP, "*** delay: sleepq\n"); 835 interruptible_sleep_on_timeout(&stuff->sleepq, jifs); 836 xtrace(SLEEP, "delay awoken\n"); 837 if (signal_pending(current)) { 838 xtrace(SLEEP, "got signal\n"); 839 } 840} 841 842static irqreturn_t mcdx_intr(int irq, void *dev_id) 843{ 844 struct s_drive_stuff *stuffp = dev_id; 845 unsigned char b; 846 847#ifdef AK2 848 if (!stuffp->busy && stuffp->pending) 849 stuffp->int_err = 1; 850 851#endif /* AK2 */ 852 /* get the interrupt status */ 853 b = inb(stuffp->rreg_status); 854 stuffp->introk = ~b & MCDX_RBIT_DTEN; 855 856 /* NOTE: We only should get interrupts if the data we 857 * requested are ready to transfer. 858 * But the drive seems to generate ``asynchronous'' interrupts 859 * on several error conditions too. (Despite the err int enable 860 * setting during initialisation) */ 861 862 /* if not ok, read the next byte as the drives status */ 863 if (!stuffp->introk) { 864 xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b); 865 if (~b & MCDX_RBIT_STEN) { 866 xinfo("intr() irq %d status 0x%02x\n", 867 irq, inb(stuffp->rreg_data)); 868 } else { 869 xinfo("intr() irq %d ambiguous hw status\n", irq); 870 } 871 } else { 872 xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b); 873 } 874 875 stuffp->busy = 0; 876 wake_up_interruptible(&stuffp->busyq); 877 return IRQ_HANDLED; 878} 879 880 881static int mcdx_talk(struct s_drive_stuff *stuffp, 882 const unsigned char *cmd, size_t cmdlen, 883 void *buffer, size_t size, unsigned int timeout, int tries) 884/* Send a command to the drive, wait for the result. 885 * returns -1 on timeout, drive status otherwise 886 * If buffer is not zero, the result (length size) is stored there. 887 * If buffer is zero the size should be the number of bytes to read 888 * from the drive. These bytes are discarded. 889 */ 890{ 891 int st; 892 char c; 893 int discard; 894 895 /* Somebody wants the data read? */ 896 if ((discard = (buffer == NULL))) 897 buffer = &c; 898 899 while (stuffp->lock) { 900 xtrace(SLEEP, "*** talk: lockq\n"); 901 interruptible_sleep_on(&stuffp->lockq); 902 xtrace(SLEEP, "talk: awoken\n"); 903 } 904 905 stuffp->lock = 1; 906 907 /* An operation other then reading data destroys the 908 * data already requested and remembered in stuffp->request, ... */ 909 stuffp->valid = 0; 910 911#if MCDX_DEBUG & TALK 912 { 913 unsigned char i; 914 xtrace(TALK, 915 "talk() %d / %d tries, res.size %d, command 0x%02x", 916 tries, timeout, size, (unsigned char) cmd[0]); 917 for (i = 1; i < cmdlen; i++) 918 xtrace(TALK, " 0x%02x", cmd[i]); 919 xtrace(TALK, "\n"); 920 } 921#endif 922 923 /* give up if all tries are done (bad) or if the status 924 * st != -1 (good) */ 925 for (st = -1; st == -1 && tries; tries--) { 926 927 char *bp = (char *) buffer; 928 size_t sz = size; 929 930 outsb(stuffp->wreg_data, cmd, cmdlen); 931 xtrace(TALK, "talk() command sent\n"); 932 933 /* get the status byte */ 934 if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { 935 xinfo("talk() %02x timed out (status), %d tr%s left\n", 936 cmd[0], tries - 1, tries == 2 ? "y" : "ies"); 937 continue; 938 } 939 st = *bp; 940 sz--; 941 if (!discard) 942 bp++; 943 944 xtrace(TALK, "talk() got status 0x%02x\n", st); 945 946 /* command error? */ 947 if (e_cmderr(st)) { 948 xwarn("command error cmd = %02x %s \n", 949 cmd[0], cmdlen > 1 ? "..." : ""); 950 st = -1; 951 continue; 952 } 953 954 /* audio status? */ 955 if (stuffp->audiostatus == CDROM_AUDIO_INVALID) 956 stuffp->audiostatus = 957 e_audiobusy(st) ? CDROM_AUDIO_PLAY : 958 CDROM_AUDIO_NO_STATUS; 959 else if (stuffp->audiostatus == CDROM_AUDIO_PLAY 960 && e_audiobusy(st) == 0) 961 stuffp->audiostatus = CDROM_AUDIO_COMPLETED; 962 963 /* media change? */ 964 if (e_changed(st)) { 965 xinfo("talk() media changed\n"); 966 stuffp->xxx = stuffp->yyy = 1; 967 } 968 969 /* now actually get the data */ 970 while (sz--) { 971 if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) { 972 xinfo("talk() %02x timed out (data), %d tr%s left\n", 973 cmd[0], tries - 1, 974 tries == 2 ? "y" : "ies"); 975 st = -1; 976 break; 977 } 978 if (!discard) 979 bp++; 980 xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1)); 981 } 982 } 983 984#if !MCDX_QUIET 985 if (!tries && st == -1) 986 xinfo("talk() giving up\n"); 987#endif 988 989 stuffp->lock = 0; 990 wake_up_interruptible(&stuffp->lockq); 991 992 xtrace(TALK, "talk() done with 0x%02x\n", st); 993 return st; 994} 995 996/* MODULE STUFF ***********************************************************/ 997 998static int __init __mcdx_init(void) 999{ 1000 int i; 1001 int drives = 0; 1002 1003 mcdx_init(); 1004 for (i = 0; i < MCDX_NDRIVES; i++) { 1005 if (mcdx_stuffp[i]) { 1006 xtrace(INIT, "init_module() drive %d stuff @ %p\n", 1007 i, mcdx_stuffp[i]); 1008 drives++; 1009 } 1010 } 1011 1012 if (!drives) 1013 return -EIO; 1014 1015 return 0; 1016} 1017 1018static void __exit mcdx_exit(void) 1019{ 1020 int i; 1021 1022 xinfo("cleanup_module called\n"); 1023 1024 for (i = 0; i < MCDX_NDRIVES; i++) { 1025 struct s_drive_stuff *stuffp = mcdx_stuffp[i]; 1026 if (!stuffp) 1027 continue; 1028 del_gendisk(stuffp->disk); 1029 if (unregister_cdrom(&stuffp->info)) { 1030 printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); 1031 continue; 1032 } 1033 put_disk(stuffp->disk); 1034 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1035 free_irq(stuffp->irq, NULL); 1036 if (stuffp->toc) { 1037 xtrace(MALLOC, "cleanup_module() free toc @ %p\n", 1038 stuffp->toc); 1039 kfree(stuffp->toc); 1040 } 1041 xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n", 1042 stuffp); 1043 mcdx_stuffp[i] = NULL; 1044 kfree(stuffp); 1045 } 1046 1047 if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) { 1048 xwarn("cleanup() unregister_blkdev() failed\n"); 1049 } 1050#if !MCDX_QUIET 1051 else 1052 xinfo("cleanup() succeeded\n"); 1053#endif 1054 blk_cleanup_queue(mcdx_queue); 1055} 1056 1057#ifdef MODULE 1058module_init(__mcdx_init); 1059#endif 1060module_exit(mcdx_exit); 1061 1062 1063/* Support functions ************************************************/ 1064 1065static int __init mcdx_init_drive(int drive) 1066{ 1067 struct s_version version; 1068 struct gendisk *disk; 1069 struct s_drive_stuff *stuffp; 1070 int size = sizeof(*stuffp); 1071 char msg[80]; 1072 1073 xtrace(INIT, "init() try drive %d\n", drive); 1074 1075 xtrace(INIT, "kmalloc space for stuffpt's\n"); 1076 xtrace(MALLOC, "init() malloc %d bytes\n", size); 1077 if (!(stuffp = kzalloc(size, GFP_KERNEL))) { 1078 xwarn("init() malloc failed\n"); 1079 return 1; 1080 } 1081 1082 disk = alloc_disk(1); 1083 if (!disk) { 1084 xwarn("init() malloc failed\n"); 1085 kfree(stuffp); 1086 return 1; 1087 } 1088 1089 xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", 1090 sizeof(*stuffp), stuffp); 1091 1092 /* set default values */ 1093 stuffp->present = 0; /* this should be 0 already */ 1094 stuffp->toc = NULL; /* this should be NULL already */ 1095 1096 /* setup our irq and i/o addresses */ 1097 stuffp->irq = irq(mcdx_drive_map[drive]); 1098 stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]); 1099 stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1; 1100 stuffp->wreg_hcon = stuffp->wreg_reset + 1; 1101 stuffp->wreg_chn = stuffp->wreg_hcon + 1; 1102 1103 init_waitqueue_head(&stuffp->busyq); 1104 init_waitqueue_head(&stuffp->lockq); 1105 init_waitqueue_head(&stuffp->sleepq); 1106 1107 /* check if i/o addresses are available */ 1108 if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) { 1109 xwarn("0x%03x,%d: Init failed. " 1110 "I/O ports (0x%03x..0x%03x) already in use.\n", 1111 stuffp->wreg_data, stuffp->irq, 1112 stuffp->wreg_data, 1113 stuffp->wreg_data + MCDX_IO_SIZE - 1); 1114 xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); 1115 kfree(stuffp); 1116 put_disk(disk); 1117 xtrace(INIT, "init() continue at next drive\n"); 1118 return 0; /* next drive */ 1119 } 1120 1121 xtrace(INIT, "init() i/o port is available at 0x%03x\n" 1122 stuffp->wreg_data); 1123 xtrace(INIT, "init() hardware reset\n"); 1124 mcdx_reset(stuffp, HARD, 1); 1125 1126 xtrace(INIT, "init() get version\n"); 1127 if (-1 == mcdx_requestversion(stuffp, &version, 4)) { 1128 /* failed, next drive */ 1129 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1130 xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n", 1131 MCDX, stuffp->wreg_data, stuffp->irq); 1132 xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); 1133 kfree(stuffp); 1134 put_disk(disk); 1135 xtrace(INIT, "init() continue at next drive\n"); 1136 return 0; 1137 } 1138 1139 switch (version.code) { 1140 case 'D': 1141 stuffp->readcmd = READ2X; 1142 stuffp->present = DOUBLE | DOOR | MULTI; 1143 break; 1144 case 'F': 1145 stuffp->readcmd = READ1X; 1146 stuffp->present = SINGLE | DOOR | MULTI; 1147 break; 1148 case 'M': 1149 stuffp->readcmd = READ1X; 1150 stuffp->present = SINGLE; 1151 break; 1152 default: 1153 stuffp->present = 0; 1154 break; 1155 } 1156 1157 stuffp->playcmd = READ1X; 1158 1159 if (!stuffp->present) { 1160 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1161 xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n", 1162 MCDX, stuffp->wreg_data, stuffp->irq); 1163 kfree(stuffp); 1164 put_disk(disk); 1165 return 0; /* next drive */ 1166 } 1167 1168 xtrace(INIT, "init() register blkdev\n"); 1169 if (register_blkdev(MAJOR_NR, "mcdx")) { 1170 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1171 kfree(stuffp); 1172 put_disk(disk); 1173 return 1; 1174 } 1175 1176 mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock); 1177 if (!mcdx_queue) { 1178 unregister_blkdev(MAJOR_NR, "mcdx"); 1179 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1180 kfree(stuffp); 1181 put_disk(disk); 1182 return 1; 1183 } 1184 1185 xtrace(INIT, "init() subscribe irq and i/o\n"); 1186 if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) { 1187 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1188 xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n", 1189 MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq); 1190 stuffp->irq = 0; 1191 blk_cleanup_queue(mcdx_queue); 1192 kfree(stuffp); 1193 put_disk(disk); 1194 return 0; 1195 } 1196 1197 xtrace(INIT, "init() get garbage\n"); 1198 { 1199 int i; 1200 mcdx_delay(stuffp, HZ / 2); 1201 for (i = 100; i; i--) 1202 (void) inb(stuffp->rreg_status); 1203 } 1204 1205 1206#ifdef WE_KNOW_WHY 1207 /* irq 11 -> channel register */ 1208 outb(0x50, stuffp->wreg_chn); 1209#endif 1210 1211 xtrace(INIT, "init() set non dma but irq mode\n"); 1212 mcdx_config(stuffp, 1); 1213 1214 stuffp->info.ops = &mcdx_dops; 1215 stuffp->info.speed = 2; 1216 stuffp->info.capacity = 1; 1217 stuffp->info.handle = stuffp; 1218 sprintf(stuffp->info.name, "mcdx%d", drive); 1219 disk->major = MAJOR_NR; 1220 disk->first_minor = drive; 1221 strcpy(disk->disk_name, stuffp->info.name); 1222 disk->fops = &mcdx_bdops; 1223 disk->flags = GENHD_FL_CD; 1224 stuffp->disk = disk; 1225 1226 sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d." 1227 " (Firmware version %c %x)\n", 1228 stuffp->wreg_data, stuffp->irq, version.code, version.ver); 1229 mcdx_stuffp[drive] = stuffp; 1230 xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp); 1231 if (register_cdrom(&stuffp->info) != 0) { 1232 printk("Cannot register Mitsumi CD-ROM!\n"); 1233 free_irq(stuffp->irq, NULL); 1234 release_region(stuffp->wreg_data, MCDX_IO_SIZE); 1235 kfree(stuffp); 1236 put_disk(disk); 1237 if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) 1238 xwarn("cleanup() unregister_blkdev() failed\n"); 1239 blk_cleanup_queue(mcdx_queue); 1240 return 2; 1241 } 1242 disk->private_data = stuffp; 1243 disk->queue = mcdx_queue; 1244 add_disk(disk); 1245 printk(msg); 1246 return 0; 1247} 1248 1249static int __init mcdx_init(void) 1250{ 1251 int drive; 1252 xwarn("Version 2.14(hs) \n"); 1253 1254 xwarn("$Id: mcdx.c,v 1.1.1.1 2007-08-03 18:52:27 $\n"); 1255 1256 /* zero the pointer array */ 1257 for (drive = 0; drive < MCDX_NDRIVES; drive++) 1258 mcdx_stuffp[drive] = NULL; 1259 1260 /* do the initialisation */ 1261 for (drive = 0; drive < MCDX_NDRIVES; drive++) { 1262 switch (mcdx_init_drive(drive)) { 1263 case 2: 1264 return -EIO; 1265 case 1: 1266 break; 1267 } 1268 } 1269 return 0; 1270} 1271 1272static int mcdx_transfer(struct s_drive_stuff *stuffp, 1273 char *p, int sector, int nr_sectors) 1274/* This seems to do the actually transfer. But it does more. It 1275 keeps track of errors occurred and will (if possible) fall back 1276 to single speed on error. 1277 Return: -1 on timeout or other error 1278 else status byte (as in stuff->st) */ 1279{ 1280 int ans; 1281 1282 ans = mcdx_xfer(stuffp, p, sector, nr_sectors); 1283 return ans; 1284#ifdef FALLBACK 1285 if (-1 == ans) 1286 stuffp->readerrs++; 1287 else 1288 return ans; 1289 1290 if (stuffp->readerrs && stuffp->readcmd == READ1X) { 1291 xwarn("XXX Already reading 1x -- no chance\n"); 1292 return -1; 1293 } 1294 1295 xwarn("XXX Fallback to 1x\n"); 1296 1297 stuffp->readcmd = READ1X; 1298 return mcdx_transfer(stuffp, p, sector, nr_sectors); 1299#endif 1300 1301} 1302 1303 1304static int mcdx_xfer(struct s_drive_stuff *stuffp, 1305 char *p, int sector, int nr_sectors) 1306/* This does actually the transfer from the drive. 1307 Return: -1 on timeout or other error 1308 else status byte (as in stuff->st) */ 1309{ 1310 int border; 1311 int done = 0; 1312 long timeout; 1313 1314 if (stuffp->audio) { 1315 xwarn("Attempt to read from audio CD.\n"); 1316 return -1; 1317 } 1318 1319 if (!stuffp->readcmd) { 1320 xinfo("Can't transfer from missing disk.\n"); 1321 return -1; 1322 } 1323 1324 while (stuffp->lock) { 1325 interruptible_sleep_on(&stuffp->lockq); 1326 } 1327 1328 if (stuffp->valid && (sector >= stuffp->pending) 1329 && (sector < stuffp->low_border)) { 1330 1331 /* All (or at least a part of the sectors requested) seems 1332 * to be already requested, so we don't need to bother the 1333 * drive with new requests ... 1334 * Wait for the drive become idle, but first 1335 * check for possible occurred errors --- the drive 1336 * seems to report them asynchronously */ 1337 1338 1339 border = stuffp->high_border < (border = 1340 sector + nr_sectors) 1341 ? stuffp->high_border : border; 1342 1343 stuffp->lock = current->pid; 1344 1345 do { 1346 1347 while (stuffp->busy) { 1348 1349 timeout = 1350 interruptible_sleep_on_timeout 1351 (&stuffp->busyq, 5 * HZ); 1352 1353 if (!stuffp->introk) { 1354 xtrace(XFER, 1355 "error via interrupt\n"); 1356 } else if (!timeout) { 1357 xtrace(XFER, "timeout\n"); 1358 } else if (signal_pending(current)) { 1359 xtrace(XFER, "signal\n"); 1360 } else 1361 continue; 1362 1363 stuffp->lock = 0; 1364 stuffp->busy = 0; 1365 stuffp->valid = 0; 1366 1367 wake_up_interruptible(&stuffp->lockq); 1368 xtrace(XFER, "transfer() done (-1)\n"); 1369 return -1; 1370 } 1371 1372 /* check if we need to set the busy flag (as we 1373 * expect an interrupt */ 1374 stuffp->busy = (3 == (stuffp->pending & 3)); 1375 1376 /* Test if it's the first sector of a block, 1377 * there we have to skip some bytes as we read raw data */ 1378 if (stuffp->xa && (0 == (stuffp->pending & 3))) { 1379 const int HEAD = 1380 CD_FRAMESIZE_RAW - CD_XA_TAIL - 1381 CD_FRAMESIZE; 1382 insb(stuffp->rreg_data, p, HEAD); 1383 } 1384 1385 /* now actually read the data */ 1386 insb(stuffp->rreg_data, p, 512); 1387 1388 /* test if it's the last sector of a block, 1389 * if so, we have to handle XA special */ 1390 if ((3 == (stuffp->pending & 3)) && stuffp->xa) { 1391 char dummy[CD_XA_TAIL]; 1392 insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL); 1393 } 1394 1395 if (stuffp->pending == sector) { 1396 p += 512; 1397 done++; 1398 sector++; 1399 } 1400 } while (++(stuffp->pending) < border); 1401 1402 stuffp->lock = 0; 1403 wake_up_interruptible(&stuffp->lockq); 1404 1405 } else { 1406 1407 /* The requested sector(s) is/are out of the 1408 * already requested range, so we have to bother the drive 1409 * with a new request. */ 1410 1411 static unsigned char cmd[] = { 1412 0, 1413 0, 0, 0, 1414 0, 0, 0 1415 }; 1416 1417 cmd[0] = stuffp->readcmd; 1418 1419 /* The numbers held in ->pending, ..., should be valid */ 1420 stuffp->valid = 1; 1421 stuffp->pending = sector & ~3; 1422 1423 /* do some sanity checks */ 1424 if (stuffp->pending > stuffp->lastsector) { 1425 xwarn 1426 ("transfer() sector %d from nirvana requested.\n", 1427 stuffp->pending); 1428 stuffp->status = MCDX_ST_EOM; 1429 stuffp->valid = 0; 1430 xtrace(XFER, "transfer() done (-1)\n"); 1431 return -1; 1432 } 1433 1434 if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE) 1435 > stuffp->lastsector + 1) { 1436 xtrace(XFER, "cut low_border\n"); 1437 stuffp->low_border = stuffp->lastsector + 1; 1438 } 1439 if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE) 1440 > stuffp->lastsector + 1) { 1441 xtrace(XFER, "cut high_border\n"); 1442 stuffp->high_border = stuffp->lastsector + 1; 1443 } 1444 1445 { /* Convert the sector to be requested to MSF format */ 1446 struct cdrom_msf0 pending; 1447 log2msf(stuffp->pending / 4, &pending); 1448 cmd[1] = pending.minute; 1449 cmd[2] = pending.second; 1450 cmd[3] = pending.frame; 1451 } 1452 1453 cmd[6] = 1454 (unsigned 1455 char) ((stuffp->high_border - stuffp->pending) / 4); 1456 xtrace(XFER, "[%2d]\n", cmd[6]); 1457 1458 stuffp->busy = 1; 1459 /* Now really issue the request command */ 1460 outsb(stuffp->wreg_data, cmd, sizeof cmd); 1461 1462 } 1463#ifdef AK2 1464 if (stuffp->int_err) { 1465 stuffp->valid = 0; 1466 stuffp->int_err = 0; 1467 return -1; 1468 } 1469#endif /* AK2 */ 1470 1471 stuffp->low_border = (stuffp->low_border += 1472 done) < 1473 stuffp->high_border ? stuffp->low_border : stuffp->high_border; 1474 1475 return done; 1476} 1477 1478 1479/* Access to elements of the mcdx_drive_map members */ 1480 1481static unsigned port(int *ip) 1482{ 1483 return ip[0]; 1484} 1485static int irq(int *ip) 1486{ 1487 return ip[1]; 1488} 1489 1490/* Misc number converters */ 1491 1492static unsigned int bcd2uint(unsigned char c) 1493{ 1494 return (c >> 4) * 10 + (c & 0x0f); 1495} 1496 1497static unsigned int uint2bcd(unsigned int ival) 1498{ 1499 return ((ival / 10) << 4) | (ival % 10); 1500} 1501 1502static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf) 1503{ 1504 l += CD_MSF_OFFSET; 1505 pmsf->minute = uint2bcd(l / 4500), l %= 4500; 1506 pmsf->second = uint2bcd(l / 75); 1507 pmsf->frame = uint2bcd(l % 75); 1508} 1509 1510static unsigned int msf2log(const struct cdrom_msf0 *pmsf) 1511{ 1512 return bcd2uint(pmsf->frame) 1513 + bcd2uint(pmsf->second) * 75 1514 + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET; 1515} 1516 1517int mcdx_readtoc(struct s_drive_stuff *stuffp) 1518/* Read the toc entries from the CD, 1519 * Return: -1 on failure, else 0 */ 1520{ 1521 1522 if (stuffp->toc) { 1523 xtrace(READTOC, "ioctl() toc already read\n"); 1524 return 0; 1525 } 1526 1527 xtrace(READTOC, "ioctl() readtoc for %d tracks\n", 1528 stuffp->di.n_last - stuffp->di.n_first + 1); 1529 1530 if (-1 == mcdx_hold(stuffp, 1)) 1531 return -1; 1532 1533 xtrace(READTOC, "ioctl() tocmode\n"); 1534 if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) 1535 return -EIO; 1536 1537 /* all seems to be ok so far ... malloc */ 1538 { 1539 int size; 1540 size = 1541 sizeof(struct s_subqcode) * (stuffp->di.n_last - 1542 stuffp->di.n_first + 2); 1543 1544 xtrace(MALLOC, "ioctl() malloc %d bytes\n", size); 1545 stuffp->toc = kmalloc(size, GFP_KERNEL); 1546 if (!stuffp->toc) { 1547 xwarn("Cannot malloc %d bytes for toc\n", size); 1548 mcdx_setdrivemode(stuffp, DATA, 1); 1549 return -EIO; 1550 } 1551 } 1552 1553 /* now read actually the index */ 1554 { 1555 int trk; 1556 int retries; 1557 1558 for (trk = 0; 1559 trk < (stuffp->di.n_last - stuffp->di.n_first + 1); 1560 trk++) 1561 stuffp->toc[trk].index = 0; 1562 1563 for (retries = 300; retries; retries--) { /* why 300? */ 1564 struct s_subqcode q; 1565 unsigned int idx; 1566 1567 if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) { 1568 mcdx_setdrivemode(stuffp, DATA, 1); 1569 return -EIO; 1570 } 1571 1572 idx = bcd2uint(q.index); 1573 1574 if ((idx > 0) 1575 && (idx <= stuffp->di.n_last) 1576 && (q.tno == 0) 1577 && (stuffp->toc[idx - stuffp->di.n_first]. 1578 index == 0)) { 1579 stuffp->toc[idx - stuffp->di.n_first] = q; 1580 xtrace(READTOC, 1581 "ioctl() toc idx %d (trk %d)\n", 1582 idx, trk); 1583 trk--; 1584 } 1585 if (trk == 0) 1586 break; 1587 } 1588 memset(&stuffp-> 1589 toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0, 1590 sizeof(stuffp->toc[0])); 1591 stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1592 1].dt = stuffp->di.msf_leadout; 1593 } 1594 1595 /* unset toc mode */ 1596 xtrace(READTOC, "ioctl() undo toc mode\n"); 1597 if (-1 == mcdx_setdrivemode(stuffp, DATA, 2)) 1598 return -EIO; 1599 1600#if MCDX_DEBUG && READTOC 1601 { 1602 int trk; 1603 for (trk = 0; 1604 trk < (stuffp->di.n_last - stuffp->di.n_first + 2); 1605 trk++) 1606 xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x" 1607 " %02x:%02x.%02x %02x:%02x.%02x\n", 1608 trk + stuffp->di.n_first, 1609 stuffp->toc[trk].control, 1610 stuffp->toc[trk].tno, 1611 stuffp->toc[trk].index, 1612 stuffp->toc[trk].tt.minute, 1613 stuffp->toc[trk].tt.second, 1614 stuffp->toc[trk].tt.frame, 1615 stuffp->toc[trk].dt.minute, 1616 stuffp->toc[trk].dt.second, 1617 stuffp->toc[trk].dt.frame); 1618 } 1619#endif 1620 1621 return 0; 1622} 1623 1624static int 1625mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf) 1626{ 1627 unsigned char cmd[7] = { 1628 0, 0, 0, 0, 0, 0, 0 1629 }; 1630 1631 if (!stuffp->readcmd) { 1632 xinfo("Can't play from missing disk.\n"); 1633 return -1; 1634 } 1635 1636 cmd[0] = stuffp->playcmd; 1637 1638 cmd[1] = msf->cdmsf_min0; 1639 cmd[2] = msf->cdmsf_sec0; 1640 cmd[3] = msf->cdmsf_frame0; 1641 cmd[4] = msf->cdmsf_min1; 1642 cmd[5] = msf->cdmsf_sec1; 1643 cmd[6] = msf->cdmsf_frame1; 1644 1645 xtrace(PLAYMSF, "ioctl(): play %x " 1646 "%02x:%02x:%02x -- %02x:%02x:%02x\n", 1647 cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]); 1648 1649 outsb(stuffp->wreg_data, cmd, sizeof cmd); 1650 1651 if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) { 1652 xwarn("playmsf() timeout\n"); 1653 return -1; 1654 } 1655 1656 stuffp->audiostatus = CDROM_AUDIO_PLAY; 1657 return 0; 1658} 1659 1660static int 1661mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti) 1662{ 1663 struct s_subqcode *p; 1664 struct cdrom_msf msf; 1665 1666 if (-1 == mcdx_readtoc(stuffp)) 1667 return -1; 1668 1669 if (ti) 1670 p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first]; 1671 else 1672 p = &stuffp->start; 1673 1674 msf.cdmsf_min0 = p->dt.minute; 1675 msf.cdmsf_sec0 = p->dt.second; 1676 msf.cdmsf_frame0 = p->dt.frame; 1677 1678 if (ti) { 1679 p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1]; 1680 stuffp->stop = *p; 1681 } else 1682 p = &stuffp->stop; 1683 1684 msf.cdmsf_min1 = p->dt.minute; 1685 msf.cdmsf_sec1 = p->dt.second; 1686 msf.cdmsf_frame1 = p->dt.frame; 1687 1688 return mcdx_playmsf(stuffp, &msf); 1689} 1690 1691 1692/* Drive functions ************************************************/ 1693 1694static int mcdx_tray_move(struct cdrom_device_info *cdi, int position) 1695{ 1696 struct s_drive_stuff *stuffp = cdi->handle; 1697 1698 if (!stuffp->present) 1699 return -ENXIO; 1700 if (!(stuffp->present & DOOR)) 1701 return -ENOSYS; 1702 1703 if (position) /* 1: eject */ 1704 return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3); 1705 else /* 0: close */ 1706 return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3); 1707 return 1; 1708} 1709 1710static int mcdx_stop(struct s_drive_stuff *stuffp, int tries) 1711{ 1712 return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries); 1713} 1714 1715static int mcdx_hold(struct s_drive_stuff *stuffp, int tries) 1716{ 1717 return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); 1718} 1719 1720static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp, 1721 struct s_subqcode *sub, int tries) 1722{ 1723 char buf[11]; 1724 int ans; 1725 1726 if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf), 1727 2 * HZ, tries))) 1728 return -1; 1729 sub->control = buf[1]; 1730 sub->tno = buf[2]; 1731 sub->index = buf[3]; 1732 sub->tt.minute = buf[4]; 1733 sub->tt.second = buf[5]; 1734 sub->tt.frame = buf[6]; 1735 sub->dt.minute = buf[8]; 1736 sub->dt.second = buf[9]; 1737 sub->dt.frame = buf[10]; 1738 1739 return ans; 1740} 1741 1742static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, 1743 struct s_multi *multi, int tries) 1744{ 1745 char buf[5]; 1746 int ans; 1747 1748 if (stuffp->present & MULTI) { 1749 ans = 1750 mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ, 1751 tries); 1752 multi->multi = buf[1]; 1753 multi->msf_last.minute = buf[2]; 1754 multi->msf_last.second = buf[3]; 1755 multi->msf_last.frame = buf[4]; 1756 return ans; 1757 } else { 1758 multi->multi = 0; 1759 return 0; 1760 } 1761} 1762 1763static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, 1764 int tries) 1765{ 1766 char buf[9]; 1767 int ans; 1768 ans = 1769 mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries); 1770 if (ans == -1) { 1771 info->n_first = 0; 1772 info->n_last = 0; 1773 } else { 1774 info->n_first = bcd2uint(buf[1]); 1775 info->n_last = bcd2uint(buf[2]); 1776 info->msf_leadout.minute = buf[3]; 1777 info->msf_leadout.second = buf[4]; 1778 info->msf_leadout.frame = buf[5]; 1779 info->msf_first.minute = buf[6]; 1780 info->msf_first.second = buf[7]; 1781 info->msf_first.frame = buf[8]; 1782 } 1783 return ans; 1784} 1785 1786static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, 1787 int tries) 1788{ 1789 char cmd[2]; 1790 int ans; 1791 1792 xtrace(HW, "setdrivemode() %d\n", mode); 1793 1794 if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries))) 1795 return -1; 1796 1797 switch (mode) { 1798 case TOC: 1799 cmd[1] |= 0x04; 1800 break; 1801 case DATA: 1802 cmd[1] &= ~0x04; 1803 break; 1804 case RAW: 1805 cmd[1] |= 0x40; 1806 break; 1807 case COOKED: 1808 cmd[1] &= ~0x40; 1809 break; 1810 default: 1811 break; 1812 } 1813 cmd[0] = 0x50; 1814 return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); 1815} 1816 1817static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, 1818 int tries) 1819{ 1820 unsigned char cmd[2] = { 0xa0 }; 1821 xtrace(HW, "setdatamode() %d\n", mode); 1822 switch (mode) { 1823 case MODE0: 1824 cmd[1] = 0x00; 1825 break; 1826 case MODE1: 1827 cmd[1] = 0x01; 1828 break; 1829 case MODE2: 1830 cmd[1] = 0x02; 1831 break; 1832 default: 1833 return -EINVAL; 1834 } 1835 return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries); 1836} 1837 1838static int mcdx_config(struct s_drive_stuff *stuffp, int tries) 1839{ 1840 char cmd[4]; 1841 1842 xtrace(HW, "config()\n"); 1843 1844 cmd[0] = 0x90; 1845 1846 cmd[1] = 0x10; /* irq enable */ 1847 cmd[2] = 0x05; /* pre, err irq enable */ 1848 1849 if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries)) 1850 return -1; 1851 1852 cmd[1] = 0x02; /* dma select */ 1853 cmd[2] = 0x00; /* no dma */ 1854 1855 return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries); 1856} 1857 1858static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, 1859 int tries) 1860{ 1861 char buf[3]; 1862 int ans; 1863 1864 if (-1 == (ans = mcdx_talk(stuffp, "\xdc", 1865 1, buf, sizeof(buf), 2 * HZ, tries))) 1866 return ans; 1867 1868 ver->code = buf[1]; 1869 ver->ver = buf[2]; 1870 1871 return ans; 1872} 1873 1874static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries) 1875{ 1876 if (mode == HARD) { 1877 outb(0, stuffp->wreg_chn); /* no dma, no irq -> hardware */ 1878 outb(0, stuffp->wreg_reset); /* hw reset */ 1879 return 0; 1880 } else 1881 return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries); 1882} 1883 1884static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock) 1885{ 1886 struct s_drive_stuff *stuffp = cdi->handle; 1887 char cmd[2] = { 0xfe }; 1888 1889 if (!(stuffp->present & DOOR)) 1890 return -ENOSYS; 1891 if (stuffp->present & DOOR) { 1892 cmd[1] = lock ? 0x01 : 0x00; 1893 return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3); 1894 } else 1895 return 0; 1896} 1897 1898static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries) 1899{ 1900 return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries); 1901} 1902 1903static int 1904mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf) 1905{ 1906 unsigned long timeout = to + jiffies; 1907 char c; 1908 1909 if (!buf) 1910 buf = &c; 1911 1912 while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) { 1913 if (time_after(jiffies, timeout)) 1914 return -1; 1915 mcdx_delay(stuffp, delay); 1916 } 1917 1918 *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff; 1919 1920 return 0; 1921} 1922 1923static int mcdx_setattentuator(struct s_drive_stuff *stuffp, 1924 struct cdrom_volctrl *vol, int tries) 1925{ 1926 char cmd[5]; 1927 cmd[0] = 0xae; 1928 cmd[1] = vol->channel0; 1929 cmd[2] = 0; 1930 cmd[3] = vol->channel1; 1931 cmd[4] = 0; 1932 1933 return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries); 1934} 1935 1936MODULE_LICENSE("GPL"); 1937MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR); 1938