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

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