root/drivers/block/sbpcd.c

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

DEFINITIONS

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

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

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