This source file includes following definitions.
- mcd_setup
 
- check_mcd_change
 
- statusCmd
 
- mcdPlay
 
- msf2hsg
 
- mcd_ioctl
 
- mcd_transfer
 
- mcd_interrupt
 
- do_mcd_request
 
- mcd_poll
 
- mcd_invalidate_buffers
 
- mcd_open
 
- mcd_release
 
- mcd_init
 
- hsg2msf
 
- bin2bcd
 
- bcd2bin
 
- mcdStatus
 
- sendMcdCmd
 
- mcdStatTimer
 
- getMcdStatus
 
- getValue
 
- GetQChannelInfo
 
- updateToc
 
- GetDiskInfo
 
- GetToc
 
- init_module
 
- cleanup_module
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 #include <linux/module.h>
  66 
  67 #include <linux/errno.h>
  68 #include <linux/signal.h>
  69 #include <linux/sched.h>
  70 #include <linux/mm.h>
  71 #include <linux/timer.h>
  72 #include <linux/fs.h>
  73 #include <linux/kernel.h>
  74 #include <linux/cdrom.h>
  75 #include <linux/ioport.h>
  76 #include <linux/string.h>
  77 #include <linux/delay.h>
  78 
  79 
  80 #include <asm/system.h>
  81 #include <asm/io.h>
  82 #include <asm/segment.h>
  83 
  84 #define MAJOR_NR MITSUMI_CDROM_MAJOR
  85 #include <linux/blk.h>
  86 
  87 #define mcd_port mcd    
  88 #include <linux/mcd.h>
  89 
  90 #if 0
  91 static int mcd_sizes[] = { 0 };
  92 #endif
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 #define SINGLE_HOLD_SECTORS 30  
 102 
 103 #define MCMD_2X_READ 0xC1       
 104 
 105 
 106 static int mcdDouble = 0; 
 107 
 108 
 109 static int mcd1xhold = 0;
 110 
 111 
 112 static int mcdPresent = 0;
 113 
 114 #if 0
 115 #define TEST1 
 116 #define TEST2 
 117 #define TEST3 */ 
 118 #define TEST4 
 119 #define TEST5 */ 
 120 #endif
 121 
 122 #if 1
 123 #define QUICK_LOOP_DELAY udelay(45)  
 124 #define QUICK_LOOP_COUNT 20
 125 #else
 126 #define QUICK_LOOP_DELAY
 127 #define QUICK_LOOP_COUNT 140 
 128 #endif
 129 
 130 
 131 #define CURRENT_VALID \
 132 (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
 133 && CURRENT -> sector != -1)
 134 
 135 #define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
 136 #define MCD_BUF_SIZ 16
 137 static volatile int mcd_transfer_is_active;
 138 static char mcd_buf[2048*MCD_BUF_SIZ];  
 139 static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
 140 static volatile int mcd_buf_in, mcd_buf_out = -1;
 141 static volatile int mcd_error;
 142 static int mcd_open_count;
 143 enum mcd_state_e {
 144   MCD_S_IDLE,   
 145   MCD_S_START,  
 146   MCD_S_MODE, 
 147   MCD_S_READ,   
 148   MCD_S_DATA,   
 149   MCD_S_STOP,   
 150   MCD_S_STOPPING 
 151 };
 152 static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
 153 static int mcd_mode = -1;
 154 static int MCMD_DATA_READ= MCMD_PLAY_READ;
 155 #define READ_TIMEOUT 3000
 156 #define WORK_AROUND_MITSUMI_BUG_92
 157 #define WORK_AROUND_MITSUMI_BUG_93
 158 #ifdef WORK_AROUND_MITSUMI_BUG_93
 159 int mitsumi_bug_93_wait = 0;
 160 #endif 
 161 
 162 static short mcd_port = MCD_BASE_ADDR; 
 163 static int   mcd_irq  = MCD_INTR_NR; 
 164 
 165 static int McdTimeout, McdTries;
 166 static struct wait_queue *mcd_waitq = NULL;
 167 
 168 static struct mcd_DiskInfo DiskInfo;
 169 static struct mcd_Toc Toc[MAX_TRACKS];
 170 static struct mcd_Play_msf mcd_Play;
 171 
 172 static int audioStatus;
 173 static char mcdDiskChanged;
 174 static char tocUpToDate;
 175 static char mcdVersion;
 176 
 177 static void mcd_transfer(void);
 178 static void mcd_poll(void);
 179 static void mcd_invalidate_buffers(void);
 180 static void hsg2msf(long hsg, struct msf *msf);
 181 static void bin2bcd(unsigned char *p);
 182 static int bcd2bin(unsigned char bcd);
 183 static int mcdStatus(void);
 184 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
 185 static int getMcdStatus(int timeout);
 186 static int GetQChannelInfo(struct mcd_Toc *qp);
 187 static int updateToc(void);
 188 static int GetDiskInfo(void);
 189 static int GetToc(void);
 190 static int getValue(unsigned char *result);
 191 
 192 
 193 void mcd_setup(char *str, int *ints)
     
 194 {
 195    if (ints[0] > 0)
 196       mcd_port = ints[1];
 197    if (ints[0] > 1)      
 198       mcd_irq  = ints[2];
 199 #ifdef WORK_AROUND_MITSUMI_BUG_93
 200    if (ints[0] > 2)
 201       mitsumi_bug_93_wait = ints[3];
 202 #endif 
 203 }
 204 
 205  
 206 static int
 207 check_mcd_change(kdev_t full_dev)
     
 208 {
 209    int retval, target;
 210 
 211 
 212 #if 1    
 213    return 0;
 214 #endif  
 215    target = MINOR(full_dev);
 216 
 217    if (target > 0) {
 218       printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
 219       return 0;
 220    }
 221 
 222    retval = mcdDiskChanged;
 223    mcdDiskChanged = 0;
 224 
 225    return retval;
 226 }
 227 
 228 
 229 
 230 
 231 
 232 
 233 
 234 static int
 235 statusCmd(void)
     
 236 {
 237         int st, retry;
 238 
 239         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
 240         {
 241 
 242                 outb(MCMD_GET_STATUS, MCDPORT(0));      
 243                 st = getMcdStatus(MCD_STATUS_DELAY);
 244                 if (st != -1)
 245                         break;
 246         }
 247 
 248         return st;
 249 }
 250 
 251 
 252 
 253 
 254 
 255 
 256 static int
 257 mcdPlay(struct mcd_Play_msf *arg)
     
 258 {
 259         int retry, st;
 260 
 261         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
 262         {
 263                 sendMcdCmd(MCMD_PLAY_READ, arg);
 264                 st = getMcdStatus(2 * MCD_STATUS_DELAY);
 265                 if (st != -1)
 266                         break;
 267         }
 268 
 269         return st;
 270 }
 271 
 272 
 273 long
 274 msf2hsg(struct msf *mp)
     
 275 {
 276         return bcd2bin(mp -> frame)
 277                 + bcd2bin(mp -> sec) * 75
 278                 + bcd2bin(mp -> min) * 4500
 279                 - 150;
 280 }
 281 
 282 
 283 static int
 284 mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
     
 285                                                 unsigned long arg)
 286 {
 287         int i, st;
 288         struct mcd_Toc qInfo;
 289         struct cdrom_ti ti;
 290         struct cdrom_tochdr tocHdr;
 291         struct cdrom_msf msf;
 292         struct cdrom_tocentry entry;
 293         struct mcd_Toc *tocPtr;
 294         struct cdrom_subchnl subchnl;
 295         struct cdrom_volctrl volctrl;
 296 
 297         if (!ip)
 298                 return -EINVAL;
 299 
 300         st = statusCmd();
 301         if (st < 0)
 302                 return -EIO;
 303 
 304         if (!tocUpToDate)
 305         {
 306                 i = updateToc();
 307                 if (i < 0)
 308                         return i;       
 309         }
 310 
 311         switch (cmd)
 312         {
 313         case CDROMSTART:     
 314                 
 315 
 316 
 317 
 318 
 319                 return 0;
 320 
 321         case CDROMSTOP:      
 322                 outb(MCMD_STOP, MCDPORT(0));
 323                 i = getMcdStatus(MCD_STATUS_DELAY);
 324 
 325                 
 326 
 327                 audioStatus = CDROM_AUDIO_NO_STATUS;
 328                 return 0;
 329 
 330         case CDROMPAUSE:     
 331                 if (audioStatus != CDROM_AUDIO_PLAY)
 332                         return -EINVAL;
 333 
 334                 outb(MCMD_STOP, MCDPORT(0));
 335                 i = getMcdStatus(MCD_STATUS_DELAY);
 336 
 337                 if (GetQChannelInfo(&qInfo) < 0)
 338                 {
 339                         
 340 
 341                         audioStatus = CDROM_AUDIO_NO_STATUS;
 342                         return 0;
 343                 }
 344 
 345                 mcd_Play.start = qInfo.diskTime;        
 346 
 347                 audioStatus = CDROM_AUDIO_PAUSED;
 348                 return 0;
 349 
 350         case CDROMRESUME:    
 351                 if (audioStatus != CDROM_AUDIO_PAUSED)
 352                         return -EINVAL;
 353 
 354                 
 355 
 356                 i = mcdPlay(&mcd_Play);
 357                 if (i < 0)
 358                 {
 359                         audioStatus = CDROM_AUDIO_ERROR;
 360                         return -EIO;
 361                 }
 362 
 363                 audioStatus = CDROM_AUDIO_PLAY;
 364                 return 0;
 365 
 366         case CDROMPLAYTRKIND:     
 367 
 368                 st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
 369                 if (st)
 370                         return st;
 371 
 372                 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
 373 
 374                 if (ti.cdti_trk0 < DiskInfo.first
 375                         || ti.cdti_trk0 > DiskInfo.last
 376                         || ti.cdti_trk1 < ti.cdti_trk0)
 377                 {
 378                         return -EINVAL;
 379                 }
 380 
 381                 if (ti.cdti_trk1 > DiskInfo.last)
 382                         ti. cdti_trk1 = DiskInfo.last;
 383 
 384                 mcd_Play.start = Toc[ti.cdti_trk0].diskTime;
 385                 mcd_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
 386 
 387 #ifdef MCD_DEBUG
 388 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
 389         mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
 390         mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
 391 #endif
 392 
 393                 i = mcdPlay(&mcd_Play);
 394                 if (i < 0)
 395                 {
 396                         audioStatus = CDROM_AUDIO_ERROR;
 397                         return -EIO;
 398                 }
 399 
 400                 audioStatus = CDROM_AUDIO_PLAY;
 401                 return 0;
 402 
 403         case CDROMPLAYMSF:   
 404 
 405                 if (audioStatus == CDROM_AUDIO_PLAY) {
 406                   outb(MCMD_STOP, MCDPORT(0));
 407                   i = getMcdStatus(MCD_STATUS_DELAY);
 408                   audioStatus = CDROM_AUDIO_NO_STATUS;
 409                 }
 410 
 411                 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
 412                 if (st)
 413                         return st;
 414 
 415                 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
 416 
 417                 
 418 
 419                 bin2bcd(&msf.cdmsf_min0);
 420                 bin2bcd(&msf.cdmsf_sec0);
 421                 bin2bcd(&msf.cdmsf_frame0);
 422                 bin2bcd(&msf.cdmsf_min1);
 423                 bin2bcd(&msf.cdmsf_sec1);
 424                 bin2bcd(&msf.cdmsf_frame1);
 425 
 426                 mcd_Play.start.min = msf.cdmsf_min0;
 427                 mcd_Play.start.sec = msf.cdmsf_sec0;
 428                 mcd_Play.start.frame = msf.cdmsf_frame0;
 429                 mcd_Play.end.min = msf.cdmsf_min1;
 430                 mcd_Play.end.sec = msf.cdmsf_sec1;
 431                 mcd_Play.end.frame = msf.cdmsf_frame1;
 432 
 433 #ifdef MCD_DEBUG
 434 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
 435 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
 436 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
 437 #endif
 438 
 439                 i = mcdPlay(&mcd_Play);
 440                 if (i < 0)
 441                 {
 442                         audioStatus = CDROM_AUDIO_ERROR;
 443                         return -EIO;
 444                 }
 445 
 446                 audioStatus = CDROM_AUDIO_PLAY;
 447                 return 0;
 448 
 449         case CDROMREADTOCHDR:        
 450                 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
 451                 if (st)
 452                         return st;
 453 
 454                 tocHdr.cdth_trk0 = DiskInfo.first;
 455                 tocHdr.cdth_trk1 = DiskInfo.last;
 456                 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
 457                 return 0;
 458 
 459         case CDROMREADTOCENTRY:      
 460 
 461                 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
 462                 if (st)
 463                         return st;
 464 
 465                 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
 466                 if (entry.cdte_track == CDROM_LEADOUT)
 467                         
 468                         tocPtr = &Toc[DiskInfo.last + 1];
 469 
 470                 else if (entry.cdte_track > DiskInfo.last
 471                                 || entry.cdte_track < DiskInfo.first)
 472                         return -EINVAL;
 473 
 474                 else
 475                         tocPtr = &Toc[entry.cdte_track];
 476 
 477                 entry.cdte_adr = tocPtr -> ctrl_addr;
 478                 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
 479 
 480                 if (entry.cdte_format == CDROM_LBA)
 481                         entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
 482 
 483                 else if (entry.cdte_format == CDROM_MSF)
 484                 {
 485                         entry.cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
 486                         entry.cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
 487                         entry.cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
 488                 }
 489 
 490                 else
 491                         return -EINVAL;
 492 
 493                 memcpy_tofs((void *) arg, &entry, sizeof entry);
 494                 return 0;
 495 
 496         case CDROMSUBCHNL:   
 497 
 498                 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
 499                 if (st)
 500                         return st;
 501 
 502                 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
 503 
 504                 if (GetQChannelInfo(&qInfo) < 0)
 505                         return -EIO;
 506 
 507                 subchnl.cdsc_audiostatus = audioStatus;
 508                 subchnl.cdsc_adr = qInfo.ctrl_addr;
 509                 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
 510                 subchnl.cdsc_trk = bcd2bin(qInfo.track);
 511                 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
 512 
 513                 if (subchnl.cdsc_format == CDROM_LBA)
 514                 {
 515                         subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
 516                         subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
 517                 }
 518 
 519                 else if (subchnl.cdsc_format == CDROM_MSF)
 520                 {
 521                         subchnl.cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
 522                         subchnl.cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
 523                         subchnl.cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
 524 
 525                         subchnl.cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
 526                         subchnl.cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
 527                         subchnl.cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
 528                 }
 529 
 530                 else
 531                         return -EINVAL;
 532 
 533                 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
 534                 return 0;
 535 
 536         case CDROMVOLCTRL:   
 537                 st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
 538                 if (st)
 539                         return st;
 540 
 541                 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
 542                 outb(MCMD_SET_VOLUME, MCDPORT(0));
 543                 outb(volctrl.channel0, MCDPORT(0));
 544                 outb(255, MCDPORT(0));
 545                 outb(volctrl.channel1, MCDPORT(0));
 546                 outb(255, MCDPORT(0));
 547 
 548                 i = getMcdStatus(MCD_STATUS_DELAY);
 549                 if (i < 0)
 550                         return -EIO;
 551 
 552                 {
 553                         char a, b, c, d;
 554 
 555                         getValue(&a);
 556                         getValue(&b);
 557                         getValue(&c);
 558                         getValue(&d);
 559                 }
 560 
 561                 return 0;
 562 
 563         case CDROMEJECT:
 564                
 565                 if (audioStatus == CDROM_AUDIO_PLAY) {
 566                   outb(MCMD_STOP, MCDPORT(0));
 567                   i = getMcdStatus(MCD_STATUS_DELAY);
 568                 }
 569  
 570                 audioStatus = CDROM_AUDIO_NO_STATUS;
 571  
 572                 outb(MCMD_EJECT, MCDPORT(0));
 573                 
 574 
 575 
 576 
 577 
 578                 i = getMcdStatus(MCD_STATUS_DELAY);
 579                 return 0;
 580         default:
 581                 return -EINVAL;
 582         }
 583 }
 584 
 585 
 586 
 587 
 588 
 589 
 590 
 591 static void
 592 mcd_transfer(void)
     
 593 {
 594   if (CURRENT_VALID) {
 595     while (CURRENT -> nr_sectors) {
 596       int bn = CURRENT -> sector / 4;
 597       int i;
 598       for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i)
 599         ;
 600       if (i < MCD_BUF_SIZ) {
 601         int offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
 602         int nr_sectors = 4 - (CURRENT -> sector & 3);
 603         if (mcd_buf_out != i) {
 604           mcd_buf_out = i;
 605           if (mcd_buf_bn[i] != bn) {
 606             mcd_buf_out = -1;
 607             continue;
 608           }
 609         }
 610         if (nr_sectors > CURRENT -> nr_sectors)
 611           nr_sectors = CURRENT -> nr_sectors;
 612         memcpy(CURRENT -> buffer, mcd_buf + offs, nr_sectors * 512);
 613         CURRENT -> nr_sectors -= nr_sectors;
 614         CURRENT -> sector += nr_sectors;
 615         CURRENT -> buffer += nr_sectors * 512;
 616       } else {
 617         mcd_buf_out = -1;
 618         break;
 619       }
 620     }
 621   }
 622 }
 623 
 624 
 625 
 626 
 627 
 628 
 629 
 630 static void
 631 mcd_interrupt(int irq, struct pt_regs * regs)
     
 632 {
 633         int st;
 634 
 635         st = inb(MCDPORT(1)) & 0xFF;
 636 #ifdef TEST1
 637                 printk("<int1-%02X>", st);
 638 #endif
 639         if (!(st & MFL_STATUS))
 640         {
 641                 st = inb(MCDPORT(0)) & 0xFF;
 642 #ifdef TEST1
 643                 printk("<int0-%02X>", st);
 644 #endif
 645                 if ((st & 0xFF) != 0xFF)
 646                   mcd_error = st ? st & 0xFF : -1;
 647         }
 648 }
 649 
 650 
 651 static void
 652 do_mcd_request(void)
     
 653 {
 654 #ifdef TEST2
 655   printk(" do_mcd_request(%ld+%ld)\n", CURRENT -> sector, CURRENT -> nr_sectors);
 656 #endif
 657   mcd_transfer_is_active = 1;
 658   while (CURRENT_VALID) {
 659     if (CURRENT->bh) {
 660       if (!buffer_locked(CURRENT->bh))
 661         panic(DEVICE_NAME ": block not locked");
 662     }
 663     mcd_transfer();
 664     if (CURRENT -> nr_sectors == 0) {
 665       end_request(1);
 666     } else {
 667       mcd_buf_out = -1;         
 668       if (mcd_state == MCD_S_IDLE) {
 669         if (!tocUpToDate) {
 670           if (updateToc() < 0) {
 671             while (CURRENT_VALID)
 672               end_request(0);
 673             break;
 674           }
 675         }
 676         mcd_state = MCD_S_START;
 677         McdTries = 5;
 678         SET_TIMER(mcd_poll, 1);
 679       }
 680       break;
 681     }
 682   }
 683   mcd_transfer_is_active = 0;
 684 #ifdef TEST2
 685   printk(" do_mcd_request ends\n");
 686 #endif
 687 }
 688 
 689 
 690 
 691 static void
 692 mcd_poll(void)
     
 693 {
 694   int st;
 695 
 696 
 697   if (mcd_error) 
 698   {
 699     if (mcd_error & 0xA5) 
 700     {
 701       printk("mcd: I/O error 0x%02x", mcd_error);
 702       if (mcd_error & 0x80)
 703         printk(" (Door open)");
 704       if (mcd_error & 0x20)
 705         printk(" (Disk changed)");
 706       if (mcd_error & 0x04)
 707         {
 708         printk(" (Read error)"); 
 709         
 710         
 711         
 712         
 713         
 714         
 715         
 716         
 717         if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_2X_READ) 
 718                 {
 719                 MCMD_DATA_READ = MCMD_PLAY_READ; 
 720                 mcd1xhold = SINGLE_HOLD_SECTORS; 
 721                 printk(" Speed now 1x");         
 722                 }
 723         }
 724       printk("\n");
 725       mcd_invalidate_buffers();
 726 #ifdef WARN_IF_READ_FAILURE
 727       if (McdTries == MCD_RETRY_ATTEMPTS)
 728         printk("mcd: read of block %d failed\n", mcd_next_bn);
 729 #endif
 730       if (!McdTries--) 
 731         {
 732         
 733         
 734         printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);
 735         if (mcd_transfer_is_active) 
 736         {
 737           McdTries = 0;
 738           goto ret;
 739         }
 740         if (CURRENT_VALID)
 741           end_request(0);
 742         McdTries = MCD_RETRY_ATTEMPTS;
 743       }
 744     }
 745     mcd_error = 0;
 746     mcd_state = MCD_S_STOP;
 747   }
 748         
 749         
 750         
 751     if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_PLAY_READ)
 752         {
 753         
 754         if (mcd1xhold == 0) 
 755                 { 
 756                 MCMD_DATA_READ = MCMD_2X_READ; 
 757                 printk("mcd: Switching back to 2X speed!\n"); 
 758                 }
 759         else mcd1xhold--; 
 760                                 
 761         }
 762 
 763 
 764 
 765  immediately:
 766   switch (mcd_state) {
 767 
 768 
 769 
 770   case MCD_S_IDLE:
 771 #ifdef TEST3
 772     printk("MCD_S_IDLE\n");
 773 #endif
 774     return;
 775 
 776 
 777 
 778   case MCD_S_START:
 779 #ifdef TEST3
 780     printk("MCD_S_START\n");
 781 #endif
 782 
 783     outb(MCMD_GET_STATUS, MCDPORT(0));
 784     mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;
 785     McdTimeout = 3000;
 786     break;
 787 
 788 
 789 
 790   case MCD_S_MODE:
 791 #ifdef TEST3
 792     printk("MCD_S_MODE\n");
 793 #endif
 794 
 795     if ((st = mcdStatus()) != -1) {
 796 
 797       if (st & MST_DSK_CHG) {
 798         mcdDiskChanged = 1;
 799         tocUpToDate = 0;
 800         mcd_invalidate_buffers();
 801       }
 802 
 803     set_mode_immediately:
 804 
 805       if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
 806         mcdDiskChanged = 1;
 807         tocUpToDate = 0;
 808         if (mcd_transfer_is_active) {
 809           mcd_state = MCD_S_START;
 810           goto immediately;
 811         }
 812         printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");
 813         mcd_state = MCD_S_IDLE;
 814         while (CURRENT_VALID)
 815           end_request(0);
 816         return;
 817       }
 818 
 819       outb(MCMD_SET_MODE, MCDPORT(0));
 820       outb(1, MCDPORT(0));
 821       mcd_mode = 1;
 822       mcd_state = MCD_S_READ;
 823       McdTimeout = 3000;
 824 
 825     }
 826     break;
 827 
 828 
 829 
 830   case MCD_S_READ:
 831 #ifdef TEST3
 832     printk("MCD_S_READ\n");
 833 #endif
 834 
 835     if ((st = mcdStatus()) != -1) {
 836 
 837       if (st & MST_DSK_CHG) {
 838         mcdDiskChanged = 1;
 839         tocUpToDate = 0;
 840         mcd_invalidate_buffers();
 841       }
 842 
 843     read_immediately:
 844 
 845       if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
 846         mcdDiskChanged = 1;
 847         tocUpToDate = 0;
 848         if (mcd_transfer_is_active) {
 849           mcd_state = MCD_S_START;
 850           goto immediately;
 851         }
 852         printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");
 853         mcd_state = MCD_S_IDLE;
 854         while (CURRENT_VALID)
 855           end_request(0);
 856         return;
 857       }
 858 
 859       if (CURRENT_VALID) {
 860         struct mcd_Play_msf msf;
 861         mcd_next_bn = CURRENT -> sector / 4;
 862         hsg2msf(mcd_next_bn, &msf.start);
 863         msf.end.min = ~0;
 864         msf.end.sec = ~0;
 865         msf.end.frame = ~0;
 866         sendMcdCmd(MCMD_DATA_READ, &msf);
 867         mcd_state = MCD_S_DATA;
 868         McdTimeout = READ_TIMEOUT;
 869       } else {
 870         mcd_state = MCD_S_STOP;
 871         goto immediately;
 872       }
 873 
 874     }
 875     break;
 876 
 877 
 878   case MCD_S_DATA:
 879 #ifdef TEST3
 880     printk("MCD_S_DATA\n");
 881 #endif
 882 
 883     st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);
 884   data_immediately:
 885 #ifdef TEST5
 886     printk("Status %02x\n",st);
 887 #endif
 888     switch (st) {
 889 
 890     case MFL_DATA:
 891 #ifdef WARN_IF_READ_FAILURE
 892       if (McdTries == 5)
 893         printk("mcd: read of block %d failed\n", mcd_next_bn);
 894 #endif
 895       if (!McdTries--) {
 896         printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);
 897         if (mcd_transfer_is_active) {
 898           McdTries = 0;
 899           break;
 900         }
 901         if (CURRENT_VALID)
 902           end_request(0);
 903         McdTries = 5;
 904       }
 905       mcd_state = MCD_S_START;
 906       McdTimeout = READ_TIMEOUT;
 907       goto immediately;
 908 
 909     case MFL_STATUSorDATA:
 910       break;
 911 
 912     default:
 913       McdTries = 5;
 914       if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) {
 915         mcd_state = MCD_S_STOP;
 916         goto immediately;
 917       }
 918       mcd_buf_bn[mcd_buf_in] = -1;
 919       READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, 2048);
 920       mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;
 921       if (mcd_buf_out == -1)
 922         mcd_buf_out = mcd_buf_in;
 923       mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;
 924       if (!mcd_transfer_is_active) {
 925         while (CURRENT_VALID) {
 926           mcd_transfer();
 927           if (CURRENT -> nr_sectors == 0)
 928             end_request(1);
 929           else
 930             break;
 931         }
 932       }
 933 
 934       if (CURRENT_VALID
 935           && (CURRENT -> sector / 4 < mcd_next_bn || 
 936               CURRENT -> sector / 4 > mcd_next_bn + 16)) {
 937         mcd_state = MCD_S_STOP;
 938         goto immediately;
 939       }
 940       McdTimeout = READ_TIMEOUT;
 941 #ifdef DOUBLE_QUICK_ONLY
 942       if (MCMD_DATA_READ != MCMD_PLAY_READ)
 943 #endif
 944       {
 945         int count= QUICK_LOOP_COUNT;
 946         while (count--) {
 947           QUICK_LOOP_DELAY;
 948           if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {
 949 #   ifdef TEST4
 950 
 951             printk(" %d ",QUICK_LOOP_COUNT-count);
 952 #   endif
 953             goto data_immediately;
 954           }
 955         }
 956 #   ifdef TEST4
 957 
 958         printk("ended ");
 959 #   endif
 960       }
 961       break;
 962     }
 963     break;
 964 
 965 
 966 
 967   case MCD_S_STOP:
 968 #ifdef TEST3
 969     printk("MCD_S_STOP\n");
 970 #endif
 971 
 972 #ifdef WORK_AROUND_MITSUMI_BUG_93
 973     if (!mitsumi_bug_93_wait)
 974       goto do_not_work_around_mitsumi_bug_93_1;
 975 
 976     McdTimeout = mitsumi_bug_93_wait;
 977     mcd_state = 9+3+1;
 978     break;
 979 
 980   case 9+3+1:
 981     if (McdTimeout)
 982       break;
 983 
 984   do_not_work_around_mitsumi_bug_93_1:
 985 #endif 
 986 
 987     outb(MCMD_STOP, MCDPORT(0));
 988 
 989 #ifdef WORK_AROUND_MITSUMI_BUG_92
 990     if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
 991       int i = 4096;
 992       do {
 993         inb(MCDPORT(0));
 994       } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
 995       outb(MCMD_STOP, MCDPORT(0));
 996       if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
 997         i = 4096;
 998         do {
 999           inb(MCDPORT(0));
1000         } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
1001         outb(MCMD_STOP, MCDPORT(0));
1002       }
1003     }
1004 #endif 
1005 
1006     mcd_state = MCD_S_STOPPING;
1007     McdTimeout = 1000;
1008     break;
1009 
1010   case MCD_S_STOPPING:
1011 #ifdef TEST3
1012     printk("MCD_S_STOPPING\n");
1013 #endif
1014 
1015     if ((st = mcdStatus()) == -1 && McdTimeout)
1016       break;
1017 
1018     if ((st != -1) && (st & MST_DSK_CHG)) {
1019       mcdDiskChanged = 1;
1020       tocUpToDate = 0;
1021       mcd_invalidate_buffers();
1022     }
1023 
1024 #ifdef WORK_AROUND_MITSUMI_BUG_93
1025     if (!mitsumi_bug_93_wait)
1026       goto do_not_work_around_mitsumi_bug_93_2;
1027 
1028     McdTimeout = mitsumi_bug_93_wait;
1029     mcd_state = 9+3+2;
1030     break;
1031 
1032   case 9+3+2:
1033     if (McdTimeout)
1034       break;
1035 
1036     st = -1;
1037 
1038   do_not_work_around_mitsumi_bug_93_2:
1039 #endif 
1040 
1041 #ifdef TEST3
1042     printk("CURRENT_VALID %d mcd_mode %d\n",
1043            CURRENT_VALID, mcd_mode);
1044 #endif
1045 
1046     if (CURRENT_VALID) {
1047       if (st != -1) {
1048         if (mcd_mode == 1)
1049           goto read_immediately;
1050         else
1051           goto set_mode_immediately;
1052       } else {
1053         mcd_state = MCD_S_START;
1054         McdTimeout = 1;
1055       }
1056     } else {
1057       mcd_state = MCD_S_IDLE;
1058       return;
1059     }
1060     break;
1061 
1062   default:
1063     printk("mcd: invalid state %d\n", mcd_state);
1064     return;
1065   }
1066 
1067  ret:
1068   if (!McdTimeout--) {
1069     printk("mcd: timeout in state %d\n", mcd_state);
1070     mcd_state = MCD_S_STOP;
1071   }
1072 
1073   SET_TIMER(mcd_poll, 1);
1074 }
1075 
1076 
1077 
1078 static void
1079 mcd_invalidate_buffers(void)
     
