From 6b30ab0a16706ed5123d8f7a2812e49fb2346230 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 23 Nov 2007 15:21:39 -0500 Subject: [PATCH] Linux 2.2.17pre6 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) --- Documentation/Configure.help | 14 +- Documentation/filesystems/ntfs.txt | 14 +- MAINTAINERS | 6 + Makefile | 2 +- arch/i386/kernel/setup.c | 21 ++- arch/ppc/kernel/feature.c | 2 +- drivers/scsi/aic7xxx.c | 2 +- drivers/scsi/aic7xxx/aic7xxx.seq | 6 +- drivers/scsi/aic7xxx_seq.c | 6 +- drivers/video/Config.in | 5 +- drivers/video/Makefile | 4 + drivers/video/aty.h | 41 ++++- drivers/video/atyfb.c | 287 +++++++++++++++++++++-------- drivers/video/chipsfb.c | 2 + drivers/video/controlfb.c | 40 ++-- drivers/video/fbmem.c | 10 + drivers/video/macmodes.c | 2 + drivers/video/offb.c | 142 +++++++++++--- fs/buffer.c | 23 ++- fs/ntfs/Makefile | 2 +- fs/ntfs/fs.c | 3 +- fs/ntfs/inode.c | 5 +- fs/ntfs/struct.h | 4 + fs/ntfs/super.c | 55 +++++- fs/ntfs/util.c | 4 + include/linux/blkdev.h | 2 +- include/linux/fs.h | 2 +- include/linux/ntfs_fs_sb.h | 3 + mm/filemap.c | 14 +- scripts/Menuconfig | 11 +- 30 files changed, 569 insertions(+), 165 deletions(-) diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 4a88f1703449..2ac8e11f0457 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -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. diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index d9789eadbdea..7f8794cf6fd2 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -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. diff --git a/MAINTAINERS b/MAINTAINERS index 80e91b564d8c..4c2e37526e63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/Makefile b/Makefile index 085821b24c04..0f70a7416edf 100644 --- 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/) diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index f7ab6508cf7a..ad654d5521a9 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -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"; diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c index 1e561dd3bdcc..04bb15fe8bc9 100644 --- a/arch/ppc/kernel/feature.c +++ b/arch/ppc/kernel/feature.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c index 7e3969021131..fb0223db25b1 100644 --- a/drivers/scsi/aic7xxx.c +++ b/drivers/scsi/aic7xxx.c @@ -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)) diff --git a/drivers/scsi/aic7xxx/aic7xxx.seq b/drivers/scsi/aic7xxx/aic7xxx.seq index 023ebbf41638..1e5a2ce5658e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.seq +++ b/drivers/scsi/aic7xxx/aic7xxx.seq @@ -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: diff --git a/drivers/scsi/aic7xxx_seq.c b/drivers/scsi/aic7xxx_seq.c index c1b92913a881..047a34de037c 100644 --- a/drivers/scsi/aic7xxx_seq.c +++ b/drivers/scsi/aic7xxx_seq.c @@ -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, diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 1c2aee936f75..d07c626e51d0 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -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 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index cbb454e910ea..0122b9dd8c1b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -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 diff --git a/drivers/video/aty.h b/drivers/video/aty.h index 783fa1b164e4..2a42d064b2a8 100644 --- a/drivers/video/aty.h +++ b/drivers/video/aty.h @@ -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 */ @@ -100,8 +105,9 @@ #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 */ @@ -725,7 +731,7 @@ /* 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 */ @@ -739,6 +745,7 @@ #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 */ @@ -951,10 +958,12 @@ #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 @@ -962,4 +971,30 @@ #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 */ diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index a338588ae8a2..dacea73c1c55 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -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 */ diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 2caf9f6782e3..be1d8bc7c19d 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -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) { diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index db4ad05c8b6a..39c154b14552 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -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) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index b24707687143..b69a7cd673f3 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -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 diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c index 0fbe917d314f..7ac48eba11d3 100644 --- a/drivers/video/macmodes.c +++ b/drivers/video/macmodes.c @@ -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; } diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 007e4a53a72e..52187b1411f6 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -42,6 +42,15 @@ 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) { diff --git a/fs/buffer.c b/fs/buffer.c index ce239d875946..2c7abea74ef3 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -27,6 +27,10 @@ /* invalidate_buffers/set_blocksize/sync_dev race conditions and fs corruption fixes, 1999, Andrea Arcangeli */ +/* Wait for dirty buffers to sync in sync_page_buffers. + * 2000, Marcelo Tosatti + */ + #include #include #include @@ -1464,20 +1468,25 @@ static int grow_buffers(int size) #define BUFFER_BUSY_BITS ((1<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. diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile index f06e122aaeee..9e7ab2eaf248 100644 --- a/fs/ntfs/Makefile +++ b/fs/ntfs/Makefile @@ -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 diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c index fdd8047e093c..2a8a82403ff0 100644 --- a/fs/ntfs/fs.c +++ b/fs/ntfs/fs.c @@ -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; diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 8a5e404b1981..35451600c514 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -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; diff --git a/fs/ntfs/struct.h b/fs/ntfs/struct.h index 2b032d7444b2..6e757e830a71 100644 --- a/fs/ntfs/struct.h +++ b/fs/ntfs/struct.h @@ -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; diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 51f14e72b957..1b6fc7ebdd4e 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -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; } diff --git a/fs/ntfs/util.c b/fs/ntfs/util.c index d6d7921eb8ad..069c2b2583fc 100644 --- a/fs/ntfs/util.c +++ b/fs/ntfs/util.c @@ -266,6 +266,8 @@ int ntfs_uni_strncmp(short int* a,short int *b,int n) return -1; if(b[i]> 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; } diff --git a/scripts/Menuconfig b/scripts/Menuconfig index d1d8f38fc52b..3ee95634651b 100644 --- a/scripts/Menuconfig +++ b/scripts/Menuconfig @@ -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 -- 2.39.5