]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.17pre6 2.2.17pre6
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:39 +0000 (15:21 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:39 +0000 (15:21 -0500)
o Fix some NTFS bugs, stop it touching win2K (Anton Altaparmakov)
o Wait for dirty buffers to sync sometimes (Marcelo Tosatti)
o AIC7xxx update (hopefully its happy now) (Doug Ledford)
o Put #!/bin/sh on the scripts from Menuconfig (Wolfgang Sourdeau)
o 2.2 elevator wasnt coalescing enough (Jens Axboe)
o Fix ppc build problem (Andreas Tobler)
o PPC video updates (Benjamin Herrenschmidt)
o List extra Athlon flags as in 2.3.* (Alan Cox)
o Handle AMD Athlon L2 cache reporting errata (Alan Cox)

30 files changed:
Documentation/Configure.help
Documentation/filesystems/ntfs.txt
MAINTAINERS
Makefile
arch/i386/kernel/setup.c
arch/ppc/kernel/feature.c
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx/aic7xxx.seq
drivers/scsi/aic7xxx_seq.c
drivers/video/Config.in
drivers/video/Makefile
drivers/video/aty.h
drivers/video/atyfb.c
drivers/video/chipsfb.c
drivers/video/controlfb.c
drivers/video/fbmem.c
drivers/video/macmodes.c
drivers/video/offb.c
fs/buffer.c
fs/ntfs/Makefile
fs/ntfs/fs.c
fs/ntfs/inode.c
fs/ntfs/struct.h
fs/ntfs/super.c
fs/ntfs/util.c
include/linux/blkdev.h
include/linux/fs.h
include/linux/ntfs_fs_sb.h
mm/filemap.c
scripts/Menuconfig

index 4a88f17034498b1607ce173335e0336c45d1ba26..2ac8e11f04577f7cf21da3f8c7d05aa84e401551 100644 (file)
@@ -7588,13 +7588,17 @@ CONFIG_NTFS_FS
   The module will be called ntfs.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-NTFS read-write support (experimental)
+NTFS read-write support (DANGEROUS)
 CONFIG_NTFS_RW
-  If you say Y here, you will (hopefully) be able to write to NTFS
-  file systems as well as read from them. The read-write support
-  in NTFS is far from being complete and is not well tested. If you
+  If you say Y here, you will (maybe) be able to write to NTFS file
+  systems as well as read from them. The read-write support in
+  NTFS is far from being complete and is not well tested. If you
   enable this, back up your NTFS volume first since it may get
-  damaged.
+  damaged. Also, make sure to run chkdsk from within Microsoft
+  Windows NT after having performed any writes to a NTFS partition
+  from Linux to detect any problems as early as possible.
+  Please note that write support is limited to Windows NT4 and
+  earlier versions.
 
   If unsure, say N.
 
index d9789eadbdeac002e4ec14aa82ed74a15a373ed0..7f8794cf6fd2678c1c21c5453d63e75fe57c2c15 100644 (file)
@@ -4,10 +4,16 @@ NTFS Overview
 To mount an NTFS volume, use the filesystem type 'ntfs'. The driver
 currently works only in read-only mode, with no fault-tolerance
 supported.  If you enable the experimental write support, make sure
-you can recover from a complete loss of data. For ftdisk support,
-limited success was reported with volume sets on top of the md driver,
-although mirror and stripe sets should work as well - if the md
-driver can be talked into using the same layout as Windows NT.
+you can recover from a complete loss of data and also always run
+chkdsk from within Microsoft Windows NT after performing a write to
+a NTFS partition from Linux to detect any problems as early as 
+possible. For ftdisk support, limited success was reported with 
+volume sets on top of the md driver, although mirror and stripe 
+sets should work as well - if the md driver can be talked into 
+using the same layout as Windows NT.
+
+Please note that the experimental write support is limited to
+Windows NT4 and earlier versions.
 
 The ntfs driver supports the following mount options:
 iocharset=name      Character set to use when returning file names.
index 80e91b564d8c3ae84ca9c76521f7941eadb57562..4c2e37526e63b758e69c462fa01bd71e4dd68f45 100644 (file)
@@ -660,6 +660,12 @@ M: emoenke@gwdg.de
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
+NTFS FILESYSTEM
+P:     Anton Altaparmakov
+M:     aia21@cus.cam.ac.uk
+L:     linux-kernel@vger.rutgers.edu
+S:     Odd Fixes
+
 OLYMPIC NETWORK DRIVER
 P:     Peter De Shrijver
 M:     p2@ace.ulyssis.sutdent.kuleuven.ac.be   
index 085821b24c045a9a56ec68750851088e13950b14..0f70a7416edfa33755994a48a3eb874f0555683a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 17
-EXTRAVERSION = pre5
+EXTRAVERSION = pre6
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index f7ab6508cf7a2808e0c18ef4dfdbf06cb80dd446..ad654d5521a9dbf55374258c2d0ddd766b238efe 100644 (file)
@@ -464,6 +464,7 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c))
                            (boot_cpu_data.x86_mask >= 8)))
                                c->x86_capability |= X86_FEATURE_MTRR;
                }
+
                /* Fall through */
 
        case X86_VENDOR_TRANSMETA:
@@ -474,7 +475,16 @@ __initfunc(static int get_model_name(struct cpuinfo_x86 *c))
                                ecx>>24, edx>>24);
                        c->x86_cache_size=(ecx>>24)+(edx>>24);
                }