1080 {
1081   int i;
1082   for (i = 0; i < MCD_BUF_SIZ; ++i)
1083     mcd_buf_bn[i] = -1;
1084   mcd_buf_out = -1;
1085 }
1086 
1087 
1088 
1089 
1090 
1091 
1092 int
1093 mcd_open(struct inode *ip, struct file *fp)
     
1094 {
1095         int st;
1096 
1097         if (mcdPresent == 0)
1098                 return -ENXIO;                  
1099         
1100         if (fp->f_mode & 2)                     
1101                 return -EROFS;
1102 
1103         if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
1104 
1105         mcd_invalidate_buffers();
1106 
1107         st = statusCmd();                       
1108         if (st == -1)
1109                 return -EIO;                    
1110 
1111         if ((st & MST_READY) == 0)              
1112         {
1113                 printk("mcd: no disk in drive\n");
1114                 return -EIO;
1115         }
1116 
1117         if (updateToc() < 0)
1118                 return -EIO;
1119 
1120         }
1121         ++mcd_open_count;
1122         MOD_INC_USE_COUNT;
1123         return 0;
1124 }
1125 
1126 
1127 
1128 
1129 
1130 
1131 static void
1132 mcd_release(struct inode * inode, struct file * file)
     
1133 { MOD_DEC_USE_COUNT;
1134   if (!--mcd_open_count) {
1135         mcd_invalidate_buffers();
1136         sync_dev(inode->i_rdev);
1137         invalidate_buffers(inode -> i_rdev);
1138   }
1139 }
1140 
1141 
1142 static struct file_operations mcd_fops = {
1143         NULL,                   
1144         block_read,             
1145         block_write,            
1146         NULL,                   
1147         NULL,                   
1148         mcd_ioctl,              
1149         NULL,                   
1150         mcd_open,               
1151         mcd_release,            
1152         NULL,                   
1153         NULL,                   
1154         check_mcd_change,       
1155         NULL                    
1156 };
1157 
1158 
1159 
1160 
1161 
1162 
1163 int mcd_init(void)
     
