root/drivers/block/sbpcd.c

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

DEFINITIONS

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

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

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