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

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