1164 {
1165         int count;
1166         unsigned char result[3];
1167 
1168         if (mcd_port <= 0 || mcd_irq <= 0) {
1169           printk("skip mcd_init\n");
1170           return -EIO;
1171         }
1172 
1173         printk("mcd=0x%x,%d: ", mcd_port, mcd_irq);
1174 
1175         if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)
1176         {
1177                 printk("Unable to get major %d for Mitsumi CD-ROM\n",
1178                        MAJOR_NR);
1179                 return -EIO;
1180         }
1181 
1182         if (check_region(mcd_port, 4)) {
1183           printk("Init failed, I/O port (%X) already in use\n",
1184                  mcd_port);
1185           return -EIO;
1186         }
1187           
1188         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1189         read_ahead[MAJOR_NR] = 4;
1190 
1191         
1192 
1193         outb(0, MCDPORT(1));                    
1194         for (count = 0; count < 2000000; count++)
1195                 (void) inb(MCDPORT(1));         
1196 
1197         outb(0x40, MCDPORT(0));                 
1198         for (count = 0; count < 2000000; count++)
1199                 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1200                         break;
1201 
1202         if (count >= 2000000) {
1203                 printk("Init failed. No mcd device at 0x%x irq %d\n",
1204                      mcd_port, mcd_irq);
1205                 return -EIO;
1206         }
1207         count = inb(MCDPORT(0));                
1208         
1209         outb(MCMD_GET_VERSION,MCDPORT(0));
1210         for(count=0;count<3;count++)
1211                 if(getValue(result+count)) {
1212                         printk("mitsumi get version failed at 0x%d\n",
1213                                mcd_port);
1214                         return -EIO;
1215                 }       
1216 
1217         if (result[0] == result[1] && result[1] == result[2])
1218                 return -EIO;
1219         printk("Mitsumi status, type and version : %02X %c %x ",
1220                result[0],result[1],result[2]);
1221 
1222      if (result[1] == 'D') 
1223         {
1224         printk("Double Speed CD ROM\n");
1225         MCMD_DATA_READ = MCMD_2X_READ;
1226         mcdDouble = 1; 
1227         }
1228        else printk("Single Speed CD ROM\n");
1229 
1230         mcdVersion=result[2];
1231 
1232         if (mcdVersion >=4)
1233                 outb(4,MCDPORT(2));     
1234 
1235         
1236 
1237         if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD"))
1238         {
1239                 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
1240                 return -EIO;
1241         }
1242         request_region(mcd_port, 4,"mcd");
1243 
1244         outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1245         outb(0x02,MCDPORT(0));
1246         outb(0x00,MCDPORT(0));
1247         getValue(result);
1248 
1249         outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1250         outb(0x10,MCDPORT(0));
1251         outb(0x04,MCDPORT(0));
1252         getValue(result);
1253 
1254         mcd_invalidate_buffers();
1255         mcdPresent = 1;
1256         return 0;
1257 }
1258 
1259 
1260 static void
1261 hsg2msf(long hsg, struct msf *msf)
     
