]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.17 2.0.17
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:17 +0000 (15:11 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:17 +0000 (15:11 -0500)
16 files changed:
Documentation/devices.tex
Makefile
drivers/block/cmd640.c
drivers/block/floppy.c
drivers/cdrom/sbpcd.c
drivers/char/console.c
drivers/char/ftape/fdc-io.c
drivers/char/ftape/fdc-isr.c
drivers/char/n_tty.c
drivers/char/tty_io.c
include/asm-i386/irq.h
include/linux/sbpcd.h
include/linux/sched.h
include/net/tcp.h
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c

index 4b5521b4813c344702535df3e1a86bece45e3802..b34f50b14740730d8ea19e86a104ed82ea1b57dc 100644 (file)
@@ -1104,7 +1104,7 @@ interface. PD is the Motorola Public Domain Interface and ICD is the
 commercial interface by P\&E.
 
 \begin{devicelist}
-\major{54}{Electrocardiognosis Holter serial card}
+\major{54}{}{char }{Electrocardiognosis Holter serial card}
        \minor{0}{/dev/holter0}{First Holter port}
        \minor{1}{/dev/holter1}{Second Holter port}
        \minor{2}{/dev/holter2}{Third Holter port}
index 179a9821ffebe0f2b16432c898a1fe192c15eebe..48cd2e50701f07ad5bf5b748f6ba704a164f3b33 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 16
+SUBLEVEL = 17
 
 ARCH = i386
 
index 7f22b4dbd855076eca578bbd2879e566c49e6f88..b8132dcd27c15b418cf308b3015aebb9865beee4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/cmd640.c       Version 1.01  Aug 12, 1996
+ *  linux/drivers/block/cmd640.c       Version 1.02  Sep 01, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
  *  Version 1.00       Mmm.. cannot depend on PCMD_ENA in all systems
  *  Version 1.01       slow/fast devsel can be selected with "hdparm -p6/-p7"
  *                      ("fast" is necessary for 32bit I/O in some systems)
+ *  Version 1.02       fix bug that resulted in slow "setup times"
+ *                      (patch courtesy of Zoltan Hidvegi)
  */
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
+#define CMD640_PREFETCH_MASKS 1
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -408,9 +411,11 @@ static void check_prefetch (unsigned int index)
                drive->no_io_32bit = 1;
                drive->io_32bit = 0;
        } else {
+#if CMD640_PREFETCH_MASKS
                drive->no_unmask = 1;
-               drive->no_io_32bit = 0;
                drive->unmask = 0;
+#endif
+               drive->no_io_32bit = 0;
        }
 }
 
@@ -454,8 +459,10 @@ static void set_prefetch_mode (unsigned int index, int mode)
        cli();
        b = get_cmd640_reg(reg);
        if (mode) {     /* want prefetch on? */
+#if CMD640_PREFETCH_MASKS
                drive->no_unmask = 1;
                drive->unmask = 0;
+#endif
                drive->no_io_32bit = 0;
                b &= ~prefetch_masks[index];    /* enable prefetch */
        } else {
@@ -556,9 +563,10 @@ static void program_drive_counts (unsigned int index)
         * Convert setup_count to internal chipset representation
         */
        switch (setup_count) {
-               case 4:  setup_count = 0x00;
-               case 3:  setup_count = 0x80;
-               case 2:  setup_count = 0x40;
+               case 4:  setup_count = 0x00; break;
+               case 3:  setup_count = 0x80; break;
+               case 1:
+               case 2:  setup_count = 0x40; break;
                default: setup_count = 0xc0; /* case 5 */
        }
 
index 43df14a575ab1154b327fafe764722dcfbee2c3c..dfa48f764b807ce320bfe770968f4bcc61cb9edd 100644 (file)
@@ -4067,12 +4067,16 @@ static int floppy_grab_irq_and_dma(void)
        if (fd_request_irq()) {
                DPRINT("Unable to grab IRQ%d for the floppy driver\n",
                        FLOPPY_IRQ);
+               MOD_DEC_USE_COUNT;
+               usage_count--;
                return -1;
        }
        if (fd_request_dma()) {
                DPRINT("Unable to grab DMA%d for the floppy driver\n",
                        FLOPPY_DMA);
                fd_free_irq();
+               MOD_DEC_USE_COUNT;
+               usage_count--;
                return -1;
        }
        for (fdc = 0; fdc < N_FDC; fdc++)
@@ -4098,7 +4102,6 @@ static void floppy_release_irq_and_dma(void)
                return;
        }
        INT_ON;
-       MOD_DEC_USE_COUNT;
        fd_disable_dma();
        fd_free_dma();
        fd_disable_irq();
@@ -4131,6 +4134,7 @@ static void floppy_release_irq_and_dma(void)
        if (floppy_tq.sync)
                printk("task queue still active\n");
 #endif
+       MOD_DEC_USE_COUNT;
 }
 
 
index 9be7c062ab35f1e547593d6522899d599ad4947f..18c1bed2a84c32f2f50a18eadc310162353d54ab 100644 (file)
@@ -13,7 +13,7 @@
  *             labelled E2550UA or MK4015 or 2800F).
  */
 
-#define VERSION "v4.5 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "v4.6 Eberhard Moenkeberg <emoenke@gwdg.de>"
 
 /*   Copyright (C) 1993, 1994, 1995  Eberhard Moenkeberg <emoenke@gwdg.de>
  *
  *       ll_rw_blk.c).
  *       "Check media change" without touching any drive.
  *
+ *  4.6  Use a semaphore to synchronize multi-activity; elaborated by Rob
+ *       Riggs <rriggs@tesser.com>. At the moment, we simply block "read"
+ *       against "ioctl" and vice versa. This could be refined further, but
+ *       I guess with almost no performance increase.
+ *       Experiments to speed up the CD-55A; again with help of Rob Riggs
+ *       (to be true, he gave both, idea & code. ;-)
  *
- *  TODO
  *
- *     synchronize multi-activity
- *        (data + audio + ioctl + disk change, multiple drives)
+ *  TODO
  *     implement "read all subchannel data" (96 bytes per frame)
  *
  *     special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
@@ -571,9 +575,8 @@ static const char *major_name="sbpcd4";
 static struct wait_queue *sbp_waitq = NULL;
 #endif FUTURE
 
-/*==========================================================================*/
-#define SBP_BUFFER_FRAMES 8 /* driver's own read_ahead, data mode */
-/*==========================================================================*/
+static int teac=SBP_TEAC_SPEED;
+static int buffers=SBP_BUFFER_FRAMES;
 
 static u_char family0[]="MATSHITA"; /* MKE CR-521, CR-522, CR-523 */
 static u_char family1[]="CR-56";    /* MKE CR-562, CR-563 */
