root/drivers/block/sbpcd.c

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

DEFINITIONS

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

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

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