1262 {
1263         hsg += 150;
1264         msf -> min = hsg / 4500;
1265         hsg %= 4500;
1266         msf -> sec = hsg / 75;
1267         msf -> frame = hsg % 75;
1268 
1269         bin2bcd(&msf -> min);           
1270         bin2bcd(&msf -> sec);
1271         bin2bcd(&msf -> frame);
1272 }
1273 
1274 
1275 static void
1276 bin2bcd(unsigned char *p)
     
1277 {
1278         int u, t;
1279 
1280         u = *p % 10;
1281         t = *p / 10;
1282         *p = u | (t << 4);
1283 }
1284 
1285 static int
1286 bcd2bin(unsigned char bcd)
     
1287 {
1288         return (bcd >> 4) * 10 + (bcd & 0xF);
1289 }
1290 
1291 
1292 
1293 
1294 
1295 
1296 
1297 static int
1298 mcdStatus(void)
     
1299 {
1300         int i;
1301         int st;
1302 
1303         st = inb(MCDPORT(1)) & MFL_STATUS;
1304         if (!st)
1305         {
1306                 i = inb(MCDPORT(0)) & 0xFF;
1307                 return i;
1308         }
1309         else
1310                 return -1;
1311 }
1312 
1313 
1314 
1315 
1316 
1317 
1318 static void
1319 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
     