@@ -592,8 +595,11 @@ static u_char infobuf[20];
 static u_char xa_head_buf[CD_XA_HEAD];
 static u_char xa_tail_buf[CD_XA_TAIL];
 
+#if OLD_BUSY
 static volatile u_char busy_data=0;
 static volatile u_char busy_audio=0; /* true semaphores would be safer */
+#endif OLD_BUSY
+static struct semaphore ioctl_read_sem = MUTEX;
 static u_long timeout;
 static volatile u_char timed_out_delay=0;
 static volatile u_char timed_out_data=0;
@@ -828,6 +834,8 @@ static void sbp_sleep(u_int time)
        sti();
 }
 /*==========================================================================*/
+#define RETURN_UP(rc) {up(&ioctl_read_sem); return(rc);}
+/*==========================================================================*/
 /*
  *  convert logical_block_address to m-s-f_number (3 bytes only)
  */
@@ -960,6 +968,57 @@ static void flush_status(void)
        sbp_sleep(15*HZ/10);
        for (i=maxtim_data;i!=0;i--) inb(CDi_status);
 }
+/*====================================================================*/
+/*
+ * CDi status loop for Teac CD-55A (Rob Riggs)
+ *
+ * This is needed because for some strange reason
+ * the CD-55A can take a real long time to give a
+ * status response. This seems to happen after we
+ * issue a READ command where a long seek is involved.
+ *
+ * I tried to ensure that we get max throughput with
+ * minimal busy waiting. We busy wait at first, then
+ * "switch gears" and start sleeping. We sleep for
+ * longer periods of time the longer we wait.
+ *
+ */
+static int CDi_stat_loop_T(void)
+{
+       int     i, gear=1;
+       u_long  timeout_1, timeout_2, timeout_3, timeout_4;
+
+       timeout_1 = jiffies + HZ / 50;  /* sbp_sleep(0) for a short period */
+       timeout_2 = jiffies + HZ / 5;   /* nap for no more than 200ms */
+       timeout_3 = jiffies + 5 * HZ;   /* sleep for up to 5s */
+       timeout_4 = jiffies + 45 * HZ;  /* long sleep for up to 45s. */
+       do
+          {
+            i = inb(CDi_status);
+            if (!(i&s_not_data_ready)) return (i);
+            if (!(i&s_not_result_ready)) return (i);
+            switch(gear)
+              {
+              case 4:
+                sbp_sleep(HZ);
+                if (jiffies > timeout_4) gear++;
+                msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
+                break;
+              case 3:
+                sbp_sleep(HZ/10);
+                if (jiffies > timeout_3) gear++;
+                break;
+              case 2:
+                sbp_sleep(HZ/100);
+                if (jiffies > timeout_2) gear++;
+                break;
+              case 1:
+                sbp_sleep(0);
+                if (jiffies > timeout_1) gear++;
+              }
+          } while (gear < 5);
+       return -1;
+}
 /*==========================================================================*/
 static int CDi_stat_loop(void)
 {
@@ -1290,8 +1349,20 @@ static int cmd_out_T(void)
        for (ntries=CMDT_TRIES;ntries>0;ntries--)
        {
                if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ); /* fixme */
+#if 01
                OUT(CDo_sel_i_d,1);
-               i=inb(CDi_status);
+#endif 01
+               if (teac==2)
+                  {
+                    if ((i=CDi_stat_loop_T()) == -1) break;
+                  }
+               else
+                  {
+#if 0
+                    OUT(CDo_sel_i_d,1);
+#endif 0
+                    i=inb(CDi_status);
+                  }
                if (!(i&s_not_data_ready)) /* f.e. CMDT_DISKINFO */
                {
                        OUT(CDo_sel_i_d,1);
@@ -1384,7 +1455,8 @@ static int cmd_out_T(void)
                        return (-D_S[d].error_state-400);
                }
                if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-               sbp_sleep(HZ/10);
+               if ((teac==0)||(ntries<(CMDT_TRIES-5))) sbp_sleep(HZ/10);
+               else sbp_sleep(HZ/100);
                if (ntries>(CMDT_TRIES-50)) continue;
                msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
        }
@@ -3343,7 +3415,7 @@ static int check_version(void)
                }
                else if (famV_drive)
                  {
-                   if (j==100) D_S[d].drv_type=drv_at;
+                   if ((j==100)||(j==150)) D_S[d].drv_type=drv_at;
                    ask_mail(); /* hopefully we get some feedback by this */
                  }
        }
@@ -3716,7 +3788,7 @@ static int DiskInfo(void)
                return (i);
        }
        if (D_S[d].f_multisession) D_S[d].sbp_bufsiz=1;  /* possibly a weird PhotoCD */
-       else D_S[d].sbp_bufsiz=SBP_BUFFER_FRAMES;
+       else D_S[d].sbp_bufsiz=buffers;
        i=cc_ReadTocEntry(D_S[d].n_first_track);
        if (i<0)
        {
@@ -3878,16 +3950,17 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                msg(DBG_INF, "ioctl: bad device: %04X\n", inode->i_rdev);
                return (-ENXIO);             /* no such drive */
        }
+       down(&ioctl_read_sem);
        if (d!=i) switch_drive(i);
        
 #if 0
        st=GetStatus();