-               if (n >= 0x80000006){
+               if(boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+                       boot_cpu_data.x86 == 6 && 
+                       boot_cpu_data.x86_model== 3 &&
+                       boot_cpu_data.x86_mask == 0)
+               {
+                       /* AMD errata T13 (order #21922) */
+                       printk("CPU: L2 Cache: 64K\n");
+                       c->x86_cache_size = 64;
+               }
+               else if (n >= 0x80000006){
                        cpuid(0x80000006, &dummy, &dummy, &ecx, &edx);
                        printk("CPU: L2 Cache: %dK\n", ecx>>16);
                        c->x86_cache_size = ecx>>16;
@@ -1118,10 +1128,15 @@ int get_cpuinfo(char * buffer)
                    case X86_VENDOR_AMD:
                        if (c->x86 == 5 && c->x86_model == 6)
                                x86_cap_flags[10] = "sep";
-                       x86_cap_flags[16] = "fcmov";
+                       if (c->x86 < 6)
+                               x86_cap_flags[16] = "fcmov";
+                       x86_cap_flags[16] = "pat";
+                       x86_cap_flags[22] = "mmxext";
+                       x86_cap_flags[24] = "fxsr";
+                       x86_cap_flags[30] = "3dnowext";
                        x86_cap_flags[31] = "3dnow";
                        break;
-
+                                                                                                                                                                                                                                                                                                                                               
                    case X86_VENDOR_INTEL:
                        x86_cap_flags[6] = "pae";
                        x86_cap_flags[9] = "apic";
index 1e561dd3bdcc0ac375366a171c3d99e94d0d432b..04bb15fe8bc9ed5a2db8190cd5a7a815e7433e4b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/spinlock.h>
+#include <asm/spinlock.h>
 #include <asm/errno.h>
 #include <asm/ohare.h>
 #include <asm/heathrow.h>
index 7e396902113151a1783c0af9d8007e590ce4d83b..fb0223db25b17ecd87eeeb3363f413ee5894182a 100644 (file)
@@ -270,7 +270,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.30"
+#define AIC7XXX_C_VERSION  "5.1.31"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
index 023ebbf41638765dd267f230f864653a8ef43c94..1e5a2ce5658e6b07e96613b4d35b5245195b0470 100644 (file)
@@ -574,7 +574,7 @@ ultra2_dmahalt:
                test    SCSIOFFSET, 0x7f        jnz ultra2_shutdown;
 ultra2_await_nreq:
                test    SCSISIGI, REQI  jz ultra2_shutdown;
-               test    SSTAT1, PHASEMIS        jz ultra2_await_nreq;
+               test    SSTAT1, (PHASEMIS|REQINIT)      jz ultra2_await_nreq;
 ultra2_shutdown:
                and     DFCNTRL, ~(HDMAEN|SCSIEN);
                test    DFCNTRL, (HDMAEN|SCSIEN) jnz .;
@@ -617,7 +617,7 @@ p_command_dma_loop:
                test    SSTAT1,PHASEMIS jz p_command_dma_loop;  /* ie. underrun */
 p_command_ultra2_dma_done:
                test    SCSISIGI, REQI  jz p_command_ultra2_shutdown;
-               test    SSTAT1, PHASEMIS        jz p_command_ultra2_dma_done;
+               test    SSTAT1, (PHASEMIS|REQINIT)      jz p_command_ultra2_dma_done;
 p_command_ultra2_shutdown:
                and     DFCNTRL, ~(HDMAEN|SCSIEN);
                test    DFCNTRL, (HDMAEN|SCSIEN) jnz .;
@@ -1069,7 +1069,7 @@ dma_dmadone:
        test    SCSIRATE, 0x0f  jnz dma_shutdown;
 dma_await_nreq:
        test    SCSISIGI, REQI  jz dma_shutdown;
-       test    SSTAT1, PHASEMIS        jz dma_await_nreq;
+       test    SSTAT1, (PHASEMIS|REQINIT)      jz dma_await_nreq;
 dma_shutdown:
        and     DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
 dma_halt:
index c1b92913a881c49bc38b099e94f83a745151d914..047a34de037c0c2c74d54a3af1ca6e0edf364b4f 100644 (file)
@@ -209,7 +209,7 @@ static unsigned char seqprog[] = {
        0x10, 0x94, 0x98, 0x69,
        0x7f, 0x05, 0xa0, 0x69,
        0x02, 0x03, 0xa0, 0x79,
-       0x10, 0x0c, 0x9c, 0x79,
+       0x11, 0x0c, 0x9c, 0x79,
        0xd7, 0x93, 0x26, 0x09,
        0x28, 0x93, 0xa2, 0x69,
        0x03, 0x08, 0x52, 0x31,
@@ -231,7 +231,7 @@ static unsigned char seqprog[] = {
        0x04, 0x0b, 0xc8, 0x69,
        0x10, 0x0c, 0xc4, 0x79,
        0x02, 0x03, 0xcc, 0x79,
-       0x10, 0x0c, 0xc8, 0x79,
+       0x11, 0x0c, 0xc8, 0x79,
        0xd7, 0x93, 0x26, 0x09,
        0x28, 0x93, 0xce, 0x69,
        0x12, 0x01, 0x02, 0x00,
@@ -388,7 +388,7 @@ static unsigned char seqprog[] = {
        0x80, 0x3d, 0x02, 0x73,
        0x0f, 0x04, 0x06, 0x6b,
        0x02, 0x03, 0x06, 0x7b,
-       0x10, 0x0c, 0x02, 0x7b,
+       0x11, 0x0c, 0x02, 0x7b,
        0xc7, 0x93, 0x26, 0x09,
        0xff, 0x99, 0xd4, 0x08,
        0x38, 0x93, 0x08, 0x6b,
index 1c2aee936f75c10d377ae30baf37d4f2b0c842b8..d07c626e51d053aab3c3cd24b548121b6a9a18cc 100644 (file)
@@ -49,6 +49,8 @@ if [ "$CONFIG_FB" = "y" ]; then
   fi
   if [ "$CONFIG_ATARI" = "y" ]; then
     bool 'Atari native chipset support' CONFIG_FB_ATARI
+  fi
+  if [ "$CONFIG_ATARI" = "y" -o "$CONFIG_PCI" != "n" ]; then
     bool 'ATI Mach64 display support' CONFIG_FB_ATY
   fi
   if [ "$CONFIG_PPC" = "y" ]; then
@@ -60,6 +62,7 @@ if [ "$CONFIG_FB" = "y" ]; then
       bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
       bool 'Chips 65550 display support' CONFIG_FB_CT65550
       bool 'S3 Trio display support' CONFIG_FB_S3TRIO
+      bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
     fi
   fi
   if [ "$CONFIG_MAC" = "y" ]; then
@@ -89,7 +92,7 @@ if [ "$CONFIG_FB" = "y" ]; then
         bool '  G100/G200 support' CONFIG_FB_MATROX_G100
         bool '  Multihead support' CONFIG_FB_MATROX_MULTIHEAD
       fi
-      bool 'ATI Mach64 display support' CONFIG_FB_ATY
+      bool 'ATI Rage128 display support' CONFIG_FB_ATY128
     fi
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
index cbb454e910ea8bf24e849bfd0f6905842fe23b54..0122b9dd8c1b8cbe918fa061b78c54b4bd1045cc 100644 (file)
@@ -104,6 +104,10 @@ ifeq ($(CONFIG_FB_ATY),y)
 L_OBJS += atyfb.o
 endif
 
+ifeq ($(CONFIG_FB_ATY128),y)
+  L_OBJS += aty128fb.o
+endif
+
 ifeq ($(CONFIG_FB_IGA),y)
 L_OBJS += igafb.o
 endif
index 783fa1b164e45944ee82e26a56eb964afb8d9224..2a42d064b2a8c2bf6309639bd7e9d96e4c92f7d7 100644 (file)
@@ -67,6 +67,8 @@
 #define CUR_HORZ_VERT_POSN     0x006C  /* Dword offset 0_1B */
 #define CUR_HORZ_VERT_OFF      0x0070  /* Dword offset 0_1C */
 
+#define CONFIG_PANEL_LG                0x0074  /* Dword offset 0_1D */
+
 #define GP_IO                  0x0078  /* Dword offset 0_1E */
 
 #define HW_DEBUG               0x007C  /* Dword offset 0_1F */
@@ -82,6 +84,9 @@
 
 #define BUS_CNTL               0x00A0  /* Dword offset 0_28 */
 
+#define LCD_INDEX              0x00A4  /* Dword offset 0_29 */
+#define LCD_DATA               0x00A8  /* Dword offset 0_2A */
+
 #define EXT_MEM_CNTL           0x00AC  /* Dword offset 0_2B */
 #define MEM_CNTL               0x00B0  /* Dword offset 0_2C */
 
 #define GEN_TEST_CNTL          0x00D0  /* Dword offset 0_34 */
 
 #define CUSTOM_MACRO_CNTL      0x00D4  /* Dword offset 0_35 */
+#define LCD_GEN_CNTL_LG                0x00D4  /* Dword offset 0_35 */
 
-#define POWER_MANAGEMENT       0x00D8  /* Dword offset 0_36 (LG) */
+#define POWER_MANAGEMENT_LG    0x00D8  /* Dword offset 0_36 (LG) */
 
 #define CONFIG_CNTL            0x00DC  /* Dword offset 0_37 (CT, ET, VT) */
 #define CONFIG_CHIP_ID         0x00E0  /* Dword offset 0_38 */
 /* mach64CT family / mach64GT (3D RAGE) class */
 #define LB_CHIP_ID     0x4c42  /* RAGE LT PRO, AGP */
 #define LD_CHIP_ID     0x4c44  /* RAGE LT PRO */
-#define LG_CHIP_ID     0x4c47  /* RAGE LT PRO */
+#define LG_CHIP_ID     0x4c47  /* RAGE LT */
 #define LI_CHIP_ID     0x4c49  /* RAGE LT PRO */
 #define LP_CHIP_ID     0x4c50  /* RAGE LT PRO */
 #define LT_CHIP_ID     0x4c54  /* RAGE LT */
 #define GI_CHIP_ID     0x4749  /* RAGE PRO, BGA, PCI33 only */
 #define GP_CHIP_ID     0x4750  /* RAGE PRO, PQFP, PCI33, full 3D */
 #define GQ_CHIP_ID     0x4751  /* RAGE PRO, PQFP, PCI33, limited 3D */
+#define LN_CHIP_ID     0x4c4d  /* RAGE Mobility AGP */
 
 
 /* Mach64 major ASIC revisions */
 #define MACH64_NUM_CLOCKS      16
 #define MACH64_NUM_FREQS       50
 
-/* Power Management register constants (LTG and LT Pro) */
+/* Power Management register constants (LT & LT Pro) */
 #define PWR_MGT_ON             0x00000001
 #define PWR_MGT_MODE_MASK      0x00000006
 #define AUTO_PWR_UP            0x00000008
+#define USE_F32KHZ             0x00000400
+#define TRISTATE_MEM_EN                0x00000800
 #define SELF_REFRESH           0x00000080
 #define PWR_BLON               0x02000000
 #define STANDBY_NOW            0x10000000
 #define PWR_MGT_STATUS_MASK    0xC0000000
 #define PWR_MGT_STATUS_SUSPEND 0x80000000
 
+/* PM Mode constants  */
+#define PWR_MGT_MODE_PIN       0x00000000
+#define PWR_MGT_MODE_REG       0x00000002
+#define PWR_MGT_MODE_TIMER     0x00000004
+#define PWR_MGT_MODE_PCI       0x00000006
+
+/* LCD registers (LT Pro) */
+
+/* LCD Index register */
+#define LCD_INDEX_MASK         0x0000003F
+#define LCD_DISPLAY_DIS                0x00000100
+#define LCD_SRC_SEL            0x00000200
+#define CRTC2_DISPLAY_DIS      0x00000400
+
+/* LCD register indices */
+#define LCD_CONFIG_PANEL       0x00
+#define LCD_GEN_CTRL           0x01
+#define LCD_DSTN_CONTROL       0x02
+#define LCD_HFB_PITCH_ADDR     0x03
+#define LCD_HORZ_STRETCHING    0x04
+#define LCD_VERT_STRETCHING    0x05
+#define LCD_EXT_VERT_STRETCH   0x06
+#define LCD_LT_GIO             0x07
+#define LCD_POWER_MANAGEMENT   0x08
+#define LCD_ZVGPIO             0x09
+
 #endif /* REGMACH64_H */
index a338588ae8a2b8ba75c1342fb777a8d8e1624fa5..dacea73c1c55b037e82b7756e761f6b23713c47a 100644 (file)
@@ -87,7 +87,7 @@
 /*
  * Debug flags.
  */
-#undef DEBUG
+#define DEBUG
 
 #define GUI_RESERVE    0x00001000
 
@@ -419,7 +419,7 @@ static int default_pll __initdata = 0;
 static int default_mclk __initdata = 0;
 
 #if defined(CONFIG_PPC)
-static int default_vmode __initdata = VMODE_NVRAM;
+static int default_vmode __initdata = VMODE_CHOOSE;
 static int default_cmode __initdata = CMODE_NVRAM;
 #endif
 
@@ -452,7 +452,7 @@ static struct aty_features {
     /* mach64CT family / mach64GT (3D RAGE) class */
     { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
     { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
-    { 0x4c47, 0x4c47, "3D RAGE LT PRO" },
+    { 0x4c47, 0x4c47, "3D RAGE LT-G" },
     { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
     { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
     { 0x4c54, 0x4c54, "3D RAGE LT" },
@@ -466,6 +466,7 @@ static struct aty_features {
     { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
     { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
     { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
+    { 0x4c4e, 0x4c4e, "3D RAGE Mobility (AGP)" }, /* Doesn't quite work yet */
 };
 
 static const char *aty_gx_ram[8] __initdata = {
@@ -485,7 +486,7 @@ static inline u32 aty_ld_le32(volatile unsigned int regindex,
 
 #if defined(__powerpc__)
     temp = info->ati_regbase;
-    asm("lwbrx %0,%1,%2" : "=r"(val) : "b" (regindex), "r" (temp));
+     __asm__ __volatile__("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b" (regindex), "r" (temp));
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
     asm("lduwa [%1] %2, %0" : "=r" (val) : "r" (temp), "i" (ASI_PL));
@@ -503,7 +504,7 @@ static inline void aty_st_le32(volatile unsigned int regindex, u32 val,
 
 #if defined(__powerpc__)
     temp = info->ati_regbase;
-    asm("stwbrx %0,%1,%2" : : "r" (val), "b" (regindex), "r" (temp) :
+     __asm__ __volatile__("stwbrx %0,%1,%2;eieio" : : "r" (val), "b" (regindex), "r" (temp) :
        "memory");
 #elif defined(__sparc_v9__)
     temp = info->ati_regbase + regindex;
@@ -517,15 +518,43 @@ static inline void aty_st_le32(volatile unsigned int regindex, u32 val,
 static inline u8 aty_ld_8(volatile unsigned int regindex,
                          const struct fb_info_aty *info)
 {
-    return *(volatile u8 *)(info->ati_regbase+regindex);
+    u8 val = *(volatile u8 *)(info->ati_regbase+regindex);
+#if defined(__powerpc__)
+    eieio();
+#endif
+    return val;
 }
 
 static inline void aty_st_8(volatile unsigned int regindex, u8 val,
                            const struct fb_info_aty *info)
 {
     *(volatile u8 *)(info->ati_regbase+regindex) = val;
+#if defined(__powerpc__)
+    eieio();
+#endif
+}
+
+static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info)
+{
+    unsigned long temp;
+    
+    /* write addr byte */
+    temp = aty_ld_le32(LCD_INDEX, info);
+    aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
+    /* write the register value */
+    aty_st_le32(LCD_DATA, val, info);
 }
 
+static u32 aty_ld_lcd(int index, const struct fb_info_aty *info)
+{
+    unsigned long temp;
+    
+    /* write addr byte */
+    temp = aty_ld_le32(LCD_INDEX, info);
+    aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, info);
+    /* read the register value */
+    return aty_ld_le32(LCD_DATA, info);
+}
 
     /*
      *  Generic Mach64 routines
@@ -683,9 +712,7 @@ static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info)
     aty_st_8(DAC_W_INDEX, offset & 0xff, info);
     /* left addr byte */
     aty_st_8(DAC_DATA, (offset >> 8) & 0xff, info);
-    eieio();
     aty_st_8(DAC_MASK, val, info);
-    eieio();
     aty_st_8(DAC_CNTL, 0, info);
 }
 
@@ -693,10 +720,8 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
 {
     /* write addr byte */
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
-    eieio();
     /* write the register value */
     aty_st_8(CLOCK_CNTL + 2, val, info);
-    eieio();
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
 }
 
@@ -706,10 +731,8 @@ static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
 
     /* write addr byte */
     aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
-    eieio();
     /* read the register value */
     res = aty_ld_8(CLOCK_CNTL + 2, info);
-    eieio();
     return res;
 }
 
@@ -1772,6 +1795,9 @@ static void atyfb_set_par(const struct atyfb_par *par,
        } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
            aty_st_le32(DAC_CNTL, 0x87010184, info);
            aty_st_le32(BUS_CNTL, 0x680000f9, info);
+       } else if (Gx == LN_CHIP_ID) {
+           aty_st_le32(DAC_CNTL, 0x80010102, info);
+           aty_st_le32(BUS_CNTL, 0x7b33a040, info);
        } else {
            /* GT */
            aty_st_le32(DAC_CNTL, 0x86010102, info);
@@ -1788,7 +1814,7 @@ static void atyfb_set_par(const struct atyfb_par *par,
        init_engine(par, info);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-    if (console_fb_info == &info->fb_info) {
+    if (!console_fb_info || console_fb_info == &info->fb_info) {
        struct fb_var_screeninfo var;
        int vmode, cmode;
        display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
@@ -2406,7 +2432,6 @@ static void atyfb_save_palette(struct fb_info *fb, int enter)
                        tmp |= 0x2;
                aty_st_8(DAC_CNTL, tmp, info);
                aty_st_8(DAC_MASK, 0xff, info);
-               eieio();
                scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
                        (info->current_par.crtc.bpp == 16)) ? 3 : 0;
                info->aty_cmap_regs->rindex = i << scale;
@@ -2549,11 +2574,19 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
            } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
                       Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
                       Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
-                      Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
+                      Gx == LD_CHIP_ID ||
                       Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
                /* RAGE PRO or LT PRO */
                pll = 230;
                mclk = 100;
+           } else if (Gx == LG_CHIP_ID) {
+               /* Rage LT */
+               pll = 230;
+               mclk = 63;
+           } else if (Gx == LN_CHIP_ID) {
+               /* Rage mobility */
+               pll = 230;
+               mclk = 100;
            } else {
                /* other RAGE */
                pll = 135;
@@ -2706,24 +2739,43 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
        }
 
 #if defined(CONFIG_PPC)
+    if (Gx == LI_CHIP_ID && machine_is_compatible("PowerBook1,1")) {
+       /* these bits let the 101 powerbook wake up from sleep -- paulus */
+       aty_st_lcd(LCD_POWER_MANAGEMENT, aty_ld_lcd(LCD_POWER_MANAGEMENT, info)
+               | (USE_F32KHZ | TRISTATE_MEM_EN), info);
+    }
+
     if (default_vmode == VMODE_NVRAM) {
+#if 0 /* This is not really supported */
        default_vmode = nvram_read_byte(NV_VMODE);
        if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+#endif
            default_vmode = VMODE_CHOOSE;
     }
+    /*
+     * The default video mode is 1024x768 @ 75Hz, as that
+     * works on iMacs as well as the G3 powerbooks. - paulus
+     */
     if (default_vmode == VMODE_CHOOSE) {
        if (Gx == LG_CHIP_ID)
            /* G3 PowerBook with 1024x768 LCD */
            default_vmode = VMODE_1024_768_60;
-       else {
-           sense = read_aty_sense(info);
-           default_vmode = mac_map_monitor_sense(sense);
-       }
+       else if (Gx == LN_CHIP_ID)
+           /* iBook with 800x600 LCD */
+           default_vmode = VMODE_800_600_60;
+       else
+           default_vmode = VMODE_1024_768_75;
+       /* 'twould be nice to get this going - paulus */
+       sense = read_aty_sense(info);
+       printk(KERN_INFO "atyfb: monitor sense=%x, maps to mode %d\n",
+              sense, mac_map_monitor_sense(sense));
     }
     if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-       default_vmode = VMODE_640_480_60;
+       default_vmode = VMODE_1024_768_75;
+#if 0
     if (default_cmode == CMODE_NVRAM)
        default_cmode = nvram_read_byte(NV_CMODE);
+#endif
     if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
        default_cmode = CMODE_8;
     if (mac_vmode_to_var(default_vmode, default_cmode, &var))
@@ -3476,11 +3528,10 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
     if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
        Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
        Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
-       Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
+       Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID)
        i |= 0x2;       /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
-    eieio();
     scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
             (info->current_par.crtc.bpp == 16)) ? 3 : 0;
     info->aty_cmap_regs->windex = regno << scale;
@@ -3930,6 +3981,124 @@ static struct display_switch fbcon_aty32 = {
 #endif
 
 #ifdef CONFIG_PMAC_PBOOK
+
+/* Power management routines. Those are used for PowerBook sleep.
+ *
+ * It appears that Rage LT and Rage LT Pro have different power
+ * management registers. There's is some confusion about which
+ * chipID is a Rage LT or LT pro :(
+ */
+static int
+aty_power_mgmt_LT(int sleep, struct fb_info_aty *info)
+{
+       unsigned int pm;
+       int timeout;
+       
+       pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+       pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
+       aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+       pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+       
+       timeout = 200000;
+       if (sleep) {
+               /* Sleep */
+               pm &= ~PWR_MGT_ON;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+               udelay(10);
+               pm &= ~(PWR_BLON | AUTO_PWR_UP);
+               pm |= SUSPEND_NOW;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+               udelay(10);
+               pm |= PWR_MGT_ON;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               do {
+                       pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                       udelay(10);
+                       if ((--timeout) == 0)
+                               break;
+               } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+       } else {
+               /* Wakeup */
+               pm &= ~PWR_MGT_ON;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+               udelay(10);
+               pm |=  (PWR_BLON | AUTO_PWR_UP);
+               pm &= ~SUSPEND_NOW;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+               udelay(10);
+               pm |= PWR_MGT_ON;
+               aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+               do {
+                       pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                       udelay(10);
+                       if ((--timeout) == 0)
+                               break;
+               } while ((pm & PWR_MGT_STATUS_MASK) != 0);
+       }
+       mdelay(500);
+
+       return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
+}
+
+static int
+aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info)
+{
+       unsigned int pm;
+       int timeout;
+       
+       pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+       pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
+       aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+       pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+
+       timeout = 200;
+       if (sleep) {
+               /* Sleep */
+               pm &= ~PWR_MGT_ON;
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+               udelay(10);
+               pm &= ~(PWR_BLON | AUTO_PWR_UP);
+               pm |= SUSPEND_NOW;
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+               udelay(10);
+               pm |= PWR_MGT_ON;
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               do {
+                       pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+                       udelay(1000);
+                       if ((--timeout) == 0)
+                               break;
+               } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+       } else {
+               /* Wakeup */
+               pm &= ~PWR_MGT_ON;
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+               udelay(10);
+               pm &= ~SUSPEND_NOW;
+               pm |= (PWR_BLON | AUTO_PWR_UP);
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);
+               udelay(10);
+               pm |= PWR_MGT_ON;
+               aty_st_lcd(LCD_POWER_MANAGEMENT, pm, info);
+               do {
+                       pm = aty_ld_lcd(LCD_POWER_MANAGEMENT, info);                    
+                       udelay(1000);
+                       if ((--timeout) == 0)
+                               break;
+               } while ((pm & PWR_MGT_STATUS_MASK) != 0);
+       }
+
+       return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
+}
+
 /*
  * Save the contents of the frame buffer when we go to sleep,
  * and restore it when we wake up again.
@@ -3938,7 +4107,9 @@ int
 aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
        struct fb_info_aty *info;
-       unsigned int pm;
+       int result;
+
+       result = PBOOK_SLEEP_OK;
 
        for (info = first_display; info != NULL; info = info->next) {
                struct fb_fix_screeninfo fix;
@@ -3950,6 +4121,8 @@ aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
                switch (when) {
                case PBOOK_SLEEP_REQUEST:
                        info->save_framebuffer = vmalloc(nb);
+                       if (info->save_framebuffer == NULL)
+                               return PBOOK_SLEEP_REFUSE;
                        break;
                case PBOOK_SLEEP_REJECT:
                        if (info->save_framebuffer) {
@@ -3966,80 +4139,38 @@ aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
 
                        /* Backup fb content */ 
                        if (info->save_framebuffer)
-                               memcpy(info->save_framebuffer,
+                               memcpy_fromio(info->save_framebuffer,
                                       (void *)info->frame_buffer, nb);
 
                        /* Blank display and LCD */
                        atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
 
-                       /* Set chip to "suspend" mode. Note: There's a HW bug
-                          in the chip which prevents proper resync on wakeup
-                          with automatic power management, we handle suspend
-                          manually using the following (weird) sequence
-                          described by ATI.
-                          Note2:
-                          We could enable this for all Rage LT Pro chip ids */
-                       if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID)
-                           || (Gx == LP_CHIP_ID)) {
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               pm &= ~PWR_MGT_ON;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               mdelay(1);
-                               pm &= ~(PWR_BLON | AUTO_PWR_UP);
-                               pm |= SUSPEND_NOW;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               mdelay(1);
-                               pm |= PWR_MGT_ON;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               do {
-                                       pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                                       /* Fix a problem with revision 4c50 of the chip */
-                                       if (Gx == LP_CHIP_ID)
-                                               break;
-                               } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
-                               mdelay(500);
-                       }
+                       /* Set chip to "suspend" mode */
+                       if (Gx == LG_CHIP_ID)
+                               result = aty_power_mgmt_LT(1, info);
+                       else
+                               result = aty_power_mgmt_LTPro(1, info);
                        break;
                case PBOOK_WAKE:
                        /* Wakeup chip */
-                       if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               pm &= ~PWR_MGT_ON;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               mdelay(1);
-                               pm |=  (PWR_BLON | AUTO_PWR_UP);
-                               pm &= ~SUSPEND_NOW;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                               mdelay(1);
-                               pm |= PWR_MGT_ON;
-                               aty_st_le32(POWER_MANAGEMENT, pm, info);
-                               do {
-                                       pm = aty_ld_le32(POWER_MANAGEMENT, info);
-                                       /* Fix a problem with revision 4c50 of the chip */
-                                       if (Gx == LP_CHIP_ID)
-                                               break;
-                               } while ((pm & PWR_MGT_STATUS_MASK) != 0);
-                               mdelay(500);
-                       }
+                       if (Gx == LG_CHIP_ID)
+                               result = aty_power_mgmt_LT(0, info);
+                       else
+                               result = aty_power_mgmt_LTPro(0, info);
 
                        /* Restore fb content */                        
                        if (info->save_framebuffer) {
-                               memcpy((void *)info->frame_buffer,
+                               memcpy_toio((void *)info->frame_buffer,
                                       info->save_framebuffer, nb);
                                vfree(info->save_framebuffer);
                                info->save_framebuffer = 0;
                        }
-
-                       /* Restore display */                   
+                       /* Restore display */
                        atyfb_set_par(&info->current_par, info);
                        atyfbcon_blank(0, (struct fb_info *)info);
                        break;
                }
        }
-       return PBOOK_SLEEP_OK;
+       return result;
 }
 #endif /* CONFIG_PMAC_PBOOK */
index 2caf9f6782e3b069e1b3f352346610e98e205570..be1d8bc7c19d19d3bdf5cf075e3fad2e8bd9ef40 100644 (file)
@@ -728,6 +728,8 @@ chips_sleep_notify(struct pmu_sleep_notifier *self, int when)
                switch (when) {
                case PBOOK_SLEEP_REQUEST:
                        p->save_framebuffer = vmalloc(nb);
+                       if (p->save_framebuffer == NULL)
+                               return PBOOK_SLEEP_REFUSE;
                        break;
                case PBOOK_SLEEP_REJECT:
                        if (p->save_framebuffer) {
index db4ad05c8b6ad88e5e06dd04f575a7598a0e4540..39c154b1455299560c8d28a8156dfe45a00480b4 100644 (file)
@@ -531,18 +531,26 @@ __initfunc(static void init_control(struct fb_info_control *p))
 
        p->sense = read_control_sense(p);
        printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
+       
        /* Try to pick a video mode out of NVRAM if we have one. */
-       par->vmode = nvram_read_byte(NV_VMODE);
-       if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])
-               par->vmode = VMODE_CHOOSE;
-       if(par->vmode == VMODE_CHOOSE)
-               par->vmode = mac_map_monitor_sense(p->sense);
-       if(!control_reg_init[par->vmode - 1])
-               par->vmode = VMODE_640_480_60;
-
-       par->cmode = nvram_read_byte(NV_CMODE);
-       if(par->cmode < CMODE_8 || par->cmode > CMODE_32)
-               par->cmode = CMODE_8;
+       if (default_vmode == VMODE_NVRAM) {
+               par->vmode = nvram_read_byte(NV_VMODE);
+               if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])
+                       par->vmode = VMODE_CHOOSE;
+               if(par->vmode == VMODE_CHOOSE)
+                       par->vmode = mac_map_monitor_sense(p->sense);
+               if(!control_reg_init[par->vmode - 1])
+                       par->vmode = VMODE_640_480_60;
+       } else
+               par->vmode=default_vmode;
+
+       if (default_cmode == CMODE_NVRAM){
+               par->cmode = nvram_read_byte(NV_CMODE);
+               if(par->cmode < CMODE_8 || par->cmode > CMODE_32)
+                       par->cmode = CMODE_8;}
+       else
+               par->cmode=default_cmode;
+
        /*
         * Reduce the pixel size if we don't have enough VRAM.
         */
@@ -780,14 +788,10 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
      *  bitfields, horizontal timing, vertical timing.
      */
        /* swiped by jonh from atyfb.c */
-       if (xres <= 512 && yres <= 384)
-               par->vmode = VMODE_512_384_60;          /* 512x384, 60Hz */
-       else if (xres <= 640 && yres <= 480)
+       if (xres <= 640 && yres <= 480)
                par->vmode = VMODE_640_480_67;          /* 640x480, 67Hz */
        else if (xres <= 640 && yres <= 870)
                par->vmode = VMODE_640_870_75P;         /* 640x870, 75Hz (portrait) */
-       else if (xres <= 768 && yres <= 576)
-               par->vmode = VMODE_768_576_50I;         /* 768x576, 50Hz (PAL full frame) */
        else if (xres <= 800 && yres <= 600)
                par->vmode = VMODE_800_600_75;          /* 800x600, 75Hz */
        else if (xres <= 832 && yres <= 624)
@@ -1176,8 +1180,8 @@ __initfunc(void control_setup(char *options, int *ints))
                }
                if (!strncmp(this_opt, "vmode:", 6)) {
                        int vmode = simple_strtoul(this_opt+6, NULL, 0);
-               if (vmode > 0 && vmode <= VMODE_MAX)
-                       default_vmode = vmode;
+                       if (vmode > 0 && vmode <= VMODE_MAX)
+                               default_vmode = vmode;
                } else if (!strncmp(this_opt, "cmode:", 6)) {
                        int depth = simple_strtoul(this_opt+6, NULL, 0);
                        switch (depth) {
index b24707687143d6e76a7f0355750cb358219830ac..b69a7cd673f35a587de6c9f9a3a9892d1b052008 100644 (file)
@@ -68,6 +68,8 @@ extern void offb_init(void);
 extern void offb_setup(char *options, int *ints);
 extern void atyfb_init(void);
 extern void atyfb_setup(char *options, int *ints);
+extern void aty128fb_init(void);
+extern void aty128fb_setup(char *options, int *ints);
 extern void igafb_init(void);
 extern void igafb_setup(char *options, int *ints);
 extern void imsttfb_init(void);
@@ -92,6 +94,8 @@ extern void sbusfb_init(void);
 extern void sbusfb_setup(char *options, int *ints);
 extern void valkyriefb_init(void);
 extern void valkyriefb_setup(char *options, int *ints);
+extern void control_init(void);
+extern void control_setup(char *options, int *ints);
 extern void g364fb_init(void);
 extern void fm2fb_init(void);
 extern void fm2fb_setup(char *options, int *ints);
@@ -143,6 +147,9 @@ static struct {
 #ifdef CONFIG_FB_ATY
        { "atyfb", atyfb_init, atyfb_setup },
 #endif
+#ifdef CONFIG_FB_ATY128
+       { "aty128fb", aty128fb_init, aty128fb_setup },
+#endif
 #ifdef CONFIG_FB_IGA
         { "igafb", igafb_init, igafb_setup },
 #endif
@@ -179,6 +186,9 @@ static struct {
 #ifdef CONFIG_FB_VALKYRIE
        { "valkyriefb", valkyriefb_init, valkyriefb_setup },
 #endif
+#ifdef CONFIG_FB_CONTROL
+       { "controlfb", control_init, control_setup },
+#endif
 #ifdef CONFIG_FB_G364
        { "g364", g364fb_init, NULL },
 #endif
index 0fbe917d314fbb7ff84245f1e6517ba2ec06286f..7ac48eba11d334e6c729ca5f2a420ddc497b12bf 100644 (file)
@@ -367,8 +367,10 @@ int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
            continue;
        if (var->pixclock > mode->pixclock)
            continue;
+#if 0
        if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
            continue;
+#endif
        *vmode = mode->number;
        return 0;
     }
index 007e4a53a72eae891ee33e84be04462013377d20..52187b1411f6930dfac71fe4b20d012a95ebbde4 100644 (file)
 
 static int currcon = 0;
 
+/* Supported palette hacks */
+enum {
+       cmap_unknown,
+       cmap_m64,       /* ATI Mach64 */
+       cmap_r128,      /* ATI Rage128 */
+       cmap_M3A,       /* ATI Rage Mobility M3 Head A */
+       cmap_M3B        /* ATI Rage Mobility M3 Head B */
+};
+
 struct fb_info_offb {
     struct fb_info info;
     struct fb_fix_screeninfo fix;
@@ -50,6 +59,7 @@ struct fb_info_offb {
     struct { u_char red, green, blue, pad; } palette[256];
     volatile unsigned char *cmap_adr;
     volatile unsigned char *cmap_data;
+    int cmap_type;
     union {
 #ifdef FBCON_HAS_CFB16
        u16 cfb16[16];
@@ -106,7 +116,8 @@ extern boot_infos_t *boot_infos;
 static int offb_init_driver(struct device_node *);
 static void offb_init_nodriver(struct device_node *);
 static void offb_init_fb(const char *name, const char *full_name, int width,
-                     int height, int depth, int pitch, unsigned long address);
+                     int height, int depth, int pitch, unsigned long address,
+                     struct device_node *dp);
 
     /*
      *  Interface to the low level console driver
@@ -293,6 +304,9 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 #ifdef CONFIG_FB_ATY
 extern void atyfb_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_ATY */
+#if defined(CONFIG_FB_ATY128)
+extern void aty128fb_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_ATY128 */
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
@@ -361,6 +375,20 @@ __initfunc(void offb_init(void))
                            goto foundit;
            }
 
+           /*
+            * The M3 on the Pismo powerbook has no addresses
+            * on the display nodes, they are on their parent.
+            */
+           if (dp->n_addrs == 0 && device_is_compatible(dp, "ATY,RageM3p")) {
+               int na;
+               unsigned int *ap = (unsigned int *)
+                   get_property(dp, "AAPL,address", &na);
+               if (ap != 0)
+                   for (na /= sizeof(unsigned int); na > 0; --na, ++ap)
+                       if (*ap <= addr && addr < *ap + 0x1000000)
+                           goto foundit;
+           }
+
            /*
             * See if the display address is in one of the address
             * ranges for this display.
@@ -386,7 +414,7 @@ __initfunc(void offb_init(void))
                         boot_infos->dispDeviceRect[2],
                         boot_infos->dispDeviceRect[3],
                         boot_infos->dispDeviceDepth,
-                        boot_infos->dispDeviceRowBytes, addr);
+                        boot_infos->dispDeviceRowBytes, addr, 0);
        }
     }
 
@@ -409,6 +437,15 @@ __initfunc(void offb_init(void))
 
 __initfunc(static int offb_init_driver(struct device_node *dp))
 {
+#ifdef CONFIG_FB_ATY128
+    if (!strncmp(dp->name, "ATY,Rage128", 11) ||
+       !strncmp(dp->name, "ATY,RageM3pA", 12)) {
+       aty128fb_of_init(dp);
+       return 1;
+    }
+    if (!strncmp(dp->name, "ATY,RageM3pB", 12))
+       return 0;
+#endif /* CONFIG_FB_ATY128*/
 #ifdef CONFIG_FB_ATY
     if (!strncmp(dp->name, "ATY", 3)) {
        atyfb_of_init(dp);
@@ -477,9 +514,11 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp))
        && len == sizeof(int))
        height = *pp;
     if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
-       && len == sizeof(int))
+       && len == sizeof(int)) {
        pitch = *pp;
-    else
+       if (pitch == 1)
+           pitch = 0x1000;
+    } else
        pitch = width;
     if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
        && len == sizeof(unsigned))
@@ -500,13 +539,14 @@ __initfunc(static void offb_init_nodriver(struct device_node *dp))
            address += 0x1000;
     }
     offb_init_fb(dp->name, dp->full_name, width, height, depth,
-                pitch, address);
+                pitch, address, dp);
     
 }
 
 __initfunc(static void offb_init_fb(const char *name, const char *full_name,
                                    int width, int height, int depth,
-                                   int pitch, unsigned long address))
+                                   int pitch, unsigned long address,
+                                   struct device_node *dp))
 {
     int i;
     struct fb_fix_screeninfo *fix;
@@ -543,13 +583,27 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
     fix->type = FB_TYPE_PACKED_PIXELS;
     fix->type_aux = 0;
 
+    info->cmap_type = cmap_unknown;
     if (depth == 8)
     {
        /* XXX kludge for ati */
-       if (strncmp(name, "ATY,", 4) == 0) {
+       if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+               unsigned long regbase = dp->addrs[2].address;
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_r128;
+       } else if (dp && !strncmp(name, "ATY,RageM3pA", 12)) {
+               unsigned long regbase = dp->parent->addrs[2].address;
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_M3A;
+       } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+               unsigned long regbase = dp->parent->addrs[2].address;
+               info->cmap_adr = ioremap(regbase, 0x1FFF);
+               info->cmap_type = cmap_M3B;
+       } else if (!strncmp(name, "ATY,", 4)) {
                unsigned long base = address & 0xff000000UL;
                info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
                info->cmap_data = info->cmap_adr + 1;
+               info->cmap_type = cmap_m64;
        }
         fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
                                     : FB_VISUAL_STATIC_PSEUDOCOLOR;
@@ -706,7 +760,7 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
        display_info.cmap_data_address = 0;
        display_info.disp_reg_address = 0;
        /* XXX kludge for ati */
-       if (strncmp(name, "ATY,", 4) == 0) {
+       if (info->cmap_type == cmap_m64) {
            unsigned long base = address & 0xff000000UL;
            display_info.disp_reg_address = base + 0x7ffc00;
            display_info.cmap_adr_address = base + 0x7ffcc0;
@@ -767,12 +821,33 @@ static void offbcon_blank(int blank, struct fb_info *info)
        return;
 
     if (blank)
-       for (i = 0; i < 256; i++) {
-           *info2->cmap_adr = i;
-           mach_eieio();
-           for (j = 0; j < 3; j++) {
-               *info2->cmap_data = 0;
-               mach_eieio();
+        for (i = 0; i < 256; i++) {
+           switch(info2->cmap_type) {
+           case cmap_m64:
+               *info2->cmap_adr = i;
+               mach_eieio();
+               for (j = 0; j < 3; j++) {
+                   *info2->cmap_data = 0;
+                   mach_eieio();
+               }
+               break;
+           case cmap_M3A:
+               /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+               out_le32((unsigned *)(info2->cmap_adr + 0x58),
+                       in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
+           case cmap_r128:
+               /* Set palette index & data */
+               out_8(info2->cmap_adr + 0xb0, i);
+               out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
+               break;
+           case cmap_M3B:
+               /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+               out_le32((unsigned *)(info2->cmap_adr + 0x58),
+                       in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
+               /* Set palette index & data */
+               out_8(info2->cmap_adr + 0xb0, i);
+               out_le32((unsigned *)(info2->cmap_adr + 0xb4), 0);
+               break;
            }
        }
     else
@@ -823,14 +898,37 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
     info2->palette[regno].green = green;
     info2->palette[regno].blue = blue;
 
-    *info2->cmap_adr = regno;/* On some chipsets, add << 3 in 15 bits */
-    mach_eieio();
-    *info2->cmap_data = red;
-    mach_eieio();
-    *info2->cmap_data = green;
-    mach_eieio();
-    *info2->cmap_data = blue;
-    mach_eieio();
+    switch(info2->cmap_type) {
+    case cmap_m64:
+        *info2->cmap_adr = regno;
+       mach_eieio();
+       *info2->cmap_data = red;
+       mach_eieio();
+       *info2->cmap_data = green;
+       mach_eieio();
+       *info2->cmap_data = blue;
+       mach_eieio();
+       break;
+    case cmap_M3A:
+       /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+       out_le32((unsigned *)(info2->cmap_adr + 0x58),
+               in_le32((unsigned *)(info2->cmap_adr + 0x58)) & ~0x20);
+    case cmap_r128:
+       /* Set palette index & data */
+       out_8(info2->cmap_adr + 0xb0, regno);
+       out_le32((unsigned *)(info2->cmap_adr + 0xb4),
+               (red << 16 | green << 8 | blue));
+       break;
+    case cmap_M3B:
+        /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+       out_le32((unsigned *)(info2->cmap_adr + 0x58),
+               in_le32((unsigned *)(info2->cmap_adr + 0x58)) | 0x20);
+       /* Set palette index & data */
+       out_8(info2->cmap_adr + 0xb0, regno);
+       out_le32((unsigned *)(info2->cmap_adr + 0xb4),
+               (red << 16 | green << 8 | blue));
+       break;
+    }
 
     if (regno < 16)
        switch (info2->var.bits_per_pixel) {
index ce239d875946491ded46de3687f38e57ac958c65..2c7abea74ef301f06d2abc19ae563e0bcb71446c 100644 (file)
 /* invalidate_buffers/set_blocksize/sync_dev race conditions and
    fs corruption fixes, 1999, Andrea Arcangeli <andrea@suse.de> */
 
+/* Wait for dirty buffers to sync in sync_page_buffers.
+ * 2000, Marcelo Tosatti <marcelo@conectiva.com.br>
+ */
+
 #include <linux/malloc.h>
 #include <linux/locks.h>
 #include <linux/errno.h>
@@ -1464,20 +1468,25 @@ static int grow_buffers(int size)
 #define BUFFER_BUSY_BITS       ((1<<BH_Dirty) | (1<<BH_Lock) | (1<<BH_Protected))
 #define buffer_busy(bh)                ((bh)->b_count || ((bh)->b_state & BUFFER_BUSY_BITS))
 
-static inline int sync_page_buffers(struct buffer_head * bh)
+static int sync_page_buffers(struct buffer_head *bh, int wait)
 {
        struct buffer_head * tmp = bh;
 
        do {
-               if (buffer_dirty(tmp) && !buffer_locked(tmp))
-                       ll_rw_block(WRITE, 1, &tmp);
+               struct buffer_head *p = tmp;
                tmp = tmp->b_this_page;
+               if (buffer_locked(p)) {
+                       if (wait)
+                               __wait_on_buffer(p);
+               } else if (buffer_dirty(p))
+                       ll_rw_block(WRITE, 1, &p);
        } while (tmp != bh);
 
        do {
-               if (buffer_busy(tmp))
-                       return 1;
+               struct buffer_head *p = tmp;
                tmp = tmp->b_this_page;
+               if (buffer_busy(p))
+                       return 1;
        } while (tmp != bh);
 
        return 0;
@@ -1490,7 +1499,7 @@ static inline int sync_page_buffers(struct buffer_head * bh)
  * Wake up bdflush() if this fails - if we're running low on memory due
  * to dirty buffers, we need to flush them out as quickly as possible.
  */
-int try_to_free_buffers(struct page * page_map)
+int try_to_free_buffers(struct page * page_map, int wait)
 {
        struct buffer_head * tmp, * bh = page_map->buffers;
 
@@ -1521,7 +1530,7 @@ int try_to_free_buffers(struct page * page_map)
        return 1;
 
  busy:
-       if (!sync_page_buffers(bh))
+       if (!sync_page_buffers(bh, wait))
                /*
                 * We can jump after the busy check because
                 * we rely on the kernel lock.
index f06e122aaeee8eb34b0e2386a0b87b61ccb00630..9e7ab2eaf2487c718dec29d3c2c5053d27c2dce2 100644 (file)
@@ -3,7 +3,7 @@
 O_TARGET := ntfs.o
 O_OBJS   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o
 M_OBJS   := $(O_TARGET)
-EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"990411\"
+EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"000607\"
 
 include $(TOPDIR)/Rules.make
 
index fdd8047e093c07c1197b69d79301fc5216d81e87..2a8a82403ff070459f2a0abfe90d1a9dd54c18dd 100644 (file)
@@ -5,6 +5,7 @@
  *  Copyright (C) 1995-1997, 1999 Martin von Löwis
  *  Copyright (C) 1996 Richard Russon
  *  Copyright (C) 1996-1997 Régis Duchesne
+ *  Copyright (C) 2000 Anton Altaparmakov
  */
 
 #ifdef HAVE_CONFIG_H
@@ -79,7 +80,7 @@ ntfs_read(struct file * filp, char *buf, size_t count, loff_t *off)
        io.param=buf;
        io.size=count;
        error=ntfs_read_attr(ino,ino->vol->at_data,NULL,*off,&io);
-       if(error)return -error;
+       if(error && !io.size)return -error;
        
        *off+=io.size;
        return io.size;
index 8a5e404b19816340df5b3f66d6fac6ce7785fc52..35451600c514ee6fb51fdc0b6479a921e3b412f4 100644 (file)
@@ -6,6 +6,7 @@
  *  Copyright (C) 1996-1997 Régis Duchesne
  *  Copyright (C) 1998 Joseph Malicki
  *  Copyright (C) 1999 Steve Dodd
+ *  Copyright (C) 2000 Anton Altaparmakov
  */
 
 #include "ntfstypes.h"
@@ -551,11 +552,11 @@ int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
                dest->size=chunk;
                error=ntfs_getput_clusters(ino->vol,s_cluster,
                                           offset-s_vcn*clustersize,dest);
-               if(error)/* FIXME: maybe return failure */
+               if(error)
                {
                        ntfs_error("Read error\n");
                        dest->size=copied;
-                       return 0;
+                       return error;
                }
                l-=chunk;
                copied+=chunk;
index 2b032d7444b25844bb918aaaf5f614cf40a7c089..6e757e830a7171e4a608801a14a9b4850695b1ea 100644 (file)
@@ -3,6 +3,7 @@
  * Structure definitions
  *
  *  Copyright (C) 1997 Régis Duchesne
+ *  Copyright (C) 2000 Anton Altaparmakov
  */
 
 /* Necessary forward definition */
@@ -42,7 +43,10 @@ typedef struct _ntfs_volume{
        ntfs_u32 at_standard_information;
        ntfs_u32 at_attribute_list;
        ntfs_u32 at_file_name;
+       ntfs_u32 at_volume_version;
        ntfs_u32 at_security_descriptor;
+       ntfs_u32 at_volume_name;
+       ntfs_u32 at_volume_information;
        ntfs_u32 at_data;
        ntfs_u32 at_index_root;
        ntfs_u32 at_index_allocation;
index 51f14e72b957c1d75e7d9eae7e60e59961406306..1b6fc7ebdd4e4b2711466ecd6a3a11fb9b1782c6 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) 1995-1997, 1999 Martin von Löwis
  *  Copyright (C) 1996-1997 Régis Duchesne
  *  Copyright (C) 1999 Steve Dodd
+ *  Copyright (C) 2000 Anton Altparmakov
  */
 
 #include "ntfstypes.h"
@@ -62,7 +63,10 @@ int ntfs_init_volume(ntfs_volume *vol,char *boot)
        vol->at_standard_information=0x10;
        vol->at_attribute_list=0x20;
        vol->at_file_name=0x30;
+       vol->at_volume_version=0x40;
        vol->at_security_descriptor=0x50;
+       vol->at_volume_name=0x60;
+       vol->at_volume_information=0x70;
        vol->at_data=0x80;
        vol->at_index_root=0x90;
        vol->at_index_allocation=0xA0;
@@ -141,8 +145,18 @@ process_attrdef(ntfs_inode* attrdef,ntfs_u8* def)
        }else if(ntfs_ua_strncmp(name,"$FILE_NAME",64)==0){
                vol->at_file_name=type;
                check_type=0x30;
+       }else if(ntfs_ua_strncmp(name,"$VOLUME_VERSION",64)==0){
+               vol->at_volume_version=type;
+               check_type=0x40;
        }else if(ntfs_ua_strncmp(name,"$SECURITY_DESCRIPTOR",64)==0){
-               vol->at_file_name=type;
+               vol->at_security_descriptor=type;
+               check_type=0x50;
+       }else if(ntfs_ua_strncmp(name,"$VOLUME_NAME",64)==0){
+               vol->at_volume_name=type;
+               check_type=0x60;
+       }else if(ntfs_ua_strncmp(name,"$VOLUME_INFORMATION",64)==0){
+               vol->at_volume_information=type;
+               check_type=0x70;
        }else if(ntfs_ua_strncmp(name,"$DATA",64)==0){
                vol->at_data=type;
                check_type=0x80;
@@ -158,6 +172,7 @@ process_attrdef(ntfs_inode* attrdef,ntfs_u8* def)
        }else if(ntfs_ua_strncmp(name,"$SYMBOLIC_LINK",64)==0 ||
                 ntfs_ua_strncmp(name,"$REPARSE_POINT",64)==0){
                vol->at_symlink=type;
+               check_type=0xC0;
        }
        if(check_type && check_type!=type){
                ntfs_error("Unexpected type %x for %x\n",type,check_type);
@@ -196,10 +211,31 @@ ntfs_init_attrdef(ntfs_inode* attrdef)
        return error;
 }
 
+/* ntfs_get_version will determine the NTFS version of the 
+   volume and will return the version in a BCD format, with
+   the MSB being the major version number and the LSB the
+   minor one. Otherwise return <0 on error. 
+   Example: version 3.1 will be returned as 0x0301.
+   This has the obvious limitation of not coping with version
+   numbers above 0x80 but that shouldn't be a problem... */
+int ntfs_get_version(ntfs_inode* volume)
+{
+       ntfs_attribute *volinfo;
+
+       volinfo = ntfs_find_attr(volume, volume->vol->at_volume_information, 0);
+       if (!volinfo) 
+               return -EINVAL;
+       if (!volinfo->resident) {
+               ntfs_error("Volume information attribute is not resident!\n");
+               return -EINVAL;
+       }
+       return ((ntfs_u8*)volinfo->d.data)[8] << 8 | ((ntfs_u8*)volinfo->d.data)[9];
+}
+
 int ntfs_load_special_files(ntfs_volume *vol)
 {
        int error;
-       ntfs_inode upcase,attrdef;
+       ntfs_inode upcase, attrdef, volume;
 
        vol->mft_ino=(ntfs_inode*)ntfs_calloc(3*sizeof(ntfs_inode));
        error=ENOMEM;
@@ -232,6 +268,21 @@ int ntfs_load_special_files(ntfs_volume *vol)
        error=ntfs_init_attrdef(&attrdef);
        ntfs_clear_inode(&attrdef);
        if(error)return error;
+
+       /* Check for NTFS version and if Win2k version (ie. 3.0+)
+          do not allow write access since the driver write support
+          is broken, especially for Win2k. */
+       ntfs_debug(DEBUG_BSD,"Going to load VOLUME\n");
+       error = ntfs_init_inode(&volume,vol,FILE_VOLUME);
+       if (error) return error;
+       if ((error = ntfs_get_version(&volume)) >= 0x0300) {
+               NTFS_SB(vol)->s_flags |= MS_RDONLY;
+               ntfs_error("Warning! NTFS volume version is Win2k+: Mounting read-only\n");
+       }
+       ntfs_clear_inode(&volume);
+       if (error < 0) return error;
+       ntfs_debug(DEBUG_BSD, "NTFS volume is version %d.%d\n", error >> 8, error & 0xff);
+
        return 0;
 }
 
index d6d7921eb8ad74168bf80014dd20c69097652c52..069c2b2583fc90d4533f238059e68fb17a169dac 100644 (file)
@@ -266,6 +266,8 @@ int ntfs_uni_strncmp(short int* a,short int *b,int n)
                        return -1;
                if(b[i]<a[i])
                        return 1;
+               if (a[i] == 0)
+                       return 0;
        }
        return 0;
 }
@@ -281,6 +283,8 @@ int ntfs_ua_strncmp(short int* a,char* b,int n)
                        return -1;
                if(b[i]<NTFS_GETU16(a+i))
                        return 1;
+               if (b[i] == 0)
+                       return 0;
        }
        return 0;
 }
index d66fe6a9f3cf151eeb957394c62594f1b6f6bfc5..9da5651d7d4d1c70d41593b6d5067de531ac89e9 100644 (file)
@@ -50,7 +50,7 @@ typedef struct elevator_s
 ((elevator_t) {                                                \
        128,                    /* read_latency */      \
        8192,                   /* write_latency */     \
-       4,                      /* max_bomb_segments */ \
+       32,                     /* max_bomb_segments */ \
         0                       /* queue_ID */          \
        })
 
index d8247e0ec0428d01a430ebaa50595a4b54c0f7ac..fe6845043cb632636fe2a9ff0cdba34c7cd90175 100644 (file)
@@ -754,7 +754,7 @@ extern struct file *inuse_filps;
 
 extern void refile_buffer(struct buffer_head * buf);
 extern void set_writetime(struct buffer_head * buf, int flag);
-extern int try_to_free_buffers(struct page *);
+extern int try_to_free_buffers(struct page *, int wait);
 
 extern int nr_buffers;
 extern long buffermem;
index 898ef7105af69caae3cf6d2ea69d9bcf111e5d46..4b958337ffb71c89cc4f6150872a7a9046f428a4 100644 (file)
@@ -15,7 +15,10 @@ struct ntfs_sb_info{
        ntfs_u32 at_standard_information;
        ntfs_u32 at_attribute_list;
        ntfs_u32 at_file_name;
+       ntfs_u32 at_volume_version;
        ntfs_u32 at_security_descriptor;
+       ntfs_u32 at_volume_name;
+       ntfs_u32 at_volume_information;
        ntfs_u32 at_data;
        ntfs_u32 at_index_root;
        ntfs_u32 at_index_allocation;
index 60bfd4b0809ab9e6f82f7eb60de7a10f9a2b379f..82065f9ea2d3e18480ee080850d00b221b23efa3 100644 (file)
@@ -141,7 +141,8 @@ int shrink_mmap(int priority, int gfp_mask)
        unsigned long limit = num_physpages;
        struct page * page;
        int count;
-
+       int nr_dirty = 0;
+       
        /* Make sure we scan all pages twice at priority 0. */
        count = (limit << 1) >> priority;
 
@@ -197,13 +198,22 @@ int shrink_mmap(int priority, int gfp_mask)
 
                /* Is it a buffer page? */
                if (page->buffers) {
+                       /*
+                        * Wait for async IO to complete
+                        * at each 64 buffers
+                        */ 
+
+                       int wait = ((gfp_mask & __GFP_IO) 
+                               && (!(nr_dirty++ % 64)));
+
                        if (buffer_under_min())
                                continue;
                        /*
                         * We can sleep if we need to do some write
                         * throttling.
                         */
-                       if (!try_to_free_buffers(page))
+
+                       if (!try_to_free_buffers(page, wait))
                                goto refresh_clock;
                        return 1;
                }
index d1d8f38fc52b5db4e6ac6064d071c54c543c8dfb..3ee95634651b63731214e4f3ee3f5f82ca09695e 100644 (file)
@@ -425,7 +425,7 @@ function menu_name () {
                        --menu '$menu_instructions' \
                        $ROWS $COLS $((ROWS-10)) \
                        '$default' " >MCmenu
-       >MCradiolists
+       echo "#!/bin/sh" >MCradiolists
 }
 
 #
@@ -713,11 +713,11 @@ function parser(ifile,menu) {
                        ++menu_no
 
                        printf("submenu %s MCmenu%s\n", $0, menu_no) >>menu
-
-                       printf( "function MCmenu%s () {\n"\
+                       printf( "#!/bin/sh\n"\
+                               "function MCmenu%s () {\n"\
                                "default=$1\n"\
                                "menu_name %s\n",\
-                                menu_no, $0) >"MCmenu"menu_no
+                                menu_no, $0) >>"MCmenu"menu_no
 
                        parser(ifile, "MCmenu"menu_no)
                }
@@ -772,7 +772,8 @@ function parser(ifile,menu) {
 function parse_config_files () {
        rm -f MCmenu*
 
-       echo "function MCmenu0 () {" >MCmenu0
+       echo "#!/bin/sh" > MCmenu0
+       echo "function MCmenu0 () {" >>MCmenu0
        echo 'default=$1' >>MCmenu0
        echo "menu_name 'Main Menu'" >>MCmenu0