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

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