-       if (st<0) return (-EIO);
+       if (st<0) RETURN_UP(-EIO);
        
        if (!toc_valid)
        {
                i=DiskInfo();
-               if (i<0) return (-EIO); /* error reading TOC */
+               if (i<0) RETURN_UP(-EIO);       /* error reading TOC */
        }
 #endif
        
@@ -3895,9 +3968,9 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
        switch (cmd)            /* Sun-compatible */
        {
        case DDIOCSDBG:         /* DDI Debug */
-               if (!suser()) return (-EPERM);
+               if (!suser()) RETURN_UP(-EPERM);
                i=sbpcd_dbg_ioctl(arg,1);
-               return (i);
+               RETURN_UP(i);
                
        case CDROMPAUSE:     /* Pause the drive */
                msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
@@ -3910,19 +3983,19 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                case audio_playing:
                        if (famL_drive) i=cc_ReadSubQ();
                        else i=cc_Pause_Resume(1);
-                       if (i<0) return (-EIO);
+                       if (i<0) RETURN_UP(-EIO);
                        if (famL_drive) i=cc_Pause_Resume(1);
                        else i=cc_ReadSubQ();
-                       if (i<0) return (-EIO);
+                       if (i<0) RETURN_UP(-EIO);
                        D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
                        D_S[d].audio_state=audio_pausing;
-                       return (0);
+                       RETURN_UP(0);
                case audio_pausing:
                        i=cc_Seek(D_S[d].pos_audio_start,1);
-                       if (i<0) return (-EIO);
-                       return (0);
+                       if (i<0) RETURN_UP(-EIO);
+                       RETURN_UP(0);
                default:
-                       return (-EINVAL);
+                       RETURN_UP(-EINVAL);
                }
                
        case CDROMRESUME: /* resume paused audio play */
@@ -3935,26 +4008,26 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        i=cc_PlayAudio(D_S[d].pos_audio_start,
                                       D_S[d].pos_audio_end);
                else i=cc_Pause_Resume(3);
-               if (i<0) return (-EIO);
+               if (i<0) RETURN_UP(-EIO);
                D_S[d].audio_state=audio_playing;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMPLAYMSF:
                msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
                if (D_S[d].audio_state==audio_playing)
                {
                        i=cc_Pause_Resume(1);
-                       if (i<0) return (-EIO);
+                       if (i<0) RETURN_UP(-EIO);
                        i=cc_ReadSubQ();
-                       if (i<0) return (-EIO);
+                       if (i<0) RETURN_UP(-EIO);
                        D_S[d].pos_audio_start=D_S[d].SubQ_run_tot;
                        i=cc_Seek(D_S[d].pos_audio_start,1);
                }
                st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
                /* values come as msf-bin */
                D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
@@ -3971,33 +4044,36 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
                        DriveReset();
                        D_S[d].audio_state=0;
-                       return (-EIO);
+                       RETURN_UP(-EIO);
                }
                D_S[d].audio_state=audio_playing;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMPLAYTRKIND: /* Play a track.  This currently ignores index. */
                msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
                if (D_S[d].audio_state==audio_playing)
                {
                        msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
-                       return (0);
-                       return (-EINVAL);
+#if 1
+                       RETURN_UP(0); /* just let us play on */
+#else
+                       RETURN_UP(-EINVAL); /* play on, but say "error" */
+#endif
                }
                st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti));
                if (st<0)
                {
                        msg(DBG_IOX,"CDROMPLAYTRKIND: verify_area error.\n");
-                       return (st);
+                       RETURN_UP(st);
                }
                memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti));
                msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
                    ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
-               if (ti.cdti_trk0<D_S[d].n_first_track) return (-EINVAL);
-               if (ti.cdti_trk0>D_S[d].n_last_track) return (-EINVAL);
+               if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
+               if (ti.cdti_trk0>D_S[d].n_last_track) RETURN_UP(-EINVAL);
                if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
                if (ti.cdti_trk1>D_S[d].n_last_track) ti.cdti_trk1=D_S[d].n_last_track;
                D_S[d].pos_audio_start=D_S[d].TocBuffer[ti.cdti_trk0].address;
@@ -4008,28 +4084,29 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
                        DriveReset();
                        D_S[d].audio_state=0;
-                       return (-EIO);
+                       RETURN_UP(-EIO);
                }
                D_S[d].audio_state=audio_playing;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMREADTOCHDR:        /* Read the table of contents header */
                msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
                tochdr.cdth_trk0=D_S[d].n_first_track;
                tochdr.cdth_trk1=D_S[d].n_last_track;
                st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
-               return (0);
+               RETURN_UP(0);
                
        case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
                msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
                st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
                i=tocentry.cdte_track;
                if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
-               else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track) return (-EINVAL);
+               else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
+                  RETURN_UP(-EINVAL);
                tocentry.cdte_adr=D_S[d].TocBuffer[i].ctl_adr&0x0F;
                tocentry.cdte_ctrl=(D_S[d].TocBuffer[i].ctl_adr>>4)&0x0F;
                tocentry.cdte_datamode=D_S[d].TocBuffer[i].format;
@@ -4041,68 +4118,68 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                }
                else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
                        tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
-               else return (-EINVAL);
+               else RETURN_UP(-EINVAL);
                memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
-               return (0);
+               RETURN_UP(0);
                
        case CDROMRESET:      /* hard reset the drive */
                msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
                i=DriveReset();
                D_S[d].audio_state=0;
-               return (i);
+               RETURN_UP(i);
                
        case CDROMSTOP:      /* Spin down the drive */
                msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
                i=cc_Pause_Resume(1);
                D_S[d].audio_state=0;
-               return (i);
+               RETURN_UP(i);
                
        case CDROMSTART:  /* Spin up the drive */
                msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
                cc_SpinUp();
                D_S[d].audio_state=0;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMEJECT:
                msg(DBG_IOC,"ioctl: CDROMEJECT entered.\n");
                if (fam0_drive) return (0);
