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

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