1320 {
1321         outb(cmd, MCDPORT(0));
1322         outb(params -> start.min, MCDPORT(0));
1323         outb(params -> start.sec, MCDPORT(0));
1324         outb(params -> start.frame, MCDPORT(0));
1325         outb(params -> end.min, MCDPORT(0));
1326         outb(params -> end.sec, MCDPORT(0));
1327         outb(params -> end.frame, MCDPORT(0));
1328 }
1329 
1330 
1331 
1332 
1333 
1334 
1335 
1336 static void
1337 mcdStatTimer(void)
     
1338 {
1339         if (!(inb(MCDPORT(1)) & MFL_STATUS))
1340         {
1341                 wake_up(&mcd_waitq);
1342                 return;
1343         }
1344 
1345         McdTimeout--;
1346         if (McdTimeout <= 0)
1347         {
1348                 wake_up(&mcd_waitq);
1349                 return;
1350         }
1351 
1352         SET_TIMER(mcdStatTimer, 1);
1353 }
1354 
1355 
1356 
1357 
1358 
1359 
1360 
1361 
1362 static int
1363 getMcdStatus(int timeout)
     
1364 {
1365         int st;
1366 
1367         McdTimeout = timeout;
1368         SET_TIMER(mcdStatTimer, 1);
1369         sleep_on(&mcd_waitq);
1370         if (McdTimeout <= 0)
1371                 return -1;
1372 
1373         st = inb(MCDPORT(0)) & 0xFF;
1374         if (st == 0xFF)
1375                 return -1;
1376 
1377         if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
1378                 
1379                 audioStatus = CDROM_AUDIO_COMPLETED;
1380 
1381         if (st & MST_DSK_CHG)
1382         {
1383                 mcdDiskChanged = 1;
1384                 tocUpToDate = 0;
1385                 audioStatus = CDROM_AUDIO_NO_STATUS;
1386         }
1387 
1388         return st;
1389 }
1390 
1391 
1392 
1393 
1394 
1395 
1396 
1397 static int
1398 getValue(unsigned char *result)
     