-               if (D_S[d].open_count>1) return (-EBUSY);
+               if (D_S[d].open_count>1) RETURN_UP(-EBUSY);
                i=UnLockDoor();
                D_S[d].open_count=-9; /* to get it locked next time again */
                i=cc_SpinDown();
                msg(DBG_IOX,"ioctl: cc_SpinDown returned %d.\n", i);
                msg(DBG_TEA,"ioctl: cc_SpinDown returned %d.\n", i);
-               if (i<0) return (-EIO);
+               if (i<0) RETURN_UP(-EIO);
                D_S[d].CD_changed=0xFF;
                D_S[d].diskstate_flags=0;
                D_S[d].audio_state=0;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMEJECT_SW:
                msg(DBG_IOC,"ioctl: CDROMEJECT_SW entered.\n");
-               if (fam0_drive) return (0);
+               if (fam0_drive) RETURN_UP(0);
                D_S[d].f_eject=arg;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMVOLCTRL:   /* Volume control */
                msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
                st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
                D_S[d].vol_chan0=0;
                D_S[d].vol_ctrl0=volctrl.channel0;
                D_S[d].vol_chan1=1;
                D_S[d].vol_ctrl1=volctrl.channel1;
                i=cc_SetVolume();
-               return (0);
+               RETURN_UP(0);
                
        case CDROMVOLREAD:   /* read Volume settings from drive */
                msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
                st=verify_area(VERIFY_WRITE,(void *)arg,sizeof(volctrl));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                st=cc_GetVolume();
                if (st<0) return (st);
                volctrl.channel0=D_S[d].vol_ctrl0;
@@ -4110,15 +4187,16 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                volctrl.channel2=0;
                volctrl.channel2=0;
                memcpy_tofs((void *)arg,&volctrl,sizeof(volctrl));
-               return (0);
+               RETURN_UP(0);
 
        case CDROMSUBCHNL:   /* Get subchannel info */
                msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
-               if ((st_spinning)||(!subq_valid)) { i=cc_ReadSubQ();
-                                                   if (i<0) return (-EIO);
-                                           }
+               if ((st_spinning)||(!subq_valid)) {
+                       i=cc_ReadSubQ();
+                       if (i<0) RETURN_UP(-EIO);
+               }
                st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
                switch (D_S[d].audio_state)
                {
@@ -4156,27 +4234,27 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                    SC.cdsc_adr,SC.cdsc_ctrl,
                    SC.cdsc_trk,SC.cdsc_ind,
                    SC.cdsc_absaddr,SC.cdsc_reladdr);
-               return (0);
+               RETURN_UP(0);
                
        case CDROMREADMODE1:
                msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
                cc_ModeSelect(CD_FRAMESIZE);
                cc_ModeSense();
                D_S[d].mode=READ_M1;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMREADMODE2: /* not usable at the moment */
                msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
                cc_ModeSelect(CD_FRAMESIZE_RAW1);
                cc_ModeSense();
                D_S[d].mode=READ_M2;
-               return (0);
+               RETURN_UP(0);
                
        case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
                msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
@@ -4193,11 +4271,11 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        }
                        else msg(DBG_INF,"audio buffer size: %d frames.\n",D_S[d].sbp_audsiz);
                }
-               return (D_S[d].sbp_audsiz);
+               RETURN_UP(D_S[d].sbp_audsiz);
 
        case CDROMREADAUDIO:
        { /* start of CDROMREADAUDIO */
-               int i=0, j=0, frame, block;
+               int i=0, j=0, frame, block=0;
                u_int try=0;
                u_long timeout;
                u_char *p;
@@ -4208,27 +4286,27 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                int error_flag;
                
                msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
-               if (fam0_drive) return (-EINVAL);
-               if (famL_drive) return (-EINVAL);
-               if (famV_drive) return (-EINVAL);
-               if (famT_drive) return (-EINVAL);
+               if (fam0_drive) RETURN_UP(-EINVAL);
+               if (famL_drive) RETURN_UP(-EINVAL);
+               if (famV_drive) RETURN_UP(-EINVAL);
+               if (famT_drive) RETURN_UP(-EINVAL);
 #if SAFE_MIXED
-               if (D_S[d].has_data>1) return (-EBUSY);
+               if (D_S[d].has_data>1) RETURN_UP(-EBUSY);
 #endif SAFE_MIXED
-               if (D_S[d].aud_buf==NULL) return (-EINVAL);
+               if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL);
                i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
-               if (i) return (i);
+               if (i) RETURN_UP(i);
                memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
-               if (read_audio.nframes>D_S[d].sbp_audsiz) return (-EINVAL);
+               if (read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
                i=verify_area(VERIFY_WRITE, read_audio.buf,
                              read_audio.nframes*CD_FRAMESIZE_RAW);
-               if (i) return (i);
+               if (i) RETURN_UP(i);
                
                if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
                        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);
+               else RETURN_UP(-EINVAL);
 #if 000
                i=cc_SetSpeed(speed_150,0,0);
                if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
@@ -4236,8 +4314,10 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
                    block, blk2msf(block));
                msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
+#if OLD_BUSY
                while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
                busy_audio=1;
+#endif OLD_BUSY
                error_flag=0;
                for (data_tries=5; data_tries>0; data_tries--)
                {
@@ -4400,43 +4480,45 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                cc_ModeSelect(CD_FRAMESIZE);
                cc_ModeSense();
                D_S[d].mode=READ_M1;
+#if OLD_BUSY
                busy_audio=0;
+#endif OLD_BUSY
                if (data_tries == 0)
                {
                        msg(DBG_AUD,"read_audio: failed after 5 tries.\n");
-                       return (-8);
+                       RETURN_UP(-EIO);
                }
                msg(DBG_AUD,"read_audio: successful return.\n");
-               return (0);
+               RETURN_UP(0);
        } /* end of CDROMREADAUDIO */
                
        case CDROMMULTISESSION: /* tell start-of-last-session */
                msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n");
                st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession));
