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