1399 {
1400         int count;
1401         int s;
1402 
1403         for (count = 0; count < 2000; count++)
1404                 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1405                         break;
1406 
1407         if (count >= 2000)
1408         {
1409                 printk("mcd: getValue timeout\n");
1410                 return -1;
1411         }
1412 
1413         s = inb(MCDPORT(0)) & 0xFF;
1414         *result = (unsigned char) s;
1415         return 0;
1416 }
1417 
1418 
1419 
1420 
1421 
1422 
1423 
1424 int
1425 GetQChannelInfo(struct mcd_Toc *qp)
     
1426 {
1427         unsigned char notUsed;
1428         int retry;
1429 
1430         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1431         {
1432                 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1433                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1434                         break;
1435         }
1436 
1437         if (retry >= MCD_RETRY_ATTEMPTS)
1438                 return -1;
1439 
1440         if (getValue(&qp -> ctrl_addr) < 0) return -1;
1441         if (getValue(&qp -> track) < 0) return -1;
1442         if (getValue(&qp -> pointIndex) < 0) return -1;
1443         if (getValue(&qp -> trackTime.min) < 0) return -1;
1444         if (getValue(&qp -> trackTime.sec) < 0) return -1;
1445         if (getValue(&qp -> trackTime.frame) < 0) return -1;
1446         if (getValue(¬Used) < 0) return -1;
1447         if (getValue(&qp -> diskTime.min) < 0) return -1;
1448         if (getValue(&qp -> diskTime.sec) < 0) return -1;
1449         if (getValue(&qp -> diskTime.frame) < 0) return -1;
1450 
1451         return 0;
1452 }
1453 
1454 
1455 
1456 
1457 
1458 
1459 static int
1460 updateToc()
     