-               if (st) return (st);
+               if (st) RETURN_UP(st);
                memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
                if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */
                        lba2msf(D_S[d].lba_multi,&ms_info.addr.msf.minute);
                else if (ms_info.addr_format==CDROM_LBA) /* lba requested */
                        ms_info.addr.lba=D_S[d].lba_multi;
-               else return (-EINVAL);
+               else RETURN_UP(-EINVAL);
                if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */
                else ms_info.xa_flag=0; /* invalid redirection address */
                memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
                msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n",
                    ms_info.xa_flag, ms_info.addr.lba);
-               return (0);
+               RETURN_UP(0);
                
        case BLKRASET:
-               if(!suser())  return -EACCES;
-               if(!(inode->i_rdev)) return -EINVAL;
-               if(arg > 0xff) return -EINVAL;
+               if(!suser()) RETURN_UP(-EACCES);
+               if(!(inode->i_rdev)) RETURN_UP(-EINVAL);
+               if(arg > 0xff) RETURN_UP(-EINVAL);
                read_ahead[MAJOR(inode->i_rdev)] = arg;
-               return (0);
+               RETURN_UP(0);
                
        default:
                msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
-               return (-EINVAL);
+               RETURN_UP(-EINVAL);
        } /* end switch(cmd) */
 }
 /*==========================================================================*/
@@ -4489,6 +4571,7 @@ static void sbp_transfer(struct request *req)
 static inline void sbpcd_end_request(struct request *req, int uptodate) {
        req->next=CURRENT;
        CURRENT=req;
+       up(&ioctl_read_sem);
        end_request(uptodate);
 }
 /*==========================================================================*/
@@ -4528,6 +4611,7 @@ static void DO_SBPCD_REQUEST(void)
        CURRENT=req->next;      /* task can fuck it up         GTL  */
        sti();
        
+       down(&ioctl_read_sem);
        if (req->rq_status == RQ_INACTIVE)
                sbpcd_end_request(req, 0);
        if (req -> sector == -1)
@@ -4545,8 +4629,10 @@ static void DO_SBPCD_REQUEST(void)
                        kdevname(req->rq_dev));
                goto err_done;
        }
+#if OLD_BUSY
        while (busy_audio) sbp_sleep(HZ); /* wait a bit */
        busy_data=1;
+#endif OLD_BUSY
        
        if (D_S[i].audio_state==audio_playing) goto err_done;
        if (d!=i) switch_drive(i);
@@ -4612,7 +4698,9 @@ static void DO_SBPCD_REQUEST(void)
        }
        
  err_done:
+#if OLD_BUSY
        busy_data=0;
+#endif OLD_BUSY
 #ifdef DEBUG_GTL
        printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
                xnr, req, req->sector, req->nr_sectors, jiffies);
@@ -4753,8 +4841,8 @@ static int sbp_data(struct request *req)
 #if LONG_TIMING
        max_latency=9*HZ;
 #else
-       if (D_S[d].f_multisession) max_latency=9*HZ;
-       else max_latency=3*HZ;
+       if (D_S[d].f_multisession) max_latency=15*HZ;
+       else max_latency=5*HZ;
 #endif
        duration=jiffies;
        for (frame=0;frame<D_S[d].sbp_read_frames&&!error_flag; frame++)
@@ -4855,9 +4943,16 @@ static int sbp_data(struct request *req)
                wait=8;
                do
                {
-                       sbp_sleep(1);
-                       OUT(CDo_sel_i_d,0);
-                       i=inb(CDi_status);
+                       if (teac==2)
+                          {
+                            if ((i=CDi_stat_loop_T()) == -1) break;
+                          }
+                        else
+                          {
+                            sbp_sleep(1);
+                            OUT(CDo_sel_i_d,0); 
+                            i=inb(CDi_status);
+                          } 
                        if (!(i&s_not_data_ready))
                        {
                                OUT(CDo_sel_i_d,1);
@@ -5018,22 +5113,26 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
        if (fp->f_mode & 2)
                return -EROFS;
        
+       down(&ioctl_read_sem);
        switch_drive(i);
        
        i=cc_ReadError();
        flags_cmd_out |= f_respo2;
-       cc_ReadStatus();                         /* command: give 1-byte status */
+       cc_ReadStatus(); /* command: give 1-byte status */
        i=ResponseStatus();
        if (famT_drive&&(i<0))
        {
                cc_DriveReset();
                i=ResponseStatus();
+#if 0
+                sbp_sleep(HZ);
+#endif 0
                i=ResponseStatus();
        }
        if (i<0)
        {
                msg(DBG_INF,"sbpcd_open: ResponseStatus timed out (%d).\n",i);
-               return (-EIO);                  /* drive doesn't respond */
+               RETURN_UP(-EIO);                  /* drive doesn't respond */
        }
        if (famT_drive) msg(DBG_TEA,"sbpcd_open: ResponseStatus=%02X\n", i);
        if (!st_door_closed)
@@ -5065,7 +5164,7 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
                        cc_SpinDown(); /* eject tray */
                }
 #endif
-               return (-ENXIO);
+               RETURN_UP(-ENXIO);
        }
        /*
         * try to keep an "open" counter here and lock the door if 0->1.
@@ -5092,7 +5191,7 @@ static int sbpcd_open(struct inode *ip, struct file *fp)
 #endif SAFE_MIXED
        }
        if (!st_spinning) cc_SpinUp();
-       return (0);
+       RETURN_UP(0);
 }
 /*==========================================================================*/
 /*
@@ -5108,6 +5207,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
                msg(DBG_INF, "release: bad device: %04X\n", ip->i_rdev);
                return;
        }
+       down(&ioctl_read_sem);
        switch_drive(i);
        /*
         * try to keep an "open" counter here and unlock the door if 1->0.
@@ -5132,6 +5232,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
 #endif SAFE_MIXED
                }
        }
+       up(&ioctl_read_sem);
 }
 /*==========================================================================*/
 /*
@@ -5365,7 +5466,10 @@ int SBPCD_INIT(void)
        }
        
        if (port_index>0)
-               msg(DBG_INF, "You should configure sbpcd.h for your hardware.\n");
+          {
+            msg(DBG_INF, "You should read linux/Documentation/cdrom/sbpcd\n");
+            msg(DBG_INF, "and then configure sbpcd.h for your hardware.\n");
+          }
        check_datarate();
        msg(DBG_INI,"check_datarate done.\n");
        
@@ -5450,7 +5554,7 @@ int SBPCD_INIT(void)
 #endif MODULE
        }
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
-       read_ahead[MAJOR_NR] = SBP_BUFFER_FRAMES * (CD_FRAMESIZE / 512);
+       read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
        
        request_region(CDo_command,4,major_name);
        
@@ -5466,7 +5570,7 @@ int SBPCD_INIT(void)
                 */
                D_S[j].aud_buf=NULL;
                D_S[j].sbp_audsiz=0;
