]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.24 1.1.24
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:32 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:32 +0000 (15:09 -0500)
Makefile
boot/setup.S
drivers/block/README.sbpcd
drivers/block/floppy.c
drivers/block/sbpcd.c
fs/buffer.c
fs/devices.c
include/linux/cdrom.h
include/linux/fs.h
include/linux/mcd.h
include/linux/sbpcd.h

index efa6d70814b19598e1b67011c582e13914d8fdd9..0b06d89ce11bc4afa4fea7abd9912cfa2a092dc1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 23
+SUBLEVEL = 24
 
 all:   Version zImage
 
index 2ba710ff2e3c4a9861db21d85b186b65c24ae619..1b927f690d29520f23abd393e89451c406ddfa55 100644 (file)
@@ -825,7 +825,7 @@ idVRAM:             .ascii  "Stealth VRAM"
 ! Number of modes is the number of chip-specific svga modes plus the extended
 ! modes available on any vga (currently 2)
 
-moati:         .byte   0x04,   0x23, 0x33 
+moati:         .byte   0x06,   0x23, 0x33, 0x22, 0x21
 moahead:       .byte   0x07,   0x22, 0x23, 0x24, 0x2f, 0x34
 mocandt:       .byte   0x04,   0x60, 0x61
 mocirrus:      .byte   0x06,   0x1f, 0x20, 0x22, 0x31
@@ -844,7 +844,7 @@ mounknown:  .byte   0x02
 ! The first two modes are standard vga modes available on any vga.
 ! mode 0 is 80x50 and mode 1 is 80x28
 
-dscati:                .word   0x5032, 0x501c, 0x8419, 0x842c
+dscati:                .word   0x5032, 0x501c, 0x8419, 0x842c, 0x641e, 0x6419
 dscahead:      .word   0x5032, 0x501c, 0x842c, 0x8419, 0x841c, 0xa032, 0x5042
 dsccandt:      .word   0x5032, 0x501c, 0x8419, 0x8432
 dsccirrus:     .word   0x5032, 0x501c, 0x8419, 0x842c, 0x841e, 0x6425
