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

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