-               D_S[j].sbp_bufsiz=SBP_BUFFER_FRAMES;
+               D_S[j].sbp_bufsiz=buffers;
                if (D_S[j].drv_type&drv_fam1)
                        if (READ_AUDIO>0) D_S[j].sbp_audsiz=READ_AUDIO;
                D_S[j].sbp_buf=(u_char *) vmalloc(D_S[j].sbp_bufsiz*CD_FRAMESIZE);
@@ -5476,7 +5580,7 @@ int SBPCD_INIT(void)
                        return -EIO;
                }
 #ifdef MODULE
-               msg(DBG_INF,"data buffer size: %d frames.\n",SBP_BUFFER_FRAMES);
+               msg(DBG_INF,"data buffer size: %d frames.\n",buffers);
 #endif MODULE
                if (D_S[j].sbp_audsiz>0)
                {
index 3bea607370b1293be065be17a80a1da6c789097b..5c5fdba8475d9577091b910f12eaaca8f81791b5 100644 (file)
@@ -1433,34 +1433,34 @@ static int con_write(struct tty_struct * tty, int from_user,
                  tc = translate[toggle_meta ? (c|0x80) : c];
                }
 
-               /* If the original code was < 32 we only allow a
-                * glyph to be displayed if the code is not normally
-                * used (such as for cursor movement) or if the
-                * disp_ctrl mode has been explicitly enabled.
-                * Note: ESC is *never* allowed to be displayed as
-                * that would disable all escape sequences!
-                * To display font position 0x1B, go into UTF mode
-                * and display character U+F01B, or change the mapping.
-                */
-               ok = (tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS
-                                           : CTRL_ACTION) >> c) & 1))));
+                /* If the original code was a control character we
+                 * only allow a glyph to be displayed if the code is
+                 * not normally used (such as for cursor movement) or
+                 * if the disp_ctrl mode has been explicitly enabled.
+                 * Certain characters (as given by the CTRL_ALWAYS
+                 * bitmap) are always displayed as control characters,
+                 * as the console would be pretty useless without
+                 * them; to display an arbitrary font position use the
+                 * direct-to-font zone in UTF-8 mode.
+                 */
+                ok = tc && (c >= 32 ||
+                            (!utf && !(((disp_ctrl ? CTRL_ALWAYS
+                                         : CTRL_ACTION) >> c) & 1)))
+                        && (c != 127 || disp_ctrl);
 
                if (vc_state == ESnormal && ok) {
                        /* Now try to find out how to display it */
                        tc = conv_uni_to_pc(tc);
-                       if ( tc == -4 )
-                         {
-                           /* If we got -4 (not found) then see if we have
-                              defined a replacement character (U+FFFD) */
-                           tc = conv_uni_to_pc(0xfffd);
-                         }
-                       else if ( tc == -3 )
-                         {
-                           /* Bad hash table -- hope for the best */
-                           tc = c;
-                         }
+                       if ( tc == -4 ) {
+                                /* If we got -4 (not found) then see if we have
+                                   defined a replacement character (U+FFFD) */
+                                tc = conv_uni_to_pc(0xfffd);
+                        } else if ( tc == -3 ) {
+                                /* Bad hash table -- hope for the best */
+                                tc = c;
+                        }
                        if (tc & ~console_charmask)
-                         continue; /* Conversion failed */
+                                continue; /* Conversion failed */
 
                        if (need_wrap) {
                                cr(currcons);
index 2c5ff53c232e8d6d344ef777a02d975ca310350c..fc756e58d5dd93d29f695e7e0a27b2dcf0d4a9a4 100644 (file)
@@ -311,7 +311,7 @@ int fdc_interrupt_wait(int time)
        int current_blocked = current->blocked;
        static int resetting = 0;
 
-       if (wait_intr) {
+       if (waitqueue_active(&wait_intr)) {
                TRACE(1, "error: nested call");
                return -EIO;    /* return error... */
        }
index 75cb8d515cfafbd5189fcfb45f9edd93e76bc95f..0fda859145da051117c92cff1094aa6e1f33b7b6 100644 (file)
@@ -771,7 +771,7 @@ fdc_isr(void)
                        }
                        seek_completed = 1;
                        fdc_mode = fdc_idle;
-               } else if (!wait_intr) {
+               } else if (!waitqueue_active(&wait_intr)) {
                        if (expected_stray_interrupts == 0) {
                                TRACE(2, "unexpected stray interrupt");
                        } else {
index 274f18950d5c39f702062ae9ac8956786cca7180..23f1e1524c39ef6ab23693cc2b54244cb8b19a72 100644 (file)
@@ -795,7 +795,7 @@ do_it_again:
                        current->timeout = (unsigned long) -1;
                        if (time)
                                tty->minimum_to_wake = 1;
-                       else if (!tty->read_wait ||
+                       else if (!waitqueue_active(&tty->read_wait) ||
                                 (tty->minimum_to_wake > minimum))
                                tty->minimum_to_wake = minimum;
                } else {
@@ -907,7 +907,7 @@ do_it_again:
        }
        remove_wait_queue(&tty->read_wait, &wait);
 
-       if (!tty->read_wait)
+       if (!waitqueue_active(&tty->read_wait))
                tty->minimum_to_wake = minimum;
 
        current->state = TASK_RUNNING;
@@ -991,7 +991,7 @@ static int normal_select(struct tty_struct * tty, struct inode * inode,
                                return 1;
                        if (tty_hung_up_p(file))
                                return 1;
-                       if (!tty->read_wait) {
+                       if (!waitqueue_active(&tty->read_wait)) {
                                if (MIN_CHAR(tty) && !TIME_CHAR(tty))
                                        tty->minimum_to_wake = MIN_CHAR(tty);
                                else
index f9c828e94ce871f1e62ef768dd94fc46b71ffabd..d403682876492bd2e3b3704eb10766204d4686d3 100644 (file)
@@ -1349,7 +1349,7 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on)
                return retval;
 
        if (on) {
-               if (!tty->read_wait)
+               if (!waitqueue_active(&tty->read_wait))
                        tty->minimum_to_wake = 1;
                if (filp->f_owner == 0) {
                        if (tty->pgrp)
@@ -1358,7 +1358,7 @@ static int tty_fasync(struct inode * inode, struct file * filp, int on)
                                filp->f_owner = current->pid;
                }
        } else {
-               if (!tty->fasync && !tty->read_wait)
+               if (!tty->fasync && !waitqueue_active(&tty->read_wait))
                        tty->minimum_to_wake = N_TTY_BUF_SIZE;
        }
        return 0;
index 77aaa7463cc95775bd022930e1e830d570d0e20e..06c6f0e3d7aff55b0992170cb5bb7f368ba3a695 100644 (file)
@@ -90,7 +90,7 @@ extern void enable_irq(unsigned int);
        "outb %al,$0x21\n\t" \
        "jmp 1f\n" \
        "1:\tjmp 1f\n" \
-       "1:\tmovb $0x60+"#nr",%al\n\t" \
+       "1:\tmovb $0xE0+"#nr",%al\n\t" \
        "outb %al,$0x20\n\t"
 
 #define ACK_SECOND(mask,nr) \
@@ -102,11 +102,11 @@ extern void enable_irq(unsigned int);
        "outb %al,$0xA1\n\t" \
        "jmp 1f\n" \
        "1:\tjmp 1f\n" \
-       "1:\tmovb $0x60+"#nr",%al\n\t" \
+       "1:\tmovb $0xE0+"#nr",%al\n\t" \
        "outb %al,$0xA0\n\t" \
        "jmp 1f\n" \
        "1:\tjmp 1f\n" \
-       "1:\tmovb $0x62,%al\n\t" \
+       "1:\tmovb $0xE2,%al\n\t" \
        "outb %al,$0x20\n\t"
 
 #define UNBLK_FIRST(mask) \
index ffeabe5b3c775b28dde17f2c4bdf02e4e038d1bd..e9021316d1e42ccd18cfbd9b5b076f4444340483 100644 (file)
 /* runtime by use of the CDROMAUDIOBUFSIZ ioctl.    */
 #define READ_AUDIO 0
 
+/* Optimizations for the Teac CD-55A drive read performance.
+ * SBP_TEAC_SPEED can be changed here, or one can set the 
+ * variable "teac" when loading as a module.
+ * Valid settings are:
+ *   0 - very slow - the recommended "DISTRIBUTION 1" setup.
+ *   1 - 2x performance with little overhead. No busy waiting.
+ *   2 - 4x performance with 5ms overhead per read. Busy wait.
+ *
+ * Setting SBP_TEAC_SPEED or the variable 'teac' to anything
+ * other than 0 may cause problems. If you run into them, first
+ * change SBP_TEAC_SPEED back to 0 and see if your drive responds
+ * normally. If yes, you are "allowed" to report your case - to help
+ * me with the driver, not to solve your hassle. DonĀ“t mail if you
+ * simply are stuck into your own "tuning" experiments, you know?
+ */
+#define SBP_TEAC_SPEED 1
+
 /*==========================================================================*/
 /*==========================================================================*/
 /*
- * nothing to change below here if you are not experimenting
+ * nothing to change below here if you are not fully aware what you're doing
  */
 #ifndef _LINUX_SBPCD_H
 
 #define _LINUX_SBPCD_H
 /*==========================================================================*/
 /*==========================================================================*/
+/*
+ * driver's own read_ahead, data mode
+ */
+#define SBP_BUFFER_FRAMES 8 
+
 #define LONG_TIMING 0 /* test against timeouts with "gold" CDs on CR-521 */
 #undef  FUTURE
 #undef SAFE_MIXED
 #define TEST_UPC 0
 #define SPEA_TEST 0
 #define TEST_STI 0
+#define OLD_BUSY 0
 #undef PATH_CHECK
 #ifndef SOUND_BASE
 #define SOUND_BASE 0
 #endif
+#if DISTRIBUTION
+#undef SBP_TEAC_SPEED
+#define SBP_TEAC_SPEED 0
+#endif
 /*==========================================================================*/
 /*
  * DDI interface definitions
index ba1ca20bfc8fc94b4a0bde7eb0640e4ded05ee09..ea88aa7987f42c09a0d1f74245d0b4e23687bb2f 100644 (file)
@@ -260,8 +260,8 @@ struct task_struct {
 #define PF_DUMPCORE    0x00000200      /* dumped core */
 #define PF_SIGNALED    0x00000400      /* killed by a signal */
 
-#define PF_STARTING    0x00000100      /* being created */
-#define PF_EXITING     0x00000200      /* getting shut down */
+#define PF_STARTING    0x00000002      /* being created */
+#define PF_EXITING     0x00000004      /* getting shut down */
 
 #define PF_USEDFPU     0x00100000      /* Process used the FPU this quantum (SMP only) */
 #define PF_DTRACE      0x00200000      /* delayed trace (used on m68k) */
index 0977df9e9f0a7a70c1eaa966ea73fd4af09ae172..82714831f8ef6af5f47c0c0af5501577123e77b1 100644 (file)
@@ -161,6 +161,7 @@ extern void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcph
 
 extern void tcp_enqueue_partial(struct sk_buff *, struct sock *);
 extern struct sk_buff * tcp_dequeue_partial(struct sock *);
+extern void tcp_shrink_skb(struct sock *,struct sk_buff *,u32);
 
 /* tcp_input.c */
 extern void tcp_cache_zap(void);
index 4514a8299b5788134fef3a81d66dee0aefc234d9..9cf24fb57ebf661c44a66f4ca52426c0ae33112e 100644 (file)
@@ -978,10 +978,11 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
        /*
         * Maybe we can take some stuff off of the write queue,
         * and put it onto the xmit queue.
-        * FIXME: (?) There is bizarre case being tested here, to check if
+        * There is bizarre case being tested here, to check if
         * the data at the head of the queue ends before the start of
-        * the sequence we already ACKed. This does not appear to be
-        * a case that can actually occur. Why are we testing it?
+        * the sequence we already ACKed. This is not an error,
+        * it can occur when we send a packet directly off of the write_queue
+        * in a zero window probe.
         */
 
        if (!skb_queue_empty(&sk->write_queue) &&
index 4ae481a7c42f115565d3b902acad5261172ec676..9ca4ab140e9d4d525016616665d633402a1858f4 100644 (file)
@@ -325,35 +325,38 @@ void tcp_write_xmit(struct sock *sk)
                skb_unlink(skb);
                
                /*
-                *      See if we really need to send the packet. 
+                *      See if we really need to send the whole packet. 
                 */
                 
-               if (before(skb->end_seq, sk->rcv_ack_seq +1)) 
-               {
+               if (before(skb->end_seq, sk->rcv_ack_seq +1)) {
                        /*
-                        *      This is acked data. We can discard it. This 
-                        *      cannot currently occur.
+                        *      This is acked data. We can discard it.
+                        *      This implies the packet was sent out
+                        *      of the write queue by a zero window probe.
                         */
                         
                        sk->retransmits = 0;
                        kfree_skb(skb, FREE_WRITE);
                        if (!sk->dead) 
                                sk->write_space(sk);
-               } 
-               else
-               {
+               } else {
                        struct tcphdr *th;
                        struct iphdr *iph;
                        int size;
-/*
- * put in the ack seq and window at this point rather than earlier,
- * in order to keep them monotonic.  We really want to avoid taking
- * back window allocations.  That's legal, but RFC1122 says it's frowned on.
- * Ack and window will in general have changed since this packet was put
- * on the write queue.
- */
+
                        iph = skb->ip_hdr;
                        th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
+
+                        /* See if we need to shrink the leading packet on
+                         * the retransmit queue. Strictly speaking, we
+                         * should never need to do this, but some buggy TCP
+                         * implementations get confused if you send them
+                         * a packet that contains both old and new data. (Feh!)
+                         * Soooo, we have this uglyness here.
+                         */
+                       if (after(sk->rcv_ack_seq,skb->seq+th->syn+th->fin))
+                               tcp_shrink_skb(sk,skb,sk->rcv_ack_seq);
+
                        size = skb->len - (((unsigned char *) th) - skb->data);
 #ifndef CONFIG_NO_PATH_MTU_DISCOVERY
                        if (size > sk->mtu - sizeof(struct iphdr))
@@ -363,6 +366,13 @@ void tcp_write_xmit(struct sock *sk)
                        }
 #endif
                        
+/*
+ * put in the ack seq and window at this point rather than earlier,
+ * in order to keep them monotonic.  We really want to avoid taking
+ * back window allocations.  That's legal, but RFC1122 says it's frowned on.
+ * Ack and window will in general have changed since this packet was put
+ * on the write queue.
+ */
                        th->ack_seq = htonl(sk->acked_seq);
                        th->window = htons(tcp_select_window(sk));
 
@@ -1190,3 +1200,56 @@ void tcp_send_probe0(struct sock *sk)
        sk->prot->retransmits ++;
        tcp_reset_xmit_timer (sk, TIME_PROBE0, sk->rto);
 }
+
+/*
+ * Remove the portion of a packet that has already been sent.
+ * Needed to deal with buggy TCP implementations that can't deal
+ * with seeing a packet that contains some data that has already
+ * been received.
+ */
+void tcp_shrink_skb(struct sock *sk, struct sk_buff *skb, u32 ack)
+{
+       struct iphdr *iph;
+       struct tcphdr *th;
+       unsigned char *old, *new;
+       unsigned long len;
+       int diff;
+
+       /*
+        *      Recover the buffer pointers
+        */
+        
+       iph = (struct iphdr *)skb->ip_hdr;
+       th = (struct tcphdr *)(((char *)iph) +(iph->ihl << 2));
+
+       /* how much data are we droping from the tcp frame */
+       diff = ack - skb->seq;
+       /* how much data are we keeping in the tcp frame */
+       len = (skb->end_seq - (th->fin + th->syn)) - ack;
+
+       /* pointers to new start of remaining data, and old start */
+       new = (unsigned char *)th + th->doff*4;
+       old = new+diff;
+
+       /* Update our starting seq number */
+       skb->seq = ack;
+       th->seq = htonl(ack);
+       iph->tot_len = htons(ntohs(iph->tot_len)-diff);
+
+       /* Get the partial checksum for the IP options */
+       if (th->doff*4 - sizeof(*th) > 0)
+               skb->csum = csum_partial((void *)(th+1),
+                               th->doff*4-sizeof(*th),0);
+       else
+               skb->csum = 0;
+
+       /* Copy the good data down and get it's checksum */
+       skb->csum = csum_partial_copy((void *)old,(void *)new,len,skb->csum);
+
+       /* shorten the skb */
+       skb_trim(skb,skb->len-diff);
+        
+       /* Checksum the shrunk buffer */
+       tcp_send_check(th, sk->saddr, sk->daddr, 
+                  th->doff * 4 + len , skb);
+}