index d8eda41f58968c52ef1701e53e3c871772bd792d..f05d78132d9b7222130cc005b3deb240f45cfaad 100644 (file)
@@ -1,4 +1,4 @@
-This README belongs to release 2.0 of the SoundBlaster Pro (Matsushita,
+This README belongs to release 2.1 of the SoundBlaster Pro (Matsushita,
 Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
 
 The driver is able to drive the whole family of IDE-style
@@ -48,14 +48,21 @@ CDplayer and WorkBone - tell me if it is not compatible with other software.
 
 With the "new" drive family CR-562 and CR-563, the reading of audio frames is
 possible. This is currently implemented by an IOCTL function which reads only
-one frame of 2352 bytes at a time. The transfer rate is as slow as 32 kB/sec.
-This will get better, and the software interface may change. We have to 
-standardize it the day the SCSI driver supports it too.
-
-MultiSession is supported (even my "old" CR-521 can handle it), "ManySession"
-(not recommended, see below) alternatively.
-Photo CDs work, too. At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's
-package to convert photo CD image files.
+up to 4 frames of 2352 bytes at once. Reading more than 1 frame at once gives
+very poor quality. Reading the same frame a second time gives different data;
+it seems that the drive is out-of-sync at the beginning. See the program
+example below. This lack has to get corrected by higher level software.
+The transfer rate with reading audio (1-frame-pieces) is as slow as 32 kB/sec.
+This could be better reading bigger chunks, but the out-of-sync parts occur at
+the beginning of each single frame.
+The software interface possibly may change a bit the day the SCSI driver
+supports it too.
+
+MultiSession is supported, "ManySession" (not recommended, see below)
+alternatively.
+Photo CDs work, too (even with my "old" CR-521).
+At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's package to convert
+photo CD image files.
 
 The transfer rate will reach 150 kB/sec with "old" drives and 300 kB/sec with
 double-speed drives. XA (PhotoCD) disks with "old" drives give only 50 kB/sec.
@@ -340,6 +347,10 @@ entry[track+1].cdte_addr.lba=190;
 }
 /*===================== end program ========================================*/
 
+At ftp.gwdg.de:/pub/linux/misc/cdda2wav-sbpcd.tar.gz is an adapted version of
+Heiko Eissfeldt's digital-audio to .WAV converter (the original is there, too).
+This is preliminary, as Heiko himself will care about it.
+
 
 Known problems:
 ---------------
index a79128be8056fbb29f05d1032281009b0616ffa7..5fd673fb163df690610e209974edab7f398daa88 100644 (file)
@@ -407,7 +407,7 @@ void request_done(int uptodate)
  * to the desired drive, but it will probably not survive the sleep if
  * several floppies are used at the same time: thus the loop.
  */
-int floppy_change(struct buffer_head * bh)
+static int floppy_change(struct buffer_head * bh)
 {
        unsigned int mask = 1 << (bh->b_dev & 0x03);
 
@@ -1289,14 +1289,13 @@ static int floppy_open(struct inode * inode, struct file * filp)
        int drive;
        int old_dev;
 
-       if (floppy_grab_irq_and_dma()) {
-               return -EBUSY;
-       }
        drive = inode->i_rdev & 3;
        old_dev = fd_device[drive];
        if (fd_ref[drive])
                if (old_dev != inode->i_rdev)
                        return -EBUSY;
+       if (floppy_grab_irq_and_dma())
+               return -EBUSY;
        fd_ref[drive]++;
        fd_device[drive] = inode->i_rdev;
        buffer_drive = buffer_track = -1;
@@ -1309,7 +1308,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
 
 static void floppy_release(struct inode * inode, struct file * filp)
 {
-       sync_dev(inode->i_rdev);
+       fsync_dev(inode->i_rdev);
        if (!fd_ref[inode->i_rdev & 3]--) {
                printk("floppy_release with fd_ref == 0");
                fd_ref[inode->i_rdev & 3] = 0;
@@ -1317,6 +1316,18 @@ static void floppy_release(struct inode * inode, struct file * filp)
         floppy_release_irq_and_dma();
 }
 
+static int check_floppy_change(dev_t dev)
+{
+       int i;
+       struct buffer_head * bh;
+
+       if (!(bh = getblk(dev,0,1024)))
+               return 0;
+       i = floppy_change(bh);
+       brelse(bh);
+       return i;
+}
+
 static struct file_operations floppy_fops = {
        NULL,                   /* lseek - default */
        block_read,             /* read - general block-dev read */
@@ -1327,26 +1338,13 @@ static struct file_operations floppy_fops = {
        NULL,                   /* mmap */
        floppy_open,            /* open */
        floppy_release,         /* release */
-       block_fsync             /* fsync */
+       block_fsync,            /* fsync */
+       NULL,                   /* fasync */
+       check_floppy_change,    /* media_change */
+       NULL                    /* revalidate */
 };
 
 
-/*
- * The version command is not supposed to generate an interrupt, but
- * my FDC does, except when booting in SVGA screen mode.
- * When it does generate an interrupt, it doesn't return any status bytes.
- * It appears to have something to do with the version command...
- *
- * This should never be called, because of the reset after the version check.
- */
-static void ignore_interrupt(void)
-{
-       printk(DEVICE_NAME ": weird interrupt ignored (%d)\n", result());
-       reset = 1;
-       CLEAR_INTR;     /* ignore only once */
-}
-
-
 static void floppy_interrupt(int unused)
 {
        void (*handler)(void) = DEVICE_INTR;
@@ -1381,7 +1379,6 @@ void floppy_init(void)
        timer_active &= ~(1 << FLOPPY_TIMER);
        config_types();
        /* Try to determine the floppy controller type */
-       DEVICE_INTR = ignore_interrupt; /* don't ask ... */
        output_byte(FD_VERSION);        /* get FDC version code */
        if (result() != 1) {
                printk(DEVICE_NAME ": FDC failed to return version byte\n");
@@ -1404,8 +1401,12 @@ void floppy_init(void)
        }
 }
 
+static int usage_count = 0;
+
 static int floppy_grab_irq_and_dma(void)
 {
+       if (usage_count++)
+               return 0;
        if (irqaction(FLOPPY_IRQ,&floppy_sigaction)) {
                printk("Unable to grab IRQ%d for the floppy driver\n", FLOPPY_IRQ);
                return -1;
@@ -1421,6 +1422,8 @@ static int floppy_grab_irq_and_dma(void)
 
 static void floppy_release_irq_and_dma(void)
 {
+       if (--usage_count)
+               return;
        disable_dma(FLOPPY_DMA);
        free_dma(FLOPPY_DMA);
        disable_irq(FLOPPY_IRQ);
index 240edb541de039106022ac17b9ec543ed1b70e77..c1f0280ccff1ed6493db2813a7cd73678ef66635 100644 (file)
@@ -5,7 +5,7 @@
  *            and for "no-sound" interfaces like Lasermate and the
  *            Panasonic CI-101P.
  *
- *  NOTE:     This is release 2.0.
+ *  NOTE:     This is release 2.1.
  *            It works with my SbPro & drive CR-521 V2.11 from 2/92
  *            and with the new CR-562-B V0.75 on a "naked" Panasonic
  *            CI-101P interface. And vice versa. 
  *       reset the drive and do again. Needs lots of resets here and sometimes
  *       that does not cure, so this can't be the solution.
  *
+ *  2.1  Found bug with multisession CDs (accessing frame 16).
+ *       "read audio" works now with address type CDROM_MSF, too.
+ *       Bigger audio frame buffer: allows reading max. 4 frames at time; but
+ *       reading more than one frame at once gives poor quality.
+ *
+ *
+ *  TODO
+ *
+ *     disk change detection
+ *     allow & synchronize multi-activity
+ *        (data + audio + ioctl + disk change, multiple drives)
+ *     implement multi-controller-support with a single driver
+ *     implement "read all subchannel data" (96 bytes per frame)
+ *
+ *
  *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
  *     elaborated speed-up experiments (and the fabulous results!), for
  *     the "push" towards load-free wait loops, and for the extensive mail
 
 #include "blk.h"
 
-#define VERSION "2.0 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "2.1 Eberhard Moenkeberg <emoenke@gwdg.de>"
 
 #define SBPCD_DEBUG
 
 #define XA_TEST2
 
 #define TEST_UPC 0
-#define READ_AUDIO 1
 #define SPEA_TEST 0
 #define PRINTK_BUG 0
 #define TEST_STI 0
@@ -289,10 +303,11 @@ static int autoprobe[] =
 {
   CDROM_PORT, SBPRO, /* probe with user's setup first */
   0x230, 1, /* Soundblaster Pro and 16 (default) */
-  0x300, 0, /* CI-101P (default), Galaxy (default), Reveal (one default) */
+  0x300, 0, /* CI-101P (default), WDH-7001C (default),
+              Galaxy (default), Reveal (one default) */
   0x250, 1, /* OmniCD default, Soundblaster Pro and 16 */
   0x260, 1, /* OmniCD */
-  0x320, 0, /* Lasermate, CI-101P, Galaxy, Reveal (other default) */
+  0x320, 0, /* Lasermate, CI-101P, WDH-7001C, Galaxy, Reveal (other default) */
   0x340, 0, /* Lasermate, CI-101P */
   0x360, 0, /* Lasermate, CI-101P */
   0x270, 1, /* Soundblaster 16 */
@@ -304,11 +319,11 @@ static int autoprobe[] =
   0x350, 2, /* SPEA Media FX */
 #if 0
 /* some "hazardous" locations (ethernet cards) */
-  0x330, 0, /* Lasermate, CI-101P */
+  0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
   0x350, 0, /* Lasermate, CI-101P */
   0x370, 0, /* Lasermate, CI-101P */
   0x290, 1, /* Soundblaster 16 */
-  0x310, 0, /* Lasermate, CI-101P */
+  0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
 /* excluded due to incomplete address decoding of the SbPro card */
   0x630, 0, /* "sound card #9" (default) */
   0x650, 0, /* "sound card #9" */
@@ -323,8 +338,9 @@ static int autoprobe[] =
  * the forward references:
  */
 static void sbp_read_cmd(void);
-static int  sbp_data(void);
+static int sbp_data(void);
 static int cmd_out(void);
+static int DiskInfo(void);
 
 /*==========================================================================*/
 
@@ -370,12 +386,7 @@ static int sbpcd_debug =  (1<<DBG_INF) |
 #else
 static int sbpcd_debug =  (1<<DBG_INF) |
                           (1<<DBG_TOC) |
-                          (1<<DBG_UPC) |
-                          (1<<DBG_TIM) |
-                          (1<<DBG_LCK) |
-                          (1<<DBG_CHK) |
-                          (1<<DBG_AUD) |
-                          (1<<DBG_IOX);
+                          (1<<DBG_UPC);
 #endif
 #endif
 static int sbpcd_ioaddr = CDROM_PORT;  /* default I/O base address */
@@ -404,7 +415,8 @@ static struct wait_queue *sbp_waitq = NULL;
 
 /*==========================================================================*/
 
-#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead */
+#define SBP_BUFFER_FRAMES 4 /* driver's own read_ahead, data mode */
+#define SBP_BUFFER_AUDIO_FRAMES 4 /* driver's own read_ahead, read audio mode */
 
 /*==========================================================================*/
 
@@ -419,6 +431,7 @@ static u_char infobuf[20];
 static u_char xa_head_buf[CD_XA_HEAD];
 static u_char xa_tail_buf[CD_XA_TAIL];
 
+static u_char busy_data=0, busy_audio=0; /* true semaphores would be safer */
 static u_char timed_out=0;
 static u_int datarate= 1000000;
 static u_int maxtim16=16000000;
@@ -460,11 +473,8 @@ static struct {
   int sbp_current;       /* Frame being currently read */
 
   u_char mode;           /* read_mode: READ_M1, READ_M2, READ_SC, READ_AU */
-#if READ_AUDIO
   u_char *aud_buf;                  /* Pointer to audio data buffer,
                                  space allocated during sbpcd_init() */
-#endif READ_AUDIO
-
   u_char drv_type;
   u_char drv_options;
   u_char status_byte;
@@ -671,22 +681,34 @@ static int msf2blk(int msfx)
   return (i);
 }
 /*==========================================================================*/
+/*
+ *  convert m-s-f_number (3 bytes only) to logical_block_address 
+ */
+static int msf2lba(u_char *msf)
+{
+  int i;
+
+  i=(msf[0] * CD_SECS + msf[1]) * CD_FRAMES + msf[2] - CD_BLOCK_OFFSET;
+  if (i<0) return (0);
+  return (i);
+}
+/*==========================================================================*/
 /* evaluate xx_ReadError code (still mysterious) */ 
 static int sta2err(int sta)
 {
   if (sta<=2) return (sta);
-  if (sta==0x05) return (-4);
-  if (sta==0x06) return (-6);
-  if (sta==0x0d) return (-6);
-  if (sta==0x0e) return (-3);
-  if (sta==0x14) return (-3);
-  if (sta==0x0c) return (-11);
-  if (sta==0x0f) return (-11);
-  if (sta==0x10) return (-11);
-  if (sta>=0x16) return (-12);
+  if (sta==0x05) return (-4); /* CRC error */
+  if (sta==0x06) return (-6); /* seek error */
+  if (sta==0x0d) return (-6); /* seek error */
+  if (sta==0x0e) return (-3); /* unknown command */
+  if (sta==0x14) return (-3); /* unknown command */
+  if (sta==0x0c) return (-11); /* read fault */
+  if (sta==0x0f) return (-11); /* read fault */
+  if (sta==0x10) return (-11); /* read fault */
+  if (sta>=0x16) return (-12); /* general failure */
   DriveStruct[d].CD_changed=0xFF;
-  if (sta==0x11) return (-15);
-  return (-2);
+  if (sta==0x11) return (-15); /* invalid disk change */
+  return (-2); /* drive not ready */
 }
 /*==========================================================================*/
 static void clr_cmdbuf(void)
@@ -1208,6 +1230,7 @@ static int xy_DriveReset(void)
       response_count=0;
       i=cmd_out();
     }
+  sbp_sleep(100); /* wait a second */
   flush_status();
   i=GetStatus();
   if (i>=0) return -1;
@@ -1244,7 +1267,7 @@ static int DriveReset(void)
     }
   while (!st_diskok);
   DriveStruct[d].CD_changed=1;
-  i=SetSpeed();
+  i=DiskInfo();
   if (i<0) return (-2);
   return (0);
 }
@@ -1730,13 +1753,13 @@ static int yy_CheckMultiSession(void)
 /*==========================================================================*/
 #if FUTURE
 static int yy_SubChanInfo(int frame, int count, u_char *buffer)
-/* "frame" is a RED BOOK address */
+/* "frame" is a RED BOOK (msf-bin) address */
 {
   int i;
 
-  if (!new_drive) return (-3);
+  if (!new_drive) return (-ENOSYS); /* drive firmware lacks it */
 #if 0
-  if (DriveStruct[d].audio_state!=audio_playing) return (-2);
+  if (DriveStruct[d].audio_state!=audio_playing) return (-ENODATA);
 #endif
   clr_cmdbuf();
   drvcmd[0]=0x11;
@@ -1748,7 +1771,7 @@ static int yy_SubChanInfo(int frame, int count, u_char *buffer)
   flags_cmd_out=f_putcmd|f_respo2|f_ResponseStatus|f_obey_p_check;
   cmd_type=READ_SC;
   DriveStruct[d].frame_size=CD_FRAMESIZE_SUB;
-  i=cmd_out(); /* read directly into user's buffer */
+  i=cmd_out(); /* which buffer to use? */
   return (i);
 }
 #endif FUTURE
@@ -2076,7 +2099,7 @@ static int ReadToC(void)
 /* fake entry for LeadOut Track */
   DriveStruct[d].TocBuffer[j].nixbyte=0;
   DriveStruct[d].TocBuffer[j].ctl_adr=0;
-  DriveStruct[d].TocBuffer[j].number=0;
+  DriveStruct[d].TocBuffer[j].number=CDROM_LEADOUT;
   DriveStruct[d].TocBuffer[j].format=0;
   DriveStruct[d].TocBuffer[j].address=DriveStruct[d].size_msf;
 
@@ -2088,9 +2111,7 @@ static int DiskInfo(void)
 {
   int i, j;
 
-#if READ_AUDIO
       DriveStruct[d].mode=READ_M1;
-#endif READ_AUDIO
 
 #undef LOOP_COUNT
 #define LOOP_COUNT 20 /* needed for some "old" drives */
@@ -2579,7 +2600,6 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
       DriveStruct[d].mode=READ_M2;
       return (0);
 
-#if READ_AUDIO
     case CDROMREADAUDIO:
       { /* start of CDROMREADAUDIO */
        int i=0, j=0, frame, block;
@@ -2596,21 +2616,30 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
 
        DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADAUDIO requested.\n"));
 
+#if 0
+       if (!new_drive) return (-EINVAL);
+#endif
+       if (DriveStruct[d].aud_buf==NULL) return (-EINVAL);
        i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
        if (i) return (i);
        memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
-       i=verify_area(VERIFY_WRITE, read_audio.buf, CD_FRAMESIZE_RAW);
+       if (read_audio.nframes>SBP_BUFFER_AUDIO_FRAMES) return (-EINVAL);
+       i=verify_area(VERIFY_WRITE, read_audio.buf,
+                     read_audio.nframes*CD_FRAMESIZE_RAW);
        if (i) return (i);
 
        if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
-         block=msf2blk(read_audio.addr.lba);
+         block=msf2lba(&read_audio.addr.msf.minute);
        else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
          block=read_audio.addr.lba;
        else return (-EINVAL);
-       if (read_audio.nframes!=1) return (-EINVAL);
        DPRINTF((DBG_AUD,"SBPCD: read_audio: lba: %d, msf: %06X\n",
                 block, blk2msf(block)));
        DPRINTF((DBG_AUD,"SBPCD: read_audio: before xx_ReadStatus.\n"));
+
+       while (busy_data) sbp_sleep(10); /* wait a bit */
+       busy_audio=1;
+
        for (data_tries=5; data_tries>0; data_tries--)
          {
            DPRINTF((DBG_AUD,"SBPCD: data_tries=%d ...\n", data_tries));
@@ -2641,7 +2670,7 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
                drvcmd[2]=(block>>8)&0x000000ff;
                drvcmd[3]=block&0x000000ff;
                drvcmd[4]=0;
-               drvcmd[5]=1;   /* # of frames */
+               drvcmd[5]=read_audio.nframes;   /* # of frames */
                drvcmd[6]=0;
              }
            else /* if new_drive */
@@ -2692,7 +2721,13 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
                error_flag=0;
                p = DriveStruct[d].aud_buf;
                if (sbpro_type==1) OUT(CDo_sel_d_i,0x01);
-               READ_DATA(CDi_data, p, CD_FRAMESIZE_RAW);
+#if 0
+               cli();
+#endif
+               READ_DATA(CDi_data, p, read_audio.nframes*CD_FRAMESIZE_RAW);
+#if 0
+               sti();
+#endif
                if (sbpro_type==1) OUT(CDo_sel_d_i,0x00);
                data_retrying = 0;
              }
@@ -2747,13 +2782,15 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
                continue;
              }
            memcpy_tofs((u_char *) read_audio.buf,
-                       (u_char *) DriveStruct[d].aud_buf, CD_FRAMESIZE_RAW);
+                       (u_char *) DriveStruct[d].aud_buf,
+                       read_audio.nframes*CD_FRAMESIZE_RAW);
            DPRINTF((DBG_AUD,"SBPCD: read_audio: memcpy_tofs done.\n"));
            break;
          }
        xx_ModeSelect(CD_FRAMESIZE);
        xx_ModeSense();
        DriveStruct[d].mode=READ_M1;
+       busy_audio=0;
        if (data_tries == 0)
          {
            DPRINTF((DBG_AUD,"SBPCD: read_audio: failed after 5 tries.\n"));
@@ -2762,7 +2799,6 @@ static int SBPCD_IOCTL(struct inode *inode, struct file *file, u_int cmd,
        DPRINTF((DBG_AUD,"SBPCD: read_audio: successful return.\n"));
        return (0);
       } /* end of CDROMREADAUDIO */
-#endif READ_AUDIO
 
     case BLKRASET:
       if(!suser())  return -EACCES;
@@ -2811,14 +2847,14 @@ request_loop:
 
   sti();
 
-  if ((CURRENT==NULL)||(CURRENT->dev<0)) return;
-  if (CURRENT -> sector == -1) return;
+  if ((CURRENT==NULL)||(CURRENT->dev<0)) goto done;
+  if (CURRENT -> sector == -1) goto done;
 
   dev = MINOR(CURRENT->dev);
   if ( (dev<0) || (dev>=NR_SBPCD) )
     {
       printk("SBPCD: do_request: bad device: %d\n", dev);
-      return;
+      goto done;
     }
   switch_drive(dev);
 
@@ -2847,6 +2883,9 @@ request_loop:
   if (i!=0)
     DPRINTF((DBG_INF,"SBPCD: \"prepare\" tells error %d -- ignored\n", i));
 
+  while (busy_audio) sbp_sleep(100); /* wait a bit */
+  busy_data=1;
+
   if (!st_spinning) xx_SpinUp();
 
 #ifdef XA_TEST1
@@ -2884,6 +2923,10 @@ request_loop:
   end_request(0);
   sbp_sleep(10);    /* wait a bit, try again */
   goto request_loop;
+
+done:
+  busy_data=0;
+  return;
 }
 /*==========================================================================*/
 /*
@@ -2904,13 +2947,13 @@ static void sbp_read_cmd(void)
       DPRINTF((DBG_MUL,"SBPCD: read MSF %08X\n", blk2msf(block)));
       if ( (DriveStruct[d].f_multisession) && (multisession_valid) )
        {
-         DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
+         DPRINTF((DBG_MUL,"SBPCD: ManySession: use %08X for %08X (msf)\n",
                         blk2msf(DriveStruct[d].lba_multi+block),
                          blk2msf(block)));
          block=DriveStruct[d].lba_multi+block;
        }
 #else
-      if ( (block==CD_BLOCK_OFFSET+16) && (DriveStruct[d].f_multisession) && (multisession_valid) )
+      if ( (block==16) && (DriveStruct[d].f_multisession) && (multisession_valid) )
        {
          DPRINTF((DBG_MUL,"SBPCD: MultiSession: use %08X for %08X (msf)\n",
                         blk2msf(DriveStruct[d].lba_multi+16),
@@ -3418,6 +3461,9 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
   check_datarate();
   DPRINTF((DBG_INI,"SBPCD: check_datarate done.\n"));
 
+  OUT(CDo_reset,0);
+  sbp_sleep(100);
+
   for (j=0;j<NR_SBPCD;j++)
     {
       if (DriveStruct[j].drv_minor==-1) continue;
@@ -3484,10 +3530,12 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
  */ 
       DriveStruct[j].sbp_buf=(u_char *)mem_start;
       mem_start += SBP_BUFFER_FRAMES*CD_FRAMESIZE;
-#if READ_AUDIO
-      DriveStruct[j].aud_buf=(u_char *)mem_start;
-      mem_start += CD_FRAMESIZE_RAW;
-#endif READ_AUDIO
+      if (new_drive)
+       {
+         DriveStruct[j].aud_buf=(u_char *)mem_start;
+         mem_start += SBP_BUFFER_AUDIO_FRAMES*CD_FRAMESIZE_RAW;
+       }
+      else DriveStruct[j].aud_buf=NULL;
 /*
  * set the block size
  */
index c6d80b6d8380a57d72fa1d9f4b86cb236fb4dede..dae8f0af0480e3efed869864881fdeae1f5ed523 100644 (file)
 #include <asm/segment.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_SCSI
-#ifdef CONFIG_BLK_DEV_SR
-extern int check_cdrom_media_change(int, int);
-#endif
-#ifdef CONFIG_BLK_DEV_SD
-extern int check_scsidisk_media_change(int, int);
-extern int revalidate_scsidisk(int, int);
-#endif
-#endif
-#ifdef CONFIG_CDU31A
-extern int check_cdu31a_media_change(int, int);
-#endif
-#ifdef CONFIG_MCD
-extern int check_mcd_media_change(int, int);
-#endif
-#ifdef CONFIG_SBPCD
-extern int check_sbpcd_media_change(int, int);
-#endif
-
 #define NR_SIZES 4
 static char buffersize_index[9] = {-1,  0,  1, -1,  2, -1, -1, -1, 3};
 static short int bufferindex_size[NR_SIZES] = {512, 1024, 2048, 4096};
@@ -286,85 +267,6 @@ void invalidate_buffers(dev_t dev)
        }
 }
 
-/*
- * This routine checks whether a floppy has been changed, and
- * invalidates all buffer-cache-entries in that case. This
- * is a relatively slow routine, so we have to try to minimize using
- * it. Thus it is called only upon a 'mount' or 'open'. This
- * is the best way of combining speed and utility, I think.
- * People changing diskettes in the middle of an operation deserve
- * to loose :-)
- *
- * NOTE! Although currently this is only for floppies, the idea is
- * that any additional removable block-device will use this routine,
- * and that mount/open needn't know that floppies/whatever are
- * special.
- */
-void check_disk_change(dev_t dev)
-{
-       int i;
-       struct buffer_head * bh;
-
-       switch(MAJOR(dev)){
-       case FLOPPY_MAJOR:
-               if (!(bh = getblk(dev,0,1024)))
-                       return;
-               i = floppy_change(bh);
-               brelse(bh);
-               break;
-
-#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
-         case SCSI_DISK_MAJOR:
-               i = check_scsidisk_media_change(dev, 0);
-               break;
-#endif
-
-#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
-        case SCSI_CDROM_MAJOR:
-               i = check_cdrom_media_change(dev, 0);
-               break;
-#endif
-
-#if defined(CONFIG_CDU31A)
-         case CDU31A_CDROM_MAJOR:
-               i = check_cdu31a_media_change(dev, 0);
-               break;
-#endif
-
-#if defined(CONFIG_MCD)
-         case MITSUMI_CDROM_MAJOR:
-               i = check_mcd_media_change(dev, 0);
-               break;
-#endif
-
-#if defined(CONFIG_SBPCD)
-         case MATSUSHITA_CDROM_MAJOR:
-               i = check_sbpcd_media_change(dev, 0);
-               break;
-#endif
-
-         default:
-               return;
-       };
-
-       if (!i) return;
-
-       printk("VFS: Disk change detected on device %d/%d\n",
-                                       MAJOR(dev), MINOR(dev));
-       for (i=0 ; i<NR_SUPER ; i++)
-               if (super_blocks[i].s_dev == dev)
-                       put_super(super_blocks[i].s_dev);
-       invalidate_inodes(dev);
-       invalidate_buffers(dev);
-
-#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
-/* This is trickier for a removable hardisk, because we have to invalidate
-   all of the partitions that lie on the disk. */
-       if (MAJOR(dev) == SCSI_DISK_MAJOR)
-               revalidate_scsidisk(dev, 0);
-#endif
-}
-
 #define _hashfn(dev,block) (((unsigned)(dev^block))%nr_hash)
 #define hash(dev,block) hash_table[_hashfn(dev,block)]
 
index ebe388c2d712056a698f32401a55686796075fdc..88353596908500a4d7e337f20003a6cfe5b305da 100644 (file)
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 
+/*
+ * Ugly. We'll fix this once all the drivers use the f_ops->check_media_change()
+ * stuff instead..
+ */
+#ifdef CONFIG_SCSI
+#ifdef CONFIG_BLK_DEV_SR
+extern int check_cdrom_media_change(int, int);
+#endif
+#ifdef CONFIG_BLK_DEV_SD
+extern int check_scsidisk_media_change(int, int);
+extern int revalidate_scsidisk(int, int);
+#endif
+#endif
+#ifdef CONFIG_CDU31A
+extern int check_cdu31a_media_change(int, int);
+#endif
+#ifdef CONFIG_MCD
+extern int check_mcd_media_change(int, int);
+#endif
+#ifdef CONFIG_SBPCD
+extern int check_sbpcd_media_change(int, int);
+#endif
+
 struct device_struct {
        const char * name;
        struct file_operations * fops;
@@ -110,6 +133,88 @@ int unregister_blkdev(unsigned int major, const char * name)
        return 0;
 }
 
+/*
+ * This routine checks whether a removable media has been changed,
+ * and invalidates all buffer-cache-entries in that case. This
+ * is a relatively slow routine, so we have to try to minimize using
+ * it. Thus it is called only upon a 'mount' or 'open'. This
+ * is the best way of combining speed and utility, I think.
+ * People changing diskettes in the middle of an operation deserve
+ * to loose :-)
+ */
+void check_disk_change(dev_t dev)
+{
+       int i;
+       struct file_operations * fops;
+
+       i = MAJOR(dev);
+       if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
+               return;
+       if (fops->check_media_change != NULL) {
+               if (!fops->check_media_change(dev))
+                       return;
+       } 
+#if 1 /* this will go soon.. */
+       else switch(MAJOR(dev)){
+#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
+         case SCSI_DISK_MAJOR:
+               if (!check_scsidisk_media_change(dev, 0))
+                       return;
+               break;
+#endif
+
+#if defined(CONFIG_BLK_DEV_SR) && defined(CONFIG_SCSI)
+        case SCSI_CDROM_MAJOR:
+               if (!check_cdrom_media_change(dev, 0))
+                       return;
+               break;
+#endif
+
+#if defined(CONFIG_CDU31A)
+         case CDU31A_CDROM_MAJOR:
+               if (!check_cdu31a_media_change(dev, 0))
+                       return;
+               break;
+#endif
+
+#if defined(CONFIG_MCD)
+         case MITSUMI_CDROM_MAJOR:
+               if (!check_mcd_media_change(dev, 0))
+                       return;
+               break;
+#endif
+
+#if defined(CONFIG_SBPCD)
+         case MATSUSHITA_CDROM_MAJOR:
+               if (!check_sbpcd_media_change(dev, 0))
+                       return;
+               break;
+#endif
+
+         default:
+               return;
+       }
+#endif /* will go away */
+
+       printk("VFS: Disk change detected on device %d/%d\n",
+                                       MAJOR(dev), MINOR(dev));
+       for (i=0 ; i<NR_SUPER ; i++)
+               if (super_blocks[i].s_dev == dev)
+                       put_super(super_blocks[i].s_dev);
+       invalidate_inodes(dev);
+       invalidate_buffers(dev);
+
+       if (fops->revalidate)
+               fops->revalidate(dev);
+
+#if defined(CONFIG_BLK_DEV_SD) && defined(CONFIG_SCSI)
+/* This is trickier for a removable hardisk, because we have to invalidate
+   all of the partitions that lie on the disk. */
+       if (MAJOR(dev) == SCSI_DISK_MAJOR)
+               revalidate_scsidisk(dev, 0);
+#endif
+}
+
 /*
  * Called every time a block special file is opened
  */
index 75d38ff8a6f0b6df0a78dec170b17112c53274a9..c74749049f502f2650e7686087308c51f3fed59d 100644 (file)
@@ -14,7 +14,7 @@
 /*
  * some fix numbers
  */
-#define CD_MINS                   75  /* minutes per CD                  */
+#define CD_MINS                   74  /* max. minutes per CD             */
 #define CD_SECS                   60  /* seconds per minute              */
 #define CD_FRAMES                 75  /* frames per second               */
 #define CD_FRAMESIZE            2048  /* bytes per frame, cooked mode    */
@@ -238,9 +238,8 @@ struct cdrom_tocentry
 /*
  * CD-ROM address types (cdrom_tocentry.cdte_format)
  */
-
-#define        CDROM_LBA       0x01
-#define        CDROM_MSF       0x02
+#define        CDROM_LBA 0x01 /* "logical block": first frame is #0 */
+#define        CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
 
 /*
  * bit to tell whether track is data or audio
@@ -328,7 +327,7 @@ struct cdrom_read_audio
              int       lba;
            } addr; /* frame address */
          u_char addr_format; /* CDROM_LBA or CDROM_MSF */
-         int nframes; /* number of 2352-byte-frames to read at once, currently only 1 allowed */
+         int nframes; /* number of 2352-byte-frames to read at once, limited by the drivers */
          u_char *buf; /* frame buffer (size: nframes*2352 bytes) */
        };
 
