root/drivers/block/sbpcd.c

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

DEFINITIONS

This source file includes following definitions.
  1. sbpcd_dprintf
  2. sbpcd_dbg_ioctl
  3. sbp_sleep
  4. lba2msf
  5. bin2bcdx
  6. blk2msf
  7. make16
  8. make32
  9. swap_nibbles
  10. byt2bcd
  11. bcd2bin
  12. msf2blk
  13. sta2err
  14. clr_cmdbuf
  15. mark_timeout
  16. flush_status
  17. CDi_stat_loop
  18. ResponseInfo
  19. EvaluateStatus
  20. ResponseStatus
  21. xx_ReadStatus
  22. xx_ReadError
  23. cmd_out
  24. xx_Seek
  25. xx_SpinUp
  26. yy_SpinDown
  27. yy_SetSpeed
  28. xx_SetVolume
  29. GetStatus
  30. xy_DriveReset
  31. SetSpeed
  32. DriveReset
  33. xx_Pause_Resume
  34. yy_LockDoor
  35. xx_ReadSubQ
  36. xx_ModeSense
  37. xx_TellVolume
  38. xx_ReadCapacity
  39. xx_ReadTocDescr
  40. xx_ReadTocEntry
  41. xx_ReadPacket
  42. convert_UPC
  43. xx_ReadUPC
  44. yy_CheckMultiSession
  45. check_datarate
  46. check_version
  47. switch_drive
  48. check_drives
  49. timewait
  50. obey_audio_state
  51. check_allowed1
  52. check_allowed2
  53. check_allowed3
  54. seek_pos_audio_end
  55. ReadToC
  56. DiskInfo
  57. prepare
  58. xx_PlayAudioMSF
  59. sbpcd_ioctl
  60. sbp_transfer
  61. sbpcd_interrupt
  62. sbp_status
  63. do_sbpcd_request
  64. sbp_read_cmd
  65. sbp_data
  66. sbpcd_open
  67. sbpcd_release
  68. sbpcd_setup
  69. sbpcd_init
  70. check_sbpcd_media_change

   1 /*
   2  *  sbpcd.c   CD-ROM device driver for the whole family of IDE-style
   3  *            Kotobuki/Matsushita/Panasonic CR-5xx drives for
   4  *            SoundBlaster ("Pro" or "16 ASP" or compatible) cards
   5  *            and for "no-sound" interfaces like Lasermate and the
   6  *            Panasonic CI-101P.
   7  *
   8  *  NOTE:     This is release 1.2.
   9  *            It works with my SbPro & drive CR-521 V2.11 from 2/92
  10  *            and with the new CR-562-B V0.75 on a "naked" Panasonic
  11  *            CI-101P interface. And vice versa. 
  12  *  
  13  *
  14  *  VERSION HISTORY
  15  *
  16  *  0.1  initial release, April/May 93, after mcd.c
  17  *  
  18  *  0.2  the "repeat:"-loop in do_sbpcd_request did not check for
  19  *       end-of-request_queue (resulting in kernel panic).
  20  *       Flow control seems stable, but throughput is not better.  
  21  *
  22  *  0.3  interrupt locking totally eliminated (maybe "inb" and "outb"
  23  *       are still locking) - 0.2 made keyboard-type-ahead losses.
  24  *       check_sbpcd_media_change added (to use by isofs/inode.c)
  25  *       - but it detects almost nothing.
  26  *
  27  *  0.4  use MAJOR 25 definitely.
  28  *       Almost total re-design to support double-speed drives and
  29  *       "naked" (no sound) interface cards.
  30  *       Flow control should be exact now (tell me if not).
  31  *       Don't occupy the SbPro IRQ line (not needed either); will
  32  *       live together with Hannu Savolainen's sndkit now.
  33  *       Speeded up data transfer to 150 kB/sec, with help from Kai
  34  *       Makisara, the "provider" of the "mt" tape utility.
  35  *       Give "SpinUp" command if necessary.
  36  *       First steps to support up to 4 drives (but currently only one).
  37  *       Implemented audio capabilities - workman should work, xcdplayer
  38  *       gives some problems.
  39  *       This version is still consuming too much CPU time, and
  40  *       sleeping still has to be worked on.
  41  *       During "long" implied seeks, it seems possible that a 
  42  *       ReadStatus command gets ignored. That gives the message
  43  *       "ResponseStatus timed out" (happens about 6 times here during
  44  *       a "ls -alR" of the YGGDRASIL LGX-Beta CD). Such a case is
  45  *       handled without data error, but it should get done better.
  46  *
  47  *  0.5  Free CPU during waits (again with help from Kai Makisara).
  48  *       Made it work together with the LILO/kernel setup standard.
  49  *       Included auto-probing code, as suggested by YGGDRASIL.
  50  *       Formal redesign to add DDI debugging.
  51  *       There are still flaws in IOCTL (workman with double speed drive).
  52  *
  53  *  1.0  Added support for all drive ids (0...3, no longer only 0)
  54  *       and up to 4 drives on one controller.
  55  *       Added "#define MANY_SESSION" for "old" multi session CDs.
  56  *
  57  *  1.1  Do SpinUp for new drives, too.
  58  *       Revised for clean compile under "old" kernels (pl9).
  59  *
  60  *  1.2  Found the "workman with double-speed drive" bug: use the driver's
  61  *       audio_state, not what the drive is reporting with ReadSubQ.
  62  *
  63  *
  64  *
  65  *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
  66  *     elaborated speed-up experiments (and the fabulous results!), for
  67  *     the "push" towards load-free wait loops, and for the extensive mail
  68  *     thread which brought additional hints and bug fixes.
  69  * 
  70  *
  71  *   Copyright (C) 1993, 1994  Eberhard Moenkeberg <emoenke@gwdg.de>
  72  *                         or <eberhard_moenkeberg@rollo.central.de>
  73  *
  74  *                  The FTP-home of this driver is 
  75  *                  ftp.gwdg.de:/pub/linux/cdrom/drivers/sbpcd/.
  76  *
  77  *                  If you change this software, you should mail a .diff
  78  *                  file with some description lines to emoenke@gwdg.de.
  79  *                  I want to know about it.
  80  *
  81  *                  If you are the editor of a Linux CD, you should
  82  *                  enable sbpcd.c within your boot floppy kernel and
  83  *                  send me one of your CDs for free.
  84  *
  85  *   This program is free software; you can redistribute it and/or modify
  86  *   it under the terms of the GNU General Public License as published by
  87  *   the Free Software Foundation; either version 2, or (at your option)
  88  *   any later version.
  89  *
  90  *   You should have received a copy of the GNU General Public License
  91  *   (for example /usr/src/linux/COPYING); if not, write to the Free
  92  *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  93  *
  94  */
  95 #ifndef PATCHLEVEL
  96 #define PATCHLEVEL 9
  97 #endif
  98 
  99 #include <linux/config.h>
 100 #include <linux/errno.h>
 101 
 102 #if SBPCD_USE_IRQ
 103 #include <linux/signal.h>
 104 #endif SBPCD_USE_IRQ
 105 
 106 #include <linux/sched.h>
 107 #include <linux/timer.h>
 108 #include <linux/fs.h>
 109 #include <linux/kernel.h>
 110 #include <linux/cdrom.h>
 111 #include <linux/ioport.h>
 112 #include <linux/sbpcd.h>
 113 
 114 #if PATCHLEVEL>13
 115 #include <linux/ddi.h>
 116 #include <linux/major.h> 
 117 #else
 118 #define DDIOCSDBG 0x9000
 119 #define MATSUSHITA_CDROM_MAJOR 25  
 120 #endif
 121 
 122 #include <asm/system.h>
 123 #include <asm/io.h>
 124 #include <asm/segment.h>
 125 #include <stdarg.h>
 126 
 127 #define MAJOR_NR MATSUSHITA_CDROM_MAJOR
 128 #include "blk.h"
 129 
 130 #define VERSION "1.2"
 131 
 132 #define SBPCD_DEBUG
 133 
 134 #ifndef CONFIG_SBPCD
 135 #error "SBPCD: \"make config\" again. Enable Matsushita/Panasonic CDROM support"
 136 #endif
 137 
 138 #ifndef CONFIG_ISO9660_FS
 139 #error "SBPCD: \"make config\" again. File system iso9660 is necessary."
 140 #endif
 141 
 142 /*
 143  * still testing around...
 144  */
 145 #define MANY_SESSION 0
 146 #define CDMKE
 147 #undef  FUTURE
 148 #define WORKMAN 0 /* some testing stuff to make it better */
 149 
 150 /*==========================================================================*/
 151 /*==========================================================================*/
 152 /*
 153  * auto-probing address list
 154  * inspired by Adam J. Richter from Yggdrasil
 155  *
 156  * still not good enough - can cause a hang.
 157  *   example: a NE 2000 ehernet card at 300 will cause a hang probing 310.
 158  * if that happens, reboot and use the LILO (kernel) command line.
 159  * the conflicting possible ethernet card addresses get probed last - to
 160  * minimize the hang possibilities. 
 161  *
 162  * The SB Pro addresses get "mirrored" at 0x6xx - to avoid a type error,
 163  * the 0x2xx-addresses must get checked before 0x6xx.
 164  *
 165  * what are other cards' default and range ???
 166  * what about ESCOM PowerSound???
 167  * what about HighScreen???
 168  */
 169 static int autoprobe[] = 
 170 {
 171   CDROM_PORT, SBPRO, /* probe with user's setup first */
 172   0x230, 1, /* Soundblaster Pro and 16 (default) */
 173   0x300, 0, /* CI-101P (default), Galaxy (default), Reveal (one default) */
 174   0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
 175   0x260, 1, /* OmniCD */
 176   0x320, 0, /* Lasermate, CI-101P, Galaxy, Reveal (other default) */
 177   0x340, 0, /* Lasermate, CI-101P */
 178   0x360, 0, /* Lasermate, CI-101P */
 179   0x270, 1, /* Soundblaster 16 */
 180   0x630, 0, /* "sound card #9" (default) */
 181   0x650, 0, /* "sound card #9" */
 182   0x670, 0, /* "sound card #9" */
 183   0x690, 0, /* "sound card #9" */
 184   0x330, 0, /* Lasermate, CI-101P */
 185   0x350, 0, /* Lasermate, CI-101P */
 186   0x370, 0, /* Lasermate, CI-101P */
 187   0x290, 1, /* Soundblaster 16 */
 188   0x310, 0, /* Lasermate, CI-101P */
 189 };
 190 
 191 #define NUM_AUTOPROBE  (sizeof(autoprobe) / sizeof(int))
 192 
 193 
 194 /*==========================================================================*/
 195 /*
 196  * the forward references:
 197  */
 198 static void sbp_read_cmd(void);
 199 static int  sbp_data(void);
 200 
 201 /*==========================================================================*/
 202 
 203 /*
 204  * pattern for printk selection:
 205  *
 206  * (1<<DBG_INF)  necessary information
 207  * (1<<DBG_IRQ)  interrupt trace
 208  * (1<<DBG_REA)  "read" status trace
 209  * (1<<DBG_CHK)  "media check" trace
 210  * (1<<DBG_TIM)  datarate timer test
 211  * (1<<DBG_INI)  initialization trace
 212  * (1<<DBG_TOC)  tell TocEntry values
 213  * (1<<DBG_IOC)  ioctl trace
 214  * (1<<DBG_STA)  "ResponseStatus" trace
 215  * (1<<DBG_ERR)  "xx_ReadError" trace
 216  * (1<<DBG_CMD)  "cmd_out" trace
 217  * (1<<DBG_WRN)  give explanation before auto-probing
 218  * (1<<DBG_MUL)  multi session code test
 219  * (1<<DBG_ID)   "drive_id != 0" test code
 220  * (1<<DBG_IOX)  some special information
 221  * (1<<DBG_DID)  drive ID test
 222  * (1<<DBG_RES)  drive reset info
 223  * (1<<DBG_SPI)  SpinUp test info
 224  * (1<<DBG_000)  unnecessary information
 225  */
 226 #if 1
 227 static int sbpcd_debug =  (1<<DBG_INF) | (1<<DBG_WRN);
 228 #else
 229 static int sbpcd_debug =  (1<<DBG_INF) |
 230                           (1<<DBG_TOC) |
 231                           (1<<DBG_IOX);
 232 #endif
 233 static int sbpcd_ioaddr = CDROM_PORT;   /* default I/O base address */
 234 static int sbpro_type = SBPRO;
 235 static int CDo_command, CDo_reset;
 236 static int CDo_sel_d_i, CDo_enable;
 237 static int CDi_info, CDi_status, CDi_data;
 238 static int MIXER_addr, MIXER_data;
 239 static struct cdrom_msf msf;
 240 static struct cdrom_ti ti;
 241 static struct cdrom_tochdr tochdr;
 242 static struct cdrom_tocentry tocentry;
 243 static struct cdrom_subchnl SC;
 244 static struct cdrom_volctrl volctrl;
 245 char *str_sb = "SoundBlaster";
 246 char *str_lm = "LaserMate";
 247 char *type;
 248 
 249 /*==========================================================================*/
 250 
 251 #if FUTURE
 252 static struct wait_queue *sbp_waitq = NULL;
 253 #endif FUTURE
 254 
 255 /*==========================================================================*/
 256 
 257 #define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead */
 258 
 259 /*==========================================================================*/
 260 
 261 static u_char drive_family[]="CR-5";
 262 static u_char drive_vendor[]="MATSHITA";
 263 
 264 static u_int response_count=0;
 265 static u_int flags_cmd_out;
 266 static u_char cmd_type=0;
 267 static u_char drvcmd[7];
 268 static u_char infobuf[20];
 269 
 270 static u_char timed_out=0;
 271 static u_int datarate= 1000000;
 272 static u_int maxtim16=16000000;
 273 static u_int maxtim04= 4000000;
 274 static u_int maxtim02= 2000000;
 275 static u_int maxtim_8=   30000;
 276 #if MANY_SESSION
 277 static u_int maxtim_data= 9000;
 278 #else
 279 static u_int maxtim_data= 3000;
 280 #endif MANY_SESSION
 281 
 282 /*==========================================================================*/
 283 
 284 static int ndrives=0;
 285 static u_char drv_pattern[4]={ 0x80, 0x80, 0x80, 0x80 }; /* auto speed */
 286 /*  /X:... drv_pattern[0] |= (sax_n1|sax_n2);         */
 287 /*  /A:... for (i=0;i<4;i++) drv_pattern[i] |= sax_a; */
 288 /*  /N:... ndrives=i-'0';                             */
 289 
 290 /*==========================================================================*/
 291 /*
 292  * drive space begins here (needed separate for each unit) 
 293  */
 294 static int d=0; /* DS index: drive number */
 295 
 296 static struct {
 297   char drv_minor; /* minor number or -1 */
 298 
 299   char drive_model[4];
 300   char firmware_version[4];
 301   u_char *sbp_buf; /* Pointer to internal data buffer,
 302                            space allocated during sbpcd_init() */
 303   int sbp_first_frame;  /* First frame in buffer */
 304   int sbp_last_frame;   /* Last frame in buffer  */
 305   int sbp_read_frames;   /* Number of frames being read to buffer */
 306   int sbp_current;       /* Frame being currently read */
 307 
 308   u_char drv_type;
 309   u_char drv_options;
 310   u_char status_byte;
 311   u_char diskstate_flags;
 312   u_char sense_byte;
 313   
 314   u_char CD_changed;
 315   
 316   u_char error_byte;
 317   
 318   u_char f_multisession;
 319   u_int lba_multi;
 320   
 321   u_char audio_state;
 322   u_int pos_audio_start;
 323   u_int pos_audio_end;
 324   char vol_chan0;
 325   u_char vol_ctrl0;
 326   char vol_chan1;
 327   u_char vol_ctrl1;
 328 #if 000
 329   char vol_chan2;
 330   u_char vol_ctrl2;
 331   char vol_chan3;
 332   u_char vol_ctrl3;
 333 #endif 000
 334   
 335   u_char SubQ_audio;
 336   u_char SubQ_ctl_adr;
 337   u_char SubQ_trk;
 338   u_char SubQ_pnt_idx;
 339   u_int SubQ_run_tot;
 340   u_int SubQ_run_trk;
 341   u_char SubQ_whatisthis;
 342   
 343   u_char UPC_ctl_adr;
 344   u_char UPC_buf[7];
 345   
 346   int CDsize_blk;
 347   int frame_size;
 348   int CDsize_frm;
 349   
 350   u_char xa_byte; /* 0x20: XA capabilities */
 351   u_char n_first_track; /* binary */
 352   u_char n_last_track; /* binary (not bcd), 0x01...0x63 */
 353   u_int size_msf; /* time of whole CD, position of LeadOut track */
 354   u_int size_blk;
 355   
 356   u_char TocEnt_nixbyte; /* em */
 357   u_char TocEnt_ctl_adr;
 358   u_char TocEnt_number;
 359   u_char TocEnt_format; /* em */
 360   u_int TocEnt_address;
 361   u_char ored_ctl_adr; /* to detect if CDROM contains data tracks */
 362   
 363   struct {
 364     u_char nixbyte; /* em */
 365     u_char ctl_adr; /* 0x4x: data, 0x0x: audio */
 366     u_char number;
 367     u_char format; /* em */ /* 0x00: lba, 0x01: msf */
 368     u_int address;
 369   } TocBuffer[MAX_TRACKS+1]; /* last entry faked */ 
 370   
 371   int in_SpinUp;
 372   
 373 } DS[4];
 374 
 375 /*
 376  * drive space ends here (needed separate for each unit)
 377  */
 378 
 379 /*==========================================================================*/
 380 /*==========================================================================*/
 381 /*
 382  * DDI interface definitions
 383  */
 384 #ifdef SBPCD_DEBUG
 385 # define DPRINTF(x)     sbpcd_dprintf x
 386 
 387 void sbpcd_dprintf(int level, char *fmt, ...)
     /* [previous][next][first][last][top][bottom][index][help] */
 388 {
 389   char buff[256];
 390   va_list args;
 391   extern int vsprintf(char *buf, const char *fmt, va_list args);
 392 
 393   if (! (sbpcd_debug & (1 << level))) return;
 394 
 395   va_start(args, fmt);
 396   vsprintf(buff, fmt, args);
 397   va_end(args);
 398   printk(buff);
 399 }
 400 
 401 #else
 402 # define DPRINTF(x)     /* nothing */
 403 
 404 #endif SBPCD_DEBUG
 405 
 406 /*
 407  * maintain trace bit pattern
 408  */
 409 static int sbpcd_dbg_ioctl(unsigned long arg, int level)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411   int val;
 412 
 413   val = get_fs_long((int *) arg);
 414   switch(val)
 415     {
 416     case 0:     /* OFF */
 417       sbpcd_debug = 0;
 418       break;
 419 
 420     default:
 421       if (val >= 128) sbpcd_debug &= ~(1 << (val - 128));
 422       else sbpcd_debug |= (1 << val);
 423     }
 424   return(0);
 425 }
 426 
 427 
 428 /*==========================================================================*/
 429 /*==========================================================================*/
 430 /*
 431  * Wait a little while (used for polling the drive).  If in initialization,
 432  * setting a timeout doesn't work, so just loop for a while.
 433  */
 434 static inline void sbp_sleep(u_int jifs)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436    current->state = TASK_INTERRUPTIBLE;
 437    current->timeout = jiffies + jifs;
 438    schedule();
 439 }
 440 
 441 /*==========================================================================*/
 442 /*==========================================================================*/
 443 /*
 444  *  convert logical_block_address to m-s-f_number (3 bytes only)
 445  */
 446 static void lba2msf(int lba, u_char *msf)
     /* [previous][next][first][last][top][bottom][index][help] */
 447 {
 448   lba += CD_BLOCK_OFFSET;
 449   msf[0] = lba / (CD_SECS*CD_FRAMES);
 450   lba %= CD_SECS*CD_FRAMES;
 451   msf[1] = lba / CD_FRAMES;
 452   msf[2] = lba % CD_FRAMES;
 453 }
 454 /*==========================================================================*/
 455 /*==========================================================================*/
 456 /*
 457  *  convert msf-bin to msf-bcd
 458  */
 459 static void bin2bcdx(u_char *p)  /* must work only up to 75 or 99 */
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461   *p=((*p/10)<<4)|(*p%10);
 462 }
 463 /*==========================================================================*/
 464 static u_int blk2msf(u_int blk)
     /* [previous][next][first][last][top][bottom][index][help] */
 465 {
 466   MSF msf;
 467   u_int mm;
 468 
 469   msf.c[3] = 0;
 470   msf.c[2] = (blk + CD_BLOCK_OFFSET) / (CD_SECS * CD_FRAMES);
 471   mm = (blk + CD_BLOCK_OFFSET) % (CD_SECS * CD_FRAMES);
 472   msf.c[1] = mm / CD_FRAMES;
 473   msf.c[0] = mm % CD_FRAMES;
 474   return (msf.n);
 475 }
 476 /*==========================================================================*/
 477 static u_int make16(u_char rh, u_char rl)
     /* [previous][next][first][last][top][bottom][index][help] */
 478 {
 479   return ((rh<<8)|rl);
 480 }
 481 /*==========================================================================*/
 482 static u_int make32(u_int rh, u_int rl)
     /* [previous][next][first][last][top][bottom][index][help] */
 483 {
 484   return ((rh<<16)|rl);
 485 }
 486 /*==========================================================================*/
 487 static u_char swap_nibbles(u_char i)
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489   return ((i<<4)|(i>>4));
 490 }
 491 /*==========================================================================*/
 492 static u_char byt2bcd(u_char i)
     /* [previous][next][first][last][top][bottom][index][help] */
 493 {
 494   return (((i/10)<<4)+i%10);
 495 }
 496 /*==========================================================================*/
 497 static u_char bcd2bin(u_char bcd)
     /* [previous][next][first][last][top][bottom][index][help] */
 498 {
 499   return ((bcd>>4)*10+(bcd&0x0F));
 500 }
 501 /*==========================================================================*/
 502 static int msf2blk(int msfx)
     /* [previous][next][first][last][top][bottom][index][help] */
 503 {
 504   MSF msf;
 505   int i;
 506 
 507   msf.n=msfx;
 508   i=(msf.c[2] * CD_SECS + msf.c[1]) * CD_FRAMES + msf.c[0] - CD_BLOCK_OFFSET;
 509   if (i<0) return (0);
 510   return (i);
 511 }
 512 /*==========================================================================*/
 513 /* evaluate xx_ReadError code (still mysterious) */ 
 514 static int sta2err(int sta)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516   if (sta<=2) return (sta);
 517   if (sta==0x05) return (-4);
 518   if (sta==0x06) return (-6);
 519   if (sta==0x0d) return (-6);
 520   if (sta==0x0e) return (-3);
 521   if (sta==0x14) return (-3);
 522   if (sta==0x0c) return (-11);
 523   if (sta==0x0f) return (-11);
 524   if (sta==0x10) return (-11);
 525   if (sta>=0x16) return (-12);
 526   DS[d].CD_changed=0xFF;
 527   if (sta==0x11) return (-15);
 528   return (-2);
 529 }
 530 /*==========================================================================*/
 531 static void clr_cmdbuf(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 532 {
 533   int i;
 534 
 535   for (i=0;i<7;i++) drvcmd[i]=0;
 536   cmd_type=0;
 537 }
 538 /*==========================================================================*/
 539 static void mark_timeout(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541   timed_out=1;
 542   DPRINTF((DBG_TIM,"SBPCD: timer stopped.\n"));
 543 }
 544 /*==========================================================================*/
 545 static void flush_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 546 {
 547 #ifdef CDMKE
 548   int i;
 549 
 550   if (current == task[0])
 551     for (i=maxtim02;i!=0;i--) inb(CDi_status);
 552   else 
 553     {
 554       sbp_sleep(150);
 555       for (i=maxtim_data;i!=0;i--) inb(CDi_status);
 556     }
 557 #else
 558   timed_out=0;
 559   SET_TIMER(mark_timeout,150);
 560   do { }
 561   while (!timed_out);
 562   CLEAR_TIMER;
 563   inb(CDi_status);
 564 #endif CDMKE
 565 }
 566 /*==========================================================================*/
 567 static int CDi_stat_loop(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 568 {
 569   int i,j;
 570   u_long timeout;
 571   
 572   if (current == task[0])
 573     for(i=maxtim16;i!=0;i--)
 574       {
 575         j=inb(CDi_status);
 576         if (!(j&s_not_data_ready)) return (j);
 577         if (!(j&s_not_result_ready)) return (j);
 578         if (!new_drive) if (j&s_attention) return (j);
 579       }
 580   else
 581     for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; )
 582       {
 583         for ( ;i!=0;i--)
 584           {
 585             j=inb(CDi_status);
 586             if (!(j&s_not_data_ready)) return (j);
 587             if (!(j&s_not_result_ready)) return (j);
 588             if (!new_drive) if (j&s_attention) return (j);
 589           }
 590         sbp_sleep(1);
 591         i = 1;
 592       }
 593   return (-1);
 594 }
 595 /*==========================================================================*/
 596 static int ResponseInfo(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 597 {
 598   int i,j, st=0;
 599   u_long timeout;
 600 
 601   if (current == task[0])
 602     for (i=0;i<response_count;i++)
 603       {
 604         for (j=maxtim_8;j!=0;j--)
 605           {
 606             st=inb(CDi_status);
 607             if (!(st&s_not_result_ready)) break;
 608           }
 609         if (j==0) return (-1);
 610         infobuf[i]=inb(CDi_info);
 611       }
 612   else 
 613     {
 614       for (i=0, timeout = jiffies + 100; i < response_count; i++) 
 615         {
 616           for (j=maxtim_data; ; )
 617             {
 618               for ( ;j!=0;j-- )
 619                 {
 620                   st=inb(CDi_status);
 621                   if (!(st&s_not_result_ready)) break;
 622                 }
 623               if (j != 0 || timeout <= jiffies) break;
 624               sbp_sleep(0);
 625               j = 1;
 626             }
 627           if (timeout <= jiffies) return (-1);
 628           infobuf[i]=inb(CDi_info);
 629         }
 630     }
 631   return (0);
 632 }
 633 /*==========================================================================*/
 634 static int EvaluateStatus(int st)
     /* [previous][next][first][last][top][bottom][index][help] */
 635 {
 636   if (!new_drive)
 637     {
 638       DS[d].status_byte=0;
 639       if (st&p_caddin_old) DS[d].status_byte |= p_door_closed|p_caddy_in;
 640       if (st&p_spinning) DS[d].status_byte |= p_spinning;
 641       if (st&p_check) DS[d].status_byte |= p_check;
 642       if (st&p_busy_old) DS[d].status_byte |= p_busy_new;
 643       if (st&p_disk_ok) DS[d].status_byte |= p_disk_ok;
 644     }
 645   else { DS[d].status_byte=st;
 646          st=p_success_old; /* for new drives: fake "successful" bit of old drives */
 647        }
 648   return (st);
 649 }
 650 /*==========================================================================*/
 651 static int ResponseStatus(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 652 {
 653   int i,j;
 654   u_long timeout;
 655 
 656   DPRINTF((DBG_STA,"SBPCD: doing ResponseStatus...\n"));
 657 
 658   if (current == task[0])
 659     {
 660       if (flags_cmd_out & f_respo3) j = maxtim_8;
 661       else if (flags_cmd_out&f_respo2) j=maxtim16;
 662       else j=maxtim04;
 663       for (;j!=0;j--)
 664         {
 665           i=inb(CDi_status);
 666           if (!(i&s_not_result_ready)) break;
 667         }
 668     }
 669   else
 670     {
 671       if (flags_cmd_out & f_respo3) timeout = jiffies;
 672       else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600;
 673       else timeout = jiffies + 400;
 674       j=maxtim_8;
 675       do
 676         {
 677           for ( ;j!=0;j--)
 678             { 
 679               i=inb(CDi_status);
 680               if (!(i&s_not_result_ready)) break;
 681             }
 682           if (j != 0 || timeout <= jiffies) break;
 683           sbp_sleep(0);
 684           j = 1;
 685         }
 686       while (1);
 687     }
 688   if (j==0) 
 689     { if ((flags_cmd_out & f_respo3) == 0)
 690         DPRINTF((DBG_STA,"SBPCD: ResponseStatus: timeout.\n"));
 691       EvaluateStatus(0);
 692       return (-1);
 693     }
 694   i=inb(CDi_info);
 695   i=EvaluateStatus(i);
 696   return (i);
 697 }
 698 /*==========================================================================*/
 699 static void xx_ReadStatus(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 700 {
 701   int i;
 702 
 703   DPRINTF((DBG_STA,"SBPCD: giving xx_ReadStatus command\n"));
 704 
 705   if (!new_drive) OUT(CDo_command,0x81);
 706   else
 707     {
 708 #if SBPCD_DIS_IRQ
 709       cli();
 710 #endif SBPCD_DIS_IRQ
 711       OUT(CDo_command,0x05);
 712       for (i=0;i<6;i++) OUT(CDo_command,0);
 713 #if SBPCD_DIS_IRQ
 714       sti();
 715 #endif SBPCD_DIS_IRQ
 716     }
 717 }
 718 /*==========================================================================*/
 719 int xx_ReadError(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 720 {
 721   int cmd_out(void);
 722   int i;
 723 
 724   clr_cmdbuf();
 725   DPRINTF((DBG_ERR,"SBPCD: giving xx_ReadError command.\n"));
 726   if (new_drive)
 727     {
 728       drvcmd[0]=0x82;
 729       response_count=8;
 730       flags_cmd_out=f_putcmd|f_ResponseStatus;
 731     }
 732   else
 733     {
 734       drvcmd[0]=0x82;
 735       response_count=6;
 736       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus;
 737     }
 738   i=cmd_out();
 739   DS[d].error_byte=0;
 740   DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: cmd_out(82) returns %d (%02X)\n",i,i));
 741   if (i<0) return (i);
 742   if (new_drive) i=2;
 743   else i=1;
 744   DS[d].error_byte=infobuf[i];
 745   DPRINTF((DBG_ERR,"SBPCD: xx_ReadError: infobuf[%d] is %d (%02X)\n",i,DS[d].error_byte,DS[d].error_byte));
 746   i=sta2err(infobuf[i]);
 747   return (i);
 748 }
 749 /*==========================================================================*/
 750 int cmd_out(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 751 {
 752   int i=0;
 753 
 754   if (flags_cmd_out&f_putcmd)
 755     { 
 756       DPRINTF((DBG_CMD,"SBPCD: cmd_out: put"));
 757       for (i=0;i<7;i++) DPRINTF((DBG_CMD," %02X",drvcmd[i]));
 758       DPRINTF((DBG_CMD,"\n"));
 759 
 760 #if SBPCD_DIS_IRQ
 761       cli();
 762 #endif SBPCD_DIS_IRQ
 763       for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
 764 #if SBPCD_DIS_IRQ
 765       sti();
 766 #endif SBPCD_DIS_IRQ
 767     }
 768   if (response_count!=0)
 769     {
 770       if (cmd_type!=0)
 771         {
 772           if (sbpro_type) OUT(CDo_sel_d_i,0x01);
 773           DPRINTF((DBG_INF,"SBPCD: misleaded to try ResponseData.\n"));
 774           if (sbpro_type) OUT(CDo_sel_d_i,0x00);
 775         }
 776       else i=ResponseInfo();
 777       if (i<0) return (-9);
 778     }
 779   if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to CDi_stat_loop.\n"));
 780   if (flags_cmd_out&f_lopsta)
 781     {
 782       i=CDi_stat_loop();
 783       if ((i<0)||!(i&s_attention)) return (-9);
 784     }
 785   if (!(flags_cmd_out&f_getsta)) goto LOC_229;
 786   
 787 LOC_228:
 788   if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadStatus.\n"));
 789   xx_ReadStatus();
 790 
 791 LOC_229:
 792   if (flags_cmd_out&f_ResponseStatus) 
 793     {
 794       if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to ResponseStatus.\n"));
 795       i=ResponseStatus();
 796                    /* builds status_byte, returns orig. status or p_busy_new */
 797       if (i<0) return (-9);
 798       if (flags_cmd_out&(f_bit1|f_wait_if_busy))
 799         {
 800           if (!st_check)
 801             {
 802               if (flags_cmd_out&f_bit1) if (i&p_success_old) goto LOC_232;
 803               if (!(flags_cmd_out&f_wait_if_busy)) goto LOC_228;
 804               if (!st_busy) goto LOC_228;
 805             }
 806         }
 807     }
 808 LOC_232:
 809   if (!(flags_cmd_out&f_obey_p_check)) return (0);
 810   if (!st_check) return (0);
 811   if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to xx_ReadError.\n"));
 812   i=xx_ReadError();
 813   if (DS[d].in_SpinUp != 0) DPRINTF((DBG_SPI,"SBPCD: to cmd_out OK.\n"));
 814   return (i);
 815 }
 816 /*==========================================================================*/
 817 static int xx_Seek(u_int pos, char f_blk_msf)
     /* [previous][next][first][last][top][bottom][index][help] */
 818 {
 819   int i;
 820 
 821   clr_cmdbuf();
 822   if (f_blk_msf>1) return (-3);
 823   if (!new_drive)
 824     {
 825       if (f_blk_msf==1) pos=msf2blk(pos);
 826       drvcmd[2]=(pos>>16)&0x00FF;
 827       drvcmd[3]=(pos>>8)&0x00FF;
 828       drvcmd[4]=pos&0x00FF;
 829       flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
 830                        f_ResponseStatus | f_obey_p_check | f_bit1;
 831     }
 832   else
 833     {
 834       if (f_blk_msf==0) pos=blk2msf(pos);
 835       drvcmd[1]=(pos>>16)&0x00FF;
 836       drvcmd[2]=(pos>>8)&0x00FF;
 837       drvcmd[3]=pos&0x00FF;
 838       flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
 839     }
 840   drvcmd[0]=0x01;
 841   response_count=0;
 842   i=cmd_out();
 843   return (i);
 844 }
 845 /*==========================================================================*/
 846 static int xx_SpinUp(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 847 {
 848   int i;
 849 
 850   DPRINTF((DBG_SPI,"SBPCD: SpinUp.\n"));
 851   DS[d].in_SpinUp = 1;
 852   clr_cmdbuf();
 853   if (!new_drive)
 854     {
 855       drvcmd[0]=0x05;
 856       flags_cmd_out=f_putcmd|f_respo2|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
 857     }
 858   else
 859     {
 860       drvcmd[0]=0x02;
 861       flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
 862     }
 863   response_count=0;
 864   i=cmd_out();
 865   DS[d].in_SpinUp = 0;
 866   return (i);
 867 }
 868 /*==========================================================================*/
 869 static int yy_SpinDown(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 870 {
 871   int i;
 872 
 873   if (!new_drive) return (-3);
 874   clr_cmdbuf();
 875   drvcmd[0]=0x06;
 876   flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
 877   response_count=0;
 878   i=cmd_out();
 879   return (i);
 880 }
 881 /*==========================================================================*/
 882 static int yy_SetSpeed(u_char speed, u_char x1, u_char x2)
     /* [previous][next][first][last][top][bottom][index][help] */
 883 {
 884   int i;
 885 
 886   if (!new_drive) return (-3);
 887   clr_cmdbuf();
 888   drvcmd[0]=0x09;
 889   drvcmd[1]=0x03;
 890   drvcmd[2]=speed;
 891   drvcmd[3]=x1;
 892   drvcmd[4]=x2;
 893   flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
 894   response_count=0;
 895   i=cmd_out();
 896   return (i);
 897 }
 898 /*==========================================================================*/
 899 static int xx_SetVolume(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 900 {
 901   int i;
 902   u_char channel0,channel1,volume0,volume1;
 903   u_char control0,value0,control1,value1;
 904 
 905   DS[d].diskstate_flags &= ~volume_bit;
 906   clr_cmdbuf();
 907   channel0=DS[d].vol_chan0;
 908   volume0=DS[d].vol_ctrl0;
 909   channel1=control1=DS[d].vol_chan1;
 910   volume1=value1=DS[d].vol_ctrl1;
 911   control0=value0=0;
 912 
 913   if (((DS[d].drv_options&sax_a)!=0)&&(DS[d].drv_type>=drv_211))
 914     {
 915       if ((volume0!=0)&&(volume1==0))
 916         {
 917           volume1=volume0;
 918           channel1=channel0;
 919         }
 920       else if ((volume0==0)&&(volume1!=0))
 921         {
 922           volume0=volume1;
 923           channel0=channel1;
 924         }
 925     }
 926   if (channel0>1)
 927     {
 928       channel0=0;
 929       volume0=0;
 930     }
 931   if (channel1>1)
 932     {
 933       channel1=1;
 934       volume1=0;
 935     }
 936   
 937   if (new_drive)
 938     {
 939       control0=channel0+1;
 940       control1=channel1+1;
 941       value0=(volume0>volume1)?volume0:volume1;
 942       value1=value0;
 943       if (volume0==0) control0=0;
 944       if (volume1==0) control1=0;
 945       drvcmd[0]=0x09;
 946       drvcmd[1]=0x05;
 947       drvcmd[3]=control0;
 948       drvcmd[4]=value0;
 949       drvcmd[5]=control1;
 950       drvcmd[6]=value1;
 951       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
 952     }
 953   else 
 954     {
 955       if (DS[d].drv_type>=drv_300)
 956         {
 957           control0=volume0&0xFC;
 958           value0=volume1&0xFC;
 959           if ((volume0!=0)&&(volume0<4)) control0 |= 0x04;
 960           if ((volume1!=0)&&(volume1<4)) value0 |= 0x04;
 961           if (channel0!=0) control0 |= 0x01;
 962           if (channel1==1) value0 |= 0x01;
 963         }
 964       else
 965         {
 966           value0=(volume0>volume1)?volume0:volume1;
 967           if (DS[d].drv_type<drv_211)
 968             {
 969               if (channel0!=0)
 970                 {
 971                   i=channel1;
 972                   channel1=channel0;
 973                   channel0=i;
 974                   i=volume1;
 975                   volume1=volume0;
 976                   volume0=i;
 977                 }
 978               if (channel0==channel1)
 979                 {
 980                   if (channel0==0)
 981                     {
 982                       channel1=1;
 983                       volume1=0;
 984                       volume0=value0;
 985                     }
 986                   else
 987                     {
 988                       channel0=0;
 989                       volume0=0;
 990                       volume1=value0;
 991                     }
 992                 }
 993             }
 994 
 995           if ((volume0!=0)&&(volume1!=0))
 996             {
 997               if (volume0==0xFF) volume1=0xFF;
 998               else if (volume1==0xFF) volume0=0xFF;
 999             }
1000           else if (DS[d].drv_type<drv_201) volume0=volume1=value0;
1001 
1002           if (DS[d].drv_type>=drv_201)
1003             {
1004               if (volume0==0) control0 |= 0x80;
1005               if (volume1==0) control0 |= 0x40;
1006             }
1007           if (DS[d].drv_type>=drv_211)
1008             {
1009               if (channel0!=0) control0 |= 0x20;
1010               if (channel1!=1) control0 |= 0x10;
1011             }
1012         }
1013       drvcmd[0]=0x84;
1014       drvcmd[1]=0x83;
1015       drvcmd[4]=control0;
1016       drvcmd[5]=value0;
1017       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1018     }
1019 
1020   response_count=0;
1021   i=cmd_out();
1022   if (i>0) return (i);
1023   DS[d].diskstate_flags |= volume_bit;
1024   return (0);
1025 }
1026 /*==========================================================================*/
1027 static int GetStatus(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1028 {
1029   int i;
1030 
1031   flags_cmd_out=f_getsta|f_ResponseStatus|f_obey_p_check;
1032   response_count=0;
1033   cmd_type=0;
1034   i=cmd_out();
1035   return (i);
1036 }
1037 /*==========================================================================*/
1038 static int xy_DriveReset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1039 {
1040   int i;
1041 
1042   DPRINTF((DBG_RES,"SBPCD: xy_DriveReset called.\n"));
1043   if (!new_drive) OUT(CDo_reset,0x00);
1044   else
1045     {
1046       clr_cmdbuf();
1047       drvcmd[0]=0x0A;
1048       flags_cmd_out=f_putcmd;
1049       response_count=0;
1050       i=cmd_out();
1051     }
1052   flush_status();
1053   i=GetStatus();
1054   if (i>=0) return -1;
1055   if (DS[d].error_byte!=aud_12) return -1;
1056   return (0);
1057 }
1058 /*==========================================================================*/
1059 static int SetSpeed(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1060 {
1061   int i, speed;
1062 
1063   if (!(DS[d].drv_options&(speed_auto|speed_300|speed_150))) return (0);
1064   speed=0x80;
1065   if (!(DS[d].drv_options&speed_auto))
1066     {
1067       speed |= 0x40;
1068       if (!(DS[d].drv_options&speed_300)) speed=0;
1069     }
1070   i=yy_SetSpeed(speed,0,0);
1071   return (i);
1072 }
1073 /*==========================================================================*/
1074 static int DriveReset(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1075 {
1076   int i;
1077 
1078   i=xy_DriveReset();
1079   if (i<0) return (-2);
1080   do
1081     {
1082       i=GetStatus();
1083       if ((i<0)&&(i!=-15)) return (-2); /* i!=-15 is from sta2err */
1084       if (!st_caddy_in) break;
1085     }
1086   while (!st_diskok);
1087   DS[d].CD_changed=1;
1088   i=SetSpeed();
1089   if (i<0) return (-2);
1090   return (0);
1091 }
1092 /*==========================================================================*/
1093 static int xx_Pause_Resume(int pau_res)
     /* [previous][next][first][last][top][bottom][index][help] */
1094 {
1095   int i;
1096 
1097   clr_cmdbuf();
1098   if (new_drive)
1099     {
1100       drvcmd[0]=0x0D;
1101       flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
1102     }
1103   else
1104     {
1105       drvcmd[0]=0x8D;
1106       flags_cmd_out=f_putcmd|f_respo2|f_getsta|f_ResponseStatus|f_obey_p_check;
1107     }
1108   if (pau_res!=1) drvcmd[1]=0x80;
1109   response_count=0;
1110   i=cmd_out();
1111   return (i);
1112 }
1113 /*==========================================================================*/
1114 #if 000
1115 static int yy_LockDoor(char lock)
     /* [previous][next][first][last][top][bottom][index][help] */
1116 {
1117   int i;
1118 
1119   if (!new_drive) return (-3);
1120   clr_cmdbuf();
1121   drvcmd[0]=0x0C;
1122   if (lock==1) drvcmd[1]=0x01;
1123   flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1124   response_count=0;
1125   i=cmd_out();
1126   return (i);
1127 }
1128 #endif 000
1129 /*==========================================================================*/
1130 static int xx_ReadSubQ(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1131 {
1132   int i,j;
1133 
1134   DS[d].diskstate_flags &= ~subq_bit;
1135   clr_cmdbuf();
1136   if (new_drive)
1137     {
1138       drvcmd[0]=0x87;
1139       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1140       response_count=11;
1141     }
1142   else
1143     {
1144       drvcmd[0]=0x89;
1145       drvcmd[1]=0x02;
1146       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1147       response_count=13;
1148     }
1149   for (j=0;j<255;j++)
1150     {
1151       i=cmd_out();
1152       if (i<0) return (i);
1153       if (infobuf[0]!=0) break;
1154       if (!st_spinning)
1155         {
1156           DS[d].SubQ_ctl_adr=DS[d].SubQ_trk=DS[d].SubQ_pnt_idx=DS[d].SubQ_whatisthis=0;
1157           DS[d].SubQ_run_tot=DS[d].SubQ_run_trk=0;
1158           return (0);
1159         }
1160     }
1161   DS[d].SubQ_audio=infobuf[0];
1162   DS[d].SubQ_ctl_adr=swap_nibbles(infobuf[1]);
1163   DS[d].SubQ_trk=byt2bcd(infobuf[2]);
1164   DS[d].SubQ_pnt_idx=byt2bcd(infobuf[3]);
1165   i=4;
1166   if (!new_drive) i=5;
1167   DS[d].SubQ_run_tot=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
1168   i=7;
1169   if (!new_drive) i=9;
1170   DS[d].SubQ_run_trk=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2])); /* msf-bin */
1171   DS[d].SubQ_whatisthis=infobuf[i+3];
1172   DS[d].diskstate_flags |= subq_bit;
1173   return (0);
1174 }
1175 /*==========================================================================*/
1176 static int xx_ModeSense(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1177 {
1178   int i;
1179 
1180   DS[d].diskstate_flags &= ~frame_size_bit;
1181   clr_cmdbuf();
1182   if (new_drive)
1183     {
1184       drvcmd[0]=0x84;
1185       drvcmd[1]=0x00;
1186       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1187       response_count=5;
1188     }
1189   else
1190     {
1191       drvcmd[0]=0x85;
1192       drvcmd[1]=0x00;
1193       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1194       response_count=2;
1195     }
1196   i=cmd_out();
1197   if (i<0) return (i);
1198   i=0;
1199   if (new_drive) DS[d].sense_byte=infobuf[i++];
1200   DS[d].frame_size=make16(infobuf[i],infobuf[i+1]);
1201   DS[d].diskstate_flags |= frame_size_bit;
1202   return (0);
1203 }
1204 /*==========================================================================*/
1205 #if 0000
1206 static int xx_TellVolume(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1207 {
1208   int i;
1209   u_char switches;
1210   u_char chan0,vol0,chan1,vol1;
1211 
1212   DS[d].diskstate_flags &= ~volume_bit;
1213   clr_cmdbuf();
1214   if (new_drive)
1215     {
1216       drvcmd[0]=0x84;
1217       drvcmd[1]=0x05;
1218       response_count=5;
1219       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1220     }
1221   else
1222     {
1223       drvcmd[0]=0x85;
1224       drvcmd[1]=0x03;
1225       response_count=2;
1226       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1227     }
1228   i=cmd_out();
1229   if (i<0) return (i);
1230   if (new_drive)
1231     {
1232       chan0=infobuf[1]&0x0F;
1233       vol0=infobuf[2];
1234       chan1=infobuf[3]&0x0F;
1235       vol1=infobuf[4];
1236       if (chan0==0)
1237         {
1238           chan0=1;
1239           vol0=0;
1240         }
1241       if (chan1==0)
1242         {
1243           chan1=2;
1244           vol1=0;
1245         }
1246       chan0 >>= 1;
1247       chan1 >>= 1;
1248     }
1249   else
1250     {
1251       chan0=0;
1252       chan1=1;
1253       vol0=vol1=infobuf[1];
1254       if (DS[d].drv_type>=drv_201)
1255         {
1256           if (DS[d].drv_type<drv_300)
1257             {
1258               switches=infobuf[0];
1259               if ((switches&0x80)!=0) vol0=0;
1260               if ((switches&0x40)!=0) vol1=0;
1261               if (DS[d].drv_type>=drv_211)
1262                 {
1263                   if ((switches&0x20)!=0) chan0=1;
1264                   if ((switches&0x10)!=0) chan1=0;
1265                 }
1266             }
1267           else
1268             {
1269               vol0=infobuf[0];
1270               if ((vol0&0x01)!=0) chan0=1;
1271               if ((vol1&0x01)==0) chan1=0;
1272               vol0 &= 0xFC;
1273               vol1 &= 0xFC;
1274               if (vol0!=0) vol0 += 3;
1275               if (vol1!=0) vol1 += 3;
1276             }
1277         }
1278     }
1279   DS[d].vol_chan0=chan0;
1280   DS[d].vol_ctrl0=vol0;
1281   DS[d].vol_chan1=chan1;
1282   DS[d].vol_ctrl1=vol1;
1283   DS[d].vol_chan2=2;
1284   DS[d].vol_ctrl2=0xFF;
1285   DS[d].vol_chan3=3;
1286   DS[d].vol_ctrl3=0xFF;
1287   DS[d].diskstate_flags |= volume_bit;
1288   return (0);
1289 }
1290 #endif
1291 /*==========================================================================*/
1292 static int xx_ReadCapacity(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1293 {
1294   int i;
1295 
1296   DS[d].diskstate_flags &= ~cd_size_bit;
1297   clr_cmdbuf();
1298   if (new_drive)
1299     {
1300       drvcmd[0]=0x85;
1301       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1302     }
1303   else
1304     {
1305       drvcmd[0]=0x88;
1306       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1307     }
1308   response_count=5;
1309   i=cmd_out();
1310   if (i<0) return (i);
1311   DS[d].CDsize_blk=make32(make16(0,infobuf[0]),make16(infobuf[1],infobuf[2]));
1312   if (new_drive) DS[d].CDsize_blk=msf2blk(DS[d].CDsize_blk);
1313   DS[d].CDsize_frm = (DS[d].CDsize_blk * make16(infobuf[3],infobuf[4])) / CD_FRAMESIZE;
1314   DS[d].CDsize_blk += 151;
1315   DS[d].diskstate_flags |= cd_size_bit;
1316   return (0);
1317 }
1318 /*==========================================================================*/
1319 static int xx_ReadTocDescr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1320 {
1321   int i;
1322 
1323   DS[d].diskstate_flags &= ~toc_bit;
1324   clr_cmdbuf();
1325   if (new_drive)
1326     {
1327       drvcmd[0]=0x8B;
1328       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1329     }
1330   else
1331     {
1332       drvcmd[0]=0x8B;
1333       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1334     }
1335   response_count=6;
1336   i=cmd_out();
1337   if (i<0) return (i);
1338   DS[d].xa_byte=infobuf[0];
1339   DS[d].n_first_track=infobuf[1];
1340   DS[d].n_last_track=infobuf[2];
1341   DS[d].size_msf=make32(make16(0,infobuf[3]),make16(infobuf[4],infobuf[5]));
1342   DS[d].size_blk=msf2blk(DS[d].size_msf);
1343   DS[d].diskstate_flags |= toc_bit;
1344   DPRINTF((DBG_TOC,"SBPCD: TocDesc: %02X %02X %02X %08X\n",
1345          DS[d].xa_byte,DS[d].n_first_track,DS[d].n_last_track,DS[d].size_msf));
1346   return (0);
1347 }
1348 /*==========================================================================*/
1349 static int xx_ReadTocEntry(int num)
     /* [previous][next][first][last][top][bottom][index][help] */
1350 {
1351   int i;
1352 
1353   clr_cmdbuf();
1354   if (new_drive)
1355     {
1356       drvcmd[0]=0x8C;
1357       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1358     }
1359   else
1360     {
1361       drvcmd[0]=0x8C;
1362       drvcmd[1]=0x02;
1363       flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1364     }
1365   drvcmd[2]=num;
1366   response_count=8;
1367   i=cmd_out();
1368   if (i<0) return (i);
1369   DS[d].TocEnt_nixbyte=infobuf[0];
1370   DS[d].TocEnt_ctl_adr=swap_nibbles(infobuf[1]);
1371   DS[d].TocEnt_number=infobuf[2];
1372   DS[d].TocEnt_format=infobuf[3];
1373   if (new_drive) i=4;
1374   else i=5;
1375   DS[d].TocEnt_address=make32(make16(0,infobuf[i]),make16(infobuf[i+1],infobuf[i+2]));
1376   DPRINTF((DBG_TOC,"SBPCD: TocEntry: %02X %02X %02X %02X %08X\n",
1377            DS[d].TocEnt_nixbyte,DS[d].TocEnt_ctl_adr,DS[d].TocEnt_number,
1378            DS[d].TocEnt_format,DS[d].TocEnt_address));
1379   return (0);
1380 }
1381 /*==========================================================================*/
1382 static int xx_ReadPacket(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1383 {
1384   int i;
1385 
1386   clr_cmdbuf();
1387   drvcmd[0]=0x8E;
1388   drvcmd[1]=response_count;
1389   flags_cmd_out=f_putcmd|f_getsta|f_ResponseStatus|f_obey_p_check;
1390   i=cmd_out();
1391   return (i);
1392 }
1393 /*==========================================================================*/
1394 static int convert_UPC(u_char *p)
     /* [previous][next][first][last][top][bottom][index][help] */
1395 {
1396   int i;
1397 
1398   p++;
1399   if (!new_drive) p[13]=0;
1400   for (i=0;i<7;i++)
1401     {
1402       if (new_drive) DS[d].UPC_buf[i]=swap_nibbles(*p++);
1403       else
1404         {
1405           DS[d].UPC_buf[i]=((*p++)<<4)&0xFF;
1406           DS[d].UPC_buf[i] |= *p++;
1407         }
1408     }
1409   DS[d].UPC_buf[6] &= 0xF0;
1410   return (0);
1411 }
1412 /*==========================================================================*/
1413 static int xx_ReadUPC(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1414 {
1415   int i;
1416 
1417   DS[d].diskstate_flags &= ~upc_bit;
1418   clr_cmdbuf();
1419   if (new_drive)
1420     {
1421       drvcmd[0]=0x88;
1422       response_count=8;
1423       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1424     }
1425   else
1426     {
1427       drvcmd[0]=0x08;
1428       response_count=0;
1429       flags_cmd_out=f_putcmd|f_lopsta|f_getsta|f_ResponseStatus|f_obey_p_check|f_bit1;
1430     }
1431   i=cmd_out();
1432   if (i<0) return (i);
1433   if (!new_drive)
1434     {
1435       response_count=16;
1436       i=xx_ReadPacket();
1437       if (i<0) return (i);
1438     }
1439   DS[d].UPC_ctl_adr=0;
1440   if (new_drive) i=0;
1441   else i=2;
1442   if ((infobuf[i]&0x80)!=0)
1443     {
1444       convert_UPC(&infobuf[i]);
1445       DS[d].UPC_ctl_adr &= 0xF0;
1446       DS[d].UPC_ctl_adr |= 0x02;
1447     }
1448   DS[d].diskstate_flags |= upc_bit;
1449   return (0);
1450 }
1451 /*==========================================================================*/
1452 static int yy_CheckMultiSession(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1453 {
1454   int i;
1455 
1456   DS[d].diskstate_flags &= ~multisession_bit;
1457   DS[d].f_multisession=0;
1458   clr_cmdbuf();
1459   if (new_drive)
1460     {
1461       drvcmd[0]=0x8D;
1462       response_count=6;
1463       flags_cmd_out=f_putcmd|f_ResponseStatus|f_obey_p_check;
1464       i=cmd_out();
1465       if (i<0) return (i);
1466       if ((infobuf[0]&0x80)!=0)
1467         {
1468           DPRINTF((DBG_MUL,"SBPCD: MultiSession CD detected: %02X %02X %02X %02X %02X %02X\n",
1469                          infobuf[0], infobuf[1], infobuf[2],
1470                          infobuf[3], infobuf[4], infobuf[5]));
1471           DS[d].f_multisession=1;
1472           DS[d].lba_multi=msf2blk(make32(make16(0,infobuf[1]),
1473                                    make16(infobuf[2],infobuf[3])));
1474         }
1475     }
1476   DS[d].diskstate_flags |= multisession_bit;
1477   return (0);
1478 }
1479 /*==========================================================================*/
1480 static void check_datarate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1481 {
1482 #ifdef CDMKE
1483   int i=0;
1484 
1485   timed_out=0;
1486   datarate=0;
1487 
1488   /* set a timer to make (timed_out!=0) after 1.1 seconds */
1489 
1490   DPRINTF((DBG_TIM,"SBPCD: timer started (110).\n"));
1491   sti(); /* to avoid possible "printf" bug */
1492 
1493   SET_TIMER(mark_timeout,110);
1494   do
1495     {
1496       i=inb(CDi_status);
1497       datarate++;
1498 
1499 #if 00000
1500       if (datarate>0x0FFFFFFF) break;
1501 #endif 00000
1502 
1503     }
1504   while (!timed_out); /* originally looping for 1.1 seconds */
1505   CLEAR_TIMER;
1506   DPRINTF((DBG_TIM,"SBPCD: datarate: %d\n", datarate));
1507   if (datarate<65536) datarate=65536;
1508 
1509   maxtim16=datarate*16;
1510   maxtim04=datarate*4;
1511   maxtim02=datarate*2;
1512   maxtim_8=datarate/32;
1513 #if MANY_SESSION
1514   maxtim_data=datarate/100;
1515 #else
1516   maxtim_data=datarate/300;
1517 #endif MANY_SESSION
1518   DPRINTF((DBG_TIM,"SBPCD: maxtim_8 %d, maxtim_data %d.\n",
1519            maxtim_8, maxtim_data));
1520 #endif CDMKE
1521 }
1522 /*==========================================================================*/
1523 static int check_version(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1524 {
1525   int i, j;
1526 
1527   /* clear any pending error state */
1528   clr_cmdbuf();
1529   drvcmd[0]=0x82;
1530   response_count=9;
1531   flags_cmd_out=f_putcmd;
1532   cmd_out();
1533 
1534   /* read drive version */
1535   clr_cmdbuf();
1536   for (i=0;i<12;i++) infobuf[i]=0;
1537   drvcmd[0]=0x83;
1538   response_count=12;
1539   flags_cmd_out=f_putcmd;
1540   i=cmd_out();
1541   if (i<0) DPRINTF((DBG_INI,"SBPCD: cmd_83 returns %d\n",i));
1542 
1543   DPRINTF((DBG_INI,"SBPCD: infobuf = \""));
1544   for (i=0;i<12;i++) DPRINTF((DBG_INI,"%c",infobuf[i]));
1545   DPRINTF((DBG_INI,"\"\n"));
1546 
1547   for (i=0;i<4;i++) if (infobuf[i]!=drive_family[i]) break;
1548   if (i==4)
1549     {
1550       DS[d].drive_model[0]=infobuf[i++];
1551       DS[d].drive_model[1]=infobuf[i++];
1552       DS[d].drive_model[2]='-';
1553       DS[d].drive_model[3]='x';
1554       DS[d].drv_type=drv_new;
1555     }
1556   else
1557     {
1558       for (i=0;i<8;i++) if (infobuf[i]!=drive_vendor[i]) break;
1559       if (i!=8) return (-1);
1560       DS[d].drive_model[0]='2';
1561       DS[d].drive_model[1]='x';
1562       DS[d].drive_model[2]='-';
1563       DS[d].drive_model[3]='x';
1564       DS[d].drv_type=drv_old;
1565     }
1566   for (j=0;j<4;j++) DS[d].firmware_version[j]=infobuf[i+j];
1567   j = (DS[d].firmware_version[0] & 0x0F) * 100 +
1568       (DS[d].firmware_version[2] & 0x0F) *10 +
1569       (DS[d].firmware_version[3] & 0x0F);
1570   if (new_drive)
1571     {
1572       if (j<100) DS[d].drv_type=drv_099;
1573       else DS[d].drv_type=drv_100;
1574     }
1575   else if (j<200) DS[d].drv_type=drv_199;
1576   else if (j<201) DS[d].drv_type=drv_200;
1577   else if (j<210) DS[d].drv_type=drv_201;
1578   else if (j<211) DS[d].drv_type=drv_210;
1579   else if (j<300) DS[d].drv_type=drv_211;
1580   else DS[d].drv_type=drv_300;
1581   return (0);
1582 }
1583 /*==========================================================================*/
1584 static int switch_drive(int num)
     /* [previous][next][first][last][top][bottom][index][help] */
1585 {
1586   int i;
1587 
1588   d=num;
1589 
1590   i=num;
1591   if (sbpro_type) i=(i&0x01)<<1|(i&0x02)>>1;
1592   OUT(CDo_enable,i);
1593   DPRINTF((DBG_DID,"SBPCD: switch_drive: drive %d activated.\n",DS[d].drv_minor));
1594   return (0);
1595 }
1596 /*==========================================================================*/
1597 /*
1598  * probe for the presence of drives on the selected controller
1599  */
1600 static int check_drives(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1601 {
1602   int i, j;
1603   char *printk_header="";
1604 
1605   DPRINTF((DBG_INI,"SBPCD: check_drives entered.\n"));
1606 
1607   ndrives=0;
1608   for (j=0;j<NR_SBPCD;j++)
1609     {
1610       DS[j].drv_minor=j;
1611       switch_drive(j);
1612       DPRINTF((DBG_ID,"SBPCD: check_drives: drive %d activated.\n",j));
1613       i=check_version();
1614       DPRINTF((DBG_ID,"SBPCD: check_version returns %d.\n",i));
1615       if (i>=0)
1616         {
1617           ndrives++;
1618           DS[d].drv_options=drv_pattern[j];
1619           if (!new_drive) DS[d].drv_options&=~(speed_auto|speed_300|speed_150);
1620           printk("%sDrive %d: %s%.4s (%.4s)\n", printk_header,
1621                  DS[d].drv_minor,
1622                  drive_family,
1623                  DS[d].drive_model,
1624                  DS[d].firmware_version);
1625           printk_header="       - ";
1626         }
1627       else DS[d].drv_minor=-1;
1628     }
1629   if (ndrives==0) return (-1);
1630   return (0);
1631 }
1632 /*==========================================================================*/
1633 #if 000
1634 static void timewait(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1635 {
1636   int i;
1637   for (i=0; i<65500; i++);
1638 }
1639 #endif 000
1640 /*==========================================================================*/
1641 #if FUTURE
1642 /*
1643  *  obtain if requested service disturbs current audio state
1644  */            
1645 static int obey_audio_state(u_char audio_state, u_char func,u_char subfunc)
     /* [previous][next][first][last][top][bottom][index][help] */
1646 {
1647   switch (audio_state)                   /* audio status from controller  */
1648     {
1649     case aud_11: /* "audio play in progress" */
1650     case audx11:
1651       switch (func)                      /* DOS command code */
1652         {
1653         case cmd_07: /* input flush  */
1654         case cmd_0d: /* open device  */
1655         case cmd_0e: /* close device */
1656         case cmd_0c: /* ioctl output */
1657           return (1);
1658         case cmd_03: /* ioctl input  */
1659           switch (subfunc)
1660             /* DOS ioctl input subfunction */
1661             {
1662             case cxi_00:
1663             case cxi_06:
1664             case cxi_09:
1665               return (1);
1666             default:
1667               return (ERROR15);
1668             }
1669           return (1);
1670         default:
1671           return (ERROR15);
1672         }
1673       return (1);
1674     case aud_12:                  /* "audio play paused"      */
1675     case audx12:
1676       return (1);
1677     default:
1678       return (2);
1679     }
1680 }
1681 #endif FUTURE
1682 /*==========================================================================*/
1683 /* allowed is only
1684  * ioctl_o, flush_input, open_device, close_device, 
1685  * tell_address, tell_volume, tell_capabiliti,
1686  * tell_framesize, tell_CD_changed, tell_audio_posi
1687  */
1688 static int check_allowed1(u_char func1, u_char func2)
     /* [previous][next][first][last][top][bottom][index][help] */
1689 {
1690 #if 000
1691   if (func1==ioctl_o) return (0);
1692   if (func1==read_long) return (-1);
1693   if (func1==read_long_prefetch) return (-1);
1694   if (func1==seek) return (-1);
1695   if (func1==audio_play) return (-1);
1696   if (func1==audio_pause) return (-1);
1697   if (func1==audio_resume) return (-1);
1698   if (func1!=ioctl_i) return (0);
1699   if (func2==tell_SubQ_run_tot) return (-1);
1700   if (func2==tell_cdsize) return (-1);
1701   if (func2==tell_TocDescrip) return (-1);
1702   if (func2==tell_TocEntry) return (-1);
1703   if (func2==tell_subQ_info) return (-1);
1704   if (new_drive) if (func2==tell_SubChanInfo) return (-1);
1705   if (func2==tell_UPC) return (-1);
1706 #else
1707   return (0);
1708 #endif 000
1709 }
1710 /*==========================================================================*/
1711 static int check_allowed2(u_char func1, u_char func2)
     /* [previous][next][first][last][top][bottom][index][help] */
1712 {
1713 #if 000
1714   if (func1==read_long) return (-1);
1715   if (func1==read_long_prefetch) return (-1);
1716   if (func1==seek) return (-1);
1717   if (func1==audio_play) return (-1);
1718   if (func1!=ioctl_o) return (0);
1719   if (new_drive)
1720     {
1721       if (func2==EjectDisk) return (-1);
1722       if (func2==CloseTray) return (-1);
1723     }
1724 #else
1725   return (0);
1726 #endif 000
1727 }
1728 /*==========================================================================*/
1729 static int check_allowed3(u_char func1, u_char func2)
     /* [previous][next][first][last][top][bottom][index][help] */
1730 {
1731 #if 000
1732   if (func1==ioctl_i)
1733     {
1734       if (func2==tell_address) return (0);
1735       if (func2==tell_capabiliti) return (0);
1736       if (func2==tell_CD_changed) return (0);
1737       if (!new_drive) if (func2==tell_SubChanInfo) return (0);
1738       return (-1);
1739     }
1740   if (func1==ioctl_o)
1741     {
1742       if (func2==DriveReset) return (0);
1743       if (!new_drive)
1744         {
1745           if (func2==EjectDisk) return (0);
1746           if (func2==LockDoor) return (0);
1747           if (func2==CloseTray) return (0);
1748         }
1749       return (-1);
1750     }
1751   if (func1==flush_input) return (-1);
1752   if (func1==read_long) return (-1);
1753   if (func1==read_long_prefetch) return (-1);
1754   if (func1==seek) return (-1);
1755   if (func1==audio_play) return (-1);
1756   if (func1==audio_pause) return (-1);
1757   if (func1==audio_resume) return (-1);
1758 #else
1759   return (0);
1760 #endif 000
1761 }
1762 /*==========================================================================*/
1763 static int seek_pos_audio_end(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1764 {
1765   int i;
1766 
1767   i=msf2blk(DS[d].pos_audio_end)-1;
1768   if (i<0) return (-1);
1769   i=xx_Seek(i,0);
1770   return (i);
1771 }
1772 /*==========================================================================*/
1773 static int ReadToC(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1774 {
1775   int i, j;
1776   DS[d].diskstate_flags &= ~toc_bit;
1777   DS[d].ored_ctl_adr=0;
1778   for (j=DS[d].n_first_track;j<=DS[d].n_last_track;j++)
1779     {
1780       i=xx_ReadTocEntry(j);
1781       if (i<0) return (i);
1782       DS[d].TocBuffer[j].nixbyte=DS[d].TocEnt_nixbyte;
1783       DS[d].TocBuffer[j].ctl_adr=DS[d].TocEnt_ctl_adr;
1784       DS[d].TocBuffer[j].number=DS[d].TocEnt_number;
1785       DS[d].TocBuffer[j].format=DS[d].TocEnt_format;
1786       DS[d].TocBuffer[j].address=DS[d].TocEnt_address;
1787       DS[d].ored_ctl_adr |= DS[d].TocEnt_ctl_adr;
1788     }
1789 /* fake entry for LeadOut Track */
1790   DS[d].TocBuffer[j].nixbyte=0;
1791   DS[d].TocBuffer[j].ctl_adr=0;
1792   DS[d].TocBuffer[j].number=0;
1793   DS[d].TocBuffer[j].format=0;
1794   DS[d].TocBuffer[j].address=DS[d].size_msf;
1795 
1796   DS[d].diskstate_flags |= toc_bit;
1797   return (0);
1798 }
1799 /*==========================================================================*/
1800 static int DiskInfo(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1801 {
1802   int i;
1803 
1804   i=SetSpeed();
1805   if (i<0)
1806     {
1807       DPRINTF((DBG_INF,"SBPCD: DiskInfo: first SetSpeed returns %d\n", i));
1808       i=SetSpeed();
1809       if (i<0)
1810         {
1811           DPRINTF((DBG_INF,"SBPCD: DiskInfo: second SetSpeed returns %d\n", i));
1812           return (i);
1813         }
1814     }
1815   i=xx_ModeSense();
1816   if (i<0)
1817     {
1818       DPRINTF((DBG_INF,"SBPCD: DiskInfo: first xx_ModeSense returns %d\n", i));
1819       i=xx_ModeSense();
1820       if (i<0)
1821         {
1822           DPRINTF((DBG_INF,"SBPCD: DiskInfo: second xx_ModeSense returns %d\n", i));
1823           return (i);
1824         }
1825       return (i);
1826     }
1827   i=xx_ReadCapacity();
1828   if (i<0)
1829     {
1830       DPRINTF((DBG_INF,"SBPCD: DiskInfo: first ReadCapacity returns %d\n", i));
1831       i=xx_ReadCapacity();
1832       if (i<0)
1833         {
1834           DPRINTF((DBG_INF,"SBPCD: DiskInfo: second ReadCapacity returns %d\n", i));
1835           return (i);
1836         }
1837       return (i);
1838     }
1839   i=xx_ReadTocDescr();
1840   if (i<0)
1841     {
1842       DPRINTF((DBG_INF,"SBPCD: DiskInfo: ReadTocDescr returns %d\n", i));
1843       return (i);
1844     }
1845   i=ReadToC();
1846   if (i<0)
1847     {
1848       DPRINTF((DBG_INF,"SBPCD: DiskInfo: ReadToC returns %d\n", i));
1849       return (i);
1850     }
1851   i=yy_CheckMultiSession();
1852   if (i<0)
1853     {
1854       DPRINTF((DBG_INF,"SBPCD: DiskInfo: yy_CheckMultiSession returns %d\n", i));
1855       return (i);
1856     }
1857   i=xx_ReadTocEntry(DS[d].n_first_track);
1858   if (i<0)
1859     {
1860       DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadTocEntry(1) returns %d\n", i));
1861       return (i);
1862     }
1863   i=xx_ReadUPC();
1864   if (i<0)
1865     {
1866       DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadUPC returns %d\n", i));
1867       return (i);
1868     }
1869   return (0);
1870 }
1871 /*==========================================================================*/
1872 /*
1873  *  called always if driver gets entered
1874  *  returns 0 or ERROR2 or ERROR15
1875  */
1876 static int prepare(u_char func, u_char subfunc)
     /* [previous][next][first][last][top][bottom][index][help] */
1877 {
1878   int i;
1879 
1880   if (!new_drive)
1881     {
1882       i=inb(CDi_status);
1883       if (i&s_attention) GetStatus();
1884     }
1885   else GetStatus();
1886   if (DS[d].CD_changed==0xFF)
1887     {
1888 #if MANY_SESSION
1889 #else
1890       DS[d].diskstate_flags=0;
1891 #endif MANY_SESSION
1892       DS[d].audio_state=0;
1893       if (!st_diskok)
1894         {
1895           i=check_allowed1(func,subfunc);
1896           if (i<0) return (-2);
1897         }
1898       else 
1899         {
1900           i=check_allowed3(func,subfunc);
1901           if (i<0)
1902             {
1903               DS[d].CD_changed=1;
1904               return (-15);
1905             }
1906         }
1907     }
1908   else
1909     {
1910       if (!st_diskok)
1911         {
1912 #if MANY_SESSION
1913 #else
1914           DS[d].diskstate_flags=0;
1915 #endif MANY_SESSION
1916           DS[d].audio_state=0;
1917           i=check_allowed1(func,subfunc);
1918           if (i<0) return (-2);
1919         }
1920       else
1921         { 
1922           if (st_busy)
1923             {
1924               if (DS[d].audio_state!=audio_pausing)
1925                 {
1926                   i=check_allowed2(func,subfunc);
1927                   if (i<0) return (-2);
1928                 }
1929             }
1930           else
1931             {
1932               if (DS[d].audio_state==audio_playing) seek_pos_audio_end();
1933               DS[d].audio_state=0;
1934             }
1935           if (!frame_size_valid)
1936             {
1937               i=DiskInfo();
1938               if (i<0)
1939                 {
1940 #if MANY_SESSION
1941 #else
1942                   DS[d].diskstate_flags=0;
1943 #endif MANY_SESSION
1944                   DS[d].audio_state=0;
1945                   i=check_allowed1(func,subfunc);
1946                   if (i<0) return (-2);
1947                 }
1948             }
1949         }
1950     }
1951   return (0);
1952 }
1953 /*==========================================================================*/
1954 static int xx_PlayAudioMSF(int pos_audio_start,int pos_audio_end)
     /* [previous][next][first][last][top][bottom][index][help] */
1955 {
1956   int i;
1957 
1958   if (DS[d].audio_state==audio_playing) return (-EINVAL);
1959   clr_cmdbuf();
1960   if (new_drive)
1961     {
1962       drvcmd[0]=0x0E;
1963       flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
1964                        f_obey_p_check | f_wait_if_busy;
1965     }
1966   else
1967     {
1968       drvcmd[0]=0x0B;
1969       flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
1970                        f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
1971     }
1972   drvcmd[1]=(pos_audio_start>>16)&0x00FF;
1973   drvcmd[2]=(pos_audio_start>>8)&0x00FF;
1974   drvcmd[3]=pos_audio_start&0x00FF;
1975   drvcmd[4]=(pos_audio_end>>16)&0x00FF;
1976   drvcmd[5]=(pos_audio_end>>8)&0x00FF;
1977   drvcmd[6]=pos_audio_end&0x00FF;
1978   response_count=0;
1979   i=cmd_out();
1980   return (i);
1981 }
1982 /*==========================================================================*/
1983 /*==========================================================================*/
1984 
1985 /*==========================================================================*/
1986 /*==========================================================================*/
1987 /*
1988  * ioctl support, adopted from scsi/sr_ioctl.c and mcd.c
1989  */
1990 static int sbpcd_ioctl(struct inode *inode,struct file *file,
     /* [previous][next][first][last][top][bottom][index][help] */
1991                        u_int cmd, u_long arg)
1992 {
1993   int i, st;
1994 
1995   DPRINTF((DBG_IOC,"SBPCD: ioctl(%d, 0x%08lX, 0x%08lX)\n",
1996                                 MINOR(inode->i_rdev), cmd, arg));
1997   if (!inode) return (-EINVAL);
1998   st=GetStatus();
1999   if (st<0) return (-EIO);
2000   
2001   if (!toc_valid)
2002     {
2003       i=DiskInfo();
2004       if (i<0) return (-EIO);   /* error reading TOC */
2005     }
2006   
2007   i=MINOR(inode->i_rdev);
2008   if ( (i<0) || (i>=NR_SBPCD) )
2009     {
2010       DPRINTF((DBG_INF,"SBPCD: ioctl: bad device: %d\n", i));
2011       return (-ENODEV);             /* no such drive */
2012     }
2013   switch_drive(i);
2014 
2015 
2016   DPRINTF((DBG_IOC,"SBPCD: ioctl: device %d, request %04X\n",i,cmd));
2017   switch (cmd)          /* Sun-compatible */
2018     {
2019     case DDIOCSDBG:             /* DDI Debug */
2020       if (! suser()) return (-EPERM);
2021       i = verify_area(VERIFY_READ, (int *) arg, sizeof(int));
2022       if (i>=0) i=sbpcd_dbg_ioctl(arg,1);
2023       return (i);
2024 
2025     case CDROMPAUSE:     /* Pause the drive */
2026       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPAUSE entered.\n"));
2027       /* pause the drive unit when it is currently in PLAY mode,         */
2028       /* or reset the starting and ending locations when in PAUSED mode. */
2029       /* If applicable, at the next stopping point it reaches            */
2030       /* the drive will discontinue playing.                             */
2031       switch (DS[d].audio_state)
2032         {
2033         case audio_playing:
2034           i=xx_Pause_Resume(1);
2035           if (i<0) return (-EIO);
2036           DS[d].audio_state=audio_pausing;
2037           i=xx_ReadSubQ();
2038           if (i<0) return (-EIO);
2039           DS[d].pos_audio_start=DS[d].SubQ_run_tot;
2040           return (0);
2041         case audio_pausing:
2042           i=xx_Seek(DS[d].pos_audio_start,1);
2043           if (i<0) return (-EIO);
2044           return (0);
2045         default:
2046           return (-EINVAL);
2047         }
2048       
2049     case CDROMRESUME: /* resume paused audio play */
2050       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMRESUME entered.\n"));
2051       /* resume playing audio tracks when a previous PLAY AUDIO call has  */
2052       /* been paused with a PAUSE command.                                */
2053       /* It will resume playing from the location saved in SubQ_run_tot.  */
2054       if (DS[d].audio_state!=audio_pausing) return -EINVAL;
2055       i=xx_Pause_Resume(3);
2056       if (i<0) return (-EIO);
2057       DS[d].audio_state=audio_playing;
2058       return (0);
2059 
2060     case CDROMPLAYMSF:
2061       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYMSF entered.\n"));
2062       if (DS[d].audio_state==audio_playing)
2063         {
2064           i=xx_Pause_Resume(1);
2065           if (i<0) return (-EIO);
2066           i=xx_ReadSubQ();
2067           if (i<0) return (-EIO);
2068           DS[d].pos_audio_start=DS[d].SubQ_run_tot;
2069           i=xx_Seek(DS[d].pos_audio_start,1);
2070         }
2071       st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
2072       if (st) return (st);
2073       memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
2074       /* values come as msf-bin */
2075       DS[d].pos_audio_start = (msf.cdmsf_min0<<16) |
2076                         (msf.cdmsf_sec0<<8) |
2077                         msf.cdmsf_frame0;
2078       DS[d].pos_audio_end = (msf.cdmsf_min1<<16) |
2079                       (msf.cdmsf_sec1<<8) |
2080                       msf.cdmsf_frame1;
2081       DPRINTF((DBG_IOX,"SBPCD: ioctl: CDROMPLAYMSF %08X %08X\n",
2082                                DS[d].pos_audio_start,DS[d].pos_audio_end));
2083       i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
2084       DPRINTF((DBG_IOC,"SBPCD: ioctl: xx_PlayAudioMSF returns %d\n",i));
2085 #if 0
2086       if (i<0) return (-EIO);
2087 #endif 0
2088       DS[d].audio_state=audio_playing;
2089       return (0);
2090 
2091     case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
2092       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYTRKIND entered.\n"));
2093       if (DS[d].audio_state==audio_playing)
2094         {
2095           DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: already audio_playing.\n"));
2096           return (0);
2097           return (-EINVAL);
2098         }
2099       st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti));
2100       if (st<0)
2101         {
2102           DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: verify_area error.\n"));
2103           return (st);
2104         }
2105       memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti));
2106       DPRINTF((DBG_IOX,"SBPCD: ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
2107              ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1));
2108       if (ti.cdti_trk0<DS[d].n_first_track) return (-EINVAL);
2109       if (ti.cdti_trk0>DS[d].n_last_track) return (-EINVAL);
2110       if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
2111       if (ti.cdti_trk1>DS[d].n_last_track) ti.cdti_trk1=DS[d].n_last_track;
2112       DS[d].pos_audio_start=DS[d].TocBuffer[ti.cdti_trk0].address;
2113       DS[d].pos_audio_end=DS[d].TocBuffer[ti.cdti_trk1+1].address;
2114       i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
2115 #if 0
2116       if (i<0) return (-EIO);
2117 #endif 0
2118       DS[d].audio_state=audio_playing;
2119       return (0);
2120             
2121     case CDROMREADTOCHDR:        /* Read the table of contents header */
2122       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCHDR entered.\n"));
2123       tochdr.cdth_trk0=DS[d].n_first_track;
2124       tochdr.cdth_trk1=DS[d].n_last_track;
2125       st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
2126       if (st) return (st);
2127       memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
2128       return (0);
2129 
2130     case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
2131       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCENTRY entered.\n"));
2132       st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry));
2133       if (st) return (st);
2134       memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
2135       i=tocentry.cdte_track;
2136       if (i==CDROM_LEADOUT) i=DS[d].n_last_track+1;
2137       else if (i<DS[d].n_first_track||i>DS[d].n_last_track) return (-EINVAL);
2138       tocentry.cdte_adr=DS[d].TocBuffer[i].ctl_adr&0x0F;
2139       tocentry.cdte_ctrl=(DS[d].TocBuffer[i].ctl_adr>>4)&0x0F;
2140       tocentry.cdte_datamode=DS[d].TocBuffer[i].format;
2141       if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
2142         { tocentry.cdte_addr.msf.minute=(DS[d].TocBuffer[i].address>>16)&0x00FF;
2143           tocentry.cdte_addr.msf.second=(DS[d].TocBuffer[i].address>>8)&0x00FF;
2144           tocentry.cdte_addr.msf.frame=DS[d].TocBuffer[i].address&0x00FF;
2145         }
2146       else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
2147         tocentry.cdte_addr.lba=msf2blk(DS[d].TocBuffer[i].address);
2148       else return (-EINVAL);
2149       st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
2150       if (st) return (st);
2151       memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
2152       return (0);
2153 
2154     case CDROMSTOP:      /* Spin down the drive */
2155       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTOP entered.\n"));
2156       i=DriveReset();
2157 #if WORKMAN
2158       DS[d].CD_changed=0xFF;
2159       DS[d].diskstate_flags=0;
2160 #endif WORKMAN
2161       DPRINTF((DBG_IOC,"SBPCD: ioctl: DriveReset returns %d\n",i));
2162       DS[d].audio_state=0;
2163       i=DiskInfo();
2164       return (0);
2165 
2166     case CDROMSTART:  /* Spin up the drive */
2167       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTART entered.\n"));
2168       i=xx_SpinUp();
2169       DS[d].audio_state=0;
2170       return (0);
2171       
2172     case CDROMEJECT:
2173       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT entered.\n"));
2174       if (!new_drive) return (0);
2175 #if WORKMAN
2176       DS[d].CD_changed=0xFF;
2177       DS[d].diskstate_flags=0;
2178 #endif WORKMAN
2179       i=yy_SpinDown();
2180       if (i<0) return (-EIO);
2181       DS[d].audio_state=0;
2182       return (0);
2183       
2184     case CDROMVOLCTRL:   /* Volume control */
2185       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMVOLCTRL entered.\n"));
2186       st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
2187       if (st) return (st);
2188       memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
2189       DS[d].vol_chan0=0;
2190       DS[d].vol_ctrl0=volctrl.channel0;
2191       DS[d].vol_chan1=1;
2192       DS[d].vol_ctrl1=volctrl.channel1;
2193       i=xx_SetVolume();
2194       return (0);
2195 
2196     case CDROMSUBCHNL:   /* Get subchannel info */
2197       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSUBCHNL entered.\n"));
2198       if ((st_spinning)||(!subq_valid)) { i=xx_ReadSubQ();
2199                                           if (i<0) return (-EIO);
2200                                         }
2201       st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
2202       if (st)   return (st);
2203       memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
2204 #if 0
2205       if (DS[d].SubQ_audio==0x80) DS[d].SubQ_audio=CDROM_AUDIO_NO_STATUS;
2206 #endif
2207       switch (DS[d].audio_state)
2208         {
2209         case audio_playing:
2210           SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
2211           break;
2212         case audio_pausing:
2213           SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
2214           break;
2215         default:
2216           SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
2217           break;
2218         }
2219       SC.cdsc_adr=DS[d].SubQ_ctl_adr;
2220       SC.cdsc_ctrl=DS[d].SubQ_ctl_adr>>4;
2221       SC.cdsc_trk=bcd2bin(DS[d].SubQ_trk);
2222       SC.cdsc_ind=bcd2bin(DS[d].SubQ_pnt_idx);
2223       if (SC.cdsc_format==CDROM_LBA)
2224         {
2225           SC.cdsc_absaddr.lba=msf2blk(DS[d].SubQ_run_tot);
2226           SC.cdsc_reladdr.lba=msf2blk(DS[d].SubQ_run_trk);
2227         }
2228       else /* not only if (SC.cdsc_format==CDROM_MSF) */
2229         {
2230           SC.cdsc_absaddr.msf.minute=(DS[d].SubQ_run_tot>>16)&0x00FF;
2231           SC.cdsc_absaddr.msf.second=(DS[d].SubQ_run_tot>>8)&0x00FF;
2232           SC.cdsc_absaddr.msf.frame=DS[d].SubQ_run_tot&0x00FF;
2233           SC.cdsc_reladdr.msf.minute=(DS[d].SubQ_run_trk>>16)&0x00FF;
2234           SC.cdsc_reladdr.msf.second=(DS[d].SubQ_run_trk>>8)&0x00FF;
2235           SC.cdsc_reladdr.msf.frame=DS[d].SubQ_run_trk&0x00FF;
2236         }
2237       memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl));
2238       DPRINTF((DBG_IOC,"SBPCD: CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
2239                SC.cdsc_format,SC.cdsc_audiostatus,
2240                SC.cdsc_adr,SC.cdsc_ctrl,
2241                SC.cdsc_trk,SC.cdsc_ind,
2242                SC.cdsc_absaddr,SC.cdsc_reladdr));
2243       return (0);
2244 
2245     case CDROMREADMODE2:
2246       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE2 requested.\n"));
2247       return (-EINVAL);
2248 
2249     case CDROMREADMODE1:
2250       DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE1 requested.\n"));
2251       return (-EINVAL);
2252       
2253     default:
2254       DPRINTF((DBG_IOX,"SBPCD: ioctl: unknown function request %04X\n", cmd));
2255       return (-EINVAL);
2256     } /* end switch(cmd) */
2257 }
2258 /*==========================================================================*/
2259 /*
2260  *  Take care of the different block sizes between cdrom and Linux.
2261  *  When Linux gets variable block sizes this will probably go away.
2262  */
2263 static void sbp_transfer(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2264 {
2265   long offs;
2266   
2267   while ( (CURRENT->nr_sectors > 0) &&
2268           (CURRENT->sector/4 >= DS[d].sbp_first_frame) &&
2269           (CURRENT->sector/4 <= DS[d].sbp_last_frame) )
2270     {
2271       offs = (CURRENT->sector - DS[d].sbp_first_frame * 4) * 512;
2272       memcpy(CURRENT->buffer, DS[d].sbp_buf + offs, 512);
2273       CURRENT->nr_sectors--;
2274       CURRENT->sector++;
2275       CURRENT->buffer += 512;
2276     }
2277 }
2278 /*==========================================================================*/
2279 /*
2280  *  We seem to get never an interrupt.
2281  */
2282 #if SBPCD_USE_IRQ
2283 static void sbpcd_interrupt(int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
2284 {
2285   int st;
2286   
2287   st = inb(CDi_status) & 0xFF;
2288   DPRINTF((DBG_IRQ,"SBPCD: INTERRUPT received - CDi_status=%02X\n", st));
2289 }
2290 #endif SBPCD_USE_IRQ
2291 /*==========================================================================*/
2292 /*
2293  * Called from the timer to check the results of the get-status cmd.
2294  */
2295 static int sbp_status(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2296 {
2297   int st;
2298 
2299   st=ResponseStatus();
2300   if (st<0)
2301     {
2302       DPRINTF((DBG_INF,"SBPCD: sbp_status: timeout.\n"));
2303       return (0);
2304     }
2305 
2306   if (!st_spinning) DPRINTF((DBG_SPI,"SBPCD: motor got off - ignoring.\n"));
2307 
2308   if (st_check) 
2309     {
2310       DPRINTF((DBG_INF,"SBPCD: st_check detected - retrying.\n"));
2311       return (0);
2312     }
2313   if (!st_door_closed)
2314     {
2315       DPRINTF((DBG_INF,"SBPCD: door is open - retrying.\n"));
2316       return (0);
2317     }
2318   if (!st_caddy_in)
2319     {
2320       DPRINTF((DBG_INF,"SBPCD: disk removed - retrying.\n"));
2321       return (0);
2322     }
2323   if (!st_diskok) 
2324     {
2325       DPRINTF((DBG_INF,"SBPCD: !st_diskok detected - retrying.\n"));
2326       return (0);
2327     }
2328   if (st_busy) 
2329     {
2330       DPRINTF((DBG_INF,"SBPCD: st_busy detected - retrying.\n"));
2331       return (0);
2332     }
2333   return (1);
2334 }
2335 /*==========================================================================*/
2336 /*
2337  *  I/O request routine, called from Linux kernel.
2338  */
2339 static void do_sbpcd_request(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2340 {
2341   u_int block;
2342   int dev;
2343   u_int nsect;
2344   int i, status_tries, data_tries;
2345   
2346 request_loop:
2347 
2348   sti();
2349 
2350   if ((CURRENT==NULL)||(CURRENT->dev<0)) return;
2351   if (CURRENT -> sector == -1)  return;
2352 
2353   dev = MINOR(CURRENT->dev);
2354   if ( (dev<0) || (dev>=NR_SBPCD) )
2355     {
2356       DPRINTF((DBG_INF,"SBPCD: do_request: bad device: %d\n", dev));
2357       return;
2358     }
2359   switch_drive(dev);
2360 
2361   INIT_REQUEST;
2362   block = CURRENT->sector;
2363   nsect = CURRENT->nr_sectors;
2364 
2365   if (CURRENT->cmd != READ)
2366     {
2367       DPRINTF((DBG_INF,"SBPCD: bad cmd %d\n", CURRENT->cmd));
2368       end_request(0);
2369       goto request_loop;
2370     }
2371 
2372   DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4));
2373   sbp_transfer();
2374 
2375   /* if we satisfied the request from the buffer, we're done. */
2376 
2377   if (CURRENT->nr_sectors == 0)
2378     {
2379       end_request(1);
2380       goto request_loop;
2381     }
2382 
2383   i=prepare(0,0); /* at moment not really a hassle check, but ... */
2384   if (i!=0) DPRINTF((DBG_INF,"SBPCD: \"prepare\" tells error %d -- ignored\n", i));
2385 
2386   if (!st_spinning) xx_SpinUp();
2387 
2388   for (data_tries=3; data_tries > 0; data_tries--)
2389     {
2390       for (status_tries=3; status_tries > 0; status_tries--)
2391         {
2392           flags_cmd_out |= f_respo3;
2393           xx_ReadStatus();
2394           if (sbp_status() != 0) break;
2395           sbp_sleep(1);    /* wait a bit, try again */
2396         }
2397       if (status_tries == 0)
2398         {
2399           DPRINTF((DBG_INF,"SBPCD: sbp_status: failed after 3 tries\n"));
2400           break;
2401         }
2402 
2403       sbp_read_cmd();
2404       sbp_sleep(0);
2405       if (sbp_data() != 0)
2406         {
2407           end_request(1);
2408           goto request_loop;
2409         }
2410     }
2411   
2412   end_request(0);
2413   sbp_sleep(10);    /* wait a bit, try again */
2414   goto request_loop;
2415 }
2416 /*==========================================================================*/
2417 /*
2418  *  build and send the READ command.
2419  *  Maybe it would be better to "set mode1" before ...
2420  */
2421 static void sbp_read_cmd(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2422 {
2423   int i;
2424   int block;
2425 
2426   DS[d].sbp_first_frame=DS[d].sbp_last_frame=-1;      /* purge buffer */
2427   block=CURRENT->sector/4;
2428 
2429   if (new_drive)
2430     {
2431 #if MANY_SESSION
2432       DPRINTF((DBG_MUL,"SBPCD: read MSF %08X\n", blk2msf(block)));
2433       if ( (DS[d].f_multisession) && (multisession_valid) )
2434         {
2435           DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
2436                          blk2msf(DS[d].lba_multi+block),
2437                          blk2msf(block)));
2438           block=DS[d].lba_multi+block;
2439         }
2440 #else
2441       if ( (block==166) && (DS[d].f_multisession) && (multisession_valid) )
2442         {
2443           DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
2444                          blk2msf(DS[d].lba_multi+16),
2445                          blk2msf(block)));
2446           block=DS[d].lba_multi+16;
2447         }
2448 #endif MANY_SESSION
2449     }
2450 
2451   if (block+SBP_BUFFER_FRAMES <= DS[d].CDsize_frm)
2452     DS[d].sbp_read_frames = SBP_BUFFER_FRAMES;
2453   else
2454     {
2455       DS[d].sbp_read_frames=DS[d].CDsize_frm-block;
2456                                       /* avoid reading past end of data */
2457       if (DS[d].sbp_read_frames < 1)
2458         {
2459           DPRINTF((DBG_INF,"SBPCD: requested frame %d, CD size %d ???\n",
2460                         block, DS[d].CDsize_frm));
2461           DS[d].sbp_read_frames=1;
2462         }
2463     }
2464   DS[d].sbp_current = 0;
2465 
2466   flags_cmd_out = f_putcmd |
2467                   f_respo2 |
2468                   f_ResponseStatus |
2469                   f_obey_p_check;
2470 
2471   if (!new_drive)
2472     {
2473       if (DS[d].drv_type>=drv_201)
2474         {
2475           lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
2476           bin2bcdx(&drvcmd[1]);
2477           bin2bcdx(&drvcmd[2]);
2478           bin2bcdx(&drvcmd[3]);
2479         }
2480       else
2481         {
2482           drvcmd[1]=(block>>16)&0x000000ff;
2483           drvcmd[2]=(block>>8)&0x000000ff;
2484           drvcmd[3]=block&0x000000ff;
2485         }
2486       drvcmd[4]=0;
2487       drvcmd[5]=DS[d].sbp_read_frames;
2488       drvcmd[6]=(DS[d].drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
2489       drvcmd[0]=0x02;              /* "read frames" command for old drives */
2490       flags_cmd_out |= f_lopsta|f_getsta|f_bit1;
2491     }
2492   else /* if new_drive */
2493     {
2494       lba2msf(block,&drvcmd[1]); /* msf-bin format required */
2495       drvcmd[4]=0;
2496       drvcmd[5]=0;
2497       drvcmd[6]=DS[d].sbp_read_frames;
2498       drvcmd[0]=0x10;              /* "read frames" command for new drives */
2499     }
2500 #if SBPCD_DIS_IRQ
2501   cli();
2502 #endif SBPCD_DIS_IRQ
2503   for (i=0;i<7;i++) OUT(CDo_command,drvcmd[i]);
2504 #if SBPCD_DIS_IRQ
2505   sti();
2506 #endif SBPCD_DIS_IRQ
2507 
2508   return;
2509 }
2510 /*==========================================================================*/
2511 /*
2512  *  Check the completion of the read-data command.  On success, read
2513  *  the SBP_BUFFER_FRAMES * 2048 bytes of data from the disk into buffer.
2514  */
2515 static int sbp_data(void)
     /* [previous][next][first][last][top][bottom][index][help] */
2516 {
2517   int i=0, j=0, frame;
2518   u_int try=0;
2519   u_long timeout;
2520   u_char *p;
2521   u_int data_tries = 0;
2522   u_int data_waits = 0;
2523   u_int data_retrying = 0;
2524   int error_flag;
2525 
2526   error_flag=0;
2527 
2528   for (frame=DS[d].sbp_current;frame<DS[d].sbp_read_frames&&!error_flag; frame++)
2529     {
2530 #if SBPCD_DIS_IRQ
2531       cli();
2532 #endif SBPCD_DIS_IRQ
2533       try=maxtim_data;
2534       for (timeout=jiffies+100; ; )
2535         {
2536           for ( ; try!=0;try--)
2537             {
2538               j=inb(CDi_status);
2539               if (!(j&s_not_data_ready)) break;
2540               if (!(j&s_not_result_ready)) break;
2541               if (!new_drive) if (j&s_attention) break;
2542             }
2543           if (try != 0 || timeout <= jiffies) break;
2544           if (data_retrying == 0) data_waits++;
2545           data_retrying = 1;
2546           sbp_sleep(1);
2547           try = 1;
2548         }
2549       if (try==0)
2550         {
2551           DPRINTF((DBG_INF,"SBPCD: sbp_data: CDi_status timeout.\n"));
2552           error_flag++;
2553           break;
2554         }
2555 
2556       if (j&s_not_data_ready)
2557         {
2558           if ((DS[d].ored_ctl_adr&0x40)==0)
2559             DPRINTF((DBG_INF,"SBPCD: CD contains no data tracks.\n"));
2560           else DPRINTF((DBG_INF,"SBPCD: sbp_data: DATA_READY timeout.\n"));
2561           error_flag++;
2562           break;
2563         }
2564       
2565 #if SBPCD_DIS_IRQ
2566       sti();
2567 #endif SBPCD_DIS_IRQ
2568 
2569       CLEAR_TIMER;
2570       error_flag=0;
2571       p = DS[d].sbp_buf + frame *  CD_FRAMESIZE;
2572 
2573       if (sbpro_type) OUT(CDo_sel_d_i,0x01);
2574       READ_DATA(CDi_data, p, CD_FRAMESIZE);
2575       if (sbpro_type) OUT(CDo_sel_d_i,0x00);
2576       DS[d].sbp_current++;
2577 
2578       data_tries++;
2579       data_retrying = 0;
2580       if (data_tries >= 1000)
2581         {
2582           DPRINTF((DBG_INF,"SBPCD: info: %d waits in %d frames.\n",
2583                         data_waits, data_tries));
2584           data_waits = data_tries = 0;
2585         }
2586     }
2587 #if SBPCD_DIS_IRQ
2588   sti();
2589 #endif SBPCD_DIS_IRQ
2590   
2591   if (error_flag)    /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
2592     {
2593       DPRINTF((DBG_INF,"SBPCD: read aborted by drive\n"));
2594       i=DriveReset();                /* ugly fix to prevent a hang */
2595       return (0);
2596     }
2597 
2598   if (!new_drive)
2599     {
2600 #if SBPCD_DIS_IRQ
2601       cli();
2602 #endif  SBPCD_DIS_IRQ
2603       i=maxtim_data;
2604       for (timeout=jiffies+100; timeout > jiffies; timeout--)
2605         {
2606           for ( ;i!=0;i--)
2607             {
2608               j=inb(CDi_status);
2609               if (!(j&s_not_data_ready)) break;
2610               if (!(j&s_not_result_ready)) break;
2611               if (j&s_attention) break;
2612             }
2613           if (i != 0 || timeout <= jiffies) break;
2614           sbp_sleep(0);
2615           i = 1;
2616         }
2617       if (i==0) { DPRINTF((DBG_INF,"SBPCD: STATUS TIMEOUT AFTER READ")); }
2618       if (!(j&s_attention))
2619         {
2620           DPRINTF((DBG_INF,"SBPCD: sbp_data: timeout waiting DRV_ATTN - retrying\n"));
2621           i=DriveReset();  /* ugly fix to prevent a hang */
2622 #if SBPCD_DIS_IRQ
2623           sti();
2624 #endif SBPCD_DIS_IRQ
2625           return (0);
2626         }
2627 #if SBPCD_DIS_IRQ
2628       sti();
2629 #endif SBPCD_DIS_IRQ
2630     }
2631 
2632   do
2633     {
2634       if (!new_drive) xx_ReadStatus();
2635       i=ResponseStatus();  /* builds status_byte, returns orig. status (old) or faked p_success_old (new) */
2636       if (i<0) { DPRINTF((DBG_INF,"SBPCD: xx_ReadStatus error after read: %02X\n",
2637                                DS[d].status_byte));
2638                  return (0);
2639                }
2640     }
2641   while ((!new_drive)&&(!st_check)&&(!(i&p_success_old)));
2642   if (st_check)
2643     {
2644       i=xx_ReadError();
2645       DPRINTF((DBG_INF,"SBPCD: xx_ReadError was necessary after read: %02X\n",i));
2646       return (0);
2647     }
2648 
2649   DS[d].sbp_first_frame = CURRENT -> sector / 4;
2650   DS[d].sbp_last_frame = DS[d].sbp_first_frame + DS[d].sbp_read_frames - 1;
2651   sbp_transfer();
2652   return (1);
2653 }
2654 /*==========================================================================*/
2655 /*==========================================================================*/
2656 /*
2657  *  Open the device special file.  Check that a disk is in. Read TOC.
2658  */
2659 int sbpcd_open(struct inode *ip, struct file *fp)
     /* [previous][next][first][last][top][bottom][index][help] */
2660 {
2661   int i;
2662 
2663   if (ndrives==0) return (-ENXIO);             /* no hardware */
2664 
2665   i = MINOR(ip->i_rdev);
2666   if ( (i<0) || (i>=NR_SBPCD) )
2667     {
2668       DPRINTF((DBG_INF,"SBPCD: open: bad device: %d\n", i));
2669       return (-ENODEV);             /* no such drive */
2670     }
2671   switch_drive(i);
2672 
2673   if (!st_spinning) xx_SpinUp();
2674 
2675   flags_cmd_out |= f_respo2;
2676   xx_ReadStatus();                         /* command: give 1-byte status */
2677   i=ResponseStatus();
2678   if (i<0)
2679     {
2680       DPRINTF((DBG_INF,"SBPCD: sbpcd_open: xx_ReadStatus timed out\n"));
2681       return (-EIO);                  /* drive doesn't respond */
2682     }
2683   DPRINTF((DBG_STA,"SBPCD: sbpcd_open: status %02X\n", DS[d].status_byte));
2684   if (!st_door_closed||!st_caddy_in)
2685     {
2686       DPRINTF((DBG_INF,"SBPCD: sbpcd_open: no disk in drive\n"));
2687       return (-EIO);
2688     }
2689 
2690 /*
2691  * we could try to keep an "open" counter here and lock the door if 0->1.
2692  * not done yet.
2693  */
2694 
2695   
2696   if (!st_spinning) xx_SpinUp();
2697 
2698   i=DiskInfo();
2699   if ((DS[d].ored_ctl_adr&0x40)==0)
2700     DPRINTF((DBG_INF,"SBPCD: CD contains no data tracks.\n"));
2701   return (0);
2702 }
2703 /*==========================================================================*/
2704 /*
2705  *  On close, we flush all sbp blocks from the buffer cache.
2706  */
2707 static void sbpcd_release(struct inode * ip, struct file * file)
     /* [previous][next][first][last][top][bottom][index][help] */
2708 {
2709   int i;
2710 /*
2711  * we could try to count down an "open" counter here
2712  * and unlock the door if zero.
2713  * not done yet.
2714  */
2715 
2716   i = MINOR(ip->i_rdev);
2717   if ( (i<0) || (i>=NR_SBPCD) ) 
2718     {
2719       DPRINTF((DBG_INF,"SBPCD: release: bad device: %d\n", i));
2720       return;
2721     }
2722   switch_drive(i);
2723 
2724   DS[d].sbp_first_frame=DS[d].sbp_last_frame=-1;
2725   sync_dev(ip->i_rdev);                    /* nonsense if read only device? */
2726   invalidate_buffers(ip->i_rdev);
2727   DS[d].diskstate_flags &= ~cd_size_bit;
2728 }
2729 /*==========================================================================*/
2730 /*
2731  *
2732  */
2733 static struct file_operations sbpcd_fops =
2734 {
2735   NULL,                   /* lseek - default */
2736   block_read,             /* read - general block-dev read */
2737   block_write,            /* write - general block-dev write */
2738   NULL,                   /* readdir - bad */
2739   NULL,                   /* select */
2740   sbpcd_ioctl,            /* ioctl */
2741   NULL,                   /* mmap */
2742   sbpcd_open,             /* open */
2743   sbpcd_release           /* release */
2744 };
2745 /*==========================================================================*/
2746 /*
2747  *  SBP interrupt descriptor
2748  */
2749 #if SBPCD_USE_IRQ
2750 static struct sigaction sbpcd_sigaction =
2751 {
2752   sbpcd_interrupt,
2753   0,
2754   SA_INTERRUPT,
2755   NULL
2756 };
2757 #endif SBPCD_USE_IRQ
2758 /*==========================================================================*/
2759 /*
2760  * accept "kernel command line" parameters 
2761  * (suggested by Peter MacDonald with SLS 1.03)
2762  *
2763  * use: tell LILO:
2764  *                 sbpcd=0x230,SoundBlaster
2765  *             or
2766  *                 sbpcd=0x300,LaserMate
2767  *
2768  * (upper/lower case sensitive here!!!).
2769  *
2770  * the address value has to be the TRUE CDROM PORT ADDRESS -
2771  * not the soundcard base address.
2772  *
2773  */
2774 void sbpcd_setup(char *s, int *p)
     /* [previous][next][first][last][top][bottom][index][help] */
2775 {
2776   DPRINTF((DBG_INI,"SBPCD: sbpcd_setup called with %04X,%s\n",p[1], s));
2777   if (!strcmp(s,str_sb)) sbpro_type=1;
2778   else sbpro_type=0;
2779   if (p[0]>0) sbpcd_ioaddr=p[1];
2780 
2781   CDo_command=sbpcd_ioaddr;
2782   CDi_info=sbpcd_ioaddr;
2783   CDi_status=sbpcd_ioaddr+1;
2784   CDo_reset=sbpcd_ioaddr+2;
2785   CDo_enable=sbpcd_ioaddr+3; 
2786   if (sbpro_type==1)
2787     {
2788       MIXER_addr=sbpcd_ioaddr-0x10+0x04;
2789       MIXER_data=sbpcd_ioaddr-0x10+0x05;
2790       CDo_sel_d_i=sbpcd_ioaddr+1;
2791       CDi_data=sbpcd_ioaddr;
2792     }
2793   else CDi_data=sbpcd_ioaddr+2;
2794 }
2795 /*==========================================================================*/
2796 /*
2797  *  Test for presence of drive and initialize it.  Called at boot time.
2798  */
2799 u_long sbpcd_init(u_long mem_start, u_long mem_end)
     /* [previous][next][first][last][top][bottom][index][help] */
2800 {
2801   int i=0, j=0;
2802   int addr[2]={1, CDROM_PORT};
2803   int port_index;
2804    
2805   DPRINTF((DBG_INF,"SBPCD version %s\n", VERSION));
2806 
2807   DPRINTF((DBG_INF,"SBPCD: Looking for a SoundBlaster/Matsushita CD-ROM drive\n"));
2808   DPRINTF((DBG_WRN,"SBPCD: \n"));
2809   DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = W A R N I N G = = = = = = = = = =\n"));
2810   DPRINTF((DBG_WRN,"SBPCD: Auto-Probing can cause a hang (f.e. touching an ethernet card).\n"));
2811   DPRINTF((DBG_WRN,"SBPCD: If that happens, you have to reboot and use the\n"));
2812   DPRINTF((DBG_WRN,"SBPCD: LILO (kernel) command line feature like:\n"));
2813   DPRINTF((DBG_WRN,"SBPCD: \n"));
2814   DPRINTF((DBG_WRN,"SBPCD:    LILO boot: linux sbpcd=0x230,SoundBlaster\n"));
2815   DPRINTF((DBG_WRN,"SBPCD: or like:\n"));
2816   DPRINTF((DBG_WRN,"SBPCD:    LILO boot: linux sbpcd=0x300,LaserMate\n"));
2817   DPRINTF((DBG_WRN,"SBPCD: \n"));
2818   DPRINTF((DBG_WRN,"SBPCD: with your REAL address.\n"));
2819   DPRINTF((DBG_WRN,"SBPCD: = = = = = = = = = = END of WARNING = = = = = = = = = =\n"));
2820   DPRINTF((DBG_WRN,"SBPCD: \n"));
2821   sti(); /* to avoid possible "printk" bug */
2822 
2823   autoprobe[0]=sbpcd_ioaddr; /* possibly changed by kernel command line */
2824   autoprobe[1]=sbpro_type; /* possibly changed by kernel command line */
2825 
2826   for (port_index=0;port_index<NUM_AUTOPROBE;port_index+=2)
2827     {
2828       addr[1]=autoprobe[port_index];
2829       if (check_region(addr[1],4)) continue;
2830       DPRINTF((DBG_INI,"SBPCD: check_region done.\n"));
2831       if (autoprobe[port_index+1]==0) type=str_lm;
2832       else type=str_sb;
2833       sbpcd_setup(type, addr);
2834       DPRINTF((DBG_INF,"SBPCD: Trying to detect a %s CD-ROM drive at 0x%X.\n",
2835                      type, CDo_command));
2836 
2837       DPRINTF((DBG_INF,"SBPCD: - "));
2838       sti(); /* to avoid possible "printk" bug */
2839       i=check_drives();
2840       DPRINTF((DBG_INI,"SBPCD: check_drives done.\n"));
2841       sti(); /* to avoid possible "printk" bug */
2842       if (i>=0) break; /* drive found */
2843       printk ("\n");
2844       sti(); /* to avoid possible "printk" bug */
2845     } /* end of cycling through the set of possible I/O port addresses */
2846 
2847   if (ndrives==0)
2848     {
2849       DPRINTF((DBG_INF,"SBPCD: No drive found.\n"));
2850       sti();
2851       return (mem_start);
2852     }
2853 
2854   DPRINTF((DBG_INF,"SBPCD: %d %s CD-ROM drive(s) at 0x%04X.\n",
2855            ndrives, type, CDo_command));
2856   sti(); /* to avoid possible "printk" bug */
2857   check_datarate();
2858   DPRINTF((DBG_INI,"SBPCD: check_datarate done.\n"));
2859   sti(); /* to avoid possible "printk" bug */
2860 
2861   for (j=0;j<NR_SBPCD;j++)
2862     {
2863       if (DS[j].drv_minor==-1) continue;
2864       switch_drive(j);
2865       xy_DriveReset();
2866       if (!st_spinning) xx_SpinUp();
2867       DS[d].sbp_first_frame = -1;  /* First frame in buffer */
2868       DS[d].sbp_last_frame = -1;   /* Last frame in buffer  */
2869       DS[d].sbp_read_frames = 0;   /* Number of frames being read to buffer */
2870       DS[d].sbp_current = 0;       /* Frame being currently read */
2871       DS[d].CD_changed=1;
2872       DS[d].frame_size=CD_FRAMESIZE;
2873 
2874       xx_ReadStatus();
2875       i=ResponseStatus();  /* returns orig. status or p_busy_new */
2876       if (i<0)
2877         DPRINTF((DBG_INF,"SBPCD: init: ResponseStatus returns %02X\n",i));
2878       else
2879         {
2880           if (st_check)
2881             {
2882               i=xx_ReadError();
2883               DPRINTF((DBG_INI,"SBPCD: init: xx_ReadError returns %d\n",i));
2884               sti(); /* to avoid possible "printk" bug */
2885             }
2886         }
2887       DPRINTF((DBG_INI,"SBPCD: init: first GetStatus: %d\n",i));
2888       sti(); /* to avoid possible "printk" bug */
2889       if (DS[d].error_byte==aud_12)
2890         {
2891           do { i=GetStatus();
2892                DPRINTF((DBG_INI,"SBPCD: init: second GetStatus: %02X\n",i));
2893                sti(); /* to avoid possible "printk" bug */
2894                if (i<0) break;
2895                if (!st_caddy_in) break;
2896              }
2897           while (!st_diskok);
2898         }
2899       i=SetSpeed();
2900       if (i>=0) DS[d].CD_changed=1;
2901     }
2902 
2903   if (sbpro_type)
2904     {
2905       OUT(MIXER_addr,MIXER_CD_Volume);
2906       OUT(MIXER_data,0xCC); /* one nibble per channel */
2907     }
2908   
2909   if (register_blkdev(MATSUSHITA_CDROM_MAJOR, "sbpcd", &sbpcd_fops) != 0)
2910     {
2911       DPRINTF((DBG_INF,"SBPCD: Can't get MAJOR %d for Matsushita CDROM\n",
2912                MATSUSHITA_CDROM_MAJOR));
2913       sti(); /* to avoid possible "printk" bug */
2914       return (mem_start);
2915     }
2916   blk_dev[MATSUSHITA_CDROM_MAJOR].request_fn = DEVICE_REQUEST;
2917   read_ahead[MATSUSHITA_CDROM_MAJOR] = 4; /* just one frame */ 
2918   
2919   snarf_region(CDo_command,4);
2920 
2921 #if SBPCD_USE_IRQ
2922   if (irqaction(SBPCD_INTR_NR, &sbpcd_sigaction))
2923     {
2924       DPRINTF((DBG_INF,"SBPCD: Can't get IRQ%d for sbpcd driver\n",
2925                SBPCD_INTR_NR));
2926       sti(); /* to avoid possible "printk" bug */
2927     }
2928 #endif SBPCD_USE_IRQ
2929 
2930 /*
2931  * allocate memory for the frame buffers
2932  */ 
2933   for (j=0;j<NR_SBPCD;j++)
2934     {
2935       if (DS[j].drv_minor==-1) continue;
2936       DS[j].sbp_buf=(u_char *)mem_start;
2937       mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE;
2938     }
2939   DPRINTF((DBG_INF,"SBPCD: init done.\n"));
2940   sti(); /* to avoid possible "printk" bug */
2941   return (mem_start);
2942 }
2943 /*==========================================================================*/
2944 /*
2945  * adopted from sr.c
2946  *
2947  * Check if the media has changed in the CD-ROM drive.
2948  * used externally (isofs/inode.c) - but still does not work.
2949  *
2950  */
2951 int check_sbpcd_media_change(int full_dev, int unused_minor)
     /* [previous][next][first][last][top][bottom][index][help] */
2952 {
2953   int st;
2954 
2955   if (MAJOR(full_dev) != MATSUSHITA_CDROM_MAJOR) 
2956     {
2957       DPRINTF((DBG_INF,"SBPCD: media_check: invalid device.\n"));
2958       return (-1);
2959     }
2960   
2961   xx_ReadStatus();                         /* command: give 1-byte status */
2962   st=ResponseStatus();
2963   DPRINTF((DBG_CHK,"SBPCD: media_check: %02X\n",DS[d].status_byte));
2964   if (st<0)
2965     {
2966       DPRINTF((DBG_INF,"SBPCD: media_check: ResponseStatus error.\n"));
2967       return (1); /* status not obtainable */
2968     }
2969   if (DS[d].CD_changed==0xFF) DPRINTF((DBG_CHK,"SBPCD: media_check: \"changed\" assumed.\n"));
2970   if (!st_spinning) DPRINTF((DBG_CHK,"SBPCD: media_check: motor off.\n"));
2971   if (!st_door_closed)
2972     {
2973       DPRINTF((DBG_CHK,"SBPCD: media_check: door open.\n"));
2974       DS[d].CD_changed=0xFF;
2975     }
2976   if (!st_caddy_in)
2977     {
2978       DPRINTF((DBG_CHK,"SBPCD: media_check: no disk in drive.\n"));
2979       DS[d].CD_changed=0xFF;
2980     }
2981   if (!st_diskok) DPRINTF((DBG_CHK,"SBPCD: media_check: !st_diskok.\n"));
2982   
2983 #if 0000
2984   if (DS[d].CD_changed==0xFF)
2985     {
2986       DS[d].CD_changed=1;
2987       return (1); /* driver had a change detected before */
2988     }
2989 #endif 0000 /* seems to give additional errors at the moment */
2990 
2991   if (!st_diskok) return (1); /* disk not o.k. */
2992   if (!st_caddy_in) return (1); /* disk removed */
2993   if (!st_door_closed) return (1); /* door open */
2994   return (0);
2995 }
2996 /*==========================================================================*/

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