root/drivers/cdrom/gscd.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. check_gscd_med_chg
  2. gscd_setup
  3. gscd_ioctl
  4. gscd_transfer
  5. do_gscd_request
  6. gscd_read_cmd
  7. gscd_open
  8. gscd_release
  9. get_status
  10. cc_invalidate
  11. clear_Audio
  12. wait_drv_ready
  13. cc_Ident
  14. cc_SetSpeed
  15. cc_Reset
  16. cmd_status
  17. cmd_out
  18. cmd_write_cmd
  19. cmd_unit_alive
  20. cmd_info_in
  21. cmd_read_b
  22. cmd_end
  23. cmd_read_w
  24. find_drives
  25. init_cd_drive
  26. update_state
  27. init_module
  28. cleanup_module
  29. gscd_init
  30. my_gscd_init
  31. gscd_hsg2msf
  32. gscd_bin2bcd
  33. gscd_msf2hsg
  34. gscd_bcd2bin

   1 #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
   2 
   3 /*
   4         linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
   5 
   6         Copyright (C) 1995  Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
   7         based upon pre-works by   Eberhard Moenkeberg <emoenke@gwdg.de>
   8         
   9 
  10         For all kind of other information about the GoldStar CDROM
  11         and this Linux device driver I installed a WWW-URL:
  12         http://linux.rz.fh-hannover.de/~raupach        
  13 
  14 
  15              If you are the editor of a Linux CD, you should
  16              enable gscd.c within your boot floppy kernel and
  17              send me one of your CDs for free.
  18 
  19 
  20         --------------------------------------------------------------------
  21         This program is free software; you can redistribute it and/or modify
  22         it under the terms of the GNU General Public License as published by
  23         the Free Software Foundation; either version 2, or (at your option)
  24         any later version.
  25 
  26         This program is distributed in the hope that it will be useful,
  27         but WITHOUT ANY WARRANTY; without even the implied warranty of
  28         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29         GNU General Public License for more details.
  30 
  31         You should have received a copy of the GNU General Public License
  32         along with this program; if not, write to the Free Software
  33         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  34 
  35 */
  36 
  37 /* These settings are for various debug-level. Leave they untouched ... */ 
  38 #define  NO_GSCD_DEBUG 
  39 #define  NO_IOCTL_DEBUG
  40 #define  NO_MODULE_DEBUG
  41 #define  NO_FUTURE_WORK
  42 /*------------------------*/
  43 
  44 #include <linux/config.h>
  45 
  46 #ifdef MODULE
  47 #include <linux/module.h>
  48 #include <linux/version.h>
  49 #include <linux/malloc.h>
  50 #ifndef CONFIG_MODVERSIONS
  51 char kernel_version[] = UTS_RELEASE;
  52 #endif
  53 #endif MODULE
  54 
  55 #include <linux/errno.h>
  56 #include <linux/signal.h>
  57 #include <linux/sched.h>
  58 #include <linux/timer.h>
  59 #include <linux/fs.h>
  60 #include <linux/mm.h>
  61 #include <linux/kernel.h>
  62 #include <linux/cdrom.h>
  63 #include <linux/ioport.h>
  64 #include <linux/major.h>
  65 #include <linux/string.h>
  66 
  67 #include <asm/system.h>
  68 #include <asm/io.h>
  69 #include <asm/segment.h>
  70 
  71 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
  72 #include <linux/blk.h>
  73 #define gscd_port gscd /* for compatible parameter passing with "insmod" */
  74 #include <linux/gscd.h>
  75 
  76 
  77 static int gscdPresent            = 0;
  78 
  79 static unsigned char gscd_buf[2048];    /* buffer for block size conversion */
  80 static int   gscd_bn              = -1;
  81 static short gscd_port            = GSCD_BASE_ADDR;
  82 
  83 /* Kommt spaeter vielleicht noch mal dran ...
  84  *    static struct wait_queue *gscd_waitq = NULL;
  85  */ 
  86 
  87 static void gscd_transfer         (void);
  88 static void gscd_read_cmd         (void);
  89 static void gscd_hsg2msf          (long hsg, struct msf *msf);
  90 static void gscd_bin2bcd          (unsigned char *p);
  91 
  92 /* Schnittstellen zum Kern/FS */
  93 
  94 static void do_gscd_request       (void);
  95 static int  gscd_ioctl            (struct inode *, struct file *, unsigned int, unsigned long);
  96 static int  gscd_open             (struct inode *, struct file *);
  97 static void gscd_release          (struct inode *, struct file *);
  98 static int  check_gscd_med_chg    (kdev_t);
  99 
 100 /*      GoldStar Funktionen    */
 101 
 102 static void cc_Reset             (void);
 103 static int  wait_drv_ready       (void);
 104 static int  find_drives          (void);
 105 static void cmd_out              (int, char *, char *, int);
 106 static void cmd_status           (void);
 107 static void cc_Ident             (char *);
 108 static void cc_SetSpeed          (void);
 109 static void init_cd_drive        (int);
 110 
 111 static int  get_status           (void);
 112 static void clear_Audio          (void);
 113 static void cc_invalidate        (void);
 114 
 115 /* some things for the next version */
 116 #ifdef FUTURE_WORK
 117 static void update_state          (void);
 118 static long gscd_msf2hsg          (struct msf *mp);
 119 static int  gscd_bcd2bin          (unsigned char bcd);
 120 #endif
 121 
 122 /*    common GoldStar Initialization    */
 123 
 124 static int my_gscd_init (void);
 125 
 126 
 127 /*      lo-level cmd-Funktionen    */
 128 
 129 static void cmd_info_in          ( char *, int );
 130 static void cmd_end              ( void );
 131 static void cmd_read_b           ( char *, int, int );
 132 static void cmd_read_w           ( char *, int, int );
 133 static int  cmd_unit_alive       ( void );
 134 static void cmd_write_cmd        ( char * );
 135 
 136 
 137 /*      GoldStar Variablen     */
 138 
 139 static int  curr_drv_state;
 140 static int  drv_states[]       = {0,0,0,0,0,0,0,0};
 141 static int  drv_mode;
 142 static int  disk_state;
 143 static int  speed;
 144 static int  ndrives;
 145 
 146 static unsigned char drv_num_read;
 147 static unsigned char f_dsk_valid;
 148 static unsigned char current_drive;
 149 static unsigned char f_drv_ok;
 150 
 151 
 152 static char f_AudioPlay;
 153 static char f_AudioPause;
 154 static int  AudioStart_m;
 155 static int  AudioStart_f;
 156 static int  AudioEnd_m;
 157 static int  AudioEnd_f;
 158  
 159 
 160 static struct file_operations gscd_fops = {
 161         NULL,                   /* lseek - default */
 162         block_read,             /* read - general block-dev read */
 163         block_write,            /* write - general block-dev write */
 164         NULL,                   /* readdir - bad */
 165         NULL,                   /* select */
 166         gscd_ioctl,             /* ioctl */
 167         NULL,                   /* mmap */
 168         gscd_open,              /* open */
 169         gscd_release,           /* release */
 170         NULL,                   /* fsync */
 171         NULL,                   /* fasync*/
 172         check_gscd_med_chg,     /* media change */
 173         NULL                    /* revalidate */
 174 };
 175 
 176 /* 
 177  * Checking if the media has been changed
 178  * (not yet implemented)
 179  */
 180 static int check_gscd_med_chg (kdev_t full_dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 181 {
 182    int target;
 183 
 184 
 185    target = MINOR(full_dev);
 186 
 187    if (target > 0) 
 188    {
 189       printk("GSCD: GoldStar CD-ROM request error: invalid device.\n");
 190       return 0;
 191    }
 192 
 193    #ifdef GSCD_DEBUG
 194    printk ("gscd: check_med_change\n");
 195    #endif
 196  
 197   return 0;
 198 }
 199 
 200 
 201 void gscd_setup (char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
 202 {
 203   if (ints[0] > 0) 
 204   {
 205      gscd_port = ints[1];
 206   }
 207 }
 208 
 209 
 210 static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212 unsigned char to_do[10];
 213 unsigned char dummy;
 214 
 215                              
 216     switch (cmd)
 217     {
 218        case CDROMSTART:     /* Spin up the drive */
 219                 /* Don't think we can do this.  Even if we could,
 220                  * I think the drive times out and stops after a while
 221                  * anyway.  For now, ignore it.
 222                  */
 223             return 0;
 224 
 225        case CDROMRESUME:   /* keine Ahnung was das ist */
 226             return 0;
 227 
 228 
 229        case CDROMEJECT:
 230             cmd_status ();
 231             to_do[0] = CMD_TRAY_CTL;
 232             cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
 233 
 234             return 0;
 235 
 236        default:
 237             return -EINVAL;
 238     }
 239 
 240 }
 241 
 242 
 243 /*
 244  * Take care of the different block sizes between cdrom and Linux.
 245  * When Linux gets variable block sizes this will probably go away.
 246  */
 247 
 248 static void gscd_transfer (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 249 {
 250 long offs;
 251 
 252         while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4)
 253         {
 254                 offs = (CURRENT -> sector & 3) * 512;
 255                 memcpy(CURRENT -> buffer, gscd_buf + offs, 512);
 256                 CURRENT -> nr_sectors--;
 257                 CURRENT -> sector++;
 258                 CURRENT -> buffer += 512;
 259         }
 260 }
 261 
 262 
 263 /*
 264  * I/O request routine called from Linux kernel.
 265  */
 266 
 267 static void do_gscd_request (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269 unsigned int block,dev;
 270 unsigned int nsect;
 271 
 272 repeat:
 273         if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) return;
 274         INIT_REQUEST;
 275         dev = MINOR(CURRENT->rq_dev);
 276         block = CURRENT->sector;
 277         nsect = CURRENT->nr_sectors;
 278 
 279         if (CURRENT == NULL || CURRENT -> sector == -1)
 280                 return;
 281 
 282         if (CURRENT -> cmd != READ)
 283         {
 284                 printk("GSCD: bad cmd %d\n", CURRENT -> cmd);
 285                 end_request(0);
 286                 goto repeat;
 287         }
 288 
 289         if (MINOR(CURRENT -> rq_dev) != 0)
 290         {
 291                 printk("GSCD: this version supports only one device\n");
 292                 end_request(0);
 293                 goto repeat;
 294         }
 295 
 296         gscd_transfer();
 297 
 298         /* if we satisfied the request from the buffer, we're done. */
 299 
 300         if (CURRENT -> nr_sectors == 0)
 301         {
 302                 end_request(1);
 303                 goto repeat;
 304         }
 305 
 306 #ifdef GSCD_DEBUG
 307         printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect );
 308 #endif
 309 
 310         gscd_read_cmd ();
 311 }
 312 
 313 
 314 
 315 /*
 316  * Check the result of the set-mode command.  On success, send the
 317  * read-data command.
 318  */
 319 
 320 static void
 321 gscd_read_cmd (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323 long   block;
 324 struct gscd_Play_msf gscdcmd;
 325 char   cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */
 326 
 327 
 328 
 329         cmd_status ();
 330         if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) )
 331         {
 332            printk ( "GSCD: no disk or door open\n" );
 333            end_request (0);
 334         }
 335         else
 336         {
 337            if ( disk_state & ST_INVALID )
 338            {
 339               printk ( "GSCD: disk invalid\n" );
 340               end_request (0);
 341            }
 342            else
 343            {
 344               gscd_bn = -1;             /* purge our buffer */
 345               block = CURRENT -> sector / 4;
 346               gscd_hsg2msf(block, &gscdcmd.start);      /* cvt to msf format */
 347 
 348               cmd[2] = gscdcmd.start.min;
 349               cmd[3] = gscdcmd.start.sec;
 350               cmd[4] = gscdcmd.start.frame;
 351 
 352 #ifdef GSCD_DEBUG
 353               printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); 
 354 #endif 
 355               cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 );
 356         
 357               gscd_bn = CURRENT -> sector / 4;
 358               gscd_transfer();
 359               end_request(1);
 360            }
 361         }
 362         SET_TIMER(do_gscd_request, 1);
 363 }
 364 
 365 
 366 /*
 367  * Open the device special file.  Check that a disk is in.
 368  */
 369 
 370 static int gscd_open (struct inode *ip, struct file *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
 371 {
 372 int   st;
 373 
 374 #ifdef GSCD_DEBUG
 375 printk ( "GSCD: open\n" );
 376 #endif
 377 
 378         if (gscdPresent == 0)
 379                 return -ENXIO;                  /* no hardware */
 380 
 381         get_status ();
 382         st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
 383         if ( st )
 384         {
 385            printk ( "GSCD: no disk or door open\n" );
 386            return -ENXIO;
 387         }
 388                    
 389 /*      if (updateToc() < 0)
 390                 return -EIO;
 391 */
 392 
 393         #ifdef MODULE
 394            MOD_INC_USE_COUNT;
 395         #endif
 396  
 397         return 0;
 398 }
 399 
 400 
 401 /*
 402  * On close, we flush all gscd blocks from the buffer cache.
 403  */
 404 
 405 static void gscd_release (struct inode * inode, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
 406 {
 407 
 408 #ifdef GSCD_DEBUG
 409 printk ( "GSCD: release\n" );
 410 #endif
 411 
 412         gscd_bn = -1;
 413         sync_dev(inode->i_rdev);
 414         invalidate_buffers(inode -> i_rdev);
 415 
 416         #ifdef MODULE
 417            MOD_DEC_USE_COUNT;
 418         #endif
 419 }
 420 
 421 
 422 int get_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 423 {
 424 int  status;
 425 
 426     cmd_status ();
 427     status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
 428      
 429     if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) )
 430     {
 431        cc_invalidate ();
 432        return 1;
 433     }
 434     else
 435     {
 436        return 0;
 437     }
 438 }
 439 
 440 
 441 void cc_invalidate (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 442 {
 443    drv_num_read  = 0xFF;
 444    f_dsk_valid   = 0xFF;
 445    current_drive = 0xFF;
 446    f_drv_ok      = 0xFF;
 447 
 448    clear_Audio ();
 449    
 450 }   
 451 
 452 void clear_Audio (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 453 {
 454 
 455    f_AudioPlay = 0;
 456    f_AudioPause = 0;
 457    AudioStart_m = 0;
 458    AudioStart_f = 0;
 459    AudioEnd_m   = 0;
 460    AudioEnd_f   = 0;
 461    
 462 }
 463 
 464 /*
 465  *   waiting ?  
 466  */
 467 
 468 int wait_drv_ready (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 469 {
 470 int found, read;
 471 
 472    do
 473    {  
 474        found = inb ( GSCDPORT(0) ); 
 475        found &= 0x0f;
 476        read  = inb ( GSCDPORT(0) );
 477        read  &= 0x0f;
 478    } while ( read != found );
 479    
 480 #ifdef GSCD_DEBUG
 481 printk ( "Wait for: %d\n", read );
 482 #endif   
 483    
 484    return read;
 485 }
 486 
 487 void cc_Ident (char * respons)
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489 char to_do [] = {CMD_IDENT, 0, 0};
 490 
 491     cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E );
 492 
 493 }
 494 
 495 void cc_SetSpeed (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 496 {
 497 char to_do [] = {CMD_SETSPEED, 0, 0};
 498 char dummy;
 499 
 500     if ( speed > 0 )
 501     {
 502        to_do[1] = speed & 0x0F;
 503        cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
 504     }
 505 }
 506 
 507 
 508 void cc_Reset (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 509 {
 510 char to_do [] = {CMD_RESET, 0};
 511 char dummy;
 512 
 513    cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
 514 }
 515 
 516 
 517 
 518 void cmd_status (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 519 {
 520 char to_do [] = {CMD_STATUS, 0};
 521 char dummy;
 522 
 523    cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
 524 
 525 #ifdef GSCD_DEBUG
 526 printk ("GSCD: Status: %d\n", disk_state );
 527 #endif
 528 
 529 }
 530 
 531 void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count )
     /* [previous][next][first][last][top][bottom][index][help] */
 532 {
 533 int        result;
 534 
 535 
 536        result = wait_drv_ready ();
 537        if ( result != drv_mode )
 538        {
 539        unsigned long test_loops = 0xFFFF;
 540        int           i,dummy;
 541 
 542           outb ( curr_drv_state, GSCDPORT(0));
 543           
 544           /* LOCLOOP_170 */
 545           do
 546           {
 547              result = wait_drv_ready ();
 548              test_loops--;
 549           } while ( (result != drv_mode) && (test_loops > 0) );
 550 
 551           if ( result != drv_mode )
 552           {
 553              disk_state = ST_x08 | ST_x04 | ST_INVALID;
 554              return;
 555           }          
 556         
 557           /* ...and waiting */
 558           for ( i=1,dummy=1 ; i<0xFFFF ; i++ )
 559           {
 560              dummy *= i;
 561           }              
 562        }
 563 
 564        /* LOC_172 */    
 565        /* check the unit */
 566        /* and wake it up */
 567        if ( cmd_unit_alive () != 0x08 )
 568        {
 569           /* LOC_174 */
 570           /* game over for this unit */
 571           disk_state = ST_x08 | ST_x04 | ST_INVALID;
 572           return;
 573        }
 574        
 575        /* LOC_176 */
 576        #ifdef GSCD_DEBUG
 577         printk ("LOC_176 ");
 578        #endif       
 579        if ( drv_mode == 0x09 )
 580        {
 581           /* magic... */
 582           printk ("GSCD: magic ...\n");       
 583           outb ( result, GSCDPORT(2));
 584        }
 585 
 586        /* write the command to the drive */
 587        cmd_write_cmd (cmd);
 588 
 589        /* LOC_178 */
 590        for (;;)
 591        {
 592           result = wait_drv_ready ();
 593           if ( result != drv_mode )
 594           {
 595              /* LOC_179 */
 596              if ( result == 0x04 )                  /* Mode 4 */
 597              {
 598                 /* LOC_205 */
 599                 #ifdef GSCD_DEBUG
 600                 printk ("LOC_205 ");                  
 601                 #endif
 602                 disk_state = inb ( GSCDPORT (2));
 603              
 604                 do
 605                 {
 606                    result = wait_drv_ready ();
 607                 } while ( result != drv_mode );
 608                 return;
 609 
 610              }
 611              else
 612              {
 613                 if ( result == 0x06 )               /* Mode 6 */
 614                 {
 615                    /* LOC_181 */
 616                    #ifdef GSCD_DEBUG
 617                     printk ("LOC_181 ");                      
 618                    #endif
 619 
 620                    if (cmd_type == TYPE_DATA)
 621                    {
 622                       /* read data */
 623                       /* LOC_184 */
 624                       if ( drv_mode == 9 )
 625                       {
 626                          /* read the data to the buffer (word) */
 627  
 628                          /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
 629                          cmd_read_w ( respo_buf, respo_count, CD_FRAMESIZE/2 );
 630                          return;
 631                       } 
 632                       else
 633                       { 
 634                          /* read the data to the buffer (byte) */
 635                          
 636                          /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW)    */
 637                          cmd_read_b ( respo_buf, respo_count, CD_FRAMESIZE );
 638                          return;
 639                       }
 640                    }
 641                    else
 642                    { 
 643                       /* read the info to the buffer */
 644                       cmd_info_in ( respo_buf, respo_count ); 
 645                       return;
 646                    }                  
 647 
 648                    return;
 649                 }
 650              }
 651 
 652           }
 653           else
 654           {
 655              disk_state = ST_x08 | ST_x04 | ST_INVALID;         
 656              return;
 657           }    
 658        } /* for (;;) */
 659 
 660 
 661 #ifdef GSCD_DEBUG
 662 printk ("\n");       
 663 #endif    
 664 }
 665 
 666 
 667 static void cmd_write_cmd ( char *pstr )
     /* [previous][next][first][last][top][bottom][index][help] */
 668 {
 669 int  i,j;
 670 
 671     /* LOC_177 */
 672     #ifdef GSCD_DEBUG
 673      printk ("LOC_177 ");       
 674     #endif
 675        
 676     /* calculate the number of parameter */
 677     j = *pstr & 0x0F;
 678 
 679     /* shift it out */
 680     for ( i=0 ; i<j ; i++ )
 681     {
 682        outb ( *pstr, GSCDPORT(2) );
 683        pstr++;
 684     }
 685 }
 686 
 687 
 688 static int cmd_unit_alive ( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 689 {
 690 int            result;
 691 unsigned long  max_test_loops;
 692 
 693 
 694     /* LOC_172 */
 695     #ifdef GSCD_DEBUG
 696      printk ("LOC_172 ");       
 697     #endif
 698 
 699     outb ( curr_drv_state, GSCDPORT(0));       
 700     max_test_loops = 0xFFFF;
 701      
 702     do
 703     {
 704        result = wait_drv_ready ();
 705        max_test_loops--;
 706     } while ( (result != 0x08) && (max_test_loops > 0) );
 707 
 708     return result;
 709 }       
 710 
 711 
 712 static void cmd_info_in ( char *pb, int count )
     /* [previous][next][first][last][top][bottom][index][help] */
 713 {
 714 int   result;
 715 char  read;
 716 
 717 
 718         /* read info */
 719         /* LOC_182 */
 720         #ifdef GSCD_DEBUG
 721          printk ("LOC_182 ");                                         
 722         #endif
 723        
 724         do
 725         {
 726            read = inb (GSCDPORT(2)); 
 727            if ( count > 0 )
 728            {
 729               *pb = read;
 730               pb++;
 731               count--;
 732            }
 733                          
 734            /* LOC_183 */
 735            do
 736            {
 737               result = wait_drv_ready ();
 738            } while ( result == 0x0E );
 739         } while ( result == 6 );                     
 740 
 741         cmd_end ();
 742         return;
 743 }
 744 
 745 
 746 static void cmd_read_b ( char *pb, int count, int size )
     /* [previous][next][first][last][top][bottom][index][help] */
 747 {
 748 int  result;
 749 int  i;
 750                      
 751                      
 752        /* LOC_188 */
 753        /* LOC_189 */
 754        #ifdef GSCD_DEBUG
 755         printk ("LOC_189 ");                                  
 756        #endif
 757 
 758        do 
 759        {
 760           do
 761           {
 762              result = wait_drv_ready ();
 763           } while ( result != 6 || result == 0x0E );
 764                          
 765           if ( result != 6 )
 766           {
 767              cmd_end ();
 768              return;
 769           }                       
 770           
 771           #ifdef GSCD_DEBUG
 772            printk ("LOC_191 ");       
 773           #endif
 774 
 775           for ( i=0 ; i< size ; i++ )
 776           {
 777              *pb = inb (GSCDPORT(2));
 778              pb++;
 779           }
 780           count--;
 781        } while ( count > 0 );
 782        
 783        cmd_end ();
 784        return;
 785 }
 786 
 787 
 788 static void cmd_end (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 789 {
 790 int   result;
 791 
 792 
 793       /* LOC_204 */
 794       #ifdef GSCD_DEBUG
 795        printk ("LOC_204 ");                                           
 796       #endif
 797       
 798       do
 799       {
 800          result = wait_drv_ready ();
 801          if ( result == drv_mode )
 802          {
 803             return;
 804          }
 805       } while ( result != 4 );
 806 
 807       /* LOC_205 */
 808       #ifdef GSCD_DEBUG
 809        printk ("LOC_205 ");                                   
 810       #endif
 811        
 812       disk_state = inb ( GSCDPORT (2));
 813              
 814       do
 815       {
 816          result = wait_drv_ready ();
 817       } while ( result != drv_mode );
 818       return;
 819 
 820 }
 821 
 822 
 823 static void cmd_read_w ( char *pb, int count, int size )
     /* [previous][next][first][last][top][bottom][index][help] */
 824 {
 825 int  result;
 826 int  i;
 827 
 828 
 829     #ifdef GSCD_DEBUG
 830      printk ("LOC_185 ");                                     
 831     #endif
 832  
 833     do 
 834     {
 835        /* LOC_185 */
 836        do
 837        {
 838           result = wait_drv_ready ();
 839        } while ( result != 6 || result == 0x0E );
 840                          
 841        if ( result != 6 )
 842        {
 843           cmd_end ();
 844           return;
 845        }                       
 846                          
 847        for ( i=0 ; i<size ; i++ )
 848        {
 849            /* na, hier muss ich noch mal drueber nachdenken */
 850            *pb = inw(GSCDPORT(2));
 851            pb++;
 852         }
 853         count--;
 854      } while ( count > 0 );
 855                     
 856      cmd_end ();
 857      return;
 858 }
 859 
 860 int find_drives (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 861 {
 862 int *pdrv;
 863 int drvnum;
 864 int subdrv;
 865 int i;
 866 
 867     speed           = 0;
 868     pdrv            = (int *)&drv_states;
 869     curr_drv_state  = 0xFE;
 870     subdrv          = 0;
 871     drvnum          = 0;
 872 
 873     for ( i=0 ; i<8 ; i++ )
 874     { 
 875        subdrv++;
 876        cmd_status ();
 877        disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
 878        if ( disk_state != (ST_x08 | ST_x04 | ST_INVALID) )
 879        {
 880           /* LOC_240 */
 881           *pdrv = curr_drv_state;
 882           init_cd_drive (drvnum);
 883           pdrv++;
 884           drvnum++;
 885        }
 886        else
 887        {
 888           if ( subdrv < 2 )
 889           {
 890              continue;
 891           }
 892           else
 893           {
 894              subdrv = 0;
 895           }
 896        }   
 897 
 898 /*       curr_drv_state<<1;         <-- das geht irgendwie nicht */ 
 899 /* muss heissen:    curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
 900          curr_drv_state *= 2;
 901          curr_drv_state |= 1;
 902 #ifdef GSCD_DEBUG
 903          printk ("DriveState: %d\n", curr_drv_state );
 904 #endif
 905     } 
 906 
 907     ndrives = drvnum;
 908     return drvnum;
 909 }    
 910 
 911 void init_cd_drive ( int num )
     /* [previous][next][first][last][top][bottom][index][help] */
 912 {
 913 char resp [50];
 914 int  i;
 915 
 916    printk ("GSCD: init unit %d\n", num );
 917    cc_Ident ((char *)&resp);
 918 
 919    printk ("GSCD: identification: ");
 920    for ( i=0 ; i<0x1E; i++ )
 921    {
 922       printk ( "%c", resp[i] );
 923    }
 924    printk ("\n");
 925    
 926    cc_SetSpeed ();  
 927 
 928 }    
 929 
 930 #ifdef FUTURE_WORK
 931 /* return_done */
 932 static void update_state ( void )
     /* [previous][next][first][last][top][bottom][index][help] */
 933 {
 934 unsigned int AX;
 935 
 936 
 937     if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
 938     {
 939        if ( disk_state == (ST_x08 | ST_x04 | ST_INVALID))
 940        {
 941           AX = ST_INVALID;
 942        }
 943   
 944        if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
 945        {
 946           invalidate ();
 947           f_drv_ok = 0;
 948        }
 949        
 950        AX |= 0x8000;
 951     }
 952     
 953     if ( disk_state & ST_PLAYING )
 954     {
 955        AX |= 0x200;
 956     }
 957     
 958     AX |= 0x100;
 959     /* pkt_esbx = AX; */
 960 
 961     disk_state = 0;
 962     
 963 }
 964 #endif
 965 
 966 /* Init for the Module-Version */
 967 int init_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 968 {
 969 long err;
 970 
 971 
 972      /* call the GoldStar-init */
 973      err = my_gscd_init ( );
 974 
 975      if ( err < 0 )
 976      {
 977          return err;
 978      }
 979      else
 980      {
 981         printk ( "Happy GoldStar !\n" );
 982         return 0;
 983      }    
 984 }
 985 
 986 #ifdef MODULE
 987 void cleanup_module (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 988 {
 989 
 990    if (MOD_IN_USE)
 991    {
 992       printk("GoldStar-module in use - can't remove it.\n" );
 993       return;
 994    }
 995  
 996    if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL))
 997    {
 998       printk("What's that: can't unregister GoldStar-module\n" );
 999       return;
1000    }
1001 
1002    release_region (gscd_port,4);
1003    printk( "GoldStar-module released.\n" );
1004 }
1005 #endif
1006 
1007 
1008 /* Test for presence of drive and initialize it.  Called only at boot time. */
1009 int gscd_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
1010 {
1011    return my_gscd_init ();
1012 }
1013 
1014 
1015 /* This is the common initalisation for the GoldStar drive. */
1016 /* It is called at boot time AND for module init.           */
1017 int my_gscd_init (void)
     /* [previous][next][first][last][top][bottom][index][help] */
1018 {
1019 int i;
1020 int result;
1021 
1022         printk ("GSCD: version %s\n", GSCD_VERSION);
1023         printk ("GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port);
1024 
1025         if (check_region(gscd_port, 4)) 
1026         {
1027           printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port);
1028           return -EIO;
1029         }
1030           
1031 
1032         /* check for card */
1033         result = wait_drv_ready ();
1034         if ( result == 0x09 )
1035         {
1036            printk ("GSCD: DMA kann ich noch nicht!\n" );
1037            return -EIO;
1038         }
1039  
1040         if ( result == 0x0b )
1041         {
1042            drv_mode = result;
1043            i = find_drives ();
1044            if ( i == 0 )
1045            {
1046               printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" );
1047               return -EIO;
1048            }
1049         }
1050 
1051         if ( (result != 0x0b) && (result != 0x09) )
1052         {
1053               printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" );
1054               return -EIO;
1055         }                                   
1056 
1057         /* reset all drives */
1058         i = 0;
1059         while ( drv_states[i] != 0 )
1060         {
1061            curr_drv_state = drv_states[i];
1062            printk ( "GSCD: Reset unit %d ... ",i );
1063            cc_Reset ();
1064            printk ( "done\n" );
1065            i++;
1066         }
1067 
1068         if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0)
1069         {
1070                 printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n",
1071                        MAJOR_NR);
1072                 return -EIO;
1073         }
1074 
1075         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1076         read_ahead[MAJOR_NR] = 4;
1077         
1078         disk_state = 0;
1079         gscdPresent = 1;
1080 
1081         request_region(gscd_port, 4, "gscd");
1082 
1083         printk ( "GSCD: GoldStar CD-ROM Drive found.\n" );
1084         return 0;
1085 }
1086 
1087 static void gscd_hsg2msf (long hsg, struct msf *msf)
     /* [previous][next][first][last][top][bottom][index][help] */
1088 {
1089         hsg += CD_BLOCK_OFFSET;
1090         msf -> min = hsg / (CD_FRAMES*CD_SECS);
1091         hsg %= CD_FRAMES*CD_SECS;
1092         msf -> sec = hsg / CD_FRAMES;
1093         msf -> frame = hsg % CD_FRAMES;
1094 
1095         gscd_bin2bcd(&msf -> min);              /* convert to BCD */
1096         gscd_bin2bcd(&msf -> sec);
1097         gscd_bin2bcd(&msf -> frame);
1098 }
1099  
1100 
1101 static void gscd_bin2bcd (unsigned char *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1102 {
1103 int u, t;
1104 
1105         u = *p % 10;
1106         t = *p / 10;
1107         *p = u | (t << 4);
1108 }
1109 
1110 
1111 #ifdef FUTURE_WOTK
1112 static long gscd_msf2hsg (struct msf *mp)
     /* [previous][next][first][last][top][bottom][index][help] */
1113 {
1114         return gscd_bcd2bin(mp -> frame)
1115                 + gscd_bcd2bin(mp -> sec) * CD_FRAMES
1116                 + gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS
1117                 - CD_BLOCK_OFFSET;
1118 }
1119 
1120 static int gscd_bcd2bin (unsigned char bcd)
     /* [previous][next][first][last][top][bottom][index][help] */
1121 {
1122         return (bcd >> 4) * 10 + (bcd & 0xF);
1123 }
1124 #endif
1125 
1126 

/* [previous][next][first][last][top][bottom][index][help] */