@@ -366,7 +365,7 @@ struct cdrom_read_audio
                                                 /* vlume control               */
 
 #define        CDROMSUBCHNL            0x530b          /* (struct cdrom_subchnl)       */
-                                                /* read sub-channel data       */
+                                                /* read Q sub-channel data     */
 
 #define        CDROMREADMODE2          0x530c          /* (struct cdrom_read)          */
                                                 /* read type-2 data (not suppt)        */
index 0bcf4475762b1f80ae6642d4194d0620b3720345..79f151c3bced1894bc686aaf5f97d4710ec50f1b 100644 (file)
@@ -292,6 +292,8 @@ struct file_operations {
        void (*release) (struct inode *, struct file *);
        int (*fsync) (struct inode *, struct file *);
        int (*fasync) (struct inode *, struct file *, int);
+       int (*check_media_change) (dev_t dev);
+       int (*revalidate) (dev_t dev);
 };
 
 struct inode_operations {
@@ -414,7 +416,6 @@ extern inline void mark_buffer_dirty(struct buffer_head * bh, int flag)
 extern void check_disk_change(dev_t dev);
 extern void invalidate_inodes(dev_t dev);
 extern void invalidate_buffers(dev_t dev);
-extern int floppy_change(struct buffer_head * first_block);
 extern void sync_inodes(dev_t dev);
 extern void sync_dev(dev_t dev);
 extern int fsync_dev(dev_t dev);
index e07e130d116744c27392fb8332136db7c60977b7..224cbdd3330adca2f6e4eb7e9387ef7408dc0fb3 100644 (file)
@@ -25,7 +25,7 @@
 #define MCD_BASE_ADDR          0x300
 
 /* *** change this to set the interrupt number */
-#define MCD_INTR_NR            11
+#define MCD_INTR_NR            10
 
 /* Increase this if you get lots of timeouts */
 #define MCD_STATUS_DELAY       100
index 9d50007e5f74fad7dbea2b1e08bb647bd606dcce..b00ef9d4eaad74cff85da77b9c8c50f5e96e934f 100644 (file)
@@ -23,7 +23,7 @@
  * and specify the type of your interface in SBPRO.
  *
  * SBPRO addresses typically are 0x0230 (=0x220+0x10), 0x0250, ...
- * LASERMATE (CI-101P) adresses typically are 0x0300, 0x0310, ...
+ * LASERMATE (CI-101P, WDH-7001C) adresses typically are 0x0300, 0x0310, ...
  * SPEA addresses are 0x320, 0x330, 0x340, 0x350
  * there are some soundcards on the market with 0x0630, 0x0650, ...
  *