1461 {
1462         if (tocUpToDate)
1463                 return 0;
1464 
1465         if (GetDiskInfo() < 0)
1466                 return -EIO;
1467 
1468         if (GetToc() < 0)
1469                 return -EIO;
1470 
1471         tocUpToDate = 1;
1472         return 0;
1473 }
1474 
1475 
1476 
1477 
1478 
1479 
1480 static int
1481 GetDiskInfo()
     
1482 {
1483         int retry;
1484 
1485         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1486         {
1487                 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1488                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1489                         break;
1490         }
1491 
1492         if (retry >= MCD_RETRY_ATTEMPTS)
1493                 return -1;
1494 
1495         if (getValue(&DiskInfo.first) < 0) return -1;
1496         if (getValue(&DiskInfo.last) < 0) return -1;
1497 
1498         DiskInfo.first = bcd2bin(DiskInfo.first);
1499         DiskInfo.last = bcd2bin(DiskInfo.last);
1500 
1501         if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1502         if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1503         if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1504         if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1505         if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1506         if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1507 
1508 #ifdef MCD_DEBUG
1509 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1510         DiskInfo.first,
1511         DiskInfo.last,
1512         DiskInfo.diskLength.min,
1513         DiskInfo.diskLength.sec,
1514         DiskInfo.diskLength.frame,
1515         DiskInfo.firstTrack.min,
1516         DiskInfo.firstTrack.sec,
1517         DiskInfo.firstTrack.frame);
1518 #endif
1519 
1520         return 0;
1521 }
1522 
1523 
1524 
1525 
1526 
1527 
1528 static int
1529 GetToc()
     
