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

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