1530 {
1531         int i, px;
1532         int limit;
1533         int retry;
1534         struct mcd_Toc qInfo;
1535 
1536         for (i = 0; i < MAX_TRACKS; i++)
1537                 Toc[i].pointIndex = 0;
1538 
1539         i = DiskInfo.last + 3;
1540 
1541         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1542         {
1543                 outb(MCMD_STOP, MCDPORT(0));
1544                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1545                         break;
1546         }
1547 
1548         if (retry >= MCD_RETRY_ATTEMPTS)
1549                 return -1;
1550 
1551         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1552         {
1553                 outb(MCMD_SET_MODE, MCDPORT(0));
1554                 outb(0x05, MCDPORT(0));                 
1555                 mcd_mode = 0x05;
1556                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1557                         break;
1558         }
1559 
1560         if (retry >= MCD_RETRY_ATTEMPTS)
1561                 return -1;
1562 
1563         for (limit = 300; limit > 0; limit--)
1564         {
1565                 if (GetQChannelInfo(&qInfo) < 0)
1566                         break;
1567 
1568                 px = bcd2bin(qInfo.pointIndex);
1569                 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1570                         if (Toc[px].pointIndex == 0)
1571                         {
1572                                 Toc[px] = qInfo;
1573                                 i--;
1574                         }
1575 
1576                 if (i <= 0)
1577                         break;
1578         }
1579 
1580         Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1581 
1582         for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1583         {
1584                 outb(MCMD_SET_MODE, MCDPORT(0));
1585                 outb(0x01, MCDPORT(0));
1586                 mcd_mode = 1;
1587                 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1588                         break;
1589         }
1590 
1591 #ifdef MCD_DEBUG
1592 for (i = 1; i <= DiskInfo.last; i++)
1593 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
1594 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1595 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1596 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1597 for (i = 100; i < 103; i++)
1598 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
1599 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1600 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1601 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1602 #endif
1603 
1604         return limit > 0 ? 0 : -1;
1605 }
1606 
1607 #ifdef MODULE
1608 int init_module(void)
     
1609 {
1610         return mcd_init();
1611 }
1612 
1613 void cleanup_module(void)
     
1614 { if (MOD_IN_USE)
1615      { printk("mcd module in use - can't remove it.\n");
1616        return;    
1617      }
1618   if ((unregister_blkdev(MAJOR_NR, "mcd") == -EINVAL))
1619      { printk("What's that: can't unregister mcd\n");
1620        return;    
1621      }
1622   release_region(mcd_port,4);
1623   free_irq(mcd_irq);
1624   printk("mcd module released.\n");
1625 }
1626 #endif MODULE