summaryrefslogtreecommitdiffstats
path: root/meta/packages/linux
diff options
context:
space:
mode:
authorMarcin Juszkiewicz <hrw@openedhand.com>2007-10-24 10:51:45 +0000
committerMarcin Juszkiewicz <hrw@openedhand.com>2007-10-24 10:51:45 +0000
commit354c5431349e0487995bebd0fb031f6e431d873f (patch)
treef170d4c4debec61002ff6e8ba672d5dbe362fce8 /meta/packages/linux
parent6e23136cc799c75f81840e933707c3411fbcd584 (diff)
downloadpoky-354c5431349e0487995bebd0fb031f6e431d873f.tar.gz
linux-rp: upgraded from 2.6.23+git to 2.6.24-rc1
Updated patches: - hx2750_base - pxa27x_overlay - squashfs3 (does not build anyway) Disabled patches: - input_power (does not like LONG() function) - tsc2101 (breaks Kconfig - something with MACH_HX2750) - squashfs3 Builds for c7x0 but is too big. git-svn-id: https://svn.o-hand.com/repos/poky/trunk@2951 311d38ba-8fff-0310-9ca6-ca027cbcb966
Diffstat (limited to 'meta/packages/linux')
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/arm_pxa_20070923.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/arm_pxa_20070923.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/binutils-buildid-arm.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/binutils-buildid-arm.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/connectplus-remove-ide-HACK.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/connectplus-remove-ide-HACK.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-akita (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-akita)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-bootcdx86 (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-bootcdx86)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-c7x0 (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-c7x0)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-collie (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-collie)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-htcuniversal (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-htcuniversal)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-hx2000 (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-hx2000)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-poodle (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-poodle)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemuarm (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemuarm)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemux86 (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemux86)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-spitz (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-spitz)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-tosa (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-tosa)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-zylonite (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-zylonite)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hostap-monitor-mode.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/hostap-monitor-mode.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni-acx.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni-acx.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hx2750_base-r31.patch1094
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/mmcsd_no_scr_check-r2.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/mmcsd_no_scr_check-r2.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pda-power.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pda-power.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa-serial-hack.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa-serial-hack.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa27x_overlay-r8.patch2427
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa_fb_overlay.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa_fb_overlay.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.0-2.6.15.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/squashfs3.0-2.6.15.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.2-2.6.20-r0.patch4376
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/uvesafb-0.1-rc3-2.6.22.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/uvesafb-0.1-rc3-2.6.22.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/vt_ioctl_race.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/vt_ioctl_race.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/w100fb-unused-var.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/w100fb-unused-var.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/wm97xx-lcdnoise-r0.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/wm97xx-lcdnoise-r0.patch)0
-rw-r--r--meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/zylonite-boot.patch (renamed from meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/zylonite-boot.patch)0
-rw-r--r--meta/packages/linux/linux-rp_2.6.23+2.6.24-rc1.bb (renamed from meta/packages/linux/linux-rp_2.6.23+2.6.24-rc0+git.bb)18
33 files changed, 7904 insertions, 11 deletions
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/arm_pxa_20070923.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/arm_pxa_20070923.patch
index ad4ce996df..ad4ce996df 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/arm_pxa_20070923.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/arm_pxa_20070923.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/binutils-buildid-arm.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/binutils-buildid-arm.patch
index 68e35e89e1..68e35e89e1 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/binutils-buildid-arm.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/binutils-buildid-arm.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/connectplus-remove-ide-HACK.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/connectplus-remove-ide-HACK.patch
index 4414b21191..4414b21191 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/connectplus-remove-ide-HACK.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/connectplus-remove-ide-HACK.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-akita b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-akita
index 59ec5c95b7..59ec5c95b7 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-akita
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-akita
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-bootcdx86 b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-bootcdx86
index 833f72ac9e..833f72ac9e 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-bootcdx86
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-bootcdx86
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-c7x0 b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-c7x0
index bd11500398..bd11500398 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-c7x0
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-c7x0
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-collie b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-collie
index 49d9596b92..49d9596b92 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-collie
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-collie
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-htcuniversal b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-htcuniversal
index 2b02621499..2b02621499 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-htcuniversal
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-htcuniversal
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-hx2000 b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-hx2000
index ee05db4e5a..ee05db4e5a 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-hx2000
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-hx2000
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-poodle b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-poodle
index 387b5e9bff..387b5e9bff 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-poodle
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-poodle
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemuarm b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemuarm
index 35cf3f5b17..35cf3f5b17 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemuarm
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemuarm
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemux86 b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemux86
index e9eb83e2dd..e9eb83e2dd 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-qemux86
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-qemux86
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-spitz b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-spitz
index 8e044e6a14..8e044e6a14 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-spitz
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-spitz
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-tosa b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-tosa
index 74fc076608..74fc076608 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-tosa
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-tosa
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-zylonite b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-zylonite
index 0321704a1f..0321704a1f 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/defconfig-zylonite
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/defconfig-zylonite
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/hostap-monitor-mode.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hostap-monitor-mode.patch
index 641fd19e50..641fd19e50 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/hostap-monitor-mode.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hostap-monitor-mode.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni-acx.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni-acx.patch
index 769674c935..769674c935 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni-acx.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni-acx.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni.patch
index 4d746749c5..4d746749c5 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/htcuni.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/htcuni.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hx2750_base-r31.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hx2750_base-r31.patch
new file mode 100644
index 0000000000..5d58bcf55d
--- /dev/null
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/hx2750_base-r31.patch
@@ -0,0 +1,1094 @@
1---
2 arch/arm/mach-pxa/Kconfig | 10
3 arch/arm/mach-pxa/Makefile | 1
4 arch/arm/mach-pxa/hx2750.c | 450 ++++++++++++++++++++++++++++++++++++++
5 arch/arm/mach-pxa/hx2750_test.c | 433 ++++++++++++++++++++++++++++++++++++
6 arch/arm/mach-pxa/pm.c | 5
7 arch/arm/mach-pxa/pxa25x.c | 4
8 arch/arm/mach-pxa/pxa27x.c | 4
9 include/asm-arm/arch-pxa/hx2750.h | 90 +++++++
10 8 files changed, 995 insertions(+), 2 deletions(-)
11
12--- /dev/null
13+++ linux-2.6.24-rc1/include/asm-arm/arch-pxa/hx2750.h
14@@ -0,0 +1,90 @@
15+/*
16+ * Hardware specific definitions for iPAQ hx2750
17+ *
18+ * Copyright 2005 Openedhand Ltd.
19+ *
20+ * Author: Richard Purdie <richard@o-hand.com>
21+ *
22+ * This program is free software; you can redistribute it and/or modify
23+ * it under the terms of the GNU General Public License version 2 as
24+ * published by the Free Software Foundation.
25+ *
26+ */
27+#ifndef __ASM_ARCH_HX2750_H
28+#define __ASM_ARCH_HX2750_H 1
29+
30+/*
31+ * HX2750 (Non Standard) GPIO Definitions
32+ */
33+
34+#define HX2750_GPIO_KEYPWR (0) /* Power button */
35+#define HX2750_GPIO_BATTCOVER1 (9) /* Battery Cover Switch */
36+#define HX2750_GPIO_CF_IRQ (11) /* CF IRQ? */
37+#define HX2750_GPIO_USBCONNECT (12) /* USB Connected? */
38+#define HX2750_GPIO_CF_DETECT (13) /* CF Card Detect? */
39+#define HX2750_GPIO_EXTPWR (14) /* External Power Detect */
40+#define HX2750_GPIO_BATLVL (15) /* Battery Level Detect */
41+#define HX2750_GPIO_CF_PWR (17) /* CF Power? */
42+#define HX2750_GPIO_SR_STROBE (18) /* Shift Register Strobe */
43+#define HX2750_GPIO_CHARGE (22) /* Charging Enable (active low) */
44+#define HX2750_GPIO_TSC2101_SS (24) /* TSC2101 SS# */
45+#define HX2750_GPIO_BTPWR (27) /* Bluetooth Power? */
46+#define HX2750_GPIO_BATTCOVER2 (33) /* Battery Cover Switch */
47+#define HX2750_GPIO_SD_DETECT (38) /* MMC Card Detect */
48+#define HX2750_GPIO_SR_CLK1 (52) /* Shift Register Clock */
49+#define HX2750_GPIO_SR_CLK2 (53)
50+#define HX2750_GPIO_CF_WIFIIRQ (54) /* CF Wifi IRQ? */
51+#define HX2750_GPIO_GPIO_DIN (88) /* Shift Register Data */
52+#define HX2750_GPIO_KEYLEFT (90) /* Left button */
53+#define HX2750_GPIO_KEYRIGHT (91) /* Right button */
54+#define HX2750_GPIO_KEYCAL (93) /* Calander button */
55+#define HX2750_GPIO_KEYTASK (94) /* Task button */
56+#define HX2750_GPIO_KEYSIDE (95) /* Side button */
57+#define HX2750_GPIO_KEYENTER (96) /* Enter Button*/
58+#define HX2750_GPIO_KEYCON (97) /* Contacts button */
59+#define HX2750_GPIO_KEYMAIL (98) /* Mail button */
60+#define HX2750_GPIO_BIOPWR (99) /* BIO Reader Power? */
61+#define HX2750_GPIO_KEYUP (100) /* Up button */
62+#define HX2750_GPIO_KEYDOWN (101) /* Down button*/
63+#define HX2750_GPIO_SD_READONLY (103) /* MMC/SD Write Protection */
64+#define HX2750_GPIO_LEDMAIL (106) /* Green Mail LED */
65+#define HX2750_GPIO_HP_JACK (108) /* Head Phone Jack Present */
66+#define HX2750_GPIO_PENDOWN (117) /* Touch Screen Pendown */
67+
68+
69+//#define HX2750_GPIO_ () /* */
70+
71+/*
72+ * HX2750 Interrupts
73+ */
74+#define HX2750_IRQ_GPIO_EXTPWR IRQ_GPIO(HX2750_GPIO_EXTPWR)
75+#define HX2750_IRQ_GPIO_SD_DETECT IRQ_GPIO(HX2750_GPIO_SD_DETECT)
76+#define HX2750_IRQ_GPIO_PENDOWN IRQ_GPIO(HX2750_GPIO_PENDOWN)
77+#define HX2750_IRQ_GPIO_CF_DETECT IRQ_GPIO(HX2750_GPIO_CF_DETECT)
78+#define HX2750_IRQ_GPIO_CF_IRQ IRQ_GPIO(HX2750_GPIO_CF_IRQ)
79+#define HX2750_IRQ_GPIO_CF_WIFIIRQ IRQ_GPIO(HX2750_GPIO_CF_WIFIIRQ)
80+
81+/*
82+ * HX2750 Extra GPIO Definitions
83+ */
84+
85+#define HX2750_EGPIO_WIFI_PWR (1 << 11) /* Wifi power */
86+#define HX2750_EGPIO_LCD_PWR (1 << 10) /* LCD Power */
87+#define HX2750_EGPIO_BL_PWR (1 << 9) /* Backlight LED Power */
88+#define HX2750_EGPIO_8 (1 << 8) /* */
89+#define HX2750_EGPIO_7 (1 << 7) /* */
90+#define HX2750_EGPIO_SD_PWR (1 << 6) /* SD Power */
91+#define HX2750_EGPIO_TSC_PWR (1 << 5) /* TS Power */
92+#define HX2750_EGPIO_CF0_RESET (1 << 4) /* CF0 Reset */
93+#define HX2750_EGPIO_CF1_RESET (1 << 3) /* CF1 Reset */
94+#define HX2750_EGPIO_2 (1 << 2) /* Power/Red LED Related?*/
95+#define HX2750_EGPIO_1 (1 << 1) /* Power/Red LED Related?*/
96+#define HX2750_EGPIO_PWRLED (1 << 0) /* Power/Red LED Related?*/
97+
98+
99+void hx2750_set_egpio(unsigned int gpio);
100+void hx2750_clear_egpio(unsigned int gpio);
101+
102+
103+#endif /* __ASM_ARCH_HX2750_H */
104+
105--- linux-2.6.24-rc1.orig/arch/arm/mach-pxa/Makefile
106+++ linux-2.6.24-rc1/arch/arm/mach-pxa/Makefile
107@@ -22,6 +22,7 @@
108 obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o
109 obj-$(CONFIG_MACH_TOSA) += tosa.o
110 obj-$(CONFIG_MACH_EM_X270) += em-x270.o
111+obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o
112
113 ifeq ($(CONFIG_MACH_ZYLONITE),y)
114 obj-y += zylonite.o
115--- /dev/null
116+++ linux-2.6.24-rc1/arch/arm/mach-pxa/hx2750_test.c
117@@ -0,0 +1,433 @@
118+/*
119+ * HP iPAQ hx2750 Test Development Code
120+ *
121+ * Copyright 2005 Openedhand Ltd.
122+ *
123+ * Author: Richard Purdie <richard@o-hand.com>
124+ *
125+ * This program is free software; you can redistribute it and/or modify
126+ * it under the terms of the GNU General Public License version 2 as
127+ * published by the Free Software Foundation.
128+ *
129+ */
130+
131+#include <linux/init.h>
132+#include <linux/kernel.h>
133+#include <linux/ioport.h>
134+#include <linux/device.h>
135+#include <linux/input.h>
136+#include <linux/delay.h>
137+#include <linux/interrupt.h>
138+
139+#include <asm/mach-types.h>
140+#include <asm/hardware.h>
141+#include <asm/mach/arch.h>
142+
143+#include <asm/arch/hx2750.h>
144+#include <asm/arch/pxa-regs.h>
145+
146+
147+static int prodval;
148+
149+/*
150+ * Sysfs functions
151+ */
152+static ssize_t test1_show(struct device *dev, char *buf)
153+{
154+ unsigned long rp;
155+
156+ asm ("mrc p15, 0, %0, cr1, cr0;\n" :"=r"(rp) );
157+ printk("%lx\n",rp);
158+
159+ asm ("mrc p15, 0, %0, cr1, cr1;\n" :"=r"(rp) );
160+ printk("%lx\n",rp);
161+
162+ asm ("mrc p15, 0, %0, cr2, cr0;\n" :"=r"(rp) );
163+ printk("%lx\n",rp);
164+
165+ asm ("mrc p15, 0, %0, cr3, cr0;\n" :"=r"(rp) );
166+ printk("%lx\n",rp);
167+
168+ asm ("mrc p15, 0, %0, cr13, cr0;\n" :"=r"(rp) );
169+ printk("%lx\n",rp);
170+
171+ return sprintf(buf, "%d\n",prodval);
172+}
173+extern void tsc2101_print_miscdata(struct device *dev);
174+extern struct platform_device tsc2101_device;
175+
176+static ssize_t test1_store(struct device *dev, const char *buf, size_t count)
177+{
178+ prodval = simple_strtoul(buf, NULL, 10);
179+
180+ tsc2101_print_miscdata(&tsc2101_device.dev);
181+
182+ return count;
183+}
184+
185+static DEVICE_ATTR(test1, 0644, test1_show, test1_store);
186+
187+static ssize_t test2_show(struct device *dev, char *buf)
188+{
189+ printk(KERN_ERR "SSCR0_P2: %08x\n", SSCR0_P2);
190+ printk(KERN_ERR "SSCR1_P2: %08x\n", SSCR1_P2);
191+ printk(KERN_ERR "SSSR_P2: %08x\n", SSSR_P2);
192+ printk(KERN_ERR "SSITR_P2: %08x\n", SSITR_P2);
193+ printk(KERN_ERR "SSDR_P2: %08x\n", SSDR_P2);
194+ printk(KERN_ERR "SSTO_P2: %08x\n", SSTO_P2);
195+ printk(KERN_ERR "SSPSP_P2: %08x\n", SSPSP_P2);
196+
197+ hx2750_ssp_init2();
198+
199+ printk(KERN_ERR "SSCR0_P2: %08x\n", SSCR0_P2);
200+ printk(KERN_ERR "SSCR1_P2: %08x\n", SSCR1_P2);
201+ printk(KERN_ERR "SSSR_P2: %08x\n", SSSR_P2);
202+ printk(KERN_ERR "SSITR_P2: %08x\n", SSITR_P2);
203+ printk(KERN_ERR "SSDR_P2: %08x\n", SSDR_P2);
204+ printk(KERN_ERR "SSTO_P2: %08x\n", SSTO_P2);
205+ printk(KERN_ERR "SSPSP_P2: %08x\n", SSPSP_P2);
206+
207+ return sprintf(buf, "%d\n",0);
208+}
209+
210+static DEVICE_ATTR(test2, 0444, test2_show, NULL);
211+
212+extern unsigned int hx2750_egpio_current;
213+
214+static ssize_t setegpio_show(struct device *dev, char *buf)
215+{
216+ return sprintf(buf, "%x\n",hx2750_egpio_current);
217+}
218+
219+static ssize_t setegpio_store(struct device *dev, const char *buf, size_t count)
220+{
221+ unsigned int val = simple_strtoul(buf, NULL, 10);
222+
223+ hx2750_set_egpio(1 << val);
224+
225+ return count;
226+}
227+
228+static DEVICE_ATTR(setegpio, 0644, setegpio_show, setegpio_store);
229+
230+static ssize_t clregpio_show(struct device *dev, char *buf)
231+{
232+ return sprintf(buf, "%x\n",hx2750_egpio_current);
233+}
234+
235+static ssize_t gpio_show(struct device *dev, char *buf)
236+{
237+ int i;
238+
239+ printk(KERN_ERR "GPIO# D S A INTER\n");
240+
241+ for (i=0;i<119;i++) {
242+ printk(KERN_ERR " %3d: ",i);
243+ if (GPDR(i) & GPIO_bit(i))
244+ printk("O ");
245+ else
246+ printk("I ");
247+ printk("%d ",(GPLR(i) & GPIO_bit(i)) != 0);
248+ printk("%d ",((GAFR(i) & (0x3 << (((i) & 0xf)*2)))) >> (((i) & 0xf)*2) );
249+ if (GEDR(i) & GPIO_bit(i))
250+ printk("ED ");
251+ if (GRER(i) & GPIO_bit(i))
252+ printk("RE ");
253+ if (GFER(i) & GPIO_bit(i))
254+ printk("FE ");
255+
256+ printk("\n");
257+ }
258+ return sprintf(buf, "EGPIO: %x\n",hx2750_egpio_current);
259+}
260+
261+static ssize_t clregpio_store(struct device *dev, const char *buf, size_t count)
262+{
263+ unsigned int val = simple_strtoul(buf, NULL, 10);
264+
265+ hx2750_clear_egpio(1 << val);
266+
267+ return count;
268+}
269+
270+static DEVICE_ATTR(clregpio, 0644, clregpio_show, clregpio_store);
271+
272+
273+static ssize_t gpioclr_store(struct device *dev, const char *buf, size_t count)
274+{
275+ int prod;
276+ prod = simple_strtoul(buf, NULL, 10);
277+
278+ GPCR(prod) = GPIO_bit(prod);
279+
280+ return count;
281+}
282+
283+static DEVICE_ATTR(gpioclr, 0644, gpio_show, gpioclr_store);
284+
285+static ssize_t gpioset_store(struct device *dev, const char *buf, size_t count)
286+{
287+ int prod;
288+ prod = simple_strtoul(buf, NULL, 10);
289+
290+ GPSR(prod) = GPIO_bit(prod);
291+
292+ return count;
293+}
294+
295+static DEVICE_ATTR(gpioset, 0644, gpio_show, gpioset_store);
296+
297+
298+static ssize_t ssp2read_store(struct device *dev, const char *buf, size_t count)
299+{
300+ unsigned int val = simple_strtoul(buf, NULL, 16);
301+
302+ printk("Read: %08x\n",hx2750_ssp2_read(val));
303+
304+ return count;
305+}
306+
307+static DEVICE_ATTR(ssp2read, 0200, NULL, ssp2read_store);
308+
309+static ssize_t ssp2write_store(struct device *dev, const char *buf, size_t count)
310+{
311+ unsigned int val = simple_strtoul(buf, NULL, 16);
312+
313+ printk("Write: %08x\n",hx2750_ssp2_write(val));
314+
315+ return count;
316+}
317+
318+static DEVICE_ATTR(ssp2write, 0200, NULL, ssp2write_store);
319+
320+
321+static ssize_t sspr_store(struct device *dev, const char *buf, size_t count)
322+{
323+ unsigned long val,ret;
324+ val = simple_strtoul(buf, NULL, 0);
325+
326+ hx2750_tsc2101_send(1<<15,val,&ret,1);
327+
328+ printk("Response: %x\n",ret);
329+
330+ return count;
331+}
332+
333+static DEVICE_ATTR(sspr, 0200, NULL, sspr_store);
334+
335+static ssize_t sspw_store(struct device *dev, const char *buf, size_t count)
336+{
337+ int val,ret;
338+ sscanf(buf, "%lx %lx", &val, &ret);
339+
340+ hx2750_tsc2101_send(0,val,&ret,1);
341+
342+ return count;
343+}
344+
345+static DEVICE_ATTR(sspw, 0200, NULL, sspw_store);
346+
347+
348+extern struct pm_ops pxa_pm_ops;
349+extern void pxa_cpu_resume(void);
350+extern unsigned long pxa_pm_pspr_value;
351+
352+static int (*pxa_pm_enter_orig)(suspend_state_t state);
353+
354+//static struct {
355+// u32 ffier, fflcr, ffmcr, ffspr, ffisr, ffdll, ffdlh;
356+//} sys_ctx;
357+
358+u32 resstruct[20];
359+
360+static int hx2750_pxa_pm_enter(suspend_state_t state)
361+{
362+ int i;
363+ u32 save[10];
364+
365+ PWER = 0xC0000003;// | PWER_RTC;
366+ PFER = 0x00000003;
367+ PRER = 0x00000003;
368+
369+ PGSR0=0x00000018;
370+ PGSR1=0x00000380;
371+ PGSR2=0x00800000;
372+ PGSR3=0x00500400;
373+
374+ //PVCR=0x494; or 0x14;
375+ //PVCR=0x14;
376+ //PCMD0=0x41f;
377+ //i=PISR;
378+ //PICR=0x00000062;
379+
380+ //PCFR=0x457;
381+ //PCFR=0x70; // Does not resume from sleep
382+ PCFR=0x077; // was 0x477
383+ PSLR=0xff100004;
384+
385+ resstruct[0]=0x0000b4e6;
386+ resstruct[1]=0x00000001;
387+ resstruct[2]=virt_to_phys(pxa_cpu_resume);
388+ resstruct[3]=0xffffffff; //value for r0
389+
390+ resstruct[14]=0x00000078; //mcr 15, 0, r0, cr1, cr0, {0}
391+ resstruct[15]=0x00000000; //mcr 15, 0, r0, cr1, cr1, {0} 0xffffffff
392+ resstruct[16]=0xa0000000; //mcr 15, 0, r0, cr2, cr0, {0} 0xa0748000
393+ resstruct[17]=0x00000001; //mcr 15, 0, r0, cr3, cr0, {0} 0x00000015
394+ resstruct[18]=0x00000000; //mcr 15, 0, r0, cr13, cr0, {0} 0x00000000
395+
396+ pxa_pm_pspr_value=virt_to_phys(&resstruct[0]);
397+
398+ hx2750_send_egpio(3);
399+
400+ pxa_gpio_mode(87 | GPIO_OUT | GPIO_DFLT_HIGH);
401+
402+ //sys_ctx.ffier = FFIER;
403+ //sys_ctx.fflcr = FFLCR;
404+ //sys_ctx.ffmcr = FFMCR;
405+ //sys_ctx.ffspr = FFSPR;
406+ //sys_ctx.ffisr = FFISR;
407+ //FFLCR |= 0x80;
408+ //sys_ctx.ffdll = FFDLL;
409+ //sys_ctx.ffdlh = FFDLH;
410+ //FFLCR &= 0xef;
411+
412+ pxa_pm_enter_orig(state);
413+
414+ //FFMCR = sys_ctx.ffmcr;
415+ //FFSPR = sys_ctx.ffspr;
416+ //FFLCR = sys_ctx.fflcr;
417+ //FFLCR |= 0x80;
418+ //FFDLH = sys_ctx.ffdlh;
419+ //FFDLL = sys_ctx.ffdll;
420+ //FFLCR = sys_ctx.fflcr;
421+ //FFISR = sys_ctx.ffisr;
422+ //FFLCR = 0x07;
423+ //FFIER = sys_ctx.ffier;
424+
425+ return 0;
426+}
427+
428+static irqreturn_t hx2750_charge_int(int irq, void *dev_id, struct pt_regs *regs)
429+{
430+ if ((GPLR(HX2750_GPIO_EXTPWR) & GPIO_bit(HX2750_GPIO_EXTPWR)) == 0) {
431+ printk("Charging On\n");
432+ GPCR(HX2750_GPIO_CHARGE);
433+ } else {
434+ printk("Charging Off\n");
435+ GPSR(HX2750_GPIO_CHARGE);
436+ }
437+
438+ return IRQ_HANDLED;
439+}
440+
441+
442+
443+
444+static irqreturn_t hx2750_interrupt(int irq, void *dev_id, struct pt_regs *regs)
445+{
446+ printk("Input %d changed.\n", irq-32);
447+
448+ return IRQ_HANDLED;
449+}
450+
451+
452+static int __init hx2750_test_probe(struct device *dev)
453+{
454+ pxa_gpio_mode(21 | GPIO_OUT | GPIO_DFLT_HIGH);
455+ pxa_gpio_mode(HX2750_GPIO_CHARGE | GPIO_OUT | GPIO_DFLT_HIGH);
456+ pxa_gpio_mode(83 | GPIO_OUT | GPIO_DFLT_HIGH);
457+ pxa_gpio_mode(HX2750_GPIO_BIOPWR | GPIO_OUT | GPIO_DFLT_HIGH);
458+ pxa_gpio_mode(116 | GPIO_OUT | GPIO_DFLT_HIGH);
459+ pxa_gpio_mode(118 | GPIO_OUT | GPIO_DFLT_HIGH);
460+
461+
462+ //pxa_gpio_mode(HX2750_GPIO_CF_PWR | GPIO_OUT | GPIO_DFLT_LOW);
463+ pxa_gpio_mode(HX2750_GPIO_CF_PWR | GPIO_OUT | GPIO_DFLT_HIGH);
464+ pxa_gpio_mode(HX2750_GPIO_BTPWR | GPIO_OUT | GPIO_DFLT_LOW);
465+ pxa_gpio_mode(79 | GPIO_OUT | GPIO_DFLT_LOW);
466+ pxa_gpio_mode(85 | GPIO_OUT | GPIO_DFLT_LOW);
467+ pxa_gpio_mode(HX2750_GPIO_LEDMAIL | GPIO_OUT | GPIO_DFLT_LOW);
468+ pxa_gpio_mode(107 | GPIO_OUT | GPIO_DFLT_LOW);
469+ pxa_gpio_mode(114 | GPIO_OUT | GPIO_DFLT_LOW);
470+
471+ pxa_gpio_mode(HX2750_GPIO_BATTCOVER1 | GPIO_IN);
472+ pxa_gpio_mode(HX2750_GPIO_BATTCOVER2 | GPIO_IN);
473+ pxa_gpio_mode(HX2750_GPIO_CF_IRQ | GPIO_IN);
474+ pxa_gpio_mode(HX2750_GPIO_USBCONNECT | GPIO_IN);
475+ pxa_gpio_mode(HX2750_GPIO_CF_DETECT | GPIO_IN);
476+ pxa_gpio_mode(HX2750_GPIO_EXTPWR | GPIO_IN);
477+
478+ pxa_gpio_mode(HX2750_GPIO_BATLVL | GPIO_IN);
479+ //pxa_gpio_mode(HX2750_GPIO_CF_WIFIIRQ | GPIO_IN);
480+ pxa_gpio_mode(80 | GPIO_IN);
481+ pxa_gpio_mode(HX2750_GPIO_HP_JACK | GPIO_IN);
482+ pxa_gpio_mode(115 | GPIO_IN);
483+ pxa_gpio_mode(119 | GPIO_IN);
484+
485+ request_irq(IRQ_GPIO(HX2750_GPIO_BATLVL), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
486+ //request_irq(IRQ_GPIO(HX2750_GPIO_CF_WIFIIRQ), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
487+ request_irq(IRQ_GPIO(80), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
488+ request_irq(IRQ_GPIO(115), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
489+ request_irq(IRQ_GPIO(119), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
490+ request_irq(IRQ_GPIO(HX2750_GPIO_SR_CLK2), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
491+
492+ //request_irq(IRQ_GPIO(10), hx2750_interrupt, SA_INTERRUPT, "hx2750test", NULL);
493+
494+ set_irq_type(IRQ_GPIO(HX2750_GPIO_BATLVL),IRQT_BOTHEDGE);
495+ //set_irq_type(IRQ_GPIO(HX2750_GPIO_CF_WIFIIRQ),IRQT_BOTHEDGE);
496+ set_irq_type(IRQ_GPIO(80),IRQT_BOTHEDGE);
497+ set_irq_type(IRQ_GPIO(115),IRQT_BOTHEDGE);
498+ set_irq_type(IRQ_GPIO(119),IRQT_BOTHEDGE);
499+ set_irq_type(IRQ_GPIO(HX2750_GPIO_SR_CLK2),IRQT_BOTHEDGE);
500+
501+ //set_irq_type(IRQ_GPIO(10),IRQT_BOTHEDGE);
502+
503+ printk("hx2750 Test Code Initialized.\n");
504+ device_create_file(dev, &dev_attr_test1);
505+ device_create_file(dev, &dev_attr_test2);
506+ device_create_file(dev, &dev_attr_setegpio);
507+ device_create_file(dev, &dev_attr_clregpio);
508+ device_create_file(dev, &dev_attr_gpioset);
509+ device_create_file(dev, &dev_attr_gpioclr);
510+ device_create_file(dev, &dev_attr_sspr);
511+ device_create_file(dev, &dev_attr_sspw);
512+ device_create_file(dev, &dev_attr_ssp2read);
513+ device_create_file(dev, &dev_attr_ssp2write);
514+
515+ request_irq(HX2750_IRQ_GPIO_EXTPWR, hx2750_charge_int, SA_INTERRUPT, "hx2750_extpwr", NULL);
516+ set_irq_type(HX2750_IRQ_GPIO_EXTPWR, IRQT_BOTHEDGE);
517+
518+ pxa_pm_enter_orig=pxa_pm_ops.enter;
519+ pxa_pm_ops.enter=hx2750_pxa_pm_enter;
520+
521+ return 0;
522+}
523+
524+static struct device_driver hx2750_test_driver = {
525+ .name = "hx2750-test",
526+ .bus = &platform_bus_type,
527+ .probe = hx2750_test_probe,
528+// .remove = hx2750_bl_remove,
529+// .suspend = hx2750_bl_suspend,
530+// .resume = hx2750_bl_resume,
531+};
532+
533+
534+static int __init hx2750_test_init(void)
535+{
536+ return driver_register(&hx2750_test_driver);
537+}
538+
539+
540+static void __exit hx2750_test_exit(void)
541+{
542+ driver_unregister(&hx2750_test_driver);
543+}
544+
545+module_init(hx2750_test_init);
546+module_exit(hx2750_test_exit);
547+
548+MODULE_AUTHOR("Richard Purdie <richard@o-hand.com>");
549+MODULE_DESCRIPTION("iPAQ hx2750 Backlight Driver");
550+MODULE_LICENSE("GPLv2");
551--- linux-2.6.24-rc1.orig/arch/arm/mach-pxa/Kconfig
552+++ linux-2.6.24-rc1/arch/arm/mach-pxa/Kconfig
553@@ -83,6 +83,15 @@
554 bool "Sharp PXA270 models (SL-Cxx00)"
555 select PXA27x
556
557+config MACH_HX2750
558+ bool "HP iPAQ hx2750"
559+ select PXA27x
560+ select PXA_KEYS
561+ select MFD_TSC2101
562+ select PXA_SSP
563+ help
564+ This enables support for the HP iPAQ HX2750 handheld.
565+
566 endchoice
567
568 endif
569@@ -181,3 +190,4 @@
570 help
571 Enable support for PXA2xx SSP ports
572 endif
573+
574--- /dev/null
575+++ linux-2.6.24-rc1/arch/arm/mach-pxa/hx2750.c
576@@ -0,0 +1,450 @@
577+/*
578+ * Machine definitions for HP iPAQ hx2750
579+ *
580+ * Copyright 2005 Openedhand Ltd.
581+ *
582+ * Author: Richard Purdie <richard@o-hand.com>
583+ *
584+ * This program is free software; you can redistribute it and/or modify
585+ * it under the terms of the GNU General Public License version 2 as
586+ * published by the Free Software Foundation.
587+ *
588+ */
589+
590+
591+#include <linux/init.h>
592+#include <linux/kernel.h>
593+#include <linux/ioport.h>
594+#include <linux/platform_device.h>
595+#include <linux/delay.h>
596+#include <linux/input.h>
597+#include <linux/irq.h>
598+#include <linux/mmc/host.h>
599+#include <linux/mfd/tsc2101.h>
600+
601+#include <asm/mach-types.h>
602+#include <asm/hardware.h>
603+#include <asm/mach/arch.h>
604+
605+#include <asm/arch/hx2750.h>
606+#include <asm/arch/pxa-regs.h>
607+#include <asm/arch/pxa_keys.h>
608+#include <asm/mach/map.h>
609+#include <asm/arch/udc.h>
610+#include <asm/arch/mmc.h>
611+#include <asm/arch/audio.h>
612+#include <asm/arch/pxafb.h>
613+#include <asm/arch/ssp.h>
614+
615+#include "generic.h"
616+
617+
618+/*
619+ * Keys Support
620+ */
621+static struct pxa_keys_button hx2750_button_table[] = {
622+ { KEY_POWER, HX2750_GPIO_KEYPWR, PXAKEY_PWR_KEY },
623+ { KEY_LEFT, HX2750_GPIO_KEYLEFT, 0 },
624+ { KEY_RIGHT, HX2750_GPIO_KEYRIGHT, 0 },
625+ { KEY_KP0, HX2750_GPIO_KEYCAL, 0 },
626+ { KEY_KP1, HX2750_GPIO_KEYTASK, 0 },
627+ { KEY_KP2, HX2750_GPIO_KEYSIDE, 0 },
628+ { KEY_ENTER, HX2750_GPIO_KEYENTER, 0 },
629+ { KEY_KP3, HX2750_GPIO_KEYCON, 0 }, //KEY_CONTACTS
630+ { KEY_MAIL, HX2750_GPIO_KEYMAIL, 0 },
631+ { KEY_UP, HX2750_GPIO_KEYUP, 0 },
632+ { KEY_DOWN, HX2750_GPIO_KEYDOWN, 0 },
633+};
634+
635+static struct pxa_keys_platform_data hx2750_pxa_keys_data = {
636+ .buttons = hx2750_button_table,
637+ .nbuttons = ARRAY_SIZE(hx2750_button_table),
638+};
639+
640+static struct platform_device hx2750_pxa_keys = {
641+ .name = "pxa2xx-keys",
642+ .dev = {
643+ .platform_data = &hx2750_pxa_keys_data,
644+ },
645+};
646+
647+
648+/*
649+ * Backlight Device
650+ */
651+extern struct platform_device pxafb_device;
652+
653+static struct platform_device hx2750_bl_device = {
654+ .name = "hx2750-bl",
655+ .id = -1,
656+// .dev = {
657+// .parent = &pxafb_device.dev,
658+// }
659+};
660+
661+
662+/*
663+ * UDC/USB
664+ */
665+static int hx2750_udc_is_connected (void)
666+{
667+ return GPLR0 & GPIO_bit(HX2750_GPIO_USBCONNECT);
668+}
669+
670+//static void hx2750_udc_command (int cmd)
671+//{
672+//}
673+
674+static struct pxa2xx_udc_mach_info hx2750_udc_mach_info = {
675+ .udc_is_connected = hx2750_udc_is_connected,
676+// .udc_command = hx2750_udc_command,
677+};
678+
679+
680+/*
681+ * SSP Devices Setup
682+ */
683+static struct ssp_dev hx2750_ssp_dev1;
684+static struct ssp_dev hx2750_ssp_dev2;
685+static struct ssp_dev hx2750_ssp_dev3;
686+
687+void hx2750_ssp_init(void)
688+{
689+ pxa_gpio_mode(HX2750_GPIO_TSC2101_SS | GPIO_OUT | GPIO_DFLT_HIGH);
690+
691+ if (ssp_init(&hx2750_ssp_dev1, 1, 0))
692+ printk(KERN_ERR "Unable to register SSP1 handler!\n");
693+ else {
694+ ssp_disable(&hx2750_ssp_dev1);
695+ ssp_config(&hx2750_ssp_dev1, (SSCR0_Motorola | (SSCR0_DSS & 0x0f )), SSCR1_SPH, 0, SSCR0_SerClkDiv(6));
696+ ssp_enable(&hx2750_ssp_dev1);
697+ hx2750_set_egpio(HX2750_EGPIO_TSC_PWR);
698+ }
699+
700+// if (ssp_init(&hx2750_ssp_dev2, 2, 0))
701+// printk(KERN_ERR "Unable to register SSP2 handler!\n");
702+// else {
703+// ssp_disable(&hx2750_ssp_dev2);
704+// ssp_config(&hx2750_ssp_dev2, (SSCR0_TI | (SSCR0_DSS & 0x09 )), 0, 0, SSCR0_SerClkDiv(140));
705+// ssp_enable(&hx2750_ssp_dev2);
706+// }
707+//
708+ if (ssp_init(&hx2750_ssp_dev3, 3, 0))
709+ printk(KERN_ERR "Unable to register SSP3 handler!\n");
710+ else {
711+ ssp_disable(&hx2750_ssp_dev3);
712+ ssp_config(&hx2750_ssp_dev3, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), SSCR1_SPO | SSCR1_SPH, 0, SSCR0_SerClkDiv(166));
713+ ssp_enable(&hx2750_ssp_dev3);
714+ }
715+
716+ printk("SSP Devices Initialised\n");
717+
718+ return;
719+}
720+
721+struct ssp_state ssp1;
722+
723+void hx2750_ssp_suspend(void)
724+{
725+ ssp_disable(&hx2750_ssp_dev1);
726+ ssp_save_state(&hx2750_ssp_dev1,&ssp1);
727+ hx2750_clear_egpio(HX2750_EGPIO_TSC_PWR);
728+}
729+
730+void hx2750_ssp_resume(void)
731+{
732+ hx2750_set_egpio(HX2750_EGPIO_TSC_PWR);
733+ ssp_restore_state(&hx2750_ssp_dev1,&ssp1);
734+ ssp_enable(&hx2750_ssp_dev1);
735+}
736+
737+void hx2750_ssp_init2(void)
738+{
739+ printk("Stage 1: %x\n",CKEN);
740+ if (ssp_init(&hx2750_ssp_dev2, 2, 0))
741+ printk(KERN_ERR "Unable to register SSP2 handler!\n");
742+ else {
743+ printk("Stage 2: %x\n",CKEN);
744+ ssp_disable(&hx2750_ssp_dev2);
745+ printk("Stage 3: %x\n",CKEN);
746+ ssp_config(&hx2750_ssp_dev2, (SSCR0_TI | (SSCR0_DSS & 0x09 )) | SSCR0_SSE, 0, 0, SSCR0_SerClkDiv(212));
747+ printk("Stage 4: %x\n",CKEN);
748+ ssp_enable(&hx2750_ssp_dev2);
749+ printk("Stage 5: %x\n",CKEN);
750+ }
751+ printk("SSP Device2 Initialised\n");
752+
753+ printk("Sent: 0x3ff\n");
754+ ssp_write_word(&hx2750_ssp_dev2,0x3ff);
755+
756+ return;
757+}
758+
759+void hx2750_ssp2_reset(void)
760+{
761+ ssp_write_word(&hx2750_ssp_dev2,0x000);
762+ ssp_write_word(&hx2750_ssp_dev2,0x000);
763+
764+}
765+
766+unsigned long hx2750_ssp2_read(void)
767+{
768+ u32 ret = 0;
769+ ssp_read_word(&hx2750_ssp_dev2, &ret);
770+ return ret;
771+}
772+
773+void hx2750_ssp2_write(unsigned long data)
774+{
775+ ssp_write_word(&hx2750_ssp_dev2, data);
776+}
777+
778+
779+/*
780+ * Extra hx2750 Specific GPIOs
781+ */
782+void hx2750_send_egpio(unsigned int val)
783+{
784+ int i;
785+
786+ GPCR0 = GPIO_bit(HX2750_GPIO_SR_STROBE);
787+ GPCR1 = GPIO_bit(HX2750_GPIO_SR_CLK1);
788+
789+ for (i=0;i<12;i++) {
790+ if (val & 0x01)
791+ GPSR2 = GPIO_bit(HX2750_GPIO_GPIO_DIN);
792+ else
793+ GPCR2 = GPIO_bit(HX2750_GPIO_GPIO_DIN);
794+ val >>= 1;
795+ GPSR1 = GPIO_bit(HX2750_GPIO_SR_CLK1);
796+ GPCR1 = GPIO_bit(HX2750_GPIO_SR_CLK1);
797+ }
798+
799+ GPSR0 = GPIO_bit(HX2750_GPIO_SR_STROBE);
800+ GPCR0 = GPIO_bit(HX2750_GPIO_SR_STROBE);
801+}
802+
803+EXPORT_SYMBOL(hx2750_send_egpio);
804+
805+unsigned int hx2750_egpio_current;
806+
807+void hx2750_set_egpio(unsigned int gpio)
808+{
809+ hx2750_egpio_current|=gpio;
810+
811+ hx2750_send_egpio(hx2750_egpio_current);
812+}
813+EXPORT_SYMBOL(hx2750_set_egpio);
814+
815+void hx2750_clear_egpio(unsigned int gpio)
816+{
817+ hx2750_egpio_current&=~gpio;
818+
819+ hx2750_send_egpio(hx2750_egpio_current);
820+}
821+EXPORT_SYMBOL(hx2750_clear_egpio);
822+
823+
824+/*
825+ * Touchscreen/Sound/Battery Status
826+ */
827+void hx2750_tsc2101_send(int read, int command, int *values, int numval)
828+{
829+ u32 ret = 0;
830+ int i;
831+
832+ GPCR0 = GPIO_bit(HX2750_GPIO_TSC2101_SS);
833+
834+ ssp_write_word(&hx2750_ssp_dev1, command | read);
835+ /* dummy read */
836+ ssp_read_word(&hx2750_ssp_dev1, &ret);
837+
838+ for (i=0; i < numval; i++) {
839+ if (read) {
840+ ssp_write_word(&hx2750_ssp_dev1, 0);
841+ ssp_read_word(&hx2750_ssp_dev1, &values[i]);
842+ } else {
843+ ssp_write_word(&hx2750_ssp_dev1, values[i]);
844+ ssp_read_word(&hx2750_ssp_dev1, &ret);
845+ }
846+ }
847+
848+ GPSR0 = GPIO_bit(HX2750_GPIO_TSC2101_SS);
849+}
850+
851+static int hx2750_tsc2101_pendown(void)
852+{
853+ if ((GPLR(HX2750_GPIO_PENDOWN) & GPIO_bit(HX2750_GPIO_PENDOWN)) == 0)
854+ return 1;
855+ return 0;
856+}
857+
858+static struct tsc2101_platform_info hx2750_tsc2101_info = {
859+ .send = hx2750_tsc2101_send,
860+ .suspend = hx2750_ssp_suspend,
861+ .resume = hx2750_ssp_resume,
862+ .irq = HX2750_IRQ_GPIO_PENDOWN,
863+ .pendown = hx2750_tsc2101_pendown,
864+};
865+
866+struct platform_device tsc2101_device = {
867+ .name = "tsc2101",
868+ .dev = {
869+ .platform_data = &hx2750_tsc2101_info,
870+ //.parent = &corgissp_device.dev,
871+ },
872+ .id = -1,
873+};
874+
875+
876+/*
877+ * MMC/SD Device
878+ *
879+ * The card detect interrupt isn't debounced so we delay it by 250ms
880+ * to give the card a chance to fully insert/eject.
881+ */
882+static struct pxamci_platform_data hx2750_mci_platform_data;
883+
884+static int hx2750_mci_init(struct device *dev, irq_handler_t hx2750_detect_int, void *data)
885+{
886+ int err;
887+
888+ /*
889+ * setup GPIO for PXA27x MMC controller
890+ */
891+ pxa_gpio_mode(GPIO32_MMCCLK_MD);
892+ pxa_gpio_mode(GPIO112_MMCCMD_MD);
893+ pxa_gpio_mode(GPIO92_MMCDAT0_MD);
894+ pxa_gpio_mode(GPIO109_MMCDAT1_MD);
895+ pxa_gpio_mode(GPIO110_MMCDAT2_MD);
896+ pxa_gpio_mode(GPIO111_MMCDAT3_MD);
897+ pxa_gpio_mode(HX2750_GPIO_SD_DETECT | GPIO_IN);
898+ pxa_gpio_mode(HX2750_GPIO_SD_READONLY | GPIO_IN);
899+
900+ hx2750_mci_platform_data.detect_delay = msecs_to_jiffies(250);
901+
902+ err = request_irq(HX2750_IRQ_GPIO_SD_DETECT, hx2750_detect_int,
903+ IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
904+ "MMC card detect", data);
905+ if (err) {
906+ printk(KERN_ERR "hx2750_mci_init: MMC/SD: can't request MMC card detect IRQ\n");
907+ return -1;
908+ }
909+
910+ return 0;
911+}
912+
913+static void hx2750_mci_setpower(struct device *dev, unsigned int vdd)
914+{
915+ struct pxamci_platform_data* p_d = dev->platform_data;
916+
917+ if (( 1 << vdd) & p_d->ocr_mask)
918+ hx2750_set_egpio(HX2750_EGPIO_SD_PWR);
919+ else
920+ hx2750_clear_egpio(HX2750_EGPIO_SD_PWR);
921+}
922+
923+static void hx2750_mci_exit(struct device *dev, void *data)
924+{
925+ free_irq(HX2750_IRQ_GPIO_SD_DETECT, data);
926+}
927+
928+static struct pxamci_platform_data hx2750_mci_platform_data = {
929+ .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
930+ .init = hx2750_mci_init,
931+ .setpower = hx2750_mci_setpower,
932+ .exit = hx2750_mci_exit,
933+};
934+
935+
936+/*
937+ * FrameBuffer
938+ */
939+static struct pxafb_mode_info hx2750_pxafb_modes = {
940+ .pixclock = 288462,
941+ .xres = 240,
942+ .yres = 320,
943+ .bpp = 16,
944+ .hsync_len = 20,
945+ .left_margin = 42,
946+ .right_margin = 18,
947+ .vsync_len = 4,
948+ .upper_margin = 3,
949+ .lower_margin = 4,
950+ .sync = 0,
951+};
952+
953+static struct pxafb_mach_info hx2750_pxafb_info = {
954+ .modes = &hx2750_pxafb_modes,
955+ .num_modes = 1,
956+ .fixed_modes = 1,
957+ .lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
958+ .lccr3 = LCCR3_PixFlEdg | LCCR3_OutEnH,
959+ .pxafb_backlight_power = NULL,
960+};
961+
962+
963+/*
964+ * Test Device
965+ */
966+static struct platform_device hx2750_test_device = {
967+ .name = "hx2750-test",
968+ .id = -1,
969+};
970+
971+
972+/* Initialization code */
973+static struct platform_device *devices[] __initdata = {
974+ &hx2750_bl_device,
975+ &hx2750_test_device,
976+ &hx2750_pxa_keys,
977+ &tsc2101_device,
978+};
979+
980+static void __init hx2750_init( void )
981+{
982+ PWER = 0xC0000003;// | PWER_RTC;
983+ PFER = 0x00000003;
984+ PRER = 0x00000003;
985+
986+ PGSR0=0x00000018;
987+ PGSR1=0x00000380;
988+ PGSR2=0x00800000;
989+ PGSR3=0x00500400;
990+
991+ //PCFR |= PCFR_OPDE;
992+ PCFR=0x77;
993+ PSLR=0xff100000;
994+ //PCFR=0x10; - does not return from suspend
995+
996+ //PCFR= 0x00004040;
997+ //PSLR= 0xff400f04;
998+
999+ /* Setup Extra GPIO Bank access */
1000+ pxa_gpio_mode(HX2750_GPIO_GPIO_DIN | GPIO_OUT | GPIO_DFLT_HIGH);
1001+ pxa_gpio_mode(HX2750_GPIO_SR_CLK1 | GPIO_OUT | GPIO_DFLT_LOW);
1002+ pxa_gpio_mode(HX2750_GPIO_SR_CLK2 | GPIO_IN);
1003+ pxa_gpio_mode(HX2750_GPIO_SR_STROBE | GPIO_OUT | GPIO_DFLT_LOW);
1004+
1005+ /* Init Extra GPIOs - Bootloader reset default is 0x484 */
1006+ /* This is 0xe84 */
1007+ hx2750_set_egpio(HX2750_EGPIO_2 | HX2750_EGPIO_7 | HX2750_EGPIO_LCD_PWR | HX2750_EGPIO_BL_PWR | HX2750_EGPIO_WIFI_PWR);
1008+
1009+ pxa_set_udc_info(&hx2750_udc_mach_info);
1010+ pxa_set_mci_info(&hx2750_mci_platform_data);
1011+ set_pxa_fb_info(&hx2750_pxafb_info);
1012+ hx2750_ssp_init();
1013+ platform_add_devices (devices, ARRAY_SIZE (devices));
1014+}
1015+
1016+
1017+MACHINE_START(HX2750, "HP iPAQ HX2750")
1018+ .phys_io = 0x40000000,
1019+ .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
1020+ .boot_params = 0xa0000100,
1021+ .map_io = pxa_map_io,
1022+ .init_irq = pxa_init_irq,
1023+ .timer = &pxa_timer,
1024+ .init_machine = hx2750_init,
1025+MACHINE_END
1026+
1027--- linux-2.6.24-rc1.orig/arch/arm/mach-pxa/pm.c
1028+++ linux-2.6.24-rc1/arch/arm/mach-pxa/pm.c
1029@@ -17,6 +17,7 @@
1030 #include <linux/time.h>
1031
1032 #include <asm/hardware.h>
1033+#include <asm/mach-types.h>
1034 #include <asm/memory.h>
1035 #include <asm/system.h>
1036 #include <asm/arch/pm.h>
1037@@ -91,6 +92,9 @@
1038 .enter = pxa_pm_enter,
1039 };
1040
1041+unsigned long pxa_pm_pspr_value;
1042+extern void pxa_cpu_resume(void);
1043+
1044 static int __init pxa_pm_init(void)
1045 {
1046 if (!pxa_cpu_pm_fns) {
1047@@ -104,6 +108,7 @@
1048 return -ENOMEM;
1049 }
1050
1051+ pxa_pm_pspr_value=virt_to_phys(pxa_cpu_resume);
1052 suspend_set_ops(&pxa_pm_ops);
1053 return 0;
1054 }
1055--- linux-2.6.24-rc1.orig/arch/arm/mach-pxa/pxa27x.c
1056+++ linux-2.6.24-rc1/arch/arm/mach-pxa/pxa27x.c
1057@@ -259,6 +259,8 @@
1058 RESTORE(PSTR);
1059 }
1060
1061+extern unsigned long pxa_pm_pspr_value;
1062+
1063 void pxa27x_cpu_pm_enter(suspend_state_t state)
1064 {
1065 extern void pxa_cpu_standby(void);
1066@@ -281,7 +283,7 @@
1067 break;
1068 case PM_SUSPEND_MEM:
1069 /* set resume return address */
1070- PSPR = virt_to_phys(pxa_cpu_resume);
1071+ PSPR = pxa_pm_pspr_value;
1072 pxa27x_cpu_suspend(PWRMODE_SLEEP);
1073 break;
1074 }
1075--- linux-2.6.24-rc1.orig/arch/arm/mach-pxa/pxa25x.c
1076+++ linux-2.6.24-rc1/arch/arm/mach-pxa/pxa25x.c
1077@@ -200,6 +200,8 @@
1078 RESTORE(PSTR);
1079 }
1080
1081+extern unsigned long pxa_pm_pspr_value;
1082+
1083 static void pxa25x_cpu_pm_enter(suspend_state_t state)
1084 {
1085 CKEN = 0;
1086@@ -207,7 +209,7 @@
1087 switch (state) {
1088 case PM_SUSPEND_MEM:
1089 /* set resume return address */
1090- PSPR = virt_to_phys(pxa_cpu_resume);
1091+ PSPR = pxa_pm_pspr_value;
1092 pxa25x_cpu_suspend(PWRMODE_SLEEP);
1093 break;
1094 }
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/mmcsd_no_scr_check-r2.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/mmcsd_no_scr_check-r2.patch
index ac2245f088..ac2245f088 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/mmcsd_no_scr_check-r2.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/mmcsd_no_scr_check-r2.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pda-power.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pda-power.patch
index face2f4ef2..face2f4ef2 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pda-power.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pda-power.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa-serial-hack.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa-serial-hack.patch
index bf20f46a05..bf20f46a05 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa-serial-hack.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa-serial-hack.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa27x_overlay-r8.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa27x_overlay-r8.patch
new file mode 100644
index 0000000000..693ad20453
--- /dev/null
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa27x_overlay-r8.patch
@@ -0,0 +1,2427 @@
1 drivers/video/Kconfig | 18
2 drivers/video/Makefile | 1
3 drivers/video/pxafb.c | 305 +++++--
4 drivers/video/pxafb.h | 65 +
5 drivers/video/pxafb_overlay.c | 1525 ++++++++++++++++++++++++++++++++++++
6 include/asm-arm/arch-pxa/pxa-regs.h | 111 ++
7 6 files changed, 1969 insertions(+), 56 deletions(-)
8
9--- linux-2.6.24-rc1.orig/drivers/video/Kconfig
10+++ linux-2.6.24-rc1/drivers/video/Kconfig
11@@ -1718,6 +1718,24 @@
12
13 If unsure, say N.
14
15+choice
16+ prompt "PXA LCD type"
17+ depends on FB_PXA
18+
19+config FB_PXA_LCD_QVGA
20+ bool "QVGA(320x240)"
21+
22+config FB_PXA_LCD_VGA
23+ bool "VGA (640x480)"
24+
25+endchoice
26+
27+config FB_PXA_OVERLAY
28+ tristate "PXA LCD overlay support"
29+ depends on FB_PXA
30+ ---help---
31+ Frame buffer overlay driver for PXA27x
32+
33 config FB_PXA_PARAMETERS
34 bool "PXA LCD command line parameters"
35 default n
36--- linux-2.6.24-rc1.orig/drivers/video/Makefile
37+++ linux-2.6.24-rc1/drivers/video/Makefile
38@@ -96,6 +96,7 @@
39 obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o
40 obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o
41 obj-$(CONFIG_FB_PXA) += pxafb.o
42+obj-$(CONFIG_FB_PXA_OVERLAY) += pxafb_overlay.o
43 obj-$(CONFIG_FB_W100) += w100fb.o
44 obj-$(CONFIG_FB_AU1100) += au1100fb.o
45 obj-$(CONFIG_FB_AU1200) += au1200fb.o
46--- linux-2.6.24-rc1.orig/drivers/video/pxafb.c
47+++ linux-2.6.24-rc1/drivers/video/pxafb.c
48@@ -59,17 +59,49 @@
49 #define LCCR0_INVALID_CONFIG_MASK (LCCR0_OUM|LCCR0_BM|LCCR0_QDM|LCCR0_DIS|LCCR0_EFM|LCCR0_IUM|LCCR0_SFM|LCCR0_LDM|LCCR0_ENB)
50 #define LCCR3_INVALID_CONFIG_MASK (LCCR3_HSP|LCCR3_VSP|LCCR3_PCD|LCCR3_BPP)
51
52+wait_queue_head_t fcs_wait_eof;
53+int fcs_in_eof;
54+static DECLARE_MUTEX(fcs_lcd_sem);
55+
56 static void (*pxafb_backlight_power)(int);
57 static void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
58
59 static int pxafb_activate_var(struct fb_var_screeninfo *var, struct pxafb_info *);
60-static void set_ctrlr_state(struct pxafb_info *fbi, u_int state);
61+void pxafb_set_ctrlr_state(struct pxafb_info *fbi, u_int state);
62
63 #ifdef CONFIG_FB_PXA_PARAMETERS
64 #define PXAFB_OPTIONS_SIZE 256
65 static char g_options[PXAFB_OPTIONS_SIZE] __devinitdata = "";
66 #endif
67
68+static struct pxafb_rgb def_rgb_8 = {
69+ red: { offset: 0, length: 8, },
70+ green: { offset: 0, length: 8, },
71+ blue: { offset: 0, length: 8, },
72+ transp: { offset: 0, length: 0, },
73+};
74+
75+static struct pxafb_rgb def_rgb_16 = {
76+ red: { offset: 11, length: 5, },
77+ green: { offset: 5, length: 6, },
78+ blue: { offset: 0, length: 5, },
79+ transp: { offset: 0, length: 0, },
80+};
81+
82+static struct pxafb_rgb def_rgb_18 = {
83+ red: { offset: 12, length: 6, },
84+ green: { offset: 6, length: 6, },
85+ blue: { offset: 0, length: 6, },
86+ transp: { offset: 0, length: 0, },
87+};
88+
89+static struct pxafb_rgb def_rgb_24 = {
90+ red: { offset: 16, length: 8, },
91+ green: { offset: 8, length: 8, },
92+ blue: { offset: 0, length: 8, },
93+ transp: { offset: 0, length: 0, },
94+};
95+
96 static inline void pxafb_schedule_work(struct pxafb_info *fbi, u_int state)
97 {
98 unsigned long flags;
99@@ -209,6 +241,10 @@
100 case 4: ret = LCCR3_4BPP; break;
101 case 8: ret = LCCR3_8BPP; break;
102 case 16: ret = LCCR3_16BPP; break;
103+ case 18: ret = LCCR3_18BPP; break;
104+ case 19: ret = LCCR3_19BPP; break;
105+ case 24: ret = LCCR3_24BPP; break;
106+ case 25: ret = LCCR3_25BPP; break;
107 }
108 return ret;
109 }
110@@ -320,18 +356,34 @@
111 * The pixel packing format is described on page 7-11 of the
112 * PXA2XX Developer's Manual.
113 */
114- if (var->bits_per_pixel == 16) {
115- var->red.offset = 11; var->red.length = 5;
116- var->green.offset = 5; var->green.length = 6;
117- var->blue.offset = 0; var->blue.length = 5;
118- var->transp.offset = var->transp.length = 0;
119- } else {
120- var->red.offset = var->green.offset = var->blue.offset = var->transp.offset = 0;
121- var->red.length = 8;
122- var->green.length = 8;
123- var->blue.length = 8;
124- var->transp.length = 0;
125- }
126+ switch (var->bits_per_pixel) {
127+ case 16:
128+ /* 2 pixels per line */
129+ var->red = def_rgb_16.red;
130+ var->green = def_rgb_16.green;
131+ var->blue = def_rgb_16.blue;
132+ var->transp = def_rgb_16.transp;
133+ break;
134+ case 18:
135+ case 19:
136+ var->red = def_rgb_18.red;
137+ var->green = def_rgb_18.green;
138+ var->blue = def_rgb_18.blue;
139+ var->transp = def_rgb_18.transp;
140+ break;
141+ case 24:
142+ case 25:
143+ var->red = def_rgb_24.red;
144+ var->green = def_rgb_24.green;
145+ var->blue = def_rgb_24.blue;
146+ var->transp = def_rgb_24.transp;
147+ break;
148+ default:
149+ var->red = def_rgb_8.red;
150+ var->green = def_rgb_8.green;
151+ var->blue = def_rgb_8.blue;
152+ var->transp = def_rgb_8.transp;
153+ }
154
155 #ifdef CONFIG_CPU_FREQ
156 pr_debug("pxafb: dma period = %d ps, clock = %d kHz\n",
157@@ -345,7 +397,7 @@
158 static inline void pxafb_set_truecolor(u_int is_true_color)
159 {
160 pr_debug("pxafb: true_color = %d\n", is_true_color);
161- // do your machine-specific setup if needed
162+ /* do your machine-specific setup if needed */
163 }
164
165 /*
166@@ -360,7 +412,8 @@
167
168 pr_debug("pxafb: set_par\n");
169
170- if (var->bits_per_pixel == 16)
171+ if (var->bits_per_pixel == 16 || var->bits_per_pixel == 18 ||var->bits_per_pixel == 19
172+ || var->bits_per_pixel == 24 || var->bits_per_pixel == 25)
173 fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
174 else if (!fbi->cmap_static)
175 fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
176@@ -373,12 +426,25 @@
177 fbi->fb.fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
178 }
179
180- fbi->fb.fix.line_length = var->xres_virtual *
181- var->bits_per_pixel / 8;
182- if (var->bits_per_pixel == 16)
183- fbi->palette_size = 0;
184- else
185- fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
186+ switch (var->bits_per_pixel) {
187+ case 16:
188+ fbi->fb.fix.line_length = var->xres_virtual * 2;
189+ fbi->palette_size = 0;
190+ break;
191+ case 18:
192+ case 19:
193+ fbi->fb.fix.line_length = var->xres_virtual * 3;
194+ fbi->palette_size = 0;
195+ break;
196+ case 24:
197+ case 25:
198+ fbi->fb.fix.line_length = var->xres_virtual * 4;
199+ fbi->palette_size = 0;
200+ break;
201+ default:
202+ fbi->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
203+ fbi->palette_size = var->bits_per_pixel == 1 ? 4 : 1 << var->bits_per_pixel;
204+ }
205
206 if ((fbi->lccr4 & LCCR4_PAL_FOR_MASK) == LCCR4_PAL_FOR_0)
207 palette_mem_size = fbi->palette_size * sizeof(u16);
208@@ -395,7 +461,8 @@
209 */
210 pxafb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
211
212- if (fbi->fb.var.bits_per_pixel == 16)
213+ if (fbi->fb.var.bits_per_pixel == 16 || fbi->fb.var.bits_per_pixel == 18 ||fbi->fb.var.bits_per_pixel == 19
214+ || fbi->fb.var.bits_per_pixel == 24 || fbi->fb.var.bits_per_pixel == 25)
215 fb_dealloc_cmap(&fbi->fb.cmap);
216 else
217 fb_alloc_cmap(&fbi->fb.cmap, 1<<fbi->fb.var.bits_per_pixel, 0);
218@@ -441,7 +508,7 @@
219 * 16 bpp mode does not really use the palette, so this will not
220 * blank the display in all modes.
221 */
222-static int pxafb_blank(int blank, struct fb_info *info)
223+int pxafb_blank(int blank, struct fb_info *info)
224 {
225 struct pxafb_info *fbi = (struct pxafb_info *)info;
226 int i;
227@@ -458,19 +525,20 @@
228 for (i = 0; i < fbi->palette_size; i++)
229 pxafb_setpalettereg(i, 0, 0, 0, 0, info);
230
231- pxafb_schedule_work(fbi, C_DISABLE);
232- //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
233+ pxafb_schedule_work(fbi, C_BLANK);
234+ /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
235 break;
236
237 case FB_BLANK_UNBLANK:
238- //TODO if (pxafb_blank_helper) pxafb_blank_helper(blank);
239+ /* TODO if (pxafb_blank_helper) pxafb_blank_helper(blank); */
240 if (fbi->fb.fix.visual == FB_VISUAL_PSEUDOCOLOR ||
241 fbi->fb.fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
242 fb_set_cmap(&fbi->fb.cmap, info);
243- pxafb_schedule_work(fbi, C_ENABLE);
244+ pxafb_schedule_work(fbi, C_UNBLANK);
245 }
246 return 0;
247 }
248+EXPORT_SYMBOL(pxafb_blank);
249
250 static int pxafb_mmap(struct fb_info *info,
251 struct vm_area_struct *vma)
252@@ -606,6 +674,10 @@
253 case 4:
254 case 8:
255 case 16:
256+ case 18:
257+ case 19:
258+ case 24:
259+ case 25:
260 break;
261 default:
262 printk(KERN_ERR "%s: invalid bit depth %d\n",
263@@ -637,7 +709,10 @@
264
265 new_regs.lccr0 = fbi->lccr0 |
266 (LCCR0_LDM | LCCR0_SFM | LCCR0_IUM | LCCR0_EFM |
267- LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
268+#ifdef CONFIG_PXA27x /* Enable overlay for PXA27x */
269+ LCCR0_OUC | LCCR0_CMDIM | LCCR0_RDSTM |
270+#endif
271+ LCCR0_QDM | LCCR0_BM | LCCR0_OUM);
272
273 new_regs.lccr1 =
274 LCCR1_DisWdth(var->xres) +
275@@ -696,7 +771,7 @@
276
277 fbi->dmadesc_fbhigh_cpu->fsadr = fbi->screen_dma;
278 fbi->dmadesc_fbhigh_cpu->fidr = 0;
279- fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL;
280+ fbi->dmadesc_fbhigh_cpu->ldcmd = BYTES_PER_PANEL | LDCMD_EOFINT;
281
282 fbi->dmadesc_palette_cpu->fsadr = fbi->palette_dma;
283 fbi->dmadesc_palette_cpu->fidr = 0;
284@@ -708,7 +783,8 @@
285 sizeof(u32);
286 fbi->dmadesc_palette_cpu->ldcmd |= LDCMD_PAL;
287
288- if (var->bits_per_pixel == 16) {
289+ if (var->bits_per_pixel == 16 || var->bits_per_pixel == 18 ||var->bits_per_pixel == 19
290+ || var->bits_per_pixel == 24 || var->bits_per_pixel == 25) {
291 /* palette shouldn't be loaded in true-color mode */
292 fbi->dmadesc_fbhigh_cpu->fdadr = fbi->dmadesc_fbhigh_dma;
293 fbi->fdadr0 = fbi->dmadesc_fbhigh_dma; /* no pal just fbhigh */
294@@ -763,8 +839,8 @@
295 }
296
297 /*
298- * NOTE! The following functions are purely helpers for set_ctrlr_state.
299- * Do not call them directly; set_ctrlr_state does the correct serialisation
300+ * NOTE! The following functions are purely helpers for pxafb_set_ctrlr_state.
301+ * Do not call them directly; pxafb_set_ctrlr_state does the correct serialisation
302 * to ensure that things happen in the right way 100% of time time.
303 * -- rmk
304 */
305@@ -786,7 +862,8 @@
306
307 static void pxafb_setup_gpio(struct pxafb_info *fbi)
308 {
309- int gpio, ldd_bits;
310+ int gpio;
311+ int ldd_bits = 0;
312 unsigned int lccr0 = fbi->lccr0;
313
314 /*
315@@ -796,28 +873,56 @@
316 /* 4 bit interface */
317 if ((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
318 (lccr0 & LCCR0_SDS) == LCCR0_Sngl &&
319- (lccr0 & LCCR0_DPD) == LCCR0_4PixMono)
320+ (lccr0 & LCCR0_DPD) == LCCR0_4PixMono) {
321 ldd_bits = 4;
322-
323+ }
324 /* 8 bit interface */
325 else if (((lccr0 & LCCR0_CMS) == LCCR0_Mono &&
326 ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_DPD) == LCCR0_8PixMono)) ||
327 ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
328- (lccr0 & LCCR0_PAS) == LCCR0_Pas && (lccr0 & LCCR0_SDS) == LCCR0_Sngl))
329+ (lccr0 & LCCR0_PAS) == LCCR0_Pas && (lccr0 & LCCR0_SDS) == LCCR0_Sngl)) {
330 ldd_bits = 8;
331-
332+ }
333 /* 16 bit interface */
334- else if ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
335- ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_PAS) == LCCR0_Act))
336- ldd_bits = 16;
337+ else if ((lccr0 & LCCR0_CMS) == LCCR0_Color &&
338+ ((lccr0 & LCCR0_SDS) == LCCR0_Dual || (lccr0 & LCCR0_PAS) == LCCR0_Act)) {
339+ switch (fbi->fb.var.bits_per_pixel) {
340+ case 16:
341+#ifdef CONFIG_PXA27x
342+ /* bits 58-77 */
343+ GPDR1 |= (0x3f << 26);
344+ GPDR2 |= 0x00003fff;
345
346+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
347+ GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
348+#endif
349+ ldd_bits = 16;
350+ break;
351+ case 18:
352+ case 19:
353+ case 24:
354+ case 25:
355+#ifdef CONFIG_PXA27x
356+ /* bits 58-77 and 86, 87 */
357+ GPDR1 |= (0x3f << 26);
358+ GPDR2 |= 0x00c03fff;
359+
360+ GAFR1_U = (GAFR1_U & ~(0xfff << 20)) | (0xaaa << 20);
361+ GAFR2_L = (GAFR2_L & 0xf0000000) | 0x0aaaaaaa;
362+ GAFR2_U = (GAFR2_U & 0xffff0fff) | 0xa000;
363+#endif
364+ ldd_bits = 25;
365+ break;
366+ }
367+ }
368 else {
369 printk(KERN_ERR "pxafb_setup_gpio: unable to determine bits per pixel\n");
370 return;
371 }
372
373- for (gpio = 58; ldd_bits; gpio++, ldd_bits--)
374+ for (gpio = 58; ldd_bits > 0; gpio++, ldd_bits--) {
375 pxa_gpio_mode(gpio | GPIO_ALT_FN_2_OUT);
376+ }
377 pxa_gpio_mode(GPIO74_LCD_FCLK_MD);
378 pxa_gpio_mode(GPIO75_LCD_LCLK_MD);
379 pxa_gpio_mode(GPIO76_LCD_PCLK_MD);
380@@ -837,6 +942,7 @@
381 /* enable LCD controller clock */
382 clk_enable(fbi->clk);
383
384+ down(&fcs_lcd_sem);
385 /* Sequence from 11.7.10 */
386 LCCR3 = fbi->reg_lccr3;
387 LCCR2 = fbi->reg_lccr2;
388@@ -847,6 +953,8 @@
389 FDADR1 = fbi->fdadr1;
390 LCCR0 |= LCCR0_ENB;
391
392+ up(&fcs_lcd_sem);
393+
394 pr_debug("FDADR0 0x%08x\n", (unsigned int) FDADR0);
395 pr_debug("FDADR1 0x%08x\n", (unsigned int) FDADR1);
396 pr_debug("LCCR0 0x%08x\n", (unsigned int) LCCR0);
397@@ -862,6 +970,7 @@
398
399 pr_debug("pxafb: disabling LCD controller\n");
400
401+ down(&fcs_lcd_sem);
402 set_current_state(TASK_UNINTERRUPTIBLE);
403 add_wait_queue(&fbi->ctrlr_wait, &wait);
404
405@@ -871,6 +980,7 @@
406
407 schedule_timeout(200 * HZ / 1000);
408 remove_wait_queue(&fbi->ctrlr_wait, &wait);
409+ up(&fcs_lcd_sem);
410
411 /* disable LCD controller clock */
412 clk_disable(fbi->clk);
413@@ -888,6 +998,11 @@
414 LCCR0 |= LCCR0_LDM;
415 wake_up(&fbi->ctrlr_wait);
416 }
417+ if (lcsr & LCSR_EOF && fcs_in_eof) {
418+ LCCR0 |= LCCR0_EFM;
419+ fcs_in_eof = 0;
420+ wake_up(&fcs_wait_eof);
421+ }
422
423 LCSR = lcsr;
424 return IRQ_HANDLED;
425@@ -898,7 +1013,7 @@
426 * sleep when disabling the LCD controller, or if we get two contending
427 * processes trying to alter state.
428 */
429-static void set_ctrlr_state(struct pxafb_info *fbi, u_int state)
430+void pxafb_set_ctrlr_state(struct pxafb_info *fbi, u_int state)
431 {
432 u_int old_state;
433
434@@ -920,7 +1035,9 @@
435 */
436 if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
437 fbi->state = state;
438- //TODO __pxafb_lcd_power(fbi, 0);
439+ /* TODO __pxafb_lcd_power(fbi, 0); */
440+ if(fbi->set_overlay_ctrlr_state)
441+ fbi->set_overlay_ctrlr_state(fbi, C_DISABLE);
442 pxafb_disable_controller(fbi);
443 }
444 break;
445@@ -934,6 +1051,8 @@
446 fbi->state = state;
447 __pxafb_backlight_power(fbi, 0);
448 __pxafb_lcd_power(fbi, 0);
449+ if(fbi->set_overlay_ctrlr_state)
450+ fbi->set_overlay_ctrlr_state(fbi, C_DISABLE);
451 if (old_state != C_DISABLE_CLKCHANGE)
452 pxafb_disable_controller(fbi);
453 }
454@@ -947,7 +1066,9 @@
455 if (old_state == C_DISABLE_CLKCHANGE) {
456 fbi->state = C_ENABLE;
457 pxafb_enable_controller(fbi);
458- //TODO __pxafb_lcd_power(fbi, 1);
459+ /* TODO __pxafb_lcd_power(fbi, 1); */
460+ if(fbi->set_overlay_ctrlr_state)
461+ fbi->set_overlay_ctrlr_state(fbi, C_ENABLE);
462 }
463 break;
464
465@@ -959,9 +1080,13 @@
466 */
467 if (old_state == C_ENABLE) {
468 __pxafb_lcd_power(fbi, 0);
469+ if(fbi->set_overlay_ctrlr_state)
470+ fbi->set_overlay_ctrlr_state(fbi, C_DISABLE);
471 pxafb_disable_controller(fbi);
472 pxafb_setup_gpio(fbi);
473 pxafb_enable_controller(fbi);
474+ if(fbi->set_overlay_ctrlr_state)
475+ fbi->set_overlay_ctrlr_state(fbi, C_ENABLE);
476 __pxafb_lcd_power(fbi, 1);
477 }
478 break;
479@@ -987,11 +1112,46 @@
480 pxafb_enable_controller(fbi);
481 __pxafb_lcd_power(fbi, 1);
482 __pxafb_backlight_power(fbi, 1);
483+ if(fbi->set_overlay_ctrlr_state)
484+ fbi->set_overlay_ctrlr_state(fbi, C_ENABLE);
485 }
486 break;
487+
488+ case C_BLANK:
489+ /*
490+ * Disable controller, blank overlays if exist.
491+ */
492+ if ((old_state != C_DISABLE) && (old_state != C_BLANK)) {
493+ fbi->state = state;
494+ __pxafb_backlight_power(fbi, 0);
495+ __pxafb_lcd_power(fbi, 0);
496+ if(fbi->set_overlay_ctrlr_state)
497+ fbi->set_overlay_ctrlr_state(fbi, C_BLANK);
498+ if (old_state != C_DISABLE_CLKCHANGE)
499+ pxafb_disable_controller(fbi);
500+ }
501+ break;
502+
503+ case C_UNBLANK:
504+ /*
505+ * Power up the LCD screen, enable controller, and
506+ * turn on the backlight, unblank overlays if exist.
507+ */
508+ if ((old_state != C_ENABLE) && (old_state != C_UNBLANK)) {
509+ fbi->state = C_UNBLANK;
510+ pxafb_setup_gpio(fbi);
511+ pxafb_enable_controller(fbi);
512+ __pxafb_lcd_power(fbi, 1);
513+ __pxafb_backlight_power(fbi, 1);
514+ if(fbi->set_overlay_ctrlr_state)
515+ fbi->set_overlay_ctrlr_state(fbi, C_UNBLANK);
516+ }
517+ break;
518+
519 }
520 up(&fbi->ctrlr_sem);
521 }
522+EXPORT_SYMBOL(pxafb_set_ctrlr_state);
523
524 /*
525 * Our LCD controller task (which is called when we blank or unblank)
526@@ -1003,7 +1163,7 @@
527 container_of(work, struct pxafb_info, task);
528 u_int state = xchg(&fbi->task_state, -1);
529
530- set_ctrlr_state(fbi, state);
531+ pxafb_set_ctrlr_state(fbi, state);
532 }
533
534 #ifdef CONFIG_CPU_FREQ
535@@ -1018,19 +1178,29 @@
536 pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
537 {
538 struct pxafb_info *fbi = TO_INF(nb, freq_transition);
539- //TODO struct cpufreq_freqs *f = data;
540+ /* TODO struct cpufreq_freqs *f = data; */
541+ struct cpufreq_freqs *clkinfo;
542 u_int pcd;
543+ u_int lccr3;
544
545 switch (val) {
546 case CPUFREQ_PRECHANGE:
547- set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
548+ pxafb_set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
549 break;
550
551 case CPUFREQ_POSTCHANGE:
552- pcd = get_pcd(fbi, fbi->fb.var.pixclock);
553+ clkinfo = (struct cpufreq_freqs *)data;
554+ /* If leaving a 13kHz state with the LCD sustained */
555+ if ((clkinfo->old == 13000))
556+ break;
557+
558+ pcd = get_pcd(fbi->fb.var.pixclock);
559+ lccr3 = fbi->reg_lccr3;
560 set_hsync_time(fbi, pcd);
561 fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
562- set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
563+ pxafb_set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
564+ if (lccr3 != fbi->reg_lccr3 && !((LCCR0 & LCCR0_DIS) || !(LCCR0 & LCCR0_ENB)))
565+ LCCR3 = fbi->reg_lccr3;
566 break;
567 }
568 return 0;
569@@ -1049,7 +1219,7 @@
570 printk(KERN_DEBUG "min dma period: %d ps, "
571 "new clock %d kHz\n", pxafb_display_dma_period(var),
572 policy->max);
573- // TODO: fill in min/max values
574+ /* TODO: fill in min/max values */
575 break;
576 #if 0
577 case CPUFREQ_NOTIFY:
578@@ -1075,7 +1245,7 @@
579 {
580 struct pxafb_info *fbi = platform_get_drvdata(dev);
581
582- set_ctrlr_state(fbi, C_DISABLE_PM);
583+ pxafb_set_ctrlr_state(fbi, C_DISABLE_PM);
584 return 0;
585 }
586
587@@ -1083,7 +1253,11 @@
588 {
589 struct pxafb_info *fbi = platform_get_drvdata(dev);
590
591- set_ctrlr_state(fbi, C_ENABLE_PM);
592+ pxafb_set_ctrlr_state(fbi, C_ENABLE_PM);
593+//RP#ifdef CONFIG_PXA27x
594+//RP LCCR4 |= (1 << 31); /* Disable the PCD Divisor, PCDDIV */
595+//RP LCCR4 |= (5 << 17); /* Undocumented feature */
596+//RP#endif
597 return 0;
598 }
599 #else
600@@ -1197,11 +1371,21 @@
601 fbi->task_state = (u_char)-1;
602
603 for (i = 0; i < inf->num_modes; i++) {
604- smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
605+ if (mode[i].bpp <= 16) { /* 8, 16 bpp */
606+ smemlen = mode[i].xres * mode[i].yres * mode[i].bpp / 8;
607+ } else if ( mode[i].bpp > 19 ) { /* 24, 25 bpp */
608+ smemlen = mode[i].xres * mode[i].yres * 4;
609+ } else { /* 18, 19 bpp */
610+ /* packed format */
611+ smemlen = mode[i].xres * mode[i].yres * 3;
612+ }
613+
614 if (smemlen > fbi->fb.fix.smem_len)
615 fbi->fb.fix.smem_len = smemlen;
616 }
617
618+ fbi->set_overlay_ctrlr_state = NULL;
619+
620 init_waitqueue_head(&fbi->ctrlr_wait);
621 INIT_WORK(&fbi->task, pxafb_task);
622 init_MUTEX(&fbi->ctrlr_sem);
623@@ -1268,6 +1452,10 @@
624 case 4:
625 case 8:
626 case 16:
627+ case 18:
628+ case 19:
629+ case 24:
630+ case 25:
631 inf->modes[0].bpp = bpp;
632 dev_info(dev, "overriding bit depth: %d\n", bpp);
633 break;
634@@ -1416,7 +1604,7 @@
635 fbi = pxafb_init_fbinfo(&dev->dev);
636 if (!fbi) {
637 dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
638- ret = -ENOMEM; // only reason for pxafb_init_fbinfo to fail is kmalloc
639+ ret = -ENOMEM; /* only reason for pxafb_init_fbinfo to fail is kmalloc */
640 goto failed;
641 }
642
643@@ -1451,7 +1639,7 @@
644 }
645
646 #ifdef CONFIG_PM
647- // TODO
648+ /* TODO */
649 #endif
650
651 #ifdef CONFIG_CPU_FREQ
652@@ -1464,7 +1652,12 @@
653 /*
654 * Ok, now enable the LCD controller
655 */
656- set_ctrlr_state(fbi, C_ENABLE);
657+ pxafb_set_ctrlr_state(fbi, C_ENABLE);
658+//#ifdef CONFIG_PXA27x
659+// LCCR4 |= (1 << 31); /* Disabel the PCD Divisor, PCDDIV */
660+// LCCR4 |= (5 << 17); /* Undocumented feature */
661+//#endif
662+ init_waitqueue_head(&fcs_wait_eof);
663
664 return 0;
665
666--- linux-2.6.24-rc1.orig/drivers/video/pxafb.h
667+++ linux-2.6.24-rc1/drivers/video/pxafb.h
668@@ -29,6 +29,60 @@
669 unsigned int lccr3;
670 };
671
672+struct pxafb_rgb {
673+ struct fb_bitfield red;
674+ struct fb_bitfield green;
675+ struct fb_bitfield blue;
676+ struct fb_bitfield transp;
677+};
678+
679+#ifdef CONFIG_PXA27x
680+/* PXA Overlay Framebuffer Support */
681+struct overlayfb_info
682+{
683+ struct fb_info fb;
684+
685+ struct fb_var_screeninfo old_var;
686+
687+ struct semaphore mutex;
688+ unsigned long refcount;
689+
690+ struct pxafb_info *basefb;
691+
692+ unsigned long map_cpu;
693+ unsigned long screen_cpu;
694+ unsigned long palette_cpu;
695+ unsigned long map_size;
696+ unsigned long palette_size;
697+
698+ dma_addr_t screen_dma;
699+ dma_addr_t map_dma;
700+ dma_addr_t palette_dma;
701+
702+ volatile u_char state;
703+
704+ /* overlay specific info */
705+ unsigned long xpos; /* screen position (x, y)*/
706+ unsigned long ypos;
707+ unsigned long format;
708+
709+ /* additional */
710+ union {
711+ struct pxafb_dma_descriptor *dma0;
712+ struct pxafb_dma_descriptor *dma1;
713+ struct {
714+ struct pxafb_dma_descriptor *dma2;
715+ struct pxafb_dma_descriptor *dma3;
716+ struct pxafb_dma_descriptor *dma4;
717+ };
718+ struct {
719+ struct pxafb_dma_descriptor *dma5_pal;
720+ struct pxafb_dma_descriptor *dma5_frame;
721+ };
722+ };
723+};
724+#endif
725+
726 /* PXA LCD DMA descriptor */
727 struct pxafb_dma_descriptor {
728 unsigned int fdadr;
729@@ -90,6 +144,14 @@
730 wait_queue_head_t ctrlr_wait;
731 struct work_struct task;
732
733+#ifdef CONFIG_PXA27x
734+ /* PXA Overlay Framebuffer Support */
735+ struct overlayfb_info *overlay1fb;
736+ struct overlayfb_info *overlay2fb;
737+ struct overlayfb_info *cursorfb;
738+#endif
739+ void (*set_overlay_ctrlr_state)(struct pxafb_info *, u_int);
740+
741 #ifdef CONFIG_CPU_FREQ
742 struct notifier_block freq_transition;
743 struct notifier_block freq_policy;
744@@ -109,6 +171,9 @@
745 #define C_DISABLE_PM (5)
746 #define C_ENABLE_PM (6)
747 #define C_STARTUP (7)
748+#define C_BLANK (8)
749+#define C_UNBLANK (9)
750+
751
752 #define PXA_NAME "PXA"
753
754--- /dev/null
755+++ linux-2.6.24-rc1/drivers/video/pxafb_overlay.c
756@@ -0,0 +1,1525 @@
757+/*
758+ * linux/drivers/video/pxafb_overlay.c
759+ *
760+ * Copyright (c) 2004, Intel Corporation
761+ *
762+ * Code Status:
763+ * 2004/10/28: <yan.yin@intel.com>
764+ * - Ported to 2.6 kernel
765+ * - Made overlay driver a loadable module
766+ * - Merged overlay optimized patch
767+ * 2004/03/10: <stanley.cai@intel.com>
768+ * - Fixed Bugs
769+ * - Added workaround for overlay1&2
770+ * 2003/08/27: <yu.tang@intel.com>
771+ * - Added Overlay 1 & Overlay2 & Hardware Cursor support
772+ *
773+ *
774+ * This software program is licensed subject to the GNU Lesser General
775+ * Public License (LGPL). Version 2.1, February 1999, available at
776+ * http://www.gnu.org/copyleft/lesser.html
777+ *
778+ * Intel PXA27x LCD Controller Frame Buffer Overlay Driver
779+ *
780+ *
781+ */
782+
783+#include <linux/module.h>
784+#include <linux/moduleparam.h>
785+#include <linux/kernel.h>
786+#include <linux/sched.h>
787+#include <linux/errno.h>
788+#include <linux/string.h>
789+#include <linux/interrupt.h>
790+#include <linux/slab.h>
791+#include <linux/fb.h>
792+#include <linux/delay.h>
793+#include <linux/init.h>
794+#include <linux/ioport.h>
795+#include <linux/cpufreq.h>
796+#include <linux/device.h>
797+#include <linux/platform_device.h>
798+#include <linux/dma-mapping.h>
799+
800+#include <asm/hardware.h>
801+#include <asm/io.h>
802+#include <asm/irq.h>
803+#include <asm/uaccess.h>
804+#include <asm/arch/bitfield.h>
805+#include <asm/arch/pxafb.h>
806+#include <asm/arch/pxa-regs.h>
807+
808+#include "pxafb.h"
809+
810+/* LCD enhancement : Overlay 1 & 2 & Hardware Cursor */
811+
812+/*
813+ * LCD enhancement : Overlay 1
814+ *
815+ * Features:
816+ * - support 16bpp (No palette)
817+ */
818+/*
819+ * debugging?
820+ */
821+#define DEBUG 0
822+
823+#ifdef DEBUG
824+#define dbg(fmt,arg...) printk(KERN_ALERT "%s(): " fmt "\n", __FUNCTION__, ##arg)
825+#else
826+#define dbg(fmt,arg...)
827+#endif
828+
829+static int overlay1fb_enable(struct fb_info *info);
830+static int overlay2fb_enable(struct fb_info *info);
831+static int cursorfb_enable(struct fb_info *info);
832+
833+static int overlay1fb_disable(struct fb_info *info);
834+static int overlay2fb_disable(struct fb_info *info);
835+static int cursorfb_disable(struct fb_info *info);
836+
837+static int overlay1fb_blank(int blank, struct fb_info *info);
838+static int overlay2fb_blank(int blank, struct fb_info *info);
839+static int cursorfb_blank(int blank, struct fb_info *info);
840+
841+extern void pxafb_set_ctrlr_state(struct pxafb_info *fbi, u_int state);
842+extern int pxafb_blank(int blank, struct fb_info *info);
843+
844+static struct pxafb_rgb def_rgb_18 = {
845+ red: { offset: 12, length: 6, },
846+ green: { offset: 6, length: 6, },
847+ blue: { offset: 0, length: 6, },
848+ transp: { offset: 0, length: 0, },
849+};
850+
851+static struct pxafb_rgb def_rgbt_16 = {
852+ red: { offset: 10, length: 5, },
853+ green: { offset: 5, length: 5, },
854+ blue: { offset: 0, length: 5, },
855+ transp: { offset: 15, length: 1, },
856+};
857+
858+static struct pxafb_rgb def_rgbt_19 = {
859+ red: { offset: 12, length: 6, },
860+ green: { offset: 6, length: 6, },
861+ blue: { offset: 0, length: 6, },
862+ transp: { offset: 18, length: 1, },
863+};
864+
865+static struct pxafb_rgb def_rgbt_24 = {
866+ red: { offset: 16, length: 7, },
867+ green: { offset: 8, length: 8, },
868+ blue: { offset: 0, length: 8, },
869+ transp: { offset: 0, length: 0, },
870+};
871+
872+static struct pxafb_rgb def_rgbt_25 = {
873+ red: { offset: 16, length: 8, },
874+ green: { offset: 8, length: 8, },
875+ blue: { offset: 0, length: 8, },
876+ transp: { offset: 24, length: 1, },
877+};
878+
879+#define CLEAR_LCD_INTR(reg, intr) do { \
880+ reg = (intr); \
881+}while(0)
882+
883+#define WAIT_FOR_LCD_INTR(reg,intr,timeout) ({ \
884+ int __done =0; \
885+ int __t = timeout; \
886+ while (__t) { \
887+ __done = (reg) & (intr); \
888+ if (__done) break; \
889+ mdelay(10); \
890+ __t--; \
891+ } \
892+ if (!__t) dbg("wait " #intr " timeount");\
893+ __done; \
894+})
895+
896+#define DISABLE_OVERLAYS(fbi) do { \
897+ if (fbi->overlay1fb && (fbi->overlay1fb->state == C_ENABLE)) { \
898+ overlay1fb_disable((struct fb_info*)fbi->overlay1fb); \
899+ } \
900+ if (fbi->overlay2fb && (fbi->overlay2fb->state == C_ENABLE)) { \
901+ overlay2fb_disable((struct fb_info*)fbi->overlay2fb); \
902+ } \
903+ if (fbi->cursorfb && (fbi->cursorfb->state == C_ENABLE)) { \
904+ cursorfb_disable((struct fb_info*)fbi->cursorfb); \
905+ } \
906+}while(0)
907+
908+#define ENABLE_OVERLAYS(fbi) do { \
909+ if (fbi->overlay1fb && (fbi->overlay1fb->state == C_DISABLE)) { \
910+ overlay1fb_enable((struct fb_info*)fbi->overlay1fb); \
911+ } \
912+ if (fbi->overlay2fb && (fbi->overlay2fb->state == C_DISABLE)) { \
913+ overlay2fb_enable((struct fb_info*)fbi->overlay2fb); \
914+ } \
915+ if (fbi->cursorfb && (fbi->cursorfb->state == C_DISABLE)) { \
916+ cursorfb_enable((struct fb_info*)fbi->cursorfb); \
917+ } \
918+}while(0)
919+
920+#define BLANK_OVERLAYS(fbi) do { \
921+ if (fbi->overlay1fb && (fbi->overlay1fb->state == C_ENABLE)) { \
922+ overlay1fb_disable((struct fb_info*)fbi->overlay1fb); \
923+ fbi->overlay1fb->state = C_BLANK; \
924+ } \
925+ if (fbi->overlay2fb && (fbi->overlay2fb->state == C_ENABLE)) { \
926+ overlay2fb_disable((struct fb_info*)fbi->overlay2fb); \
927+ fbi->overlay2fb->state = C_BLANK; \
928+ } \
929+ if (fbi->cursorfb && (fbi->cursorfb->state == C_ENABLE)) { \
930+ cursorfb_disable((struct fb_info*)fbi->cursorfb); \
931+ fbi->cursorfb->state = C_BLANK; \
932+ } \
933+}while(0)
934+
935+#define UNBLANK_OVERLAYS(fbi) do { \
936+ if (fbi->overlay1fb && (fbi->overlay1fb->state == C_BLANK)) { \
937+ overlay1fb_enable((struct fb_info*)fbi->overlay1fb); \
938+ fbi->overlay1fb->state = C_ENABLE; \
939+ } \
940+ if (fbi->overlay2fb && (fbi->overlay2fb->state == C_BLANK)) { \
941+ overlay2fb_enable((struct fb_info*)fbi->overlay2fb); \
942+ fbi->overlay2fb->state = C_ENABLE; \
943+ } \
944+ if (fbi->cursorfb && (fbi->cursorfb->state == C_BLANK)) { \
945+ cursorfb_enable((struct fb_info*)fbi->cursorfb); \
946+ fbi->cursorfb->state = C_ENABLE; \
947+ } \
948+}while(0)
949+
950+static int overlay1fb_open(struct fb_info *info, int user)
951+{
952+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
953+ int ret = 0;
954+
955+/* If basefb is disable, enable fb. */
956+ if (fbi->basefb && fbi->basefb->state != C_ENABLE)
957+ pxafb_blank(VESA_NO_BLANKING, (struct fb_info *)(fbi->basefb));
958+
959+ down(&fbi->mutex);
960+
961+ if (fbi->refcount)
962+ ret = -EACCES;
963+ else
964+ fbi->refcount ++;
965+
966+ up(&fbi->mutex);
967+
968+ /* Initialize the variables in overlay1 framebuffer. */
969+ fbi->fb.var.xres = fbi->fb.var.yres = 0;
970+ fbi->fb.var.bits_per_pixel = 0;
971+
972+ return ret;
973+}
974+
975+static int overlay1fb_release(struct fb_info *info, int user)
976+{
977+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
978+ down(&fbi->mutex);
979+
980+ if (fbi->refcount)
981+ fbi->refcount --;
982+
983+ up(&fbi->mutex);
984+ /* disable overlay when released */
985+ overlay1fb_blank(1, info);
986+
987+ return 0;
988+}
989+
990+static int overlay1fb_map_video_memory(struct fb_info *info)
991+{
992+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
993+
994+ if (fbi->map_cpu)
995+ dma_free_writecombine(NULL, fbi->map_size, (void*)fbi->map_cpu, fbi->map_dma);
996+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
997+
998+ fbi->map_cpu = (unsigned long)dma_alloc_writecombine(NULL, fbi->map_size,
999+ &fbi->map_dma, GFP_KERNEL );
1000+
1001+ if (!fbi->map_cpu) return -ENOMEM;
1002+
1003+ fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
1004+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
1005+
1006+ fbi->fb.fix.smem_start = fbi->screen_dma;
1007+
1008+ /* setup dma descriptor */
1009+ fbi->dma1 = (struct pxafb_dma_descriptor*)
1010+ (fbi->screen_cpu - sizeof(struct pxafb_dma_descriptor));
1011+
1012+ fbi->dma1->fdadr = (fbi->screen_dma - sizeof(struct pxafb_dma_descriptor));
1013+ fbi->dma1->fsadr = fbi->screen_dma;
1014+ fbi->dma1->fidr = 0;
1015+ fbi->dma1->ldcmd = fbi->fb.fix.smem_len;
1016+
1017+ return 0;
1018+}
1019+
1020+static int overlay1fb_enable(struct fb_info *info)
1021+{
1022+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1023+ unsigned long bpp1;
1024+
1025+ if (!fbi->map_cpu) return -EINVAL;
1026+
1027+ switch (fbi->fb.var.bits_per_pixel) {
1028+ case 16:
1029+ bpp1 = 0x4;
1030+ break;
1031+ case 18:
1032+ bpp1 = 0x6;
1033+ break;
1034+ case 19:
1035+ bpp1 = 0x8;
1036+ break;
1037+ case 24:
1038+ bpp1 = 0x9;
1039+ break;
1040+ case 25:
1041+ bpp1 = 0xa;
1042+ break;
1043+ default:
1044+ return -EINVAL;
1045+ }
1046+
1047+ /* disable branch/start/end of frame interrupt */
1048+ LCCR5 |= (LCCR5_IUM1 | LCCR5_BSM1 | LCCR5_EOFM1 | LCCR5_SOFM1);
1049+
1050+ if (fbi->state == C_DISABLE || fbi->state == C_BLANK)
1051+ FDADR1 = (fbi->dma1->fdadr);
1052+ else
1053+ FBR1 = fbi->dma1->fdadr | 0x1;
1054+
1055+ /* enable overlay 1 window */
1056+ OVL1C2 = (fbi->ypos << 10) | fbi->xpos;
1057+ OVL1C1 = OVL1C1_O1EN | (bpp1 << 20) | ((fbi->fb.var.yres-1)<<10) | (fbi->fb.var.xres-1);
1058+
1059+ fbi->state = C_ENABLE;
1060+
1061+ return 0;
1062+}
1063+
1064+static int overlay1fb_disable(struct fb_info *info)
1065+{
1066+ struct overlayfb_info *fbi = (struct overlayfb_info*)info;
1067+ int done;
1068+
1069+ if ((fbi->state == C_DISABLE) || (fbi->state == C_BLANK))
1070+ return 0;
1071+
1072+ fbi->state = C_DISABLE;
1073+
1074+ /* clear O1EN */
1075+ OVL1C1 &= ~OVL1C1_O1EN;
1076+
1077+ CLEAR_LCD_INTR(LCSR1, LCSR1_BS1);
1078+ FBR1 = 0x3;
1079+ done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS1, 100);
1080+
1081+ if (!done) {
1082+ pr_debug(KERN_INFO "%s: timeout\n", __FUNCTION__);
1083+ return -1;
1084+ }
1085+ return 0;
1086+}
1087+
1088+static int overlay1fb_blank(int blank, struct fb_info *info)
1089+{
1090+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1091+ int err=0;
1092+
1093+ switch (blank) {
1094+ case 0:
1095+ err = overlay1fb_enable(info);
1096+ if (err) {
1097+ fbi->state = C_DISABLE;
1098+ pxafb_set_ctrlr_state(fbi->basefb, C_REENABLE);
1099+ }
1100+ break;
1101+ case 1:
1102+ err = overlay1fb_disable(info);
1103+ if (err) {
1104+ fbi->state = C_DISABLE;
1105+ pxafb_set_ctrlr_state(fbi->basefb, C_REENABLE);
1106+ }
1107+ break;
1108+ default:
1109+ break;
1110+ }
1111+
1112+ return err;
1113+}
1114+
1115+static int overlay1fb_check_var( struct fb_var_screeninfo *var, struct fb_info *info)
1116+{
1117+ int xpos, ypos;
1118+ struct overlayfb_info *fbi=(struct overlayfb_info*)info;
1119+
1120+ /* must in base frame */
1121+ xpos = (var->nonstd & 0x3ff);
1122+ ypos = ((var->nonstd>>10) & 0x3ff);
1123+
1124+ if ( (xpos + var->xres) > fbi->basefb->fb.var.xres )
1125+ return -EINVAL;
1126+
1127+ if ( (ypos + var->yres) > fbi->basefb->fb.var.yres )
1128+ return -EINVAL;
1129+
1130+ switch (var->bits_per_pixel) {
1131+ case 16:
1132+ if ( var->xres & 0x1 ) {
1133+ printk("xres should be a multiple of 2 pixels!\n");
1134+ return -EINVAL;
1135+ }
1136+ break;
1137+ case 18:
1138+ case 19:
1139+ if ( var->xres & 0x7 ) {
1140+ printk("xres should be a multiple of 8 pixels!\n");
1141+ return -EINVAL;
1142+ }
1143+ break;
1144+ default:
1145+ break;
1146+ }
1147+
1148+ fbi->old_var=*var;
1149+
1150+ var->activate=FB_ACTIVATE_NOW;
1151+
1152+ return 0;
1153+}
1154+
1155+
1156+static int overlay1fb_set_par(struct fb_info *info)
1157+{
1158+ int nbytes=0, err=0, pixels_per_line=0;
1159+
1160+ struct overlayfb_info *fbi=(struct overlayfb_info*)info;
1161+ struct fb_var_screeninfo *var = &fbi->fb.var;
1162+
1163+ info->flags &= ~FBINFO_MISC_USEREVENT;
1164+
1165+ if (fbi->state == C_BLANK)
1166+ return 0;
1167+
1168+ if (fbi->state == C_DISABLE)
1169+ goto out1;
1170+
1171+ /* only xpos & ypos change */
1172+ if ( (var->xres == fbi->old_var.xres) &&
1173+ (var->yres == fbi->old_var.yres) &&
1174+ (var->bits_per_pixel == fbi->old_var.bits_per_pixel) )
1175+ goto out2;
1176+
1177+out1:
1178+ switch(var->bits_per_pixel) {
1179+ case 16:
1180+ /* 2 pixels per line */
1181+ pixels_per_line = (fbi->fb.var.xres + 0x1) & (~0x1);
1182+ nbytes = 2;
1183+
1184+ var->red = def_rgbt_16.red;
1185+ var->green = def_rgbt_16.green;
1186+ var->blue = def_rgbt_16.blue;
1187+ var->transp = def_rgbt_16.transp;
1188+
1189+ break;
1190+ case 18:
1191+ /* 8 pixels per line */
1192+ pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7);
1193+ nbytes = 3;
1194+
1195+ var->red = def_rgb_18.red;
1196+ var->green = def_rgb_18.green;
1197+ var->blue = def_rgb_18.blue;
1198+ var->transp = def_rgb_18.transp;
1199+
1200+ break;
1201+ case 19:
1202+ /* 8 pixels per line */
1203+ pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7);
1204+ nbytes = 3;
1205+
1206+ var->red = def_rgbt_19.red;
1207+ var->green = def_rgbt_19.green;
1208+ var->blue = def_rgbt_19.blue;
1209+ var->transp = def_rgbt_19.transp;
1210+
1211+ break;
1212+ case 24:
1213+ pixels_per_line = fbi->fb.var.xres;
1214+ nbytes = 4;
1215+
1216+ var->red = def_rgbt_24.red;
1217+ var->green = def_rgbt_24.green;
1218+ var->blue = def_rgbt_24.blue;
1219+ var->transp = def_rgbt_24.transp;
1220+
1221+ break;
1222+ case 25:
1223+ pixels_per_line = fbi->fb.var.xres;
1224+ nbytes = 4;
1225+
1226+ var->red = def_rgbt_25.red;
1227+ var->green = def_rgbt_25.green;
1228+ var->blue = def_rgbt_25.blue;
1229+ var->transp = def_rgbt_25.transp;
1230+
1231+ break;
1232+ }
1233+
1234+ fbi->fb.fix.line_length = nbytes * pixels_per_line;
1235+ fbi->fb.fix.smem_len = fbi->fb.fix.line_length * fbi->fb.var.yres;
1236+
1237+ err= overlay1fb_map_video_memory((struct fb_info*)fbi);
1238+
1239+ if (err)
1240+ return err;
1241+
1242+out2:
1243+ fbi->xpos = var->nonstd & 0x3ff;
1244+ fbi->ypos = (var->nonstd>>10) & 0x3ff;
1245+
1246+ overlay1fb_enable(info);
1247+
1248+ return 0;
1249+
1250+}
1251+
1252+static struct fb_ops overlay1fb_ops = {
1253+ .owner = THIS_MODULE,
1254+ .fb_open = overlay1fb_open,
1255+ .fb_release = overlay1fb_release,
1256+ .fb_check_var = overlay1fb_check_var,
1257+ .fb_set_par = overlay1fb_set_par,
1258+ .fb_blank = overlay1fb_blank,
1259+ .fb_fillrect = cfb_fillrect,
1260+ .fb_copyarea = cfb_copyarea,
1261+ .fb_imageblit = cfb_imageblit,
1262+};
1263+
1264+ /*
1265+ * LCD enhancement : Overlay 2
1266+ *
1267+ * Features:
1268+ * - support planar YCbCr420/YCbCr422/YCbCr444;
1269+ */
1270+static int overlay2fb_open(struct fb_info *info, int user)
1271+{
1272+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1273+ int ret = 0;
1274+
1275+ /* if basefb is disable, enable fb. */
1276+ if (fbi->basefb && fbi->basefb->state != C_ENABLE)
1277+ pxafb_blank(VESA_NO_BLANKING, (struct fb_info *)(fbi->basefb));
1278+
1279+ down(&fbi->mutex);
1280+
1281+ if (fbi->refcount)
1282+ ret = -EACCES;
1283+ else
1284+ fbi->refcount ++;
1285+
1286+ up(&fbi->mutex);
1287+ fbi->fb.var.xres = fbi->fb.var.yres = 0;
1288+
1289+ return ret;
1290+}
1291+
1292+static int overlay2fb_release(struct fb_info *info, int user)
1293+{
1294+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1295+
1296+ down(&fbi->mutex);
1297+
1298+ if (fbi->refcount)
1299+ fbi->refcount --;
1300+
1301+ up(&fbi->mutex);
1302+
1303+ /* disable overlay when released */
1304+ overlay2fb_blank(1, info);
1305+
1306+ return 0;
1307+}
1308+
1309+static int overlay2fb_map_YUV_memory( struct fb_info *info)
1310+{
1311+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1312+ unsigned int ylen, cblen, crlen, aylen, acblen, acrlen;
1313+ unsigned int yoff, cboff, croff;
1314+ unsigned int xres,yres;
1315+ unsigned int nbytes;
1316+
1317+ ylen = cblen = crlen = aylen = acblen = acrlen = 0;
1318+ yoff = cboff = croff = 0;
1319+
1320+ if (fbi->map_cpu)
1321+ dma_free_writecombine(NULL, fbi->map_size, (void*)fbi->map_cpu, fbi->map_dma);
1322+
1323+ yres = fbi->fb.var.yres;
1324+
1325+ switch(fbi->format) {
1326+ case 0x4: /* YCbCr 4:2:0 planar */
1327+ pr_debug("420 planar\n");
1328+ /* 16 pixels per line */
1329+ xres = (fbi->fb.var.xres + 0xf) & (~0xf);
1330+ fbi->fb.fix.line_length = xres;
1331+
1332+ nbytes = xres * yres;
1333+ ylen = nbytes;
1334+ cblen = crlen = (nbytes/4);
1335+
1336+ break;
1337+ case 0x3: /* YCbCr 4:2:2 planar */
1338+ /* 8 pixles per line */
1339+ pr_debug("422 planar\n");
1340+ xres = (fbi->fb.var.xres + 0x7) & (~0x7);
1341+ fbi->fb.fix.line_length = xres;
1342+
1343+ nbytes = xres * yres;
1344+ ylen = nbytes;
1345+ cblen = crlen = (nbytes/2);
1346+
1347+ break;
1348+ case 0x2: /* YCbCr 4:4:4 planar */
1349+ /* 4 pixels per line */
1350+ pr_debug("444 planar\n");
1351+ xres = (fbi->fb.var.xres + 0x3) & (~0x3);
1352+ fbi->fb.fix.line_length = xres;
1353+
1354+ nbytes = xres * yres;
1355+ ylen = cblen = crlen = nbytes;
1356+ break;
1357+ }
1358+
1359+ /* 16-bytes alignment for DMA */
1360+ aylen = (ylen + 0xf) & (~0xf);
1361+ acblen = (cblen + 0xf) & (~0xf);
1362+ acrlen = (crlen + 0xf) & (~0xf);
1363+
1364+ fbi->fb.fix.smem_len = aylen + acblen + acrlen;
1365+
1366+ /* alloc memory */
1367+
1368+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
1369+ fbi->map_cpu = (unsigned long)dma_alloc_writecombine(NULL, fbi->map_size,
1370+ &fbi->map_dma, GFP_KERNEL );
1371+
1372+ if (!fbi->map_cpu) return -ENOMEM;
1373+
1374+ fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
1375+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
1376+
1377+ fbi->fb.fix.smem_start = fbi->screen_dma;
1378+
1379+ /* setup dma for Planar format */
1380+ fbi->dma2 = (struct pxafb_dma_descriptor*)
1381+ (fbi->screen_cpu - sizeof(struct pxafb_dma_descriptor));
1382+ fbi->dma3 = fbi->dma2 - 1;
1383+ fbi->dma4 = fbi->dma3 - 1;
1384+
1385+ /* offset */
1386+ yoff = 0;
1387+ cboff = aylen;
1388+ croff = cboff + acblen;
1389+
1390+ /* Y vector */
1391+ fbi->dma2->fdadr = (fbi->screen_dma - sizeof(struct pxafb_dma_descriptor));
1392+ fbi->dma2->fsadr = fbi->screen_dma + yoff;
1393+ fbi->dma2->fidr = 0;
1394+ fbi->dma2->ldcmd = ylen;
1395+
1396+ /* Cb vector */
1397+ fbi->dma3->fdadr = (fbi->dma2->fdadr - sizeof(struct pxafb_dma_descriptor));
1398+ fbi->dma3->fsadr = (fbi->screen_dma + cboff);
1399+ fbi->dma3->fidr = 0;
1400+ fbi->dma3->ldcmd = cblen;
1401+
1402+ /* Cr vector */
1403+
1404+ fbi->dma4->fdadr = (fbi->dma3->fdadr - sizeof(struct pxafb_dma_descriptor));
1405+ fbi->dma4->fsadr = (fbi->screen_dma + croff);
1406+ fbi->dma4->fidr = 0;
1407+ fbi->dma4->ldcmd = crlen;
1408+
1409+ /* adjust for user */
1410+ fbi->fb.var.red.length = ylen;
1411+ fbi->fb.var.red.offset = yoff;
1412+ fbi->fb.var.green.length = cblen;
1413+ fbi->fb.var.green.offset = cboff;
1414+ fbi->fb.var.blue.length = crlen;
1415+ fbi->fb.var.blue.offset = croff;
1416+
1417+ return 0;
1418+};
1419+
1420+static int overlay2fb_map_RGB_memory( struct fb_info *info)
1421+{
1422+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1423+ struct fb_var_screeninfo *var = &fbi->fb.var;
1424+ int pixels_per_line=0 , nbytes=0;
1425+
1426+ if (fbi->map_cpu)
1427+ dma_free_writecombine(NULL, fbi->map_size, (void*)fbi->map_cpu, fbi->map_dma);
1428+
1429+ switch(var->bits_per_pixel) {
1430+ case 16:
1431+ /* 2 pixels per line */
1432+ pixels_per_line = (fbi->fb.var.xres + 0x1) & (~0x1);
1433+ nbytes = 2;
1434+
1435+ var->red = def_rgbt_16.red;
1436+ var->green = def_rgbt_16.green;
1437+ var->blue = def_rgbt_16.blue;
1438+ var->transp = def_rgbt_16.transp;
1439+ break;
1440+
1441+ case 18:
1442+ /* 8 pixels per line */
1443+ pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7);
1444+ nbytes = 3;
1445+
1446+ var->red = def_rgb_18.red;
1447+ var->green = def_rgb_18.green;
1448+ var->blue = def_rgb_18.blue;
1449+ var->transp = def_rgb_18.transp;
1450+
1451+ break;
1452+ case 19:
1453+ /* 8 pixels per line */
1454+ pixels_per_line = (fbi->fb.var.xres + 0x7 ) & (~0x7);
1455+ nbytes = 3;
1456+
1457+ var->red = def_rgbt_19.red;
1458+ var->green = def_rgbt_19.green;
1459+ var->blue = def_rgbt_19.blue;
1460+ var->transp = def_rgbt_19.transp;
1461+
1462+ break;
1463+ case 24:
1464+ pixels_per_line = fbi->fb.var.xres;
1465+ nbytes = 4;
1466+
1467+ var->red = def_rgbt_24.red;
1468+ var->green = def_rgbt_24.green;
1469+ var->blue = def_rgbt_24.blue;
1470+ var->transp = def_rgbt_24.transp;
1471+
1472+ break;
1473+
1474+ case 25:
1475+ pixels_per_line = fbi->fb.var.xres;
1476+ nbytes = 4;
1477+
1478+ var->red = def_rgbt_25.red;
1479+ var->green = def_rgbt_25.green;
1480+ var->blue = def_rgbt_25.blue;
1481+ var->transp = def_rgbt_25.transp;
1482+
1483+ break;
1484+ }
1485+
1486+ fbi->fb.fix.line_length = nbytes * pixels_per_line;
1487+ fbi->fb.fix.smem_len = fbi->fb.fix.line_length * fbi->fb.var.yres;
1488+
1489+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
1490+ fbi->map_cpu = (unsigned long)dma_alloc_writecombine(NULL, fbi->map_size,
1491+ &fbi->map_dma, GFP_KERNEL );
1492+
1493+ if (!fbi->map_cpu) return -ENOMEM;
1494+
1495+ fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;
1496+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
1497+
1498+ fbi->fb.fix.smem_start = fbi->screen_dma;
1499+
1500+ /* setup dma descriptor */
1501+ fbi->dma2 = (struct pxafb_dma_descriptor*)
1502+ (fbi->screen_cpu - sizeof(struct pxafb_dma_descriptor));
1503+
1504+ fbi->dma2->fdadr = (fbi->screen_dma - sizeof(struct pxafb_dma_descriptor));
1505+ fbi->dma2->fsadr = fbi->screen_dma;
1506+ fbi->dma2->fidr = 0;
1507+ fbi->dma2->ldcmd = fbi->fb.fix.smem_len;
1508+
1509+ return 0;
1510+}
1511+
1512+static int overlay2fb_enable(struct fb_info *info)
1513+{
1514+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1515+ unsigned long bpp2;
1516+ unsigned int xres, yres;
1517+
1518+ if (!fbi->map_cpu) return -EINVAL;
1519+
1520+ switch(fbi->fb.var.bits_per_pixel) {
1521+ case 16:
1522+ bpp2 = 0x4;
1523+ break;
1524+ case 18:
1525+ bpp2 = 0x6;
1526+ break;
1527+ case 19:
1528+ bpp2 = 0x8;
1529+ break;
1530+ case 24:
1531+ bpp2 = 0x9;
1532+ break;
1533+ case 25:
1534+ bpp2 = 0xa;
1535+ break;
1536+ default:
1537+ return -EINVAL;
1538+ }
1539+
1540+ /* disable branch/start/end of frame interrupt */
1541+ LCCR5 |= (LCCR5_IUM4 | LCCR5_IUM3 | LCCR5_IUM2 |
1542+ LCCR5_BSM4 | LCCR5_BSM3 | LCCR5_BSM2 |
1543+ LCCR5_EOFM4 | LCCR5_EOFM3 | LCCR5_EOFM2 |
1544+ LCCR5_SOFM4 | LCCR5_SOFM3 | LCCR5_SOFM2);
1545+
1546+ if (fbi->format == 0) {
1547+ /* overlay2 RGB resolution, RGB and YUV have different xres value*/
1548+ xres = fbi->fb.var.xres;
1549+ yres = fbi->fb.var.yres;
1550+
1551+ OVL2C2 = (fbi->format << 20) | (fbi->ypos << 10) | fbi->xpos;
1552+ OVL2C1 = OVL2C1_O2EN | (bpp2 << 20) | ((yres-1)<<10) | (xres-1);
1553+ /* setup RGB DMA */
1554+ if (fbi->state == C_DISABLE || fbi->state == C_BLANK)
1555+ FDADR2 = fbi->dma2->fdadr;
1556+ else
1557+ FBR2 = fbi->dma2->fdadr | 0x1;
1558+ } else {
1559+ /* overlay2 YUV resolution */
1560+ xres = fbi->fb.fix.line_length;
1561+ yres = fbi->fb.var.yres;
1562+
1563+ OVL2C2 = (fbi->format << 20) | (fbi->ypos << 10) | fbi->xpos;
1564+ OVL2C1 = OVL2C1_O2EN | (bpp2 << 20) | ((yres-1)<<10) | (xres-1);
1565+
1566+ if (fbi->state == C_DISABLE || fbi->state == C_BLANK) {
1567+ FDADR2 = fbi->dma2->fdadr;
1568+ FDADR3 = fbi->dma3->fdadr;
1569+ FDADR4 = fbi->dma4->fdadr;
1570+ } else {
1571+ FBR2 = fbi->dma2->fdadr | 0x01;
1572+ FBR3 = fbi->dma3->fdadr | 0x01;
1573+ FBR4 = fbi->dma4->fdadr | 0x01;
1574+ }
1575+ }
1576+
1577+ fbi->state = C_ENABLE;
1578+ return 0;
1579+}
1580+
1581+static int overlay2fb_disable(struct fb_info *info)
1582+{
1583+ struct overlayfb_info *fbi = (struct overlayfb_info*)info;
1584+ int done;
1585+
1586+ if (fbi->state == C_DISABLE)
1587+ return 0;
1588+ if (fbi->state == C_BLANK) {
1589+ fbi->state = C_DISABLE;
1590+ return 0;
1591+ }
1592+
1593+ fbi->state = C_DISABLE;
1594+
1595+ /* clear O2EN */
1596+ OVL2C1 &= ~OVL2C1_O2EN;
1597+
1598+ /* Make overlay2 can't disable/enable
1599+ * correctly sometimes.
1600+ */
1601+ CLEAR_LCD_INTR(LCSR1, LCSR1_BS2);
1602+
1603+ if (fbi->format == 0)
1604+ FBR2 = 0x3;
1605+ else {
1606+ FBR2 = 0x3;
1607+ FBR3 = 0x3;
1608+ FBR4 = 0x3;
1609+ }
1610+
1611+ done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS2, 100);
1612+
1613+ if (!done) {
1614+ pr_debug(KERN_INFO "%s: timeout\n", __FUNCTION__);
1615+ return -1;
1616+ }
1617+ return 0;
1618+}
1619+
1620+static int overlay2fb_blank(int blank, struct fb_info *info)
1621+{
1622+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1623+ int err=0;
1624+
1625+ switch(blank)
1626+ {
1627+ case 0:
1628+ err = overlay2fb_enable(info);
1629+ if (err) {
1630+ fbi->state = C_DISABLE;
1631+ pxafb_set_ctrlr_state(fbi->basefb, C_REENABLE);
1632+ }
1633+ break;
1634+ case 1:
1635+ err = overlay2fb_disable(info);
1636+ if (err) {
1637+ fbi->state = C_DISABLE;
1638+ pxafb_set_ctrlr_state(fbi->basefb, C_REENABLE);
1639+ }
1640+ break;
1641+ default:
1642+ /* reserved */
1643+ break;
1644+ }
1645+
1646+ return err;
1647+}
1648+
1649+
1650+static int overlay2fb_check_var( struct fb_var_screeninfo *var, struct fb_info *info)
1651+{
1652+ int xpos, ypos, xres, yres;
1653+ int format;
1654+ struct overlayfb_info *fbi=(struct overlayfb_info*)info;
1655+
1656+ xres=yres=0;
1657+
1658+ xpos = (var->nonstd & 0x3ff);
1659+ ypos = (var->nonstd >> 10) & 0x3ff;
1660+ format = (var->nonstd >>20) & 0x7;
1661+
1662+
1663+ /* Palnar YCbCr444, YCbCr422, YCbCr420 */
1664+ if ( (format != 0x4) && (format != 0x3) && (format != 0x2) && (format !=0x0))
1665+ return -EINVAL;
1666+
1667+ /* dummy pixels */
1668+ switch(format) {
1669+ case 0x0: /* RGB */
1670+ xres = var->xres;
1671+ break;
1672+ case 0x2: /* 444 */
1673+ xres = (var->xres + 0x3) & ~(0x3);
1674+ break;
1675+ case 0x3: /* 422 */
1676+ xres = (var->xres + 0x7) & ~(0x7);
1677+ break;
1678+ case 0x4: /* 420 */
1679+ xres = (var->xres + 0xf) & ~(0xf);
1680+ break;
1681+ }
1682+ yres = var->yres;
1683+
1684+ if ( (xpos + xres) > fbi->basefb->fb.var.xres )
1685+ return -EINVAL;
1686+
1687+ if ( (ypos + yres) > fbi->basefb->fb.var.yres )
1688+ return -EINVAL;
1689+
1690+ fbi->old_var=*var;
1691+
1692+ var->activate=FB_ACTIVATE_NOW;
1693+
1694+ return 0;
1695+
1696+}
1697+
1698+
1699+/*
1700+ * overlay2fb_set_var()
1701+ *
1702+ * var.nonstd is used as YCbCr format.
1703+ * var.red/green/blue is used as (Y/Cb/Cr) vector
1704+ */
1705+
1706+static int overlay2fb_set_par(struct fb_info *info)
1707+{
1708+ unsigned int xpos, ypos;
1709+ int format, err;
1710+
1711+ struct overlayfb_info *fbi=(struct overlayfb_info*)info;
1712+ struct fb_var_screeninfo *var = &fbi->fb.var;
1713+
1714+ info->flags &= ~FBINFO_MISC_USEREVENT;
1715+
1716+ if (fbi->state == C_BLANK)
1717+ return 0;
1718+
1719+ if (fbi->state == C_DISABLE)
1720+ goto out1;
1721+
1722+ if ( (var->xres == fbi->old_var.xres) &&
1723+ (var->yres == fbi->old_var.yres) &&
1724+ (var->bits_per_pixel == fbi->old_var.bits_per_pixel) &&
1725+ (((var->nonstd>>20) & 0x7) == fbi->format) )
1726+ goto out2;
1727+
1728+out1:
1729+ xpos = var->nonstd & 0x3ff;
1730+ ypos = (var->nonstd>>10) & 0x3ff;
1731+ format = (var->nonstd>>20) & 0x7;
1732+
1733+
1734+ fbi->format = format;
1735+ if ( fbi->format==0 )
1736+ err = overlay2fb_map_RGB_memory(info);
1737+ else
1738+ err = overlay2fb_map_YUV_memory(info);
1739+
1740+ if (err) return err;
1741+
1742+out2:
1743+ /* position */
1744+ fbi->xpos = var->nonstd & 0x3ff;
1745+ fbi->ypos = (var->nonstd>>10) & 0x3ff;
1746+
1747+ overlay2fb_enable(info);
1748+
1749+ return 0;
1750+}
1751+
1752+static struct fb_ops overlay2fb_ops = {
1753+ .owner = THIS_MODULE,
1754+ .fb_open = overlay2fb_open,
1755+ .fb_release = overlay2fb_release,
1756+ .fb_check_var = overlay2fb_check_var,
1757+ .fb_set_par = overlay2fb_set_par,
1758+ .fb_blank = overlay2fb_blank,
1759+ .fb_fillrect = cfb_fillrect,
1760+ .fb_copyarea = cfb_copyarea,
1761+ .fb_imageblit = cfb_imageblit,
1762+};
1763+
1764+/* Hardware cursor */
1765+
1766+/* Bulverde Cursor Modes */
1767+struct cursorfb_mode{
1768+ int xres;
1769+ int yres;
1770+ int bpp;
1771+};
1772+
1773+static struct cursorfb_mode cursorfb_modes[]={
1774+ { 32, 32, 2},
1775+ { 32, 32, 2},
1776+ { 32, 32, 2},
1777+ { 64, 64, 2},
1778+ { 64, 64, 2},
1779+ { 64, 64, 2},
1780+ {128, 128, 1},
1781+ {128, 128, 1}
1782+};
1783+
1784+static int cursorfb_enable(struct fb_info *info)
1785+{
1786+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1787+
1788+ if (!fbi->map_cpu) return -EINVAL;
1789+
1790+ CCR &= ~CCR_CEN;
1791+
1792+ /* set palette format
1793+ *
1794+ * FIXME: if only cursor uses palette
1795+ */
1796+ LCCR4 = (LCCR4 & (~(0x3<<15))) | (0x1<<15);
1797+
1798+ /* disable branch/start/end of frame interrupt */
1799+ LCCR5 |= (LCCR5_IUM5 | LCCR5_BSM5 | LCCR5_EOFM5 | LCCR5_SOFM5);
1800+
1801+ /* load palette and frame data */
1802+ if (fbi->state == C_DISABLE) {
1803+ FDADR5 = fbi->dma5_pal->fdadr;
1804+ udelay(1);
1805+ FDADR5 = fbi->dma5_frame->fdadr;
1806+ udelay(1);
1807+
1808+ }
1809+ else {
1810+ FBR5 = fbi->dma5_pal->fdadr | 0x1;
1811+ udelay(1);
1812+ FBR5 = fbi->dma5_frame->fdadr | 0x1;
1813+ udelay(1);
1814+ }
1815+
1816+ CCR = CCR_CEN | (fbi->ypos << 15) | (fbi->xpos << 5) | (fbi->format);
1817+
1818+ fbi->state = C_ENABLE;
1819+
1820+ return 0;
1821+}
1822+
1823+static int cursorfb_disable(struct fb_info *info)
1824+{
1825+ struct overlayfb_info *fbi = (struct overlayfb_info*)info;
1826+ int done, ret = 0;
1827+
1828+ fbi->state = C_DISABLE;
1829+
1830+ done = WAIT_FOR_LCD_INTR(LCSR1, LCSR1_BS5, 100);
1831+ if (!done) ret = -1;
1832+
1833+ CCR &= ~CCR_CEN;
1834+
1835+ return ret;
1836+}
1837+
1838+static int cursorfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1839+ u_int trans, struct fb_info *info)
1840+{
1841+ struct overlayfb_info *fbi = (struct overlayfb_info *)info;
1842+ u_int val, ret = 1;
1843+ u_int *pal=(u_int*) fbi->palette_cpu;
1844+
1845+ /* 25bit with Transparcy for 16bpp format */
1846+ if (regno < fbi->palette_size) {
1847+ val = ((trans << 24) & 0x1000000);
1848+ val |= ((red << 16) & 0x0ff0000);
1849+ val |= ((green << 8 ) & 0x000ff00);
1850+ val |= ((blue << 0) & 0x00000ff);
1851+
1852+ pal[regno] = val;
1853+ ret = 0;
1854+ }
1855+ return ret;
1856+}
1857+
1858+int cursorfb_blank(int blank, struct fb_info *info)
1859+{
1860+ switch(blank)
1861+ {
1862+ case 0:
1863+ cursorfb_enable(info);
1864+ break;
1865+ case 1:
1866+ cursorfb_disable(info);
1867+ break;
1868+ default:
1869+ /* reserved */
1870+ break;
1871+ }
1872+ return 0;
1873+}
1874+
1875+static int cursorfb_check_var( struct fb_var_screeninfo *var, struct fb_info *info)
1876+{
1877+ int xpos, ypos, xres, yres;
1878+ int mode;
1879+ struct cursorfb_mode *cursor;
1880+ struct overlayfb_info *fbi=(struct overlayfb_info*)info;
1881+
1882+ mode = var->nonstd & 0x7;
1883+ xpos = (var->nonstd>>5) & 0x3ff;
1884+ ypos = (var->nonstd>>15) & 0x3ff;
1885+
1886+ if (mode>7 || mode <0 )
1887+ return -EINVAL;
1888+
1889+ cursor = cursorfb_modes + mode;
1890+
1891+ xres = cursor->xres;
1892+ yres = cursor->yres;
1893+
1894+ if ( (xpos + xres) > fbi->basefb->fb.var.xres )
1895+ return -EINVAL;
1896+
1897+ if ( (ypos + yres) > fbi->basefb->fb.var.yres )
1898+ return -EINVAL;
1899+
1900+ return 0;
1901+
1902+}
1903+
1904+static int cursorfb_set_par(struct fb_info *info)
1905+{
1906+ struct overlayfb_info *fbi = (struct overlayfb_info*) info;
1907+ struct fb_var_screeninfo *var = &fbi->fb.var;
1908+ struct cursorfb_mode *cursor;
1909+ int mode, xpos, ypos;
1910+ int err;
1911+
1912+ info->flags &= ~FBINFO_MISC_USEREVENT;
1913+
1914+ mode = var->nonstd & 0x7;
1915+ xpos = (var->nonstd>>5) & 0x3ff;
1916+ ypos = (var->nonstd>>15) & 0x3ff;
1917+
1918+ if (mode != fbi->format) {
1919+ cursor = cursorfb_modes + mode;
1920+
1921+ /* update "var" info */
1922+ fbi->fb.var.xres = cursor->xres;
1923+ fbi->fb.var.yres = cursor->yres;
1924+ fbi->fb.var.bits_per_pixel = cursor->bpp;
1925+
1926+ /* alloc video memory
1927+ *
1928+ * 4k is engouh for 128x128x1 cursor,
1929+ * - 2k for cursor pixels,
1930+ * - 2k for palette data, plus 2 dma descriptor
1931+ */
1932+ if (!fbi->map_cpu) {
1933+ fbi->map_size = PAGE_SIZE;
1934+ fbi->map_cpu = (unsigned long)dma_alloc_writecombine(NULL, fbi->map_size,
1935+ &fbi->map_dma, GFP_KERNEL );
1936+ if (!fbi->map_cpu) return -ENOMEM;
1937+ }
1938+
1939+ cursor = cursorfb_modes + mode;
1940+
1941+ /* update overlay & fix "info" */
1942+ fbi->screen_cpu = fbi->map_cpu;
1943+ fbi->palette_cpu = fbi->map_cpu + (PAGE_SIZE/2);
1944+ fbi->screen_dma = fbi->map_dma;
1945+ fbi->palette_dma = fbi->map_dma + (PAGE_SIZE/2);
1946+
1947+ fbi->format = mode;
1948+ fbi->palette_size = (1<<cursor->bpp);
1949+ fbi->fb.fix.smem_start = fbi->screen_dma;
1950+ fbi->fb.fix.smem_len = cursor->xres * cursor->yres * cursor->bpp / 8;
1951+ fbi->fb.fix.line_length = cursor->xres * cursor->bpp / 8;
1952+
1953+ fbi->dma5_pal = (struct pxafb_dma_descriptor*)(fbi->map_cpu + PAGE_SIZE - 16 );
1954+ fbi->dma5_pal->fdadr = (fbi->map_dma + PAGE_SIZE - 16);
1955+ fbi->dma5_pal->fsadr = fbi->palette_dma;
1956+ fbi->dma5_pal->fidr = 0;
1957+ fbi->dma5_pal->ldcmd = (fbi->palette_size<<2) | LDCMD_PAL;
1958+
1959+ fbi->dma5_frame = (struct pxafb_dma_descriptor*)(fbi->map_cpu + PAGE_SIZE - 32 );
1960+ fbi->dma5_frame->fdadr = (fbi->map_dma + PAGE_SIZE - 32);
1961+ fbi->dma5_frame->fsadr = fbi->screen_dma;
1962+ fbi->dma5_frame->fidr = 0;
1963+ fbi->dma5_frame->ldcmd = fbi->fb.fix.smem_len;
1964+
1965+ /* alloc & set default cmap */
1966+ err = fb_alloc_cmap(&fbi->fb.cmap, fbi->palette_size, 0);
1967+ if (err) return err;
1968+ err = fb_set_cmap(&fbi->fb.cmap, info);
1969+ if (err) return err;
1970+ }
1971+
1972+ /* update overlay info */
1973+ if ( (xpos != fbi->xpos) || (ypos != fbi->ypos) ) {
1974+ fbi->xpos = xpos;
1975+ fbi->ypos = ypos;
1976+ }
1977+
1978+ cursorfb_enable(info);
1979+ pxafb_set_ctrlr_state(fbi->basefb, C_REENABLE);
1980+
1981+ return 0;
1982+}
1983+
1984+static struct fb_ops cursorfb_ops = {
1985+ .owner = THIS_MODULE,
1986+ .fb_check_var = cursorfb_check_var,
1987+ .fb_set_par = cursorfb_set_par,
1988+ .fb_blank = cursorfb_blank,
1989+ .fb_fillrect = cfb_fillrect,
1990+ .fb_copyarea = cfb_copyarea,
1991+ .fb_imageblit = cfb_imageblit,
1992+ .fb_setcolreg = cursorfb_setcolreg,
1993+};
1994+
1995+static struct overlayfb_info * __init overlay1fb_init_fbinfo(void)
1996+{
1997+ struct overlayfb_info *fbi;
1998+
1999+ fbi = kmalloc(sizeof(struct overlayfb_info) + sizeof(u16) * 16, GFP_KERNEL);
2000+ if (!fbi)
2001+ return NULL;
2002+
2003+ memset(fbi, 0, sizeof(struct overlayfb_info) );
2004+
2005+ fbi->refcount = 0;
2006+ init_MUTEX(&fbi->mutex);
2007+
2008+ strcpy(fbi->fb.fix.id, "overlay1");
2009+
2010+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
2011+ fbi->fb.fix.type_aux = 0;
2012+ fbi->fb.fix.xpanstep = 0;
2013+ fbi->fb.fix.ypanstep = 0;
2014+ fbi->fb.fix.ywrapstep = 0;
2015+ fbi->fb.fix.accel = FB_ACCEL_NONE;
2016+
2017+ fbi->fb.var.nonstd = 0;
2018+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
2019+ fbi->fb.var.height = -1;
2020+ fbi->fb.var.width = -1;
2021+ fbi->fb.var.accel_flags = 0;
2022+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
2023+
2024+
2025+ fbi->fb.fbops = &overlay1fb_ops;
2026+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
2027+ fbi->fb.node = -1;
2028+ fbi->fb.pseudo_palette = NULL;
2029+
2030+ fbi->xpos = 0;
2031+ fbi->ypos = 0;
2032+ fbi->format = -1;
2033+ fbi->state = C_DISABLE;
2034+
2035+ return fbi;
2036+}
2037+
2038+static struct overlayfb_info * __init overlay2fb_init_fbinfo(void)
2039+{
2040+ struct overlayfb_info *fbi;
2041+
2042+ fbi = kmalloc(sizeof(struct overlayfb_info) + sizeof(u16) * 16, GFP_KERNEL);
2043+ if (!fbi)
2044+ return NULL;
2045+
2046+ memset(fbi, 0, sizeof(struct overlayfb_info) );
2047+
2048+ fbi->refcount = 0;
2049+ init_MUTEX(&fbi->mutex);
2050+
2051+ strcpy(fbi->fb.fix.id, "overlay2");
2052+
2053+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
2054+ fbi->fb.fix.type_aux = 0;
2055+ fbi->fb.fix.xpanstep = 0;
2056+ fbi->fb.fix.ypanstep = 0;
2057+ fbi->fb.fix.ywrapstep = 0;
2058+ fbi->fb.fix.accel = FB_ACCEL_NONE;
2059+
2060+ fbi->fb.var.nonstd = 0;
2061+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
2062+ fbi->fb.var.height = -1;
2063+ fbi->fb.var.width = -1;
2064+ fbi->fb.var.accel_flags = 0;
2065+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
2066+
2067+ fbi->fb.fbops = &overlay2fb_ops;
2068+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
2069+ fbi->fb.node = -1;
2070+ fbi->fb.pseudo_palette = NULL;
2071+
2072+ fbi->xpos = 0;
2073+ fbi->ypos = 0;
2074+ fbi->format = -1;
2075+ fbi->state = C_DISABLE;
2076+
2077+ return fbi;
2078+}
2079+
2080+static struct overlayfb_info * __init cursorfb_init_fbinfo(void)
2081+{
2082+ struct overlayfb_info *fbi;
2083+
2084+ fbi = kmalloc(sizeof(struct overlayfb_info) + sizeof(u16) * 16, GFP_KERNEL);
2085+ if (!fbi)
2086+ return NULL;
2087+
2088+ memset(fbi, 0, sizeof(struct overlayfb_info) );
2089+
2090+ fbi->refcount = 0;
2091+ init_MUTEX(&fbi->mutex);
2092+
2093+ strcpy(fbi->fb.fix.id, "cursor");
2094+
2095+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
2096+ fbi->fb.fix.type_aux = 0;
2097+ fbi->fb.fix.xpanstep = 0;
2098+ fbi->fb.fix.ypanstep = 0;
2099+ fbi->fb.fix.ywrapstep = 0;
2100+ fbi->fb.fix.accel = FB_ACCEL_NONE;
2101+
2102+ fbi->fb.var.nonstd = 0;
2103+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
2104+ fbi->fb.var.height = -1;
2105+ fbi->fb.var.width = -1;
2106+ fbi->fb.var.accel_flags = 0;
2107+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
2108+
2109+ fbi->fb.fbops = &cursorfb_ops;
2110+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
2111+ fbi->fb.node = -1;
2112+ fbi->fb.pseudo_palette = NULL;
2113+
2114+
2115+ fbi->xpos = 0;
2116+ fbi->ypos = 0;
2117+ fbi->format = -1;
2118+ fbi->state = C_DISABLE;
2119+
2120+ return fbi;
2121+}
2122+
2123+
2124+void pxa_set_overlay_ctrlr_state(struct pxafb_info *fbi, u_int state)
2125+{
2126+ switch (state) {
2127+ case C_DISABLE:
2128+ DISABLE_OVERLAYS(fbi);
2129+ break;
2130+ case C_ENABLE:
2131+ ENABLE_OVERLAYS(fbi);
2132+ break;
2133+ case C_BLANK:
2134+ BLANK_OVERLAYS(fbi);
2135+ break;
2136+ case C_UNBLANK:
2137+ UNBLANK_OVERLAYS(fbi);
2138+ break;
2139+ default:
2140+ break;
2141+ }
2142+}
2143+
2144+static int is_pxafb_device(struct device * dev, void * data)
2145+{
2146+ struct platform_device *pdev = container_of(dev, struct platform_device, dev);
2147+
2148+ return (strncmp(pdev->name, "pxa2xx-fb", 9) == 0);
2149+}
2150+
2151+static int __devinit pxafb_overlay_init(void)
2152+{
2153+ int ret;
2154+ struct overlayfb_info *overlay1fb, *overlay2fb, *cursorfb;
2155+ struct pxafb_info *fbi;
2156+ struct device *dev;
2157+
2158+ ret = -1;
2159+ overlay1fb = overlay2fb = cursorfb = NULL;
2160+ fbi = NULL;
2161+
2162+ dev = bus_find_device(&platform_bus_type, NULL, NULL, is_pxafb_device);
2163+ if (!dev) {
2164+ printk(KERN_INFO "Base framebuffer not exists, failed to load overlay driver!\n");
2165+ return ret;
2166+ }
2167+
2168+ fbi = dev_get_drvdata(dev);
2169+ if (fbi == NULL) {
2170+ printk(KERN_INFO "Base framebuffer not initialized, failed to load overlay driver!\n");
2171+ return ret;
2172+ }
2173+
2174+ /* Overlay 1 windows */
2175+ overlay1fb = overlay1fb_init_fbinfo();
2176+
2177+ if (!overlay1fb) {
2178+ ret = -ENOMEM;
2179+ printk("overlay1fb_init_fbinfo failed\n");
2180+ goto failed;
2181+ }
2182+
2183+ ret = register_framebuffer(&overlay1fb->fb);
2184+ if (ret < 0)
2185+ goto failed;
2186+
2187+ /* Overlay 2 window */
2188+ overlay2fb = overlay2fb_init_fbinfo();
2189+
2190+ if (!overlay2fb) {
2191+ ret = -ENOMEM;
2192+ printk("overlay2fb_init_fbinfo failed\n");
2193+ goto failed;
2194+ }
2195+
2196+ ret = register_framebuffer(&overlay2fb->fb);
2197+ if (ret < 0) goto failed;
2198+
2199+ /* Hardware cursor window */
2200+ cursorfb = cursorfb_init_fbinfo();
2201+
2202+ if (!cursorfb) {
2203+ ret = -ENOMEM;
2204+ printk("cursorfb_init_fbinfo failed\n");
2205+ goto failed;
2206+ }
2207+
2208+ ret = register_framebuffer(&cursorfb->fb);
2209+ if (ret < 0) goto failed;
2210+
2211+
2212+ /* set refernce to Overlays */
2213+ fbi->overlay1fb = overlay1fb;
2214+ fbi->overlay2fb = overlay2fb;
2215+ fbi->cursorfb = cursorfb;
2216+ fbi->set_overlay_ctrlr_state=pxa_set_overlay_ctrlr_state;
2217+
2218+ /* set refernce to BaseFrame */
2219+ overlay1fb->basefb = fbi;
2220+ overlay2fb->basefb = fbi;
2221+ cursorfb->basefb = fbi;
2222+
2223+ printk(KERN_INFO "Load PXA Overlay driver successfully!\n");
2224+
2225+ return 0;
2226+
2227+failed:
2228+ if (overlay1fb)
2229+ kfree(overlay1fb);
2230+ if (overlay2fb)
2231+ kfree(overlay2fb);
2232+ if (cursorfb)
2233+ kfree(cursorfb);
2234+ printk(KERN_INFO "Load PXA Overlay driver failed!\n");
2235+ return ret;
2236+}
2237+
2238+static void __exit pxafb_overlay_exit(void)
2239+{
2240+ struct pxafb_info *fbi;
2241+ struct device *dev;
2242+
2243+ dev = bus_find_device(&platform_bus_type, NULL, NULL, is_pxafb_device);
2244+ if (!dev)
2245+ return;
2246+
2247+ fbi = dev_get_drvdata(dev);
2248+ if (!fbi)
2249+ return;
2250+
2251+ if (fbi->overlay1fb) {
2252+ unregister_framebuffer(&(fbi->overlay1fb->fb));
2253+ kfree(fbi->overlay1fb);
2254+ fbi->overlay1fb = NULL;
2255+ }
2256+
2257+ if (fbi->overlay2fb) {
2258+ unregister_framebuffer(&(fbi->overlay2fb->fb));
2259+ kfree(fbi->overlay2fb);
2260+ fbi->overlay2fb = NULL;
2261+ }
2262+
2263+ if (fbi->cursorfb) {
2264+ unregister_framebuffer(&(fbi->cursorfb->fb));
2265+ kfree(fbi->cursorfb);
2266+ fbi->cursorfb = NULL;
2267+ }
2268+
2269+ fbi->set_overlay_ctrlr_state = NULL;
2270+
2271+ printk(KERN_INFO "Unload PXA Overlay driver successfully!\n");
2272+ return;
2273+}
2274+
2275+
2276+module_init(pxafb_overlay_init);
2277+module_exit(pxafb_overlay_exit);
2278+
2279+MODULE_DESCRIPTION("Loadable framebuffer overlay driver for PXA");
2280+MODULE_LICENSE("GPL");
2281+
2282--- linux-2.6.24-rc1.orig/include/asm-arm/arch-pxa/pxa-regs.h
2283+++ linux-2.6.24-rc1/include/asm-arm/arch-pxa/pxa-regs.h
2284@@ -789,11 +789,18 @@
2285 #define UDC_INT_PACKETCMP (0x1)
2286
2287 #define UDCICR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
2288+/* Older defines, do not use. */
2289 #define UDCICR1_IECC (1 << 31) /* IntEn - Configuration Change */
2290 #define UDCICR1_IESOF (1 << 30) /* IntEn - Start of Frame */
2291 #define UDCICR1_IERU (1 << 29) /* IntEn - Resume */
2292 #define UDCICR1_IESU (1 << 28) /* IntEn - Suspend */
2293 #define UDCICR1_IERS (1 << 27) /* IntEn - Reset */
2294+/* New defines. */
2295+#define UDCISR1_IRCC (1 << 31) /* IntEn - Configuration Change */
2296+#define UDCISR1_IRSOF (1 << 30) /* IntEn - Start of Frame */
2297+#define UDCISR1_IRRU (1 << 29) /* IntEn - Resume */
2298+#define UDCISR1_IRSU (1 << 28) /* IntEn - Suspend */
2299+#define UDCISR1_IRRS (1 << 27) /* IntEn - Reset */
2300
2301 #define UDCISR0 __REG(0x4060000C) /* UDC Interrupt Status Register 0 */
2302 #define UDCISR1 __REG(0x40600010) /* UDC Interrupt Status Register 1 */
2303@@ -1827,6 +1834,8 @@
2304 #define DFBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
2305 #define DFBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
2306 #define LCSR __REG(0x44000038) /* LCD Controller Status Register */
2307+#define LCSR0 __REG(0x44000038) /* LCD Controller Status Register */
2308+#define LCSR1 __REG(0x44000034) /* LCD Controller Status Register */
2309 #define LIIDR __REG(0x4400003C) /* LCD Controller Interrupt ID Register */
2310 #define TMEDRGBR __REG(0x44000040) /* TMED RGB Seed Register */
2311 #define TMEDCR __REG(0x44000044) /* TMED Control Register */
2312@@ -1836,6 +1845,10 @@
2313 #define LCCR3_4BPP (2 << 24)
2314 #define LCCR3_8BPP (3 << 24)
2315 #define LCCR3_16BPP (4 << 24)
2316+#define LCCR3_18BPP (6 << 24)
2317+#define LCCR3_19BPP (8 << 24)
2318+#define LCCR3_24BPP (9 << 24)
2319+#define LCCR3_25BPP (10<< 24)
2320
2321 #define LCCR3_PDFOR_0 (0 << 30)
2322 #define LCCR3_PDFOR_1 (1 << 30)
2323@@ -2010,6 +2023,104 @@
2324
2325 #define LDCMD_PAL (1 << 26) /* instructs DMA to load palette buffer */
2326
2327+/* Overlay1 & Overlay2 & Hardware Cursor */
2328+#define LCSR1_SOF1 (1 << 0)
2329+#define LCSR1_SOF2 (1 << 1)
2330+#define LCSR1_SOF3 (1 << 2)
2331+#define LCSR1_SOF4 (1 << 3)
2332+#define LCSR1_SOF5 (1 << 4)
2333+#define LCSR1_SOF6 (1 << 5)
2334+
2335+#define LCSR1_EOF1 (1 << 8)
2336+#define LCSR1_EOF2 (1 << 9)
2337+#define LCSR1_EOF3 (1 << 10)
2338+#define LCSR1_EOF4 (1 << 11)
2339+#define LCSR1_EOF5 (1 << 12)
2340+#define LCSR1_EOF6 (1 << 13)
2341+
2342+#define LCSR1_BS1 (1 << 16)
2343+#define LCSR1_BS2 (1 << 17)
2344+#define LCSR1_BS3 (1 << 18)
2345+#define LCSR1_BS4 (1 << 19)
2346+#define LCSR1_BS5 (1 << 20)
2347+#define LCSR1_BS6 (1 << 21)
2348+
2349+#define LCSR1_IU2 (1 << 25)
2350+#define LCSR1_IU3 (1 << 26)
2351+#define LCSR1_IU4 (1 << 27)
2352+#define LCSR1_IU5 (1 << 28)
2353+#define LCSR1_IU6 (1 << 29)
2354+
2355+#define LDCMD_SOFINT (1 << 22)
2356+#define LDCMD_EOFINT (1 << 21)
2357+
2358+
2359+#define LCCR5_SOFM1 (1<<0) /* Start Of Frame Mask for Overlay 1 (channel 1) */
2360+#define LCCR5_SOFM2 (1<<1) /* Start Of Frame Mask for Overlay 2 (channel 2) */
2361+#define LCCR5_SOFM3 (1<<2) /* Start Of Frame Mask for Overlay 2 (channel 3) */
2362+#define LCCR5_SOFM4 (1<<3) /* Start Of Frame Mask for Overlay 2 (channel 4) */
2363+#define LCCR5_SOFM5 (1<<4) /* Start Of Frame Mask for cursor (channel 5) */
2364+#define LCCR5_SOFM6 (1<<5) /* Start Of Frame Mask for command data (channel 6) */
2365+
2366+#define LCCR5_EOFM1 (1<<8) /* End Of Frame Mask for Overlay 1 (channel 1) */
2367+#define LCCR5_EOFM2 (1<<9) /* End Of Frame Mask for Overlay 2 (channel 2) */
2368+#define LCCR5_EOFM3 (1<<10) /* End Of Frame Mask for Overlay 2 (channel 3) */
2369+#define LCCR5_EOFM4 (1<<11) /* End Of Frame Mask for Overlay 2 (channel 4) */
2370+#define LCCR5_EOFM5 (1<<12) /* End Of Frame Mask for cursor (channel 5) */
2371+#define LCCR5_EOFM6 (1<<13) /* End Of Frame Mask for command data (channel 6) */
2372+
2373+#define LCCR5_BSM1 (1<<16) /* Branch mask for Overlay 1 (channel 1) */
2374+#define LCCR5_BSM2 (1<<17) /* Branch mask for Overlay 2 (channel 2) */
2375+#define LCCR5_BSM3 (1<<18) /* Branch mask for Overlay 2 (channel 3) */
2376+#define LCCR5_BSM4 (1<<19) /* Branch mask for Overlay 2 (channel 4) */
2377+#define LCCR5_BSM5 (1<<20) /* Branch mask for cursor (channel 5) */
2378+#define LCCR5_BSM6 (1<<21) /* Branch mask for data command (channel 6) */
2379+
2380+#define LCCR5_IUM1 (1<<24) /* Input FIFO Underrun Mask for Overlay 1 */
2381+#define LCCR5_IUM2 (1<<25) /* Input FIFO Underrun Mask for Overlay 2 */
2382+#define LCCR5_IUM3 (1<<26) /* Input FIFO Underrun Mask for Overlay 2 */
2383+#define LCCR5_IUM4 (1<<27) /* Input FIFO Underrun Mask for Overlay 2 */
2384+#define LCCR5_IUM5 (1<<28) /* Input FIFO Underrun Mask for cursor */
2385+#define LCCR5_IUM6 (1<<29) /* Input FIFO Underrun Mask for data command */
2386+
2387+#define OVL1C1_O1EN (1<<31) /* Enable bit for Overlay 1 */
2388+#define OVL2C1_O2EN (1<<31) /* Enable bit for Overlay 2 */
2389+#define CCR_CEN (1<<31) /* Enable bit for Cursor */
2390+
2391+/* LCD registers */
2392+#define LCCR4 __REG(0x44000010) /* LCD Controller Control Register 4 */
2393+#define LCCR5 __REG(0x44000014) /* LCD Controller Control Register 5 */
2394+#define FBR0 __REG(0x44000020) /* DMA Channel 0 Frame Branch Register */
2395+#define FBR1 __REG(0x44000024) /* DMA Channel 1 Frame Branch Register */
2396+#define FBR2 __REG(0x44000028) /* DMA Channel 2 Frame Branch Register */
2397+#define FBR3 __REG(0x4400002C) /* DMA Channel 3 Frame Branch Register */
2398+#define FBR4 __REG(0x44000030) /* DMA Channel 4 Frame Branch Register */
2399+#define FDADR2 __REG(0x44000220) /* DMA Channel 2 Frame Descriptor Address Register */
2400+#define FSADR2 __REG(0x44000224) /* DMA Channel 2 Frame Source Address Register */
2401+#define FIDR2 __REG(0x44000228) /* DMA Channel 2 Frame ID Register */
2402+#define LDCMD2 __REG(0x4400022C) /* DMA Channel 2 Command Register */
2403+#define FDADR3 __REG(0x44000230) /* DMA Channel 3 Frame Descriptor Address Register */
2404+#define FSADR3 __REG(0x44000234) /* DMA Channel 3 Frame Source Address Register */
2405+#define FIDR3 __REG(0x44000238) /* DMA Channel 3 Frame ID Register */
2406+#define LDCMD3 __REG(0x4400023C) /* DMA Channel 3 Command Register */
2407+#define FDADR4 __REG(0x44000240) /* DMA Channel 4 Frame Descriptor Address Register */
2408+#define FSADR4 __REG(0x44000244) /* DMA Channel 4 Frame Source Address Register */
2409+#define FIDR4 __REG(0x44000248) /* DMA Channel 4 Frame ID Register */
2410+#define LDCMD4 __REG(0x4400024C) /* DMA Channel 4 Command Register */
2411+#define FDADR5 __REG(0x44000250) /* DMA Channel 5 Frame Descriptor Address Register */
2412+#define FSADR5 __REG(0x44000254) /* DMA Channel 5 Frame Source Address Register */
2413+#define FIDR5 __REG(0x44000258) /* DMA Channel 5 Frame ID Register */
2414+#define LDCMD5 __REG(0x4400025C) /* DMA Channel 5 Command Register */
2415+
2416+#define OVL1C1 __REG(0x44000050) /* Overlay 1 Control Register 1 */
2417+#define OVL1C2 __REG(0x44000060) /* Overlay 1 Control Register 2 */
2418+#define OVL2C1 __REG(0x44000070) /* Overlay 2 Control Register 1 */
2419+#define OVL2C2 __REG(0x44000080) /* Overlay 2 Control Register 2 */
2420+#define CCR __REG(0x44000090) /* Cursor Control Register */
2421+
2422+#define FBR5 __REG(0x44000110) /* DMA Channel 5 Frame Branch Register */
2423+#define FBR6 __REG(0x44000114) /* DMA Channel 6 Frame Branch Register */
2424+
2425 /*
2426 * Memory controller
2427 */
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa_fb_overlay.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa_fb_overlay.patch
index 49c59b3275..49c59b3275 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/pxa_fb_overlay.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/pxa_fb_overlay.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
index b513ba1466..b513ba1466 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/serial-add-support-for-non-standard-xtals-to-16c950-driver.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/squashfs3.0-2.6.15.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.0-2.6.15.patch
index a210afcaf8..a210afcaf8 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/squashfs3.0-2.6.15.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.0-2.6.15.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.2-2.6.20-r0.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.2-2.6.20-r0.patch
new file mode 100644
index 0000000000..3870b317e4
--- /dev/null
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/squashfs3.2-2.6.20-r0.patch
@@ -0,0 +1,4376 @@
1--- linux-2.6.24-rc1.orig/fs/Kconfig
2+++ linux-2.6.24-rc1/fs/Kconfig
3@@ -1405,6 +1405,71 @@
4
5 If unsure, say N.
6
7+config SQUASHFS
8+ tristate "SquashFS 3.2 - Squashed file system support"
9+ select ZLIB_INFLATE
10+ help
11+ Saying Y here includes support for SquashFS 3.2 (a Compressed Read-Only File
12+ System). Squashfs is a highly compressed read-only filesystem for Linux.
13+ It uses zlib compression to compress both files, inodes and directories.
14+ Inodes in the system are very small and all blocks are packed to minimise
15+ data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
16+ SquashFS 3.1 supports 64 bit filesystems and files (larger than 4GB), full
17+ uid/gid information, hard links and timestamps.
18+
19+ Squashfs is intended for general read-only filesystem use, for archival
20+ use (i.e. in cases where a .tar.gz file may be used), and in embedded
21+ systems where low overhead is needed. Further information and filesystem tools
22+ are available from http://squashfs.sourceforge.net.
23+
24+ If you want to compile this as a module ( = code which can be
25+ inserted in and removed from the running kernel whenever you want),
26+ say M here and read <file:Documentation/modules.txt>. The module
27+ will be called squashfs. Note that the root file system (the one
28+ containing the directory /) cannot be compiled as a module.
29+
30+ If unsure, say N.
31+
32+config SQUASHFS_EMBEDDED
33+
34+ bool "Additional options for memory-constrained systems"
35+ depends on SQUASHFS
36+ default n
37+ help
38+ Saying Y here allows you to specify cache sizes and how Squashfs
39+ allocates memory. This is only intended for memory constrained
40+ systems.
41+
42+ If unsure, say N.
43+
44+config SQUASHFS_FRAGMENT_CACHE_SIZE
45+ int "Number of fragments cached" if SQUASHFS_EMBEDDED
46+ depends on SQUASHFS
47+ default "3"
48+ help
49+ By default SquashFS caches the last 3 fragments read from
50+ the filesystem. Increasing this amount may mean SquashFS
51+ has to re-read fragments less often from disk, at the expense
52+ of extra system memory. Decreasing this amount will mean
53+ SquashFS uses less memory at the expense of extra reads from disk.
54+
55+ Note there must be at least one cached fragment. Anything
56+ much more than three will probably not make much difference.
57+
58+config SQUASHFS_VMALLOC
59+ bool "Use Vmalloc rather than Kmalloc" if SQUASHFS_EMBEDDED
60+ depends on SQUASHFS
61+ default n
62+ help
63+ By default SquashFS uses kmalloc to obtain fragment cache memory.
64+ Kmalloc memory is the standard kernel allocator, but it can fail
65+ on memory constrained systems. Because of the way Vmalloc works,
66+ Vmalloc can succeed when kmalloc fails. Specifying this option
67+ will make SquashFS always use Vmalloc to allocate the
68+ fragment cache memory.
69+
70+ If unsure, say N.
71+
72 config VXFS_FS
73 tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
74 depends on BLOCK
75--- linux-2.6.24-rc1.orig/fs/Makefile
76+++ linux-2.6.24-rc1/fs/Makefile
77@@ -72,6 +72,7 @@
78 obj-$(CONFIG_JBD2) += jbd2/
79 obj-$(CONFIG_EXT2_FS) += ext2/
80 obj-$(CONFIG_CRAMFS) += cramfs/
81+obj-$(CONFIG_SQUASHFS) += squashfs/
82 obj-y += ramfs/
83 obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
84 obj-$(CONFIG_CODA_FS) += coda/
85--- /dev/null
86+++ linux-2.6.24-rc1/fs/squashfs/inode.c
87@@ -0,0 +1,2329 @@
88+/*
89+ * Squashfs - a compressed read only filesystem for Linux
90+ *
91+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
92+ * Phillip Lougher <phillip@lougher.org.uk>
93+ *
94+ * This program is free software; you can redistribute it and/or
95+ * modify it under the terms of the GNU General Public License
96+ * as published by the Free Software Foundation; either version 2,
97+ * or (at your option) any later version.
98+ *
99+ * This program is distributed in the hope that it will be useful,
100+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
101+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102+ * GNU General Public License for more details.
103+ *
104+ * You should have received a copy of the GNU General Public License
105+ * along with this program; if not, write to the Free Software
106+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
107+ *
108+ * inode.c
109+ */
110+
111+#include <linux/squashfs_fs.h>
112+#include <linux/module.h>
113+#include <linux/zlib.h>
114+#include <linux/fs.h>
115+#include <linux/squashfs_fs_sb.h>
116+#include <linux/squashfs_fs_i.h>
117+#include <linux/buffer_head.h>
118+#include <linux/vfs.h>
119+#include <linux/vmalloc.h>
120+#include <linux/smp_lock.h>
121+
122+#include "squashfs.h"
123+
124+static void vfs_read_inode(struct inode *i);
125+static struct dentry *squashfs_get_parent(struct dentry *child);
126+static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode);
127+static int squashfs_statfs(struct dentry *, struct kstatfs *);
128+static int squashfs_symlink_readpage(struct file *file, struct page *page);
129+static long long read_blocklist(struct inode *inode, int index,
130+ int readahead_blks, char *block_list,
131+ unsigned short **block_p, unsigned int *bsize);
132+static int squashfs_readpage(struct file *file, struct page *page);
133+static int squashfs_readpage4K(struct file *file, struct page *page);
134+static int squashfs_readdir(struct file *, void *, filldir_t);
135+static struct dentry *squashfs_lookup(struct inode *, struct dentry *,
136+ struct nameidata *);
137+static int squashfs_remount(struct super_block *s, int *flags, char *data);
138+static void squashfs_put_super(struct super_block *);
139+static int squashfs_get_sb(struct file_system_type *,int, const char *, void *,
140+ struct vfsmount *);
141+static struct inode *squashfs_alloc_inode(struct super_block *sb);
142+static void squashfs_destroy_inode(struct inode *inode);
143+static int init_inodecache(void);
144+static void destroy_inodecache(void);
145+
146+static struct file_system_type squashfs_fs_type = {
147+ .owner = THIS_MODULE,
148+ .name = "squashfs",
149+ .get_sb = squashfs_get_sb,
150+ .kill_sb = kill_block_super,
151+ .fs_flags = FS_REQUIRES_DEV
152+};
153+
154+static const unsigned char squashfs_filetype_table[] = {
155+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
156+};
157+
158+static struct super_operations squashfs_super_ops = {
159+ .alloc_inode = squashfs_alloc_inode,
160+ .destroy_inode = squashfs_destroy_inode,
161+ .statfs = squashfs_statfs,
162+ .put_super = squashfs_put_super,
163+ .remount_fs = squashfs_remount
164+};
165+
166+static struct super_operations squashfs_export_super_ops = {
167+ .alloc_inode = squashfs_alloc_inode,
168+ .destroy_inode = squashfs_destroy_inode,
169+ .statfs = squashfs_statfs,
170+ .put_super = squashfs_put_super,
171+ .read_inode = vfs_read_inode
172+};
173+
174+static struct export_operations squashfs_export_ops = {
175+ .get_parent = squashfs_get_parent
176+};
177+
178+SQSH_EXTERN const struct address_space_operations squashfs_symlink_aops = {
179+ .readpage = squashfs_symlink_readpage
180+};
181+
182+SQSH_EXTERN const struct address_space_operations squashfs_aops = {
183+ .readpage = squashfs_readpage
184+};
185+
186+SQSH_EXTERN const struct address_space_operations squashfs_aops_4K = {
187+ .readpage = squashfs_readpage4K
188+};
189+
190+static const struct file_operations squashfs_dir_ops = {
191+ .read = generic_read_dir,
192+ .readdir = squashfs_readdir
193+};
194+
195+SQSH_EXTERN struct inode_operations squashfs_dir_inode_ops = {
196+ .lookup = squashfs_lookup
197+};
198+
199+
200+static struct buffer_head *get_block_length(struct super_block *s,
201+ int *cur_index, int *offset, int *c_byte)
202+{
203+ struct squashfs_sb_info *msblk = s->s_fs_info;
204+ unsigned short temp;
205+ struct buffer_head *bh;
206+
207+ if (!(bh = sb_bread(s, *cur_index)))
208+ goto out;
209+
210+ if (msblk->devblksize - *offset == 1) {
211+ if (msblk->swap)
212+ ((unsigned char *) &temp)[1] = *((unsigned char *)
213+ (bh->b_data + *offset));
214+ else
215+ ((unsigned char *) &temp)[0] = *((unsigned char *)
216+ (bh->b_data + *offset));
217+ brelse(bh);
218+ if (!(bh = sb_bread(s, ++(*cur_index))))
219+ goto out;
220+ if (msblk->swap)
221+ ((unsigned char *) &temp)[0] = *((unsigned char *)
222+ bh->b_data);
223+ else
224+ ((unsigned char *) &temp)[1] = *((unsigned char *)
225+ bh->b_data);
226+ *c_byte = temp;
227+ *offset = 1;
228+ } else {
229+ if (msblk->swap) {
230+ ((unsigned char *) &temp)[1] = *((unsigned char *)
231+ (bh->b_data + *offset));
232+ ((unsigned char *) &temp)[0] = *((unsigned char *)
233+ (bh->b_data + *offset + 1));
234+ } else {
235+ ((unsigned char *) &temp)[0] = *((unsigned char *)
236+ (bh->b_data + *offset));
237+ ((unsigned char *) &temp)[1] = *((unsigned char *)
238+ (bh->b_data + *offset + 1));
239+ }
240+ *c_byte = temp;
241+ *offset += 2;
242+ }
243+
244+ if (SQUASHFS_CHECK_DATA(msblk->sblk.flags)) {
245+ if (*offset == msblk->devblksize) {
246+ brelse(bh);
247+ if (!(bh = sb_bread(s, ++(*cur_index))))
248+ goto out;
249+ *offset = 0;
250+ }
251+ if (*((unsigned char *) (bh->b_data + *offset)) !=
252+ SQUASHFS_MARKER_BYTE) {
253+ ERROR("Metadata block marker corrupt @ %x\n",
254+ *cur_index);
255+ brelse(bh);
256+ goto out;
257+ }
258+ (*offset)++;
259+ }
260+ return bh;
261+
262+out:
263+ return NULL;
264+}
265+
266+
267+SQSH_EXTERN unsigned int squashfs_read_data(struct super_block *s, char *buffer,
268+ long long index, unsigned int length,
269+ long long *next_index, int srclength)
270+{
271+ struct squashfs_sb_info *msblk = s->s_fs_info;
272+ struct squashfs_super_block *sblk = &msblk->sblk;
273+ struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >>
274+ msblk->devblksize_log2) + 2];
275+ unsigned int offset = index & ((1 << msblk->devblksize_log2) - 1);
276+ unsigned int cur_index = index >> msblk->devblksize_log2;
277+ int bytes, avail_bytes, b = 0, k = 0;
278+ unsigned int compressed;
279+ unsigned int c_byte = length;
280+
281+ if (c_byte) {
282+ bytes = msblk->devblksize - offset;
283+ compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte);
284+ c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
285+
286+ TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n", index, compressed
287+ ? "" : "un", (unsigned int) c_byte, srclength);
288+
289+ if (c_byte > srclength || index < 0 || (index + c_byte) > sblk->bytes_used)
290+ goto read_failure;
291+
292+ if (!(bh[0] = sb_getblk(s, cur_index)))
293+ goto block_release;
294+
295+ for (b = 1; bytes < c_byte; b++) {
296+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
297+ goto block_release;
298+ bytes += msblk->devblksize;
299+ }
300+ ll_rw_block(READ, b, bh);
301+ } else {
302+ if (index < 0 || (index + 2) > sblk->bytes_used)
303+ goto read_failure;
304+
305+ if (!(bh[0] = get_block_length(s, &cur_index, &offset,
306+ &c_byte)))
307+ goto read_failure;
308+
309+ bytes = msblk->devblksize - offset;
310+ compressed = SQUASHFS_COMPRESSED(c_byte);
311+ c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
312+
313+ TRACE("Block @ 0x%llx, %scompressed size %d\n", index, compressed
314+ ? "" : "un", (unsigned int) c_byte);
315+
316+ if (c_byte > srclength || (index + c_byte) > sblk->bytes_used)
317+ goto read_failure;
318+
319+ for (b = 1; bytes < c_byte; b++) {
320+ if (!(bh[b] = sb_getblk(s, ++cur_index)))
321+ goto block_release;
322+ bytes += msblk->devblksize;
323+ }
324+ ll_rw_block(READ, b - 1, bh + 1);
325+ }
326+
327+ if (compressed) {
328+ int zlib_err = 0;
329+
330+ /*
331+ * uncompress block
332+ */
333+
334+ mutex_lock(&msblk->read_data_mutex);
335+
336+ msblk->stream.next_out = buffer;
337+ msblk->stream.avail_out = srclength;
338+
339+ for (bytes = 0; k < b; k++) {
340+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
341+ msblk->devblksize - offset :
342+ c_byte - bytes;
343+ wait_on_buffer(bh[k]);
344+ if (!buffer_uptodate(bh[k]))
345+ goto release_mutex;
346+
347+ msblk->stream.next_in = bh[k]->b_data + offset;
348+ msblk->stream.avail_in = avail_bytes;
349+
350+ if (k == 0) {
351+ zlib_err = zlib_inflateInit(&msblk->stream);
352+ if (zlib_err != Z_OK) {
353+ ERROR("zlib_inflateInit returned unexpected result 0x%x, srclength %d\n",
354+ zlib_err, srclength);
355+ goto release_mutex;
356+ }
357+
358+ if (avail_bytes == 0) {
359+ offset = 0;
360+ brelse(bh[k]);
361+ continue;
362+ }
363+ }
364+
365+ zlib_err = zlib_inflate(&msblk->stream, Z_NO_FLUSH);
366+ if (zlib_err != Z_OK && zlib_err != Z_STREAM_END) {
367+ ERROR("zlib_inflate returned unexpected result 0x%x, srclength %d, avail_in %d, avail_out %d\n",
368+ zlib_err, srclength, msblk->stream.avail_in, msblk->stream.avail_out);
369+ goto release_mutex;
370+ }
371+
372+ bytes += avail_bytes;
373+ offset = 0;
374+ brelse(bh[k]);
375+ }
376+
377+ if (zlib_err != Z_STREAM_END)
378+ goto release_mutex;
379+
380+ zlib_err = zlib_inflateEnd(&msblk->stream);
381+ if (zlib_err != Z_OK) {
382+ ERROR("zlib_inflateEnd returned unexpected result 0x%x, srclength %d\n",
383+ zlib_err, srclength);
384+ goto release_mutex;
385+ }
386+ bytes = msblk->stream.total_out;
387+ mutex_unlock(&msblk->read_data_mutex);
388+ } else {
389+ int i;
390+
391+ for(i = 0; i < b; i++) {
392+ wait_on_buffer(bh[i]);
393+ if(!buffer_uptodate(bh[i]))
394+ goto block_release;
395+ }
396+
397+ for (bytes = 0; k < b; k++) {
398+ avail_bytes = (c_byte - bytes) > (msblk->devblksize - offset) ?
399+ msblk->devblksize - offset :
400+ c_byte - bytes;
401+ memcpy(buffer + bytes, bh[k]->b_data + offset, avail_bytes);
402+ bytes += avail_bytes;
403+ offset = 0;
404+ brelse(bh[k]);
405+ }
406+ }
407+
408+ if (next_index)
409+ *next_index = index + c_byte + (length ? 0 :
410+ (SQUASHFS_CHECK_DATA(msblk->sblk.flags)
411+ ? 3 : 2));
412+ return bytes;
413+
414+release_mutex:
415+ mutex_unlock(&msblk->read_data_mutex);
416+
417+block_release:
418+ for (; k < b; k++)
419+ brelse(bh[k]);
420+
421+read_failure:
422+ ERROR("sb_bread failed reading block 0x%x\n", cur_index);
423+ return 0;
424+}
425+
426+
427+SQSH_EXTERN int squashfs_get_cached_block(struct super_block *s, char *buffer,
428+ long long block, unsigned int offset,
429+ int length, long long *next_block,
430+ unsigned int *next_offset)
431+{
432+ struct squashfs_sb_info *msblk = s->s_fs_info;
433+ int n, i, bytes, return_length = length;
434+ long long next_index;
435+
436+ TRACE("Entered squashfs_get_cached_block [%llx:%x]\n", block, offset);
437+
438+ while ( 1 ) {
439+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
440+ if (msblk->block_cache[i].block == block)
441+ break;
442+
443+ mutex_lock(&msblk->block_cache_mutex);
444+
445+ if (i == SQUASHFS_CACHED_BLKS) {
446+ /* read inode header block */
447+ for (i = msblk->next_cache, n = SQUASHFS_CACHED_BLKS;
448+ n ; n --, i = (i + 1) %
449+ SQUASHFS_CACHED_BLKS)
450+ if (msblk->block_cache[i].block !=
451+ SQUASHFS_USED_BLK)
452+ break;
453+
454+ if (n == 0) {
455+ wait_queue_t wait;
456+
457+ init_waitqueue_entry(&wait, current);
458+ add_wait_queue(&msblk->waitq, &wait);
459+ set_current_state(TASK_UNINTERRUPTIBLE);
460+ mutex_unlock(&msblk->block_cache_mutex);
461+ schedule();
462+ set_current_state(TASK_RUNNING);
463+ remove_wait_queue(&msblk->waitq, &wait);
464+ continue;
465+ }
466+ msblk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
467+
468+ if (msblk->block_cache[i].block ==
469+ SQUASHFS_INVALID_BLK) {
470+ if (!(msblk->block_cache[i].data =
471+ kmalloc(SQUASHFS_METADATA_SIZE,
472+ GFP_KERNEL))) {
473+ ERROR("Failed to allocate cache"
474+ "block\n");
475+ mutex_unlock(&msblk->block_cache_mutex);
476+ goto out;
477+ }
478+ }
479+
480+ msblk->block_cache[i].block = SQUASHFS_USED_BLK;
481+ mutex_unlock(&msblk->block_cache_mutex);
482+
483+ msblk->block_cache[i].length = squashfs_read_data(s,
484+ msblk->block_cache[i].data, block, 0, &next_index, SQUASHFS_METADATA_SIZE);
485+ if (msblk->block_cache[i].length == 0) {
486+ ERROR("Unable to read cache block [%llx:%x]\n",
487+ block, offset);
488+ mutex_lock(&msblk->block_cache_mutex);
489+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
490+ kfree(msblk->block_cache[i].data);
491+ wake_up(&msblk->waitq);
492+ mutex_unlock(&msblk->block_cache_mutex);
493+ goto out;
494+ }
495+
496+ mutex_lock(&msblk->block_cache_mutex);
497+ wake_up(&msblk->waitq);
498+ msblk->block_cache[i].block = block;
499+ msblk->block_cache[i].next_index = next_index;
500+ TRACE("Read cache block [%llx:%x]\n", block, offset);
501+ }
502+
503+ if (msblk->block_cache[i].block != block) {
504+ mutex_unlock(&msblk->block_cache_mutex);
505+ continue;
506+ }
507+
508+ bytes = msblk->block_cache[i].length - offset;
509+
510+ if (bytes < 1) {
511+ mutex_unlock(&msblk->block_cache_mutex);
512+ goto out;
513+ } else if (bytes >= length) {
514+ if (buffer)
515+ memcpy(buffer, msblk->block_cache[i].data +
516+ offset, length);
517+ if (msblk->block_cache[i].length - offset == length) {
518+ *next_block = msblk->block_cache[i].next_index;
519+ *next_offset = 0;
520+ } else {
521+ *next_block = block;
522+ *next_offset = offset + length;
523+ }
524+ mutex_unlock(&msblk->block_cache_mutex);
525+ goto finish;
526+ } else {
527+ if (buffer) {
528+ memcpy(buffer, msblk->block_cache[i].data +
529+ offset, bytes);
530+ buffer += bytes;
531+ }
532+ block = msblk->block_cache[i].next_index;
533+ mutex_unlock(&msblk->block_cache_mutex);
534+ length -= bytes;
535+ offset = 0;
536+ }
537+ }
538+
539+finish:
540+ return return_length;
541+out:
542+ return 0;
543+}
544+
545+
546+static int get_fragment_location(struct super_block *s, unsigned int fragment,
547+ long long *fragment_start_block,
548+ unsigned int *fragment_size)
549+{
550+ struct squashfs_sb_info *msblk = s->s_fs_info;
551+ long long start_block =
552+ msblk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
553+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
554+ struct squashfs_fragment_entry fragment_entry;
555+
556+ if (msblk->swap) {
557+ struct squashfs_fragment_entry sfragment_entry;
558+
559+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
560+ start_block, offset,
561+ sizeof(sfragment_entry), &start_block,
562+ &offset))
563+ goto out;
564+ SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
565+ } else
566+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
567+ start_block, offset,
568+ sizeof(fragment_entry), &start_block,
569+ &offset))
570+ goto out;
571+
572+ *fragment_start_block = fragment_entry.start_block;
573+ *fragment_size = fragment_entry.size;
574+
575+ return 1;
576+
577+out:
578+ return 0;
579+}
580+
581+
582+SQSH_EXTERN void release_cached_fragment(struct squashfs_sb_info *msblk, struct
583+ squashfs_fragment_cache *fragment)
584+{
585+ mutex_lock(&msblk->fragment_mutex);
586+ fragment->locked --;
587+ wake_up(&msblk->fragment_wait_queue);
588+ mutex_unlock(&msblk->fragment_mutex);
589+}
590+
591+
592+SQSH_EXTERN struct squashfs_fragment_cache *get_cached_fragment(struct super_block
593+ *s, long long start_block,
594+ int length)
595+{
596+ int i, n;
597+ struct squashfs_sb_info *msblk = s->s_fs_info;
598+ struct squashfs_super_block *sblk = &msblk->sblk;
599+
600+ while ( 1 ) {
601+ mutex_lock(&msblk->fragment_mutex);
602+
603+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS &&
604+ msblk->fragment[i].block != start_block; i++);
605+
606+ if (i == SQUASHFS_CACHED_FRAGMENTS) {
607+ for (i = msblk->next_fragment, n =
608+ SQUASHFS_CACHED_FRAGMENTS; n &&
609+ msblk->fragment[i].locked; n--, i = (i + 1) %
610+ SQUASHFS_CACHED_FRAGMENTS);
611+
612+ if (n == 0) {
613+ wait_queue_t wait;
614+
615+ init_waitqueue_entry(&wait, current);
616+ add_wait_queue(&msblk->fragment_wait_queue,
617+ &wait);
618+ set_current_state(TASK_UNINTERRUPTIBLE);
619+ mutex_unlock(&msblk->fragment_mutex);
620+ schedule();
621+ set_current_state(TASK_RUNNING);
622+ remove_wait_queue(&msblk->fragment_wait_queue,
623+ &wait);
624+ continue;
625+ }
626+ msblk->next_fragment = (msblk->next_fragment + 1) %
627+ SQUASHFS_CACHED_FRAGMENTS;
628+
629+ if (msblk->fragment[i].data == NULL)
630+ if (!(msblk->fragment[i].data = SQUASHFS_ALLOC
631+ (SQUASHFS_FILE_MAX_SIZE))) {
632+ ERROR("Failed to allocate fragment "
633+ "cache block\n");
634+ mutex_unlock(&msblk->fragment_mutex);
635+ goto out;
636+ }
637+
638+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
639+ msblk->fragment[i].locked = 1;
640+ mutex_unlock(&msblk->fragment_mutex);
641+
642+ if (!(msblk->fragment[i].length = squashfs_read_data(s,
643+ msblk->fragment[i].data,
644+ start_block, length, NULL, sblk->block_size))) {
645+ ERROR("Unable to read fragment cache block "
646+ "[%llx]\n", start_block);
647+ msblk->fragment[i].locked = 0;
648+ smp_mb();
649+ goto out;
650+ }
651+
652+ mutex_lock(&msblk->fragment_mutex);
653+ msblk->fragment[i].block = start_block;
654+ TRACE("New fragment %d, start block %lld, locked %d\n",
655+ i, msblk->fragment[i].block,
656+ msblk->fragment[i].locked);
657+ mutex_unlock(&msblk->fragment_mutex);
658+ break;
659+ }
660+
661+ msblk->fragment[i].locked++;
662+ mutex_unlock(&msblk->fragment_mutex);
663+ TRACE("Got fragment %d, start block %lld, locked %d\n", i,
664+ msblk->fragment[i].block,
665+ msblk->fragment[i].locked);
666+ break;
667+ }
668+
669+ return &msblk->fragment[i];
670+
671+out:
672+ return NULL;
673+}
674+
675+
676+static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
677+ struct squashfs_base_inode_header *inodeb)
678+{
679+ i->i_ino = inodeb->inode_number;
680+ i->i_mtime.tv_sec = inodeb->mtime;
681+ i->i_atime.tv_sec = inodeb->mtime;
682+ i->i_ctime.tv_sec = inodeb->mtime;
683+ i->i_uid = msblk->uid[inodeb->uid];
684+ i->i_mode = inodeb->mode;
685+ i->i_size = 0;
686+ if (inodeb->guid == SQUASHFS_GUIDS)
687+ i->i_gid = i->i_uid;
688+ else
689+ i->i_gid = msblk->guid[inodeb->guid];
690+}
691+
692+
693+static squashfs_inode_t squashfs_inode_lookup(struct super_block *s, int ino)
694+{
695+ struct squashfs_sb_info *msblk = s->s_fs_info;
696+ long long start = msblk->inode_lookup_table[SQUASHFS_LOOKUP_BLOCK(ino - 1)];
697+ int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino - 1);
698+ squashfs_inode_t inode;
699+
700+ TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino);
701+
702+ if (msblk->swap) {
703+ squashfs_inode_t sinode;
704+
705+ if (!squashfs_get_cached_block(s, (char *) &sinode, start, offset,
706+ sizeof(sinode), &start, &offset))
707+ goto out;
708+ SQUASHFS_SWAP_INODE_T((&inode), &sinode);
709+ } else if (!squashfs_get_cached_block(s, (char *) &inode, start, offset,
710+ sizeof(inode), &start, &offset))
711+ goto out;
712+
713+ TRACE("squashfs_inode_lookup, inode = 0x%llx\n", inode);
714+
715+ return inode;
716+
717+out:
718+ return SQUASHFS_INVALID_BLK;
719+}
720+
721+
722+static void vfs_read_inode(struct inode *i)
723+{
724+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
725+ squashfs_inode_t inode = squashfs_inode_lookup(i->i_sb, i->i_ino);
726+
727+ TRACE("Entered vfs_read_inode\n");
728+
729+ if(inode != SQUASHFS_INVALID_BLK)
730+ (msblk->read_inode)(i, inode);
731+}
732+
733+
734+static struct dentry *squashfs_get_parent(struct dentry *child)
735+{
736+ struct inode *i = child->d_inode;
737+ struct inode *parent = iget(i->i_sb, SQUASHFS_I(i)->u.s2.parent_inode);
738+ struct dentry *rv;
739+
740+ TRACE("Entered squashfs_get_parent\n");
741+
742+ if(parent == NULL) {
743+ rv = ERR_PTR(-EACCES);
744+ goto out;
745+ }
746+
747+ rv = d_alloc_anon(parent);
748+ if(rv == NULL)
749+ rv = ERR_PTR(-ENOMEM);
750+
751+out:
752+ return rv;
753+}
754+
755+
756+SQSH_EXTERN struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number)
757+{
758+ struct squashfs_sb_info *msblk = s->s_fs_info;
759+ struct inode *i = iget_locked(s, inode_number);
760+
761+ TRACE("Entered squashfs_iget\n");
762+
763+ if(i && (i->i_state & I_NEW)) {
764+ (msblk->read_inode)(i, inode);
765+ unlock_new_inode(i);
766+ }
767+
768+ return i;
769+}
770+
771+
772+static int squashfs_read_inode(struct inode *i, squashfs_inode_t inode)
773+{
774+ struct super_block *s = i->i_sb;
775+ struct squashfs_sb_info *msblk = s->s_fs_info;
776+ struct squashfs_super_block *sblk = &msblk->sblk;
777+ long long block = SQUASHFS_INODE_BLK(inode) +
778+ sblk->inode_table_start;
779+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
780+ long long next_block;
781+ unsigned int next_offset;
782+ union squashfs_inode_header id, sid;
783+ struct squashfs_base_inode_header *inodeb = &id.base,
784+ *sinodeb = &sid.base;
785+
786+ TRACE("Entered squashfs_read_inode\n");
787+
788+ if (msblk->swap) {
789+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
790+ offset, sizeof(*sinodeb), &next_block,
791+ &next_offset))
792+ goto failed_read;
793+ SQUASHFS_SWAP_BASE_INODE_HEADER(inodeb, sinodeb,
794+ sizeof(*sinodeb));
795+ } else
796+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
797+ offset, sizeof(*inodeb), &next_block,
798+ &next_offset))
799+ goto failed_read;
800+
801+ squashfs_new_inode(msblk, i, inodeb);
802+
803+ switch(inodeb->inode_type) {
804+ case SQUASHFS_FILE_TYPE: {
805+ unsigned int frag_size;
806+ long long frag_blk;
807+ struct squashfs_reg_inode_header *inodep = &id.reg;
808+ struct squashfs_reg_inode_header *sinodep = &sid.reg;
809+
810+ if (msblk->swap) {
811+ if (!squashfs_get_cached_block(s, (char *)
812+ sinodep, block, offset,
813+ sizeof(*sinodep), &next_block,
814+ &next_offset))
815+ goto failed_read;
816+ SQUASHFS_SWAP_REG_INODE_HEADER(inodep, sinodep);
817+ } else
818+ if (!squashfs_get_cached_block(s, (char *)
819+ inodep, block, offset,
820+ sizeof(*inodep), &next_block,
821+ &next_offset))
822+ goto failed_read;
823+
824+ frag_blk = SQUASHFS_INVALID_BLK;
825+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
826+ !get_fragment_location(s,
827+ inodep->fragment, &frag_blk, &frag_size))
828+ goto failed_read;
829+
830+ i->i_nlink = 1;
831+ i->i_size = inodep->file_size;
832+ i->i_fop = &generic_ro_fops;
833+ i->i_mode |= S_IFREG;
834+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
835+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
836+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
837+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
838+ SQUASHFS_I(i)->start_block = inodep->start_block;
839+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
840+ SQUASHFS_I(i)->offset = next_offset;
841+ if (sblk->block_size > 4096)
842+ i->i_data.a_ops = &squashfs_aops;
843+ else
844+ i->i_data.a_ops = &squashfs_aops_4K;
845+
846+ TRACE("File inode %x:%x, start_block %llx, "
847+ "block_list_start %llx, offset %x\n",
848+ SQUASHFS_INODE_BLK(inode), offset,
849+ inodep->start_block, next_block,
850+ next_offset);
851+ break;
852+ }
853+ case SQUASHFS_LREG_TYPE: {
854+ unsigned int frag_size;
855+ long long frag_blk;
856+ struct squashfs_lreg_inode_header *inodep = &id.lreg;
857+ struct squashfs_lreg_inode_header *sinodep = &sid.lreg;
858+
859+ if (msblk->swap) {
860+ if (!squashfs_get_cached_block(s, (char *)
861+ sinodep, block, offset,
862+ sizeof(*sinodep), &next_block,
863+ &next_offset))
864+ goto failed_read;
865+ SQUASHFS_SWAP_LREG_INODE_HEADER(inodep, sinodep);
866+ } else
867+ if (!squashfs_get_cached_block(s, (char *)
868+ inodep, block, offset,
869+ sizeof(*inodep), &next_block,
870+ &next_offset))
871+ goto failed_read;
872+
873+ frag_blk = SQUASHFS_INVALID_BLK;
874+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
875+ !get_fragment_location(s,
876+ inodep->fragment, &frag_blk, &frag_size))
877+ goto failed_read;
878+
879+ i->i_nlink = inodep->nlink;
880+ i->i_size = inodep->file_size;
881+ i->i_fop = &generic_ro_fops;
882+ i->i_mode |= S_IFREG;
883+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
884+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
885+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
886+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
887+ SQUASHFS_I(i)->start_block = inodep->start_block;
888+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
889+ SQUASHFS_I(i)->offset = next_offset;
890+ if (sblk->block_size > 4096)
891+ i->i_data.a_ops = &squashfs_aops;
892+ else
893+ i->i_data.a_ops = &squashfs_aops_4K;
894+
895+ TRACE("File inode %x:%x, start_block %llx, "
896+ "block_list_start %llx, offset %x\n",
897+ SQUASHFS_INODE_BLK(inode), offset,
898+ inodep->start_block, next_block,
899+ next_offset);
900+ break;
901+ }
902+ case SQUASHFS_DIR_TYPE: {
903+ struct squashfs_dir_inode_header *inodep = &id.dir;
904+ struct squashfs_dir_inode_header *sinodep = &sid.dir;
905+
906+ if (msblk->swap) {
907+ if (!squashfs_get_cached_block(s, (char *)
908+ sinodep, block, offset,
909+ sizeof(*sinodep), &next_block,
910+ &next_offset))
911+ goto failed_read;
912+ SQUASHFS_SWAP_DIR_INODE_HEADER(inodep, sinodep);
913+ } else
914+ if (!squashfs_get_cached_block(s, (char *)
915+ inodep, block, offset,
916+ sizeof(*inodep), &next_block,
917+ &next_offset))
918+ goto failed_read;
919+
920+ i->i_nlink = inodep->nlink;
921+ i->i_size = inodep->file_size;
922+ i->i_op = &squashfs_dir_inode_ops;
923+ i->i_fop = &squashfs_dir_ops;
924+ i->i_mode |= S_IFDIR;
925+ SQUASHFS_I(i)->start_block = inodep->start_block;
926+ SQUASHFS_I(i)->offset = inodep->offset;
927+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
928+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
929+
930+ TRACE("Directory inode %x:%x, start_block %x, offset "
931+ "%x\n", SQUASHFS_INODE_BLK(inode),
932+ offset, inodep->start_block,
933+ inodep->offset);
934+ break;
935+ }
936+ case SQUASHFS_LDIR_TYPE: {
937+ struct squashfs_ldir_inode_header *inodep = &id.ldir;
938+ struct squashfs_ldir_inode_header *sinodep = &sid.ldir;
939+
940+ if (msblk->swap) {
941+ if (!squashfs_get_cached_block(s, (char *)
942+ sinodep, block, offset,
943+ sizeof(*sinodep), &next_block,
944+ &next_offset))
945+ goto failed_read;
946+ SQUASHFS_SWAP_LDIR_INODE_HEADER(inodep,
947+ sinodep);
948+ } else
949+ if (!squashfs_get_cached_block(s, (char *)
950+ inodep, block, offset,
951+ sizeof(*inodep), &next_block,
952+ &next_offset))
953+ goto failed_read;
954+
955+ i->i_nlink = inodep->nlink;
956+ i->i_size = inodep->file_size;
957+ i->i_op = &squashfs_dir_inode_ops;
958+ i->i_fop = &squashfs_dir_ops;
959+ i->i_mode |= S_IFDIR;
960+ SQUASHFS_I(i)->start_block = inodep->start_block;
961+ SQUASHFS_I(i)->offset = inodep->offset;
962+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
963+ SQUASHFS_I(i)->u.s2.directory_index_offset =
964+ next_offset;
965+ SQUASHFS_I(i)->u.s2.directory_index_count =
966+ inodep->i_count;
967+ SQUASHFS_I(i)->u.s2.parent_inode = inodep->parent_inode;
968+
969+ TRACE("Long directory inode %x:%x, start_block %x, "
970+ "offset %x\n",
971+ SQUASHFS_INODE_BLK(inode), offset,
972+ inodep->start_block, inodep->offset);
973+ break;
974+ }
975+ case SQUASHFS_SYMLINK_TYPE: {
976+ struct squashfs_symlink_inode_header *inodep =
977+ &id.symlink;
978+ struct squashfs_symlink_inode_header *sinodep =
979+ &sid.symlink;
980+
981+ if (msblk->swap) {
982+ if (!squashfs_get_cached_block(s, (char *)
983+ sinodep, block, offset,
984+ sizeof(*sinodep), &next_block,
985+ &next_offset))
986+ goto failed_read;
987+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER(inodep,
988+ sinodep);
989+ } else
990+ if (!squashfs_get_cached_block(s, (char *)
991+ inodep, block, offset,
992+ sizeof(*inodep), &next_block,
993+ &next_offset))
994+ goto failed_read;
995+
996+ i->i_nlink = inodep->nlink;
997+ i->i_size = inodep->symlink_size;
998+ i->i_op = &page_symlink_inode_operations;
999+ i->i_data.a_ops = &squashfs_symlink_aops;
1000+ i->i_mode |= S_IFLNK;
1001+ SQUASHFS_I(i)->start_block = next_block;
1002+ SQUASHFS_I(i)->offset = next_offset;
1003+
1004+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
1005+ "offset %x\n",
1006+ SQUASHFS_INODE_BLK(inode), offset,
1007+ next_block, next_offset);
1008+ break;
1009+ }
1010+ case SQUASHFS_BLKDEV_TYPE:
1011+ case SQUASHFS_CHRDEV_TYPE: {
1012+ struct squashfs_dev_inode_header *inodep = &id.dev;
1013+ struct squashfs_dev_inode_header *sinodep = &sid.dev;
1014+
1015+ if (msblk->swap) {
1016+ if (!squashfs_get_cached_block(s, (char *)
1017+ sinodep, block, offset,
1018+ sizeof(*sinodep), &next_block,
1019+ &next_offset))
1020+ goto failed_read;
1021+ SQUASHFS_SWAP_DEV_INODE_HEADER(inodep, sinodep);
1022+ } else
1023+ if (!squashfs_get_cached_block(s, (char *)
1024+ inodep, block, offset,
1025+ sizeof(*inodep), &next_block,
1026+ &next_offset))
1027+ goto failed_read;
1028+
1029+ i->i_nlink = inodep->nlink;
1030+ i->i_mode |= (inodeb->inode_type ==
1031+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
1032+ S_IFBLK;
1033+ init_special_inode(i, i->i_mode,
1034+ old_decode_dev(inodep->rdev));
1035+
1036+ TRACE("Device inode %x:%x, rdev %x\n",
1037+ SQUASHFS_INODE_BLK(inode), offset,
1038+ inodep->rdev);
1039+ break;
1040+ }
1041+ case SQUASHFS_FIFO_TYPE:
1042+ case SQUASHFS_SOCKET_TYPE: {
1043+ struct squashfs_ipc_inode_header *inodep = &id.ipc;
1044+ struct squashfs_ipc_inode_header *sinodep = &sid.ipc;
1045+
1046+ if (msblk->swap) {
1047+ if (!squashfs_get_cached_block(s, (char *)
1048+ sinodep, block, offset,
1049+ sizeof(*sinodep), &next_block,
1050+ &next_offset))
1051+ goto failed_read;
1052+ SQUASHFS_SWAP_IPC_INODE_HEADER(inodep, sinodep);
1053+ } else
1054+ if (!squashfs_get_cached_block(s, (char *)
1055+ inodep, block, offset,
1056+ sizeof(*inodep), &next_block,
1057+ &next_offset))
1058+ goto failed_read;
1059+
1060+ i->i_nlink = inodep->nlink;
1061+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
1062+ ? S_IFIFO : S_IFSOCK;
1063+ init_special_inode(i, i->i_mode, 0);
1064+ break;
1065+ }
1066+ default:
1067+ ERROR("Unknown inode type %d in squashfs_iget!\n",
1068+ inodeb->inode_type);
1069+ goto failed_read1;
1070+ }
1071+
1072+ return 1;
1073+
1074+failed_read:
1075+ ERROR("Unable to read inode [%llx:%x]\n", block, offset);
1076+
1077+failed_read1:
1078+ make_bad_inode(i);
1079+ return 0;
1080+}
1081+
1082+
1083+static int read_inode_lookup_table(struct super_block *s)
1084+{
1085+ struct squashfs_sb_info *msblk = s->s_fs_info;
1086+ struct squashfs_super_block *sblk = &msblk->sblk;
1087+ unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(sblk->inodes);
1088+
1089+ TRACE("In read_inode_lookup_table, length %d\n", length);
1090+
1091+ /* Allocate inode lookup table */
1092+ if (!(msblk->inode_lookup_table = kmalloc(length, GFP_KERNEL))) {
1093+ ERROR("Failed to allocate inode lookup table\n");
1094+ return 0;
1095+ }
1096+
1097+ if (!squashfs_read_data(s, (char *) msblk->inode_lookup_table,
1098+ sblk->lookup_table_start, length |
1099+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
1100+ ERROR("unable to read inode lookup table\n");
1101+ return 0;
1102+ }
1103+
1104+ if (msblk->swap) {
1105+ int i;
1106+ long long block;
1107+
1108+ for (i = 0; i < SQUASHFS_LOOKUP_BLOCKS(sblk->inodes); i++) {
1109+ SQUASHFS_SWAP_LOOKUP_BLOCKS((&block),
1110+ &msblk->inode_lookup_table[i], 1);
1111+ msblk->inode_lookup_table[i] = block;
1112+ }
1113+ }
1114+
1115+ return 1;
1116+}
1117+
1118+
1119+static int read_fragment_index_table(struct super_block *s)
1120+{
1121+ struct squashfs_sb_info *msblk = s->s_fs_info;
1122+ struct squashfs_super_block *sblk = &msblk->sblk;
1123+ unsigned int length = SQUASHFS_FRAGMENT_INDEX_BYTES(sblk->fragments);
1124+
1125+ if(length == 0)
1126+ return 1;
1127+
1128+ /* Allocate fragment index table */
1129+ if (!(msblk->fragment_index = kmalloc(length, GFP_KERNEL))) {
1130+ ERROR("Failed to allocate fragment index table\n");
1131+ return 0;
1132+ }
1133+
1134+ if (!squashfs_read_data(s, (char *) msblk->fragment_index,
1135+ sblk->fragment_table_start, length |
1136+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, length)) {
1137+ ERROR("unable to read fragment index table\n");
1138+ return 0;
1139+ }
1140+
1141+ if (msblk->swap) {
1142+ int i;
1143+ long long fragment;
1144+
1145+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sblk->fragments); i++) {
1146+ SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment),
1147+ &msblk->fragment_index[i], 1);
1148+ msblk->fragment_index[i] = fragment;
1149+ }
1150+ }
1151+
1152+ return 1;
1153+}
1154+
1155+
1156+static int supported_squashfs_filesystem(struct squashfs_sb_info *msblk, int silent)
1157+{
1158+ struct squashfs_super_block *sblk = &msblk->sblk;
1159+
1160+ msblk->read_inode = squashfs_read_inode;
1161+ msblk->read_blocklist = read_blocklist;
1162+ msblk->read_fragment_index_table = read_fragment_index_table;
1163+
1164+ if (sblk->s_major == 1) {
1165+ if (!squashfs_1_0_supported(msblk)) {
1166+ SERROR("Major/Minor mismatch, Squashfs 1.0 filesystems "
1167+ "are unsupported\n");
1168+ SERROR("Please recompile with "
1169+ "Squashfs 1.0 support enabled\n");
1170+ return 0;
1171+ }
1172+ } else if (sblk->s_major == 2) {
1173+ if (!squashfs_2_0_supported(msblk)) {
1174+ SERROR("Major/Minor mismatch, Squashfs 2.0 filesystems "
1175+ "are unsupported\n");
1176+ SERROR("Please recompile with "
1177+ "Squashfs 2.0 support enabled\n");
1178+ return 0;
1179+ }
1180+ } else if(sblk->s_major != SQUASHFS_MAJOR || sblk->s_minor >
1181+ SQUASHFS_MINOR) {
1182+ SERROR("Major/Minor mismatch, trying to mount newer %d.%d "
1183+ "filesystem\n", sblk->s_major, sblk->s_minor);
1184+ SERROR("Please update your kernel\n");
1185+ return 0;
1186+ }
1187+
1188+ return 1;
1189+}
1190+
1191+
1192+static int squashfs_fill_super(struct super_block *s, void *data, int silent)
1193+{
1194+ struct squashfs_sb_info *msblk;
1195+ struct squashfs_super_block *sblk;
1196+ int i;
1197+ char b[BDEVNAME_SIZE];
1198+ struct inode *root;
1199+
1200+ TRACE("Entered squashfs_read_superblock\n");
1201+
1202+ if (!(s->s_fs_info = kmalloc(sizeof(struct squashfs_sb_info),
1203+ GFP_KERNEL))) {
1204+ ERROR("Failed to allocate superblock\n");
1205+ goto failure;
1206+ }
1207+ memset(s->s_fs_info, 0, sizeof(struct squashfs_sb_info));
1208+ msblk = s->s_fs_info;
1209+ if (!(msblk->stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
1210+ ERROR("Failed to allocate zlib workspace\n");
1211+ goto failure;
1212+ }
1213+ sblk = &msblk->sblk;
1214+
1215+ msblk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
1216+ msblk->devblksize_log2 = ffz(~msblk->devblksize);
1217+
1218+ mutex_init(&msblk->read_data_mutex);
1219+ mutex_init(&msblk->read_page_mutex);
1220+ mutex_init(&msblk->block_cache_mutex);
1221+ mutex_init(&msblk->fragment_mutex);
1222+ mutex_init(&msblk->meta_index_mutex);
1223+
1224+ init_waitqueue_head(&msblk->waitq);
1225+ init_waitqueue_head(&msblk->fragment_wait_queue);
1226+
1227+ sblk->bytes_used = sizeof(struct squashfs_super_block);
1228+ if (!squashfs_read_data(s, (char *) sblk, SQUASHFS_START,
1229+ sizeof(struct squashfs_super_block) |
1230+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, sizeof(struct squashfs_super_block))) {
1231+ SERROR("unable to read superblock\n");
1232+ goto failed_mount;
1233+ }
1234+
1235+ /* Check it is a SQUASHFS superblock */
1236+ msblk->swap = 0;
1237+ if ((s->s_magic = sblk->s_magic) != SQUASHFS_MAGIC) {
1238+ if (sblk->s_magic == SQUASHFS_MAGIC_SWAP) {
1239+ struct squashfs_super_block ssblk;
1240+
1241+ WARNING("Mounting a different endian SQUASHFS "
1242+ "filesystem on %s\n", bdevname(s->s_bdev, b));
1243+
1244+ SQUASHFS_SWAP_SUPER_BLOCK(&ssblk, sblk);
1245+ memcpy(sblk, &ssblk, sizeof(struct squashfs_super_block));
1246+ msblk->swap = 1;
1247+ } else {
1248+ SERROR("Can't find a SQUASHFS superblock on %s\n",
1249+ bdevname(s->s_bdev, b));
1250+ goto failed_mount;
1251+ }
1252+ }
1253+
1254+ /* Check the MAJOR & MINOR versions */
1255+ if(!supported_squashfs_filesystem(msblk, silent))
1256+ goto failed_mount;
1257+
1258+ /* Check the filesystem does not extend beyond the end of the
1259+ block device */
1260+ if(sblk->bytes_used < 0 || sblk->bytes_used > i_size_read(s->s_bdev->bd_inode))
1261+ goto failed_mount;
1262+
1263+ /* Check the root inode for sanity */
1264+ if (SQUASHFS_INODE_OFFSET(sblk->root_inode) > SQUASHFS_METADATA_SIZE)
1265+ goto failed_mount;
1266+
1267+ TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
1268+ TRACE("Inodes are %scompressed\n",
1269+ SQUASHFS_UNCOMPRESSED_INODES
1270+ (sblk->flags) ? "un" : "");
1271+ TRACE("Data is %scompressed\n",
1272+ SQUASHFS_UNCOMPRESSED_DATA(sblk->flags)
1273+ ? "un" : "");
1274+ TRACE("Check data is %s present in the filesystem\n",
1275+ SQUASHFS_CHECK_DATA(sblk->flags) ?
1276+ "" : "not");
1277+ TRACE("Filesystem size %lld bytes\n", sblk->bytes_used);
1278+ TRACE("Block size %d\n", sblk->block_size);
1279+ TRACE("Number of inodes %d\n", sblk->inodes);
1280+ if (sblk->s_major > 1)
1281+ TRACE("Number of fragments %d\n", sblk->fragments);
1282+ TRACE("Number of uids %d\n", sblk->no_uids);
1283+ TRACE("Number of gids %d\n", sblk->no_guids);
1284+ TRACE("sblk->inode_table_start %llx\n", sblk->inode_table_start);
1285+ TRACE("sblk->directory_table_start %llx\n", sblk->directory_table_start);
1286+ if (sblk->s_major > 1)
1287+ TRACE("sblk->fragment_table_start %llx\n",
1288+ sblk->fragment_table_start);
1289+ TRACE("sblk->uid_start %llx\n", sblk->uid_start);
1290+
1291+ s->s_flags |= MS_RDONLY;
1292+ s->s_op = &squashfs_super_ops;
1293+
1294+ /* Init inode_table block pointer array */
1295+ if (!(msblk->block_cache = kmalloc(sizeof(struct squashfs_cache) *
1296+ SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
1297+ ERROR("Failed to allocate block cache\n");
1298+ goto failed_mount;
1299+ }
1300+
1301+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
1302+ msblk->block_cache[i].block = SQUASHFS_INVALID_BLK;
1303+
1304+ msblk->next_cache = 0;
1305+
1306+ /* Allocate read_page block */
1307+ if (!(msblk->read_page = kmalloc(sblk->block_size, GFP_KERNEL))) {
1308+ ERROR("Failed to allocate read_page block\n");
1309+ goto failed_mount;
1310+ }
1311+
1312+ /* Allocate uid and gid tables */
1313+ if (!(msblk->uid = kmalloc((sblk->no_uids + sblk->no_guids) *
1314+ sizeof(unsigned int), GFP_KERNEL))) {
1315+ ERROR("Failed to allocate uid/gid table\n");
1316+ goto failed_mount;
1317+ }
1318+ msblk->guid = msblk->uid + sblk->no_uids;
1319+
1320+ if (msblk->swap) {
1321+ unsigned int suid[sblk->no_uids + sblk->no_guids];
1322+
1323+ if (!squashfs_read_data(s, (char *) &suid, sblk->uid_start,
1324+ ((sblk->no_uids + sblk->no_guids) *
1325+ sizeof(unsigned int)) |
1326+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
1327+ ERROR("unable to read uid/gid table\n");
1328+ goto failed_mount;
1329+ }
1330+
1331+ SQUASHFS_SWAP_DATA(msblk->uid, suid, (sblk->no_uids +
1332+ sblk->no_guids), (sizeof(unsigned int) * 8));
1333+ } else
1334+ if (!squashfs_read_data(s, (char *) msblk->uid, sblk->uid_start,
1335+ ((sblk->no_uids + sblk->no_guids) *
1336+ sizeof(unsigned int)) |
1337+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, (sblk->no_uids + sblk->no_guids) * sizeof(unsigned int))) {
1338+ ERROR("unable to read uid/gid table\n");
1339+ goto failed_mount;
1340+ }
1341+
1342+
1343+ if (sblk->s_major == 1 && squashfs_1_0_supported(msblk))
1344+ goto allocate_root;
1345+
1346+ if (!(msblk->fragment = kmalloc(sizeof(struct squashfs_fragment_cache) *
1347+ SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
1348+ ERROR("Failed to allocate fragment block cache\n");
1349+ goto failed_mount;
1350+ }
1351+
1352+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
1353+ msblk->fragment[i].locked = 0;
1354+ msblk->fragment[i].block = SQUASHFS_INVALID_BLK;
1355+ msblk->fragment[i].data = NULL;
1356+ }
1357+
1358+ msblk->next_fragment = 0;
1359+
1360+ /* Allocate and read fragment index table */
1361+ if (msblk->read_fragment_index_table(s) == 0)
1362+ goto failed_mount;
1363+
1364+ if(sblk->s_major < 3 || sblk->lookup_table_start == SQUASHFS_INVALID_BLK)
1365+ goto allocate_root;
1366+
1367+ /* Allocate and read inode lookup table */
1368+ if (read_inode_lookup_table(s) == 0)
1369+ goto failed_mount;
1370+
1371+ s->s_op = &squashfs_export_super_ops;
1372+ s->s_export_op = &squashfs_export_ops;
1373+
1374+allocate_root:
1375+ root = new_inode(s);
1376+ if ((msblk->read_inode)(root, sblk->root_inode) == 0)
1377+ goto failed_mount;
1378+ insert_inode_hash(root);
1379+
1380+ if ((s->s_root = d_alloc_root(root)) == NULL) {
1381+ ERROR("Root inode create failed\n");
1382+ iput(root);
1383+ goto failed_mount;
1384+ }
1385+
1386+ TRACE("Leaving squashfs_read_super\n");
1387+ return 0;
1388+
1389+failed_mount:
1390+ kfree(msblk->inode_lookup_table);
1391+ kfree(msblk->fragment_index);
1392+ kfree(msblk->fragment);
1393+ kfree(msblk->uid);
1394+ kfree(msblk->read_page);
1395+ kfree(msblk->block_cache);
1396+ kfree(msblk->fragment_index_2);
1397+ vfree(msblk->stream.workspace);
1398+ kfree(s->s_fs_info);
1399+ s->s_fs_info = NULL;
1400+ return -EINVAL;
1401+
1402+failure:
1403+ return -ENOMEM;
1404+}
1405+
1406+
1407+static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
1408+{
1409+ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
1410+ struct squashfs_super_block *sblk = &msblk->sblk;
1411+
1412+ TRACE("Entered squashfs_statfs\n");
1413+
1414+ buf->f_type = SQUASHFS_MAGIC;
1415+ buf->f_bsize = sblk->block_size;
1416+ buf->f_blocks = ((sblk->bytes_used - 1) >> sblk->block_log) + 1;
1417+ buf->f_bfree = buf->f_bavail = 0;
1418+ buf->f_files = sblk->inodes;
1419+ buf->f_ffree = 0;
1420+ buf->f_namelen = SQUASHFS_NAME_LEN;
1421+
1422+ return 0;
1423+}
1424+
1425+
1426+static int squashfs_symlink_readpage(struct file *file, struct page *page)
1427+{
1428+ struct inode *inode = page->mapping->host;
1429+ int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
1430+ long long block = SQUASHFS_I(inode)->start_block;
1431+ int offset = SQUASHFS_I(inode)->offset;
1432+ void *pageaddr = kmap(page);
1433+
1434+ TRACE("Entered squashfs_symlink_readpage, page index %ld, start block "
1435+ "%llx, offset %x\n", page->index,
1436+ SQUASHFS_I(inode)->start_block,
1437+ SQUASHFS_I(inode)->offset);
1438+
1439+ for (length = 0; length < index; length += bytes) {
1440+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, NULL,
1441+ block, offset, PAGE_CACHE_SIZE, &block,
1442+ &offset))) {
1443+ ERROR("Unable to read symbolic link [%llx:%x]\n", block,
1444+ offset);
1445+ goto skip_read;
1446+ }
1447+ }
1448+
1449+ if (length != index) {
1450+ ERROR("(squashfs_symlink_readpage) length != index\n");
1451+ bytes = 0;
1452+ goto skip_read;
1453+ }
1454+
1455+ bytes = (i_size_read(inode) - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE :
1456+ i_size_read(inode) - length;
1457+
1458+ if (!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block,
1459+ offset, bytes, &block, &offset)))
1460+ ERROR("Unable to read symbolic link [%llx:%x]\n", block, offset);
1461+
1462+skip_read:
1463+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1464+ kunmap(page);
1465+ flush_dcache_page(page);
1466+ SetPageUptodate(page);
1467+ unlock_page(page);
1468+
1469+ return 0;
1470+}
1471+
1472+
1473+struct meta_index *locate_meta_index(struct inode *inode, int index, int offset)
1474+{
1475+ struct meta_index *meta = NULL;
1476+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1477+ int i;
1478+
1479+ mutex_lock(&msblk->meta_index_mutex);
1480+
1481+ TRACE("locate_meta_index: index %d, offset %d\n", index, offset);
1482+
1483+ if(msblk->meta_index == NULL)
1484+ goto not_allocated;
1485+
1486+ for (i = 0; i < SQUASHFS_META_NUMBER; i ++)
1487+ if (msblk->meta_index[i].inode_number == inode->i_ino &&
1488+ msblk->meta_index[i].offset >= offset &&
1489+ msblk->meta_index[i].offset <= index &&
1490+ msblk->meta_index[i].locked == 0) {
1491+ TRACE("locate_meta_index: entry %d, offset %d\n", i,
1492+ msblk->meta_index[i].offset);
1493+ meta = &msblk->meta_index[i];
1494+ offset = meta->offset;
1495+ }
1496+
1497+ if (meta)
1498+ meta->locked = 1;
1499+
1500+not_allocated:
1501+ mutex_unlock(&msblk->meta_index_mutex);
1502+
1503+ return meta;
1504+}
1505+
1506+
1507+struct meta_index *empty_meta_index(struct inode *inode, int offset, int skip)
1508+{
1509+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1510+ struct meta_index *meta = NULL;
1511+ int i;
1512+
1513+ mutex_lock(&msblk->meta_index_mutex);
1514+
1515+ TRACE("empty_meta_index: offset %d, skip %d\n", offset, skip);
1516+
1517+ if(msblk->meta_index == NULL) {
1518+ if (!(msblk->meta_index = kmalloc(sizeof(struct meta_index) *
1519+ SQUASHFS_META_NUMBER, GFP_KERNEL))) {
1520+ ERROR("Failed to allocate meta_index\n");
1521+ goto failed;
1522+ }
1523+ for(i = 0; i < SQUASHFS_META_NUMBER; i++) {
1524+ msblk->meta_index[i].inode_number = 0;
1525+ msblk->meta_index[i].locked = 0;
1526+ }
1527+ msblk->next_meta_index = 0;
1528+ }
1529+
1530+ for(i = SQUASHFS_META_NUMBER; i &&
1531+ msblk->meta_index[msblk->next_meta_index].locked; i --)
1532+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
1533+ SQUASHFS_META_NUMBER;
1534+
1535+ if(i == 0) {
1536+ TRACE("empty_meta_index: failed!\n");
1537+ goto failed;
1538+ }
1539+
1540+ TRACE("empty_meta_index: returned meta entry %d, %p\n",
1541+ msblk->next_meta_index,
1542+ &msblk->meta_index[msblk->next_meta_index]);
1543+
1544+ meta = &msblk->meta_index[msblk->next_meta_index];
1545+ msblk->next_meta_index = (msblk->next_meta_index + 1) %
1546+ SQUASHFS_META_NUMBER;
1547+
1548+ meta->inode_number = inode->i_ino;
1549+ meta->offset = offset;
1550+ meta->skip = skip;
1551+ meta->entries = 0;
1552+ meta->locked = 1;
1553+
1554+failed:
1555+ mutex_unlock(&msblk->meta_index_mutex);
1556+ return meta;
1557+}
1558+
1559+
1560+void release_meta_index(struct inode *inode, struct meta_index *meta)
1561+{
1562+ meta->locked = 0;
1563+ smp_mb();
1564+}
1565+
1566+
1567+static int read_block_index(struct super_block *s, int blocks, char *block_list,
1568+ long long *start_block, int *offset)
1569+{
1570+ struct squashfs_sb_info *msblk = s->s_fs_info;
1571+ unsigned int *block_listp;
1572+ int block = 0;
1573+
1574+ if (msblk->swap) {
1575+ char sblock_list[blocks << 2];
1576+
1577+ if (!squashfs_get_cached_block(s, sblock_list, *start_block,
1578+ *offset, blocks << 2, start_block, offset)) {
1579+ ERROR("Unable to read block list [%llx:%x]\n",
1580+ *start_block, *offset);
1581+ goto failure;
1582+ }
1583+ SQUASHFS_SWAP_INTS(((unsigned int *)block_list),
1584+ ((unsigned int *)sblock_list), blocks);
1585+ } else
1586+ if (!squashfs_get_cached_block(s, block_list, *start_block,
1587+ *offset, blocks << 2, start_block, offset)) {
1588+ ERROR("Unable to read block list [%llx:%x]\n",
1589+ *start_block, *offset);
1590+ goto failure;
1591+ }
1592+
1593+ for (block_listp = (unsigned int *) block_list; blocks;
1594+ block_listp++, blocks --)
1595+ block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
1596+
1597+ return block;
1598+
1599+failure:
1600+ return -1;
1601+}
1602+
1603+
1604+#define SIZE 256
1605+
1606+static inline int calculate_skip(int blocks) {
1607+ int skip = (blocks - 1) / ((SQUASHFS_SLOTS * SQUASHFS_META_ENTRIES + 1) * SQUASHFS_META_INDEXES);
1608+ return skip >= 7 ? 7 : skip + 1;
1609+}
1610+
1611+
1612+static int get_meta_index(struct inode *inode, int index,
1613+ long long *index_block, int *index_offset,
1614+ long long *data_block, char *block_list)
1615+{
1616+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1617+ struct squashfs_super_block *sblk = &msblk->sblk;
1618+ int skip = calculate_skip(i_size_read(inode) >> sblk->block_log);
1619+ int offset = 0;
1620+ struct meta_index *meta;
1621+ struct meta_entry *meta_entry;
1622+ long long cur_index_block = SQUASHFS_I(inode)->u.s1.block_list_start;
1623+ int cur_offset = SQUASHFS_I(inode)->offset;
1624+ long long cur_data_block = SQUASHFS_I(inode)->start_block;
1625+ int i;
1626+
1627+ index /= SQUASHFS_META_INDEXES * skip;
1628+
1629+ while ( offset < index ) {
1630+ meta = locate_meta_index(inode, index, offset + 1);
1631+
1632+ if (meta == NULL) {
1633+ if ((meta = empty_meta_index(inode, offset + 1,
1634+ skip)) == NULL)
1635+ goto all_done;
1636+ } else {
1637+ if(meta->entries == 0)
1638+ goto failed;
1639+ offset = index < meta->offset + meta->entries ? index :
1640+ meta->offset + meta->entries - 1;
1641+ meta_entry = &meta->meta_entry[offset - meta->offset];
1642+ cur_index_block = meta_entry->index_block + sblk->inode_table_start;
1643+ cur_offset = meta_entry->offset;
1644+ cur_data_block = meta_entry->data_block;
1645+ TRACE("get_meta_index: offset %d, meta->offset %d, "
1646+ "meta->entries %d\n", offset, meta->offset,
1647+ meta->entries);
1648+ TRACE("get_meta_index: index_block 0x%llx, offset 0x%x"
1649+ " data_block 0x%llx\n", cur_index_block,
1650+ cur_offset, cur_data_block);
1651+ }
1652+
1653+ for (i = meta->offset + meta->entries; i <= index &&
1654+ i < meta->offset + SQUASHFS_META_ENTRIES; i++) {
1655+ int blocks = skip * SQUASHFS_META_INDEXES;
1656+
1657+ while (blocks) {
1658+ int block = blocks > (SIZE >> 2) ? (SIZE >> 2) :
1659+ blocks;
1660+ int res = read_block_index(inode->i_sb, block,
1661+ block_list, &cur_index_block,
1662+ &cur_offset);
1663+
1664+ if (res == -1)
1665+ goto failed;
1666+
1667+ cur_data_block += res;
1668+ blocks -= block;
1669+ }
1670+
1671+ meta_entry = &meta->meta_entry[i - meta->offset];
1672+ meta_entry->index_block = cur_index_block - sblk->inode_table_start;
1673+ meta_entry->offset = cur_offset;
1674+ meta_entry->data_block = cur_data_block;
1675+ meta->entries ++;
1676+ offset ++;
1677+ }
1678+
1679+ TRACE("get_meta_index: meta->offset %d, meta->entries %d\n",
1680+ meta->offset, meta->entries);
1681+
1682+ release_meta_index(inode, meta);
1683+ }
1684+
1685+all_done:
1686+ *index_block = cur_index_block;
1687+ *index_offset = cur_offset;
1688+ *data_block = cur_data_block;
1689+
1690+ return offset * SQUASHFS_META_INDEXES * skip;
1691+
1692+failed:
1693+ release_meta_index(inode, meta);
1694+ return -1;
1695+}
1696+
1697+
1698+static long long read_blocklist(struct inode *inode, int index,
1699+ int readahead_blks, char *block_list,
1700+ unsigned short **block_p, unsigned int *bsize)
1701+{
1702+ long long block_ptr;
1703+ int offset;
1704+ long long block;
1705+ int res = get_meta_index(inode, index, &block_ptr, &offset, &block,
1706+ block_list);
1707+
1708+ TRACE("read_blocklist: res %d, index %d, block_ptr 0x%llx, offset"
1709+ " 0x%x, block 0x%llx\n", res, index, block_ptr, offset,
1710+ block);
1711+
1712+ if(res == -1)
1713+ goto failure;
1714+
1715+ index -= res;
1716+
1717+ while ( index ) {
1718+ int blocks = index > (SIZE >> 2) ? (SIZE >> 2) : index;
1719+ int res = read_block_index(inode->i_sb, blocks, block_list,
1720+ &block_ptr, &offset);
1721+ if (res == -1)
1722+ goto failure;
1723+ block += res;
1724+ index -= blocks;
1725+ }
1726+
1727+ if (read_block_index(inode->i_sb, 1, block_list,
1728+ &block_ptr, &offset) == -1)
1729+ goto failure;
1730+ *bsize = *((unsigned int *) block_list);
1731+
1732+ return block;
1733+
1734+failure:
1735+ return 0;
1736+}
1737+
1738+
1739+static int squashfs_readpage(struct file *file, struct page *page)
1740+{
1741+ struct inode *inode = page->mapping->host;
1742+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1743+ struct squashfs_super_block *sblk = &msblk->sblk;
1744+ unsigned char *block_list;
1745+ long long block;
1746+ unsigned int bsize, i = 0, bytes = 0, byte_offset = 0;
1747+ int index = page->index >> (sblk->block_log - PAGE_CACHE_SHIFT);
1748+ void *pageaddr;
1749+ struct squashfs_fragment_cache *fragment = NULL;
1750+ char *data_ptr = msblk->read_page;
1751+
1752+ int mask = (1 << (sblk->block_log - PAGE_CACHE_SHIFT)) - 1;
1753+ int start_index = page->index & ~mask;
1754+ int end_index = start_index | mask;
1755+
1756+ TRACE("Entered squashfs_readpage, page index %lx, start block %llx\n",
1757+ page->index,
1758+ SQUASHFS_I(inode)->start_block);
1759+
1760+ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
1761+ ERROR("Failed to allocate block_list\n");
1762+ goto skip_read;
1763+ }
1764+
1765+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1766+ PAGE_CACHE_SHIFT))
1767+ goto skip_read;
1768+
1769+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1770+ || index < (i_size_read(inode) >>
1771+ sblk->block_log)) {
1772+ if ((block = (msblk->read_blocklist)(inode, index, 1,
1773+ block_list, NULL, &bsize)) == 0)
1774+ goto skip_read;
1775+
1776+ mutex_lock(&msblk->read_page_mutex);
1777+
1778+ if (!(bytes = squashfs_read_data(inode->i_sb, msblk->read_page,
1779+ block, bsize, NULL, sblk->block_size))) {
1780+ ERROR("Unable to read page, block %llx, size %x\n", block,
1781+ bsize);
1782+ mutex_unlock(&msblk->read_page_mutex);
1783+ goto skip_read;
1784+ }
1785+ } else {
1786+ if ((fragment = get_cached_fragment(inode->i_sb,
1787+ SQUASHFS_I(inode)->
1788+ u.s1.fragment_start_block,
1789+ SQUASHFS_I(inode)->u.s1.fragment_size))
1790+ == NULL) {
1791+ ERROR("Unable to read page, block %llx, size %x\n",
1792+ SQUASHFS_I(inode)->
1793+ u.s1.fragment_start_block,
1794+ (int) SQUASHFS_I(inode)->
1795+ u.s1.fragment_size);
1796+ goto skip_read;
1797+ }
1798+ bytes = SQUASHFS_I(inode)->u.s1.fragment_offset +
1799+ (i_size_read(inode) & (sblk->block_size
1800+ - 1));
1801+ byte_offset = SQUASHFS_I(inode)->u.s1.fragment_offset;
1802+ data_ptr = fragment->data;
1803+ }
1804+
1805+ for (i = start_index; i <= end_index && byte_offset < bytes;
1806+ i++, byte_offset += PAGE_CACHE_SIZE) {
1807+ struct page *push_page;
1808+ int avail = (bytes - byte_offset) > PAGE_CACHE_SIZE ?
1809+ PAGE_CACHE_SIZE : bytes - byte_offset;
1810+
1811+ TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n",
1812+ bytes, i, byte_offset, avail);
1813+
1814+ push_page = (i == page->index) ? page :
1815+ grab_cache_page_nowait(page->mapping, i);
1816+
1817+ if (!push_page)
1818+ continue;
1819+
1820+ if (PageUptodate(push_page))
1821+ goto skip_page;
1822+
1823+ pageaddr = kmap_atomic(push_page, KM_USER0);
1824+ memcpy(pageaddr, data_ptr + byte_offset, avail);
1825+ memset(pageaddr + avail, 0, PAGE_CACHE_SIZE - avail);
1826+ kunmap_atomic(pageaddr, KM_USER0);
1827+ flush_dcache_page(push_page);
1828+ SetPageUptodate(push_page);
1829+skip_page:
1830+ unlock_page(push_page);
1831+ if(i != page->index)
1832+ page_cache_release(push_page);
1833+ }
1834+
1835+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1836+ || index < (i_size_read(inode) >>
1837+ sblk->block_log))
1838+ mutex_unlock(&msblk->read_page_mutex);
1839+ else
1840+ release_cached_fragment(msblk, fragment);
1841+
1842+ kfree(block_list);
1843+ return 0;
1844+
1845+skip_read:
1846+ pageaddr = kmap_atomic(page, KM_USER0);
1847+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1848+ kunmap_atomic(pageaddr, KM_USER0);
1849+ flush_dcache_page(page);
1850+ SetPageUptodate(page);
1851+ unlock_page(page);
1852+
1853+ kfree(block_list);
1854+ return 0;
1855+}
1856+
1857+
1858+static int squashfs_readpage4K(struct file *file, struct page *page)
1859+{
1860+ struct inode *inode = page->mapping->host;
1861+ struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info;
1862+ struct squashfs_super_block *sblk = &msblk->sblk;
1863+ unsigned char *block_list;
1864+ long long block;
1865+ unsigned int bsize, bytes = 0;
1866+ void *pageaddr;
1867+
1868+ TRACE("Entered squashfs_readpage4K, page index %lx, start block %llx\n",
1869+ page->index,
1870+ SQUASHFS_I(inode)->start_block);
1871+
1872+ if (page->index >= ((i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
1873+ PAGE_CACHE_SHIFT)) {
1874+ block_list = NULL;
1875+ goto skip_read;
1876+ }
1877+
1878+ if (!(block_list = kmalloc(SIZE, GFP_KERNEL))) {
1879+ ERROR("Failed to allocate block_list\n");
1880+ goto skip_read;
1881+ }
1882+
1883+ if (SQUASHFS_I(inode)->u.s1.fragment_start_block == SQUASHFS_INVALID_BLK
1884+ || page->index < (i_size_read(inode) >>
1885+ sblk->block_log)) {
1886+ block = (msblk->read_blocklist)(inode, page->index, 1,
1887+ block_list, NULL, &bsize);
1888+ if(block == 0)
1889+ goto skip_read;
1890+
1891+ mutex_lock(&msblk->read_page_mutex);
1892+ bytes = squashfs_read_data(inode->i_sb, msblk->read_page, block,
1893+ bsize, NULL, sblk->block_size);
1894+ if (bytes) {
1895+ pageaddr = kmap_atomic(page, KM_USER0);
1896+ memcpy(pageaddr, msblk->read_page, bytes);
1897+ kunmap_atomic(pageaddr, KM_USER0);
1898+ } else
1899+ ERROR("Unable to read page, block %llx, size %x\n",
1900+ block, bsize);
1901+ mutex_unlock(&msblk->read_page_mutex);
1902+ } else {
1903+ struct squashfs_fragment_cache *fragment =
1904+ get_cached_fragment(inode->i_sb,
1905+ SQUASHFS_I(inode)->
1906+ u.s1.fragment_start_block,
1907+ SQUASHFS_I(inode)-> u.s1.fragment_size);
1908+ if (fragment) {
1909+ bytes = i_size_read(inode) & (sblk->block_size - 1);
1910+ pageaddr = kmap_atomic(page, KM_USER0);
1911+ memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->
1912+ u.s1.fragment_offset, bytes);
1913+ kunmap_atomic(pageaddr, KM_USER0);
1914+ release_cached_fragment(msblk, fragment);
1915+ } else
1916+ ERROR("Unable to read page, block %llx, size %x\n",
1917+ SQUASHFS_I(inode)->
1918+ u.s1.fragment_start_block, (int)
1919+ SQUASHFS_I(inode)-> u.s1.fragment_size);
1920+ }
1921+
1922+skip_read:
1923+ pageaddr = kmap_atomic(page, KM_USER0);
1924+ memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
1925+ kunmap_atomic(pageaddr, KM_USER0);
1926+ flush_dcache_page(page);
1927+ SetPageUptodate(page);
1928+ unlock_page(page);
1929+
1930+ kfree(block_list);
1931+ return 0;
1932+}
1933+
1934+
1935+static int get_dir_index_using_offset(struct super_block *s, long long
1936+ *next_block, unsigned int *next_offset,
1937+ long long index_start,
1938+ unsigned int index_offset, int i_count,
1939+ long long f_pos)
1940+{
1941+ struct squashfs_sb_info *msblk = s->s_fs_info;
1942+ struct squashfs_super_block *sblk = &msblk->sblk;
1943+ int i, length = 0;
1944+ struct squashfs_dir_index index;
1945+
1946+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
1947+ i_count, (unsigned int) f_pos);
1948+
1949+ f_pos =- 3;
1950+ if (f_pos == 0)
1951+ goto finish;
1952+
1953+ for (i = 0; i < i_count; i++) {
1954+ if (msblk->swap) {
1955+ struct squashfs_dir_index sindex;
1956+ squashfs_get_cached_block(s, (char *) &sindex,
1957+ index_start, index_offset,
1958+ sizeof(sindex), &index_start,
1959+ &index_offset);
1960+ SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);
1961+ } else
1962+ squashfs_get_cached_block(s, (char *) &index,
1963+ index_start, index_offset,
1964+ sizeof(index), &index_start,
1965+ &index_offset);
1966+
1967+ if (index.index > f_pos)
1968+ break;
1969+
1970+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
1971+ index.size + 1, &index_start,
1972+ &index_offset);
1973+
1974+ length = index.index;
1975+ *next_block = index.start_block + sblk->directory_table_start;
1976+ }
1977+
1978+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
1979+
1980+finish:
1981+ return length + 3;
1982+}
1983+
1984+
1985+static int get_dir_index_using_name(struct super_block *s, long long
1986+ *next_block, unsigned int *next_offset,
1987+ long long index_start,
1988+ unsigned int index_offset, int i_count,
1989+ const char *name, int size)
1990+{
1991+ struct squashfs_sb_info *msblk = s->s_fs_info;
1992+ struct squashfs_super_block *sblk = &msblk->sblk;
1993+ int i, length = 0;
1994+ struct squashfs_dir_index *index;
1995+ char *str;
1996+
1997+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
1998+
1999+ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
2000+ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
2001+ ERROR("Failed to allocate squashfs_dir_index\n");
2002+ goto failure;
2003+ }
2004+
2005+ index = (struct squashfs_dir_index *) (str + SQUASHFS_NAME_LEN + 1);
2006+ strncpy(str, name, size);
2007+ str[size] = '\0';
2008+
2009+ for (i = 0; i < i_count; i++) {
2010+ if (msblk->swap) {
2011+ struct squashfs_dir_index sindex;
2012+ squashfs_get_cached_block(s, (char *) &sindex,
2013+ index_start, index_offset,
2014+ sizeof(sindex), &index_start,
2015+ &index_offset);
2016+ SQUASHFS_SWAP_DIR_INDEX(index, &sindex);
2017+ } else
2018+ squashfs_get_cached_block(s, (char *) index,
2019+ index_start, index_offset,
2020+ sizeof(struct squashfs_dir_index),
2021+ &index_start, &index_offset);
2022+
2023+ squashfs_get_cached_block(s, index->name, index_start,
2024+ index_offset, index->size + 1,
2025+ &index_start, &index_offset);
2026+
2027+ index->name[index->size + 1] = '\0';
2028+
2029+ if (strcmp(index->name, str) > 0)
2030+ break;
2031+
2032+ length = index->index;
2033+ *next_block = index->start_block + sblk->directory_table_start;
2034+ }
2035+
2036+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2037+ kfree(str);
2038+failure:
2039+ return length + 3;
2040+}
2041+
2042+
2043+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
2044+{
2045+ struct inode *i = file->f_dentry->d_inode;
2046+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2047+ struct squashfs_super_block *sblk = &msblk->sblk;
2048+ long long next_block = SQUASHFS_I(i)->start_block +
2049+ sblk->directory_table_start;
2050+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
2051+ dir_count;
2052+ struct squashfs_dir_header dirh;
2053+ struct squashfs_dir_entry *dire;
2054+
2055+ TRACE("Entered squashfs_readdir [%llx:%x]\n", next_block, next_offset);
2056+
2057+ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
2058+ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
2059+ ERROR("Failed to allocate squashfs_dir_entry\n");
2060+ goto finish;
2061+ }
2062+
2063+ while(file->f_pos < 3) {
2064+ char *name;
2065+ int size, i_ino;
2066+
2067+ if(file->f_pos == 0) {
2068+ name = ".";
2069+ size = 1;
2070+ i_ino = i->i_ino;
2071+ } else {
2072+ name = "..";
2073+ size = 2;
2074+ i_ino = SQUASHFS_I(i)->u.s2.parent_inode;
2075+ }
2076+ TRACE("Calling filldir(%x, %s, %d, %d, %d, %d)\n",
2077+ (unsigned int) dirent, name, size, (int)
2078+ file->f_pos, i_ino,
2079+ squashfs_filetype_table[1]);
2080+
2081+ if (filldir(dirent, name, size,
2082+ file->f_pos, i_ino,
2083+ squashfs_filetype_table[1]) < 0) {
2084+ TRACE("Filldir returned less than 0\n");
2085+ goto finish;
2086+ }
2087+ file->f_pos += size;
2088+ }
2089+
2090+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
2091+ SQUASHFS_I(i)->u.s2.directory_index_start,
2092+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2093+ SQUASHFS_I(i)->u.s2.directory_index_count,
2094+ file->f_pos);
2095+
2096+ while (length < i_size_read(i)) {
2097+ /* read directory header */
2098+ if (msblk->swap) {
2099+ struct squashfs_dir_header sdirh;
2100+
2101+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2102+ next_block, next_offset, sizeof(sdirh),
2103+ &next_block, &next_offset))
2104+ goto failed_read;
2105+
2106+ length += sizeof(sdirh);
2107+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
2108+ } else {
2109+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2110+ next_block, next_offset, sizeof(dirh),
2111+ &next_block, &next_offset))
2112+ goto failed_read;
2113+
2114+ length += sizeof(dirh);
2115+ }
2116+
2117+ dir_count = dirh.count + 1;
2118+ while (dir_count--) {
2119+ if (msblk->swap) {
2120+ struct squashfs_dir_entry sdire;
2121+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2122+ &sdire, next_block, next_offset,
2123+ sizeof(sdire), &next_block,
2124+ &next_offset))
2125+ goto failed_read;
2126+
2127+ length += sizeof(sdire);
2128+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
2129+ } else {
2130+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2131+ dire, next_block, next_offset,
2132+ sizeof(*dire), &next_block,
2133+ &next_offset))
2134+ goto failed_read;
2135+
2136+ length += sizeof(*dire);
2137+ }
2138+
2139+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2140+ next_block, next_offset,
2141+ dire->size + 1, &next_block,
2142+ &next_offset))
2143+ goto failed_read;
2144+
2145+ length += dire->size + 1;
2146+
2147+ if (file->f_pos >= length)
2148+ continue;
2149+
2150+ dire->name[dire->size + 1] = '\0';
2151+
2152+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d, %d)\n",
2153+ (unsigned int) dirent, dire->name,
2154+ dire->size + 1, (int) file->f_pos,
2155+ dirh.start_block, dire->offset,
2156+ dirh.inode_number + dire->inode_number,
2157+ squashfs_filetype_table[dire->type]);
2158+
2159+ if (filldir(dirent, dire->name, dire->size + 1,
2160+ file->f_pos,
2161+ dirh.inode_number + dire->inode_number,
2162+ squashfs_filetype_table[dire->type])
2163+ < 0) {
2164+ TRACE("Filldir returned less than 0\n");
2165+ goto finish;
2166+ }
2167+ file->f_pos = length;
2168+ }
2169+ }
2170+
2171+finish:
2172+ kfree(dire);
2173+ return 0;
2174+
2175+failed_read:
2176+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
2177+ next_offset);
2178+ kfree(dire);
2179+ return 0;
2180+}
2181+
2182+
2183+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry,
2184+ struct nameidata *nd)
2185+{
2186+ const unsigned char *name = dentry->d_name.name;
2187+ int len = dentry->d_name.len;
2188+ struct inode *inode = NULL;
2189+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2190+ struct squashfs_super_block *sblk = &msblk->sblk;
2191+ long long next_block = SQUASHFS_I(i)->start_block +
2192+ sblk->directory_table_start;
2193+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
2194+ dir_count;
2195+ struct squashfs_dir_header dirh;
2196+ struct squashfs_dir_entry *dire;
2197+
2198+ TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset);
2199+
2200+ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
2201+ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
2202+ ERROR("Failed to allocate squashfs_dir_entry\n");
2203+ goto exit_lookup;
2204+ }
2205+
2206+ if (len > SQUASHFS_NAME_LEN)
2207+ goto exit_lookup;
2208+
2209+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
2210+ SQUASHFS_I(i)->u.s2.directory_index_start,
2211+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2212+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
2213+ len);
2214+
2215+ while (length < i_size_read(i)) {
2216+ /* read directory header */
2217+ if (msblk->swap) {
2218+ struct squashfs_dir_header sdirh;
2219+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2220+ next_block, next_offset, sizeof(sdirh),
2221+ &next_block, &next_offset))
2222+ goto failed_read;
2223+
2224+ length += sizeof(sdirh);
2225+ SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
2226+ } else {
2227+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2228+ next_block, next_offset, sizeof(dirh),
2229+ &next_block, &next_offset))
2230+ goto failed_read;
2231+
2232+ length += sizeof(dirh);
2233+ }
2234+
2235+ dir_count = dirh.count + 1;
2236+ while (dir_count--) {
2237+ if (msblk->swap) {
2238+ struct squashfs_dir_entry sdire;
2239+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2240+ &sdire, next_block,next_offset,
2241+ sizeof(sdire), &next_block,
2242+ &next_offset))
2243+ goto failed_read;
2244+
2245+ length += sizeof(sdire);
2246+ SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
2247+ } else {
2248+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2249+ dire, next_block,next_offset,
2250+ sizeof(*dire), &next_block,
2251+ &next_offset))
2252+ goto failed_read;
2253+
2254+ length += sizeof(*dire);
2255+ }
2256+
2257+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2258+ next_block, next_offset, dire->size + 1,
2259+ &next_block, &next_offset))
2260+ goto failed_read;
2261+
2262+ length += dire->size + 1;
2263+
2264+ if (name[0] < dire->name[0])
2265+ goto exit_lookup;
2266+
2267+ if ((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
2268+ squashfs_inode_t ino = SQUASHFS_MKINODE(dirh.start_block,
2269+ dire->offset);
2270+
2271+ TRACE("calling squashfs_iget for directory "
2272+ "entry %s, inode %x:%x, %d\n", name,
2273+ dirh.start_block, dire->offset,
2274+ dirh.inode_number + dire->inode_number);
2275+
2276+ inode = squashfs_iget(i->i_sb, ino, dirh.inode_number + dire->inode_number);
2277+
2278+ goto exit_lookup;
2279+ }
2280+ }
2281+ }
2282+
2283+exit_lookup:
2284+ kfree(dire);
2285+ if (inode)
2286+ return d_splice_alias(inode, dentry);
2287+ d_add(dentry, inode);
2288+ return ERR_PTR(0);
2289+
2290+failed_read:
2291+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
2292+ next_offset);
2293+ goto exit_lookup;
2294+}
2295+
2296+
2297+static int squashfs_remount(struct super_block *s, int *flags, char *data)
2298+{
2299+ *flags |= MS_RDONLY;
2300+ return 0;
2301+}
2302+
2303+
2304+static void squashfs_put_super(struct super_block *s)
2305+{
2306+ int i;
2307+
2308+ if (s->s_fs_info) {
2309+ struct squashfs_sb_info *sbi = s->s_fs_info;
2310+ if (sbi->block_cache)
2311+ for (i = 0; i < SQUASHFS_CACHED_BLKS; i++)
2312+ if (sbi->block_cache[i].block !=
2313+ SQUASHFS_INVALID_BLK)
2314+ kfree(sbi->block_cache[i].data);
2315+ if (sbi->fragment)
2316+ for (i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++)
2317+ SQUASHFS_FREE(sbi->fragment[i].data);
2318+ kfree(sbi->fragment);
2319+ kfree(sbi->block_cache);
2320+ kfree(sbi->read_page);
2321+ kfree(sbi->uid);
2322+ kfree(sbi->fragment_index);
2323+ kfree(sbi->fragment_index_2);
2324+ kfree(sbi->meta_index);
2325+ vfree(sbi->stream.workspace);
2326+ kfree(s->s_fs_info);
2327+ s->s_fs_info = NULL;
2328+ }
2329+}
2330+
2331+
2332+static int squashfs_get_sb(struct file_system_type *fs_type, int flags,
2333+ const char *dev_name, void *data,
2334+ struct vfsmount *mnt)
2335+{
2336+ return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super,
2337+ mnt);
2338+}
2339+
2340+
2341+static int __init init_squashfs_fs(void)
2342+{
2343+ int err = init_inodecache();
2344+ if (err)
2345+ goto out;
2346+
2347+ printk(KERN_INFO "squashfs: version 3.2-r2 (2007/01/15) "
2348+ "Phillip Lougher\n");
2349+
2350+ if ((err = register_filesystem(&squashfs_fs_type)))
2351+ destroy_inodecache();
2352+
2353+out:
2354+ return err;
2355+}
2356+
2357+
2358+static void __exit exit_squashfs_fs(void)
2359+{
2360+ unregister_filesystem(&squashfs_fs_type);
2361+ destroy_inodecache();
2362+}
2363+
2364+
2365+static struct kmem_cache * squashfs_inode_cachep;
2366+
2367+
2368+static struct inode *squashfs_alloc_inode(struct super_block *sb)
2369+{
2370+ struct squashfs_inode_info *ei;
2371+ ei = kmem_cache_alloc(squashfs_inode_cachep, GFP_KERNEL);
2372+ if (!ei)
2373+ return NULL;
2374+ return &ei->vfs_inode;
2375+}
2376+
2377+
2378+static void squashfs_destroy_inode(struct inode *inode)
2379+{
2380+ kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
2381+}
2382+
2383+
2384+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
2385+{
2386+ struct squashfs_inode_info *ei = foo;
2387+
2388+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
2389+ SLAB_CTOR_CONSTRUCTOR)
2390+ inode_init_once(&ei->vfs_inode);
2391+}
2392+
2393+
2394+static int __init init_inodecache(void)
2395+{
2396+ squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
2397+ sizeof(struct squashfs_inode_info),
2398+ 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
2399+ init_once, NULL);
2400+ if (squashfs_inode_cachep == NULL)
2401+ return -ENOMEM;
2402+ return 0;
2403+}
2404+
2405+
2406+static void destroy_inodecache(void)
2407+{
2408+ kmem_cache_destroy(squashfs_inode_cachep);
2409+}
2410+
2411+
2412+module_init(init_squashfs_fs);
2413+module_exit(exit_squashfs_fs);
2414+MODULE_DESCRIPTION("squashfs 3.2-r2, a compressed read-only filesystem");
2415+MODULE_AUTHOR("Phillip Lougher <phillip@lougher.org.uk>");
2416+MODULE_LICENSE("GPL");
2417--- /dev/null
2418+++ linux-2.6.24-rc1/fs/squashfs/Makefile
2419@@ -0,0 +1,7 @@
2420+#
2421+# Makefile for the linux squashfs routines.
2422+#
2423+
2424+obj-$(CONFIG_SQUASHFS) += squashfs.o
2425+squashfs-y += inode.o
2426+squashfs-y += squashfs2_0.o
2427--- /dev/null
2428+++ linux-2.6.24-rc1/fs/squashfs/squashfs2_0.c
2429@@ -0,0 +1,742 @@
2430+/*
2431+ * Squashfs - a compressed read only filesystem for Linux
2432+ *
2433+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
2434+ * Phillip Lougher <phillip@lougher.org.uk>
2435+ *
2436+ * This program is free software; you can redistribute it and/or
2437+ * modify it under the terms of the GNU General Public License
2438+ * as published by the Free Software Foundation; either version 2,
2439+ * or (at your option) any later version.
2440+ *
2441+ * This program is distributed in the hope that it will be useful,
2442+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2443+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2444+ * GNU General Public License for more details.
2445+ *
2446+ * You should have received a copy of the GNU General Public License
2447+ * along with this program; if not, write to the Free Software
2448+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2449+ *
2450+ * squashfs2_0.c
2451+ */
2452+
2453+#include <linux/squashfs_fs.h>
2454+#include <linux/module.h>
2455+#include <linux/zlib.h>
2456+#include <linux/fs.h>
2457+#include <linux/squashfs_fs_sb.h>
2458+#include <linux/squashfs_fs_i.h>
2459+
2460+#include "squashfs.h"
2461+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir);
2462+static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *,
2463+ struct nameidata *);
2464+
2465+static struct file_operations squashfs_dir_ops_2 = {
2466+ .read = generic_read_dir,
2467+ .readdir = squashfs_readdir_2
2468+};
2469+
2470+static struct inode_operations squashfs_dir_inode_ops_2 = {
2471+ .lookup = squashfs_lookup_2
2472+};
2473+
2474+static unsigned char squashfs_filetype_table[] = {
2475+ DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
2476+};
2477+
2478+static int read_fragment_index_table_2(struct super_block *s)
2479+{
2480+ struct squashfs_sb_info *msblk = s->s_fs_info;
2481+ struct squashfs_super_block *sblk = &msblk->sblk;
2482+
2483+ if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2
2484+ (sblk->fragments), GFP_KERNEL))) {
2485+ ERROR("Failed to allocate uid/gid table\n");
2486+ return 0;
2487+ }
2488+
2489+ if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) &&
2490+ !squashfs_read_data(s, (char *)
2491+ msblk->fragment_index_2,
2492+ sblk->fragment_table_start,
2493+ SQUASHFS_FRAGMENT_INDEX_BYTES_2
2494+ (sblk->fragments) |
2495+ SQUASHFS_COMPRESSED_BIT_BLOCK, NULL, SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments))) {
2496+ ERROR("unable to read fragment index table\n");
2497+ return 0;
2498+ }
2499+
2500+ if (msblk->swap) {
2501+ int i;
2502+ unsigned int fragment;
2503+
2504+ for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments);
2505+ i++) {
2506+ SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment),
2507+ &msblk->fragment_index_2[i], 1);
2508+ msblk->fragment_index_2[i] = fragment;
2509+ }
2510+ }
2511+
2512+ return 1;
2513+}
2514+
2515+
2516+static int get_fragment_location_2(struct super_block *s, unsigned int fragment,
2517+ long long *fragment_start_block,
2518+ unsigned int *fragment_size)
2519+{
2520+ struct squashfs_sb_info *msblk = s->s_fs_info;
2521+ long long start_block =
2522+ msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)];
2523+ int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment);
2524+ struct squashfs_fragment_entry_2 fragment_entry;
2525+
2526+ if (msblk->swap) {
2527+ struct squashfs_fragment_entry_2 sfragment_entry;
2528+
2529+ if (!squashfs_get_cached_block(s, (char *) &sfragment_entry,
2530+ start_block, offset,
2531+ sizeof(sfragment_entry), &start_block,
2532+ &offset))
2533+ goto out;
2534+ SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry);
2535+ } else
2536+ if (!squashfs_get_cached_block(s, (char *) &fragment_entry,
2537+ start_block, offset,
2538+ sizeof(fragment_entry), &start_block,
2539+ &offset))
2540+ goto out;
2541+
2542+ *fragment_start_block = fragment_entry.start_block;
2543+ *fragment_size = fragment_entry.size;
2544+
2545+ return 1;
2546+
2547+out:
2548+ return 0;
2549+}
2550+
2551+
2552+static void squashfs_new_inode(struct squashfs_sb_info *msblk, struct inode *i,
2553+ struct squashfs_base_inode_header_2 *inodeb, unsigned int ino)
2554+{
2555+ struct squashfs_super_block *sblk = &msblk->sblk;
2556+
2557+ i->i_ino = ino;
2558+ i->i_mtime.tv_sec = sblk->mkfs_time;
2559+ i->i_atime.tv_sec = sblk->mkfs_time;
2560+ i->i_ctime.tv_sec = sblk->mkfs_time;
2561+ i->i_uid = msblk->uid[inodeb->uid];
2562+ i->i_mode = inodeb->mode;
2563+ i->i_nlink = 1;
2564+ i->i_size = 0;
2565+ if (inodeb->guid == SQUASHFS_GUIDS)
2566+ i->i_gid = i->i_uid;
2567+ else
2568+ i->i_gid = msblk->guid[inodeb->guid];
2569+}
2570+
2571+
2572+static int squashfs_read_inode_2(struct inode *i, squashfs_inode_t inode)
2573+{
2574+ struct super_block *s = i->i_sb;
2575+ struct squashfs_sb_info *msblk = s->s_fs_info;
2576+ struct squashfs_super_block *sblk = &msblk->sblk;
2577+ unsigned int block = SQUASHFS_INODE_BLK(inode) +
2578+ sblk->inode_table_start;
2579+ unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
2580+ unsigned int ino = i->i_ino;
2581+ long long next_block;
2582+ unsigned int next_offset;
2583+ union squashfs_inode_header_2 id, sid;
2584+ struct squashfs_base_inode_header_2 *inodeb = &id.base,
2585+ *sinodeb = &sid.base;
2586+
2587+ TRACE("Entered squashfs_iget\n");
2588+
2589+ if (msblk->swap) {
2590+ if (!squashfs_get_cached_block(s, (char *) sinodeb, block,
2591+ offset, sizeof(*sinodeb), &next_block,
2592+ &next_offset))
2593+ goto failed_read;
2594+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb,
2595+ sizeof(*sinodeb));
2596+ } else
2597+ if (!squashfs_get_cached_block(s, (char *) inodeb, block,
2598+ offset, sizeof(*inodeb), &next_block,
2599+ &next_offset))
2600+ goto failed_read;
2601+
2602+ squashfs_new_inode(msblk, i, inodeb, ino);
2603+
2604+ switch(inodeb->inode_type) {
2605+ case SQUASHFS_FILE_TYPE: {
2606+ struct squashfs_reg_inode_header_2 *inodep = &id.reg;
2607+ struct squashfs_reg_inode_header_2 *sinodep = &sid.reg;
2608+ long long frag_blk;
2609+ unsigned int frag_size = 0;
2610+
2611+ if (msblk->swap) {
2612+ if (!squashfs_get_cached_block(s, (char *)
2613+ sinodep, block, offset,
2614+ sizeof(*sinodep), &next_block,
2615+ &next_offset))
2616+ goto failed_read;
2617+ SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep);
2618+ } else
2619+ if (!squashfs_get_cached_block(s, (char *)
2620+ inodep, block, offset,
2621+ sizeof(*inodep), &next_block,
2622+ &next_offset))
2623+ goto failed_read;
2624+
2625+ frag_blk = SQUASHFS_INVALID_BLK;
2626+ if (inodep->fragment != SQUASHFS_INVALID_FRAG &&
2627+ !get_fragment_location_2(s,
2628+ inodep->fragment, &frag_blk, &frag_size))
2629+ goto failed_read;
2630+
2631+ i->i_size = inodep->file_size;
2632+ i->i_fop = &generic_ro_fops;
2633+ i->i_mode |= S_IFREG;
2634+ i->i_mtime.tv_sec = inodep->mtime;
2635+ i->i_atime.tv_sec = inodep->mtime;
2636+ i->i_ctime.tv_sec = inodep->mtime;
2637+ i->i_blocks = ((i->i_size - 1) >> 9) + 1;
2638+ SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk;
2639+ SQUASHFS_I(i)->u.s1.fragment_size = frag_size;
2640+ SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset;
2641+ SQUASHFS_I(i)->start_block = inodep->start_block;
2642+ SQUASHFS_I(i)->u.s1.block_list_start = next_block;
2643+ SQUASHFS_I(i)->offset = next_offset;
2644+ if (sblk->block_size > 4096)
2645+ i->i_data.a_ops = &squashfs_aops;
2646+ else
2647+ i->i_data.a_ops = &squashfs_aops_4K;
2648+
2649+ TRACE("File inode %x:%x, start_block %x, "
2650+ "block_list_start %llx, offset %x\n",
2651+ SQUASHFS_INODE_BLK(inode), offset,
2652+ inodep->start_block, next_block,
2653+ next_offset);
2654+ break;
2655+ }
2656+ case SQUASHFS_DIR_TYPE: {
2657+ struct squashfs_dir_inode_header_2 *inodep = &id.dir;
2658+ struct squashfs_dir_inode_header_2 *sinodep = &sid.dir;
2659+
2660+ if (msblk->swap) {
2661+ if (!squashfs_get_cached_block(s, (char *)
2662+ sinodep, block, offset,
2663+ sizeof(*sinodep), &next_block,
2664+ &next_offset))
2665+ goto failed_read;
2666+ SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep);
2667+ } else
2668+ if (!squashfs_get_cached_block(s, (char *)
2669+ inodep, block, offset,
2670+ sizeof(*inodep), &next_block,
2671+ &next_offset))
2672+ goto failed_read;
2673+
2674+ i->i_size = inodep->file_size;
2675+ i->i_op = &squashfs_dir_inode_ops_2;
2676+ i->i_fop = &squashfs_dir_ops_2;
2677+ i->i_mode |= S_IFDIR;
2678+ i->i_mtime.tv_sec = inodep->mtime;
2679+ i->i_atime.tv_sec = inodep->mtime;
2680+ i->i_ctime.tv_sec = inodep->mtime;
2681+ SQUASHFS_I(i)->start_block = inodep->start_block;
2682+ SQUASHFS_I(i)->offset = inodep->offset;
2683+ SQUASHFS_I(i)->u.s2.directory_index_count = 0;
2684+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
2685+
2686+ TRACE("Directory inode %x:%x, start_block %x, offset "
2687+ "%x\n", SQUASHFS_INODE_BLK(inode),
2688+ offset, inodep->start_block,
2689+ inodep->offset);
2690+ break;
2691+ }
2692+ case SQUASHFS_LDIR_TYPE: {
2693+ struct squashfs_ldir_inode_header_2 *inodep = &id.ldir;
2694+ struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir;
2695+
2696+ if (msblk->swap) {
2697+ if (!squashfs_get_cached_block(s, (char *)
2698+ sinodep, block, offset,
2699+ sizeof(*sinodep), &next_block,
2700+ &next_offset))
2701+ goto failed_read;
2702+ SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep,
2703+ sinodep);
2704+ } else
2705+ if (!squashfs_get_cached_block(s, (char *)
2706+ inodep, block, offset,
2707+ sizeof(*inodep), &next_block,
2708+ &next_offset))
2709+ goto failed_read;
2710+
2711+ i->i_size = inodep->file_size;
2712+ i->i_op = &squashfs_dir_inode_ops_2;
2713+ i->i_fop = &squashfs_dir_ops_2;
2714+ i->i_mode |= S_IFDIR;
2715+ i->i_mtime.tv_sec = inodep->mtime;
2716+ i->i_atime.tv_sec = inodep->mtime;
2717+ i->i_ctime.tv_sec = inodep->mtime;
2718+ SQUASHFS_I(i)->start_block = inodep->start_block;
2719+ SQUASHFS_I(i)->offset = inodep->offset;
2720+ SQUASHFS_I(i)->u.s2.directory_index_start = next_block;
2721+ SQUASHFS_I(i)->u.s2.directory_index_offset =
2722+ next_offset;
2723+ SQUASHFS_I(i)->u.s2.directory_index_count =
2724+ inodep->i_count;
2725+ SQUASHFS_I(i)->u.s2.parent_inode = 0;
2726+
2727+ TRACE("Long directory inode %x:%x, start_block %x, "
2728+ "offset %x\n",
2729+ SQUASHFS_INODE_BLK(inode), offset,
2730+ inodep->start_block, inodep->offset);
2731+ break;
2732+ }
2733+ case SQUASHFS_SYMLINK_TYPE: {
2734+ struct squashfs_symlink_inode_header_2 *inodep =
2735+ &id.symlink;
2736+ struct squashfs_symlink_inode_header_2 *sinodep =
2737+ &sid.symlink;
2738+
2739+ if (msblk->swap) {
2740+ if (!squashfs_get_cached_block(s, (char *)
2741+ sinodep, block, offset,
2742+ sizeof(*sinodep), &next_block,
2743+ &next_offset))
2744+ goto failed_read;
2745+ SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep,
2746+ sinodep);
2747+ } else
2748+ if (!squashfs_get_cached_block(s, (char *)
2749+ inodep, block, offset,
2750+ sizeof(*inodep), &next_block,
2751+ &next_offset))
2752+ goto failed_read;
2753+
2754+ i->i_size = inodep->symlink_size;
2755+ i->i_op = &page_symlink_inode_operations;
2756+ i->i_data.a_ops = &squashfs_symlink_aops;
2757+ i->i_mode |= S_IFLNK;
2758+ SQUASHFS_I(i)->start_block = next_block;
2759+ SQUASHFS_I(i)->offset = next_offset;
2760+
2761+ TRACE("Symbolic link inode %x:%x, start_block %llx, "
2762+ "offset %x\n",
2763+ SQUASHFS_INODE_BLK(inode), offset,
2764+ next_block, next_offset);
2765+ break;
2766+ }
2767+ case SQUASHFS_BLKDEV_TYPE:
2768+ case SQUASHFS_CHRDEV_TYPE: {
2769+ struct squashfs_dev_inode_header_2 *inodep = &id.dev;
2770+ struct squashfs_dev_inode_header_2 *sinodep = &sid.dev;
2771+
2772+ if (msblk->swap) {
2773+ if (!squashfs_get_cached_block(s, (char *)
2774+ sinodep, block, offset,
2775+ sizeof(*sinodep), &next_block,
2776+ &next_offset))
2777+ goto failed_read;
2778+ SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep);
2779+ } else
2780+ if (!squashfs_get_cached_block(s, (char *)
2781+ inodep, block, offset,
2782+ sizeof(*inodep), &next_block,
2783+ &next_offset))
2784+ goto failed_read;
2785+
2786+ i->i_mode |= (inodeb->inode_type ==
2787+ SQUASHFS_CHRDEV_TYPE) ? S_IFCHR :
2788+ S_IFBLK;
2789+ init_special_inode(i, i->i_mode,
2790+ old_decode_dev(inodep->rdev));
2791+
2792+ TRACE("Device inode %x:%x, rdev %x\n",
2793+ SQUASHFS_INODE_BLK(inode), offset,
2794+ inodep->rdev);
2795+ break;
2796+ }
2797+ case SQUASHFS_FIFO_TYPE:
2798+ case SQUASHFS_SOCKET_TYPE: {
2799+
2800+ i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE)
2801+ ? S_IFIFO : S_IFSOCK;
2802+ init_special_inode(i, i->i_mode, 0);
2803+ break;
2804+ }
2805+ default:
2806+ ERROR("Unknown inode type %d in squashfs_iget!\n",
2807+ inodeb->inode_type);
2808+ goto failed_read1;
2809+ }
2810+
2811+ return 1;
2812+
2813+failed_read:
2814+ ERROR("Unable to read inode [%x:%x]\n", block, offset);
2815+
2816+failed_read1:
2817+ return 0;
2818+}
2819+
2820+
2821+static int get_dir_index_using_offset(struct super_block *s, long long
2822+ *next_block, unsigned int *next_offset,
2823+ long long index_start,
2824+ unsigned int index_offset, int i_count,
2825+ long long f_pos)
2826+{
2827+ struct squashfs_sb_info *msblk = s->s_fs_info;
2828+ struct squashfs_super_block *sblk = &msblk->sblk;
2829+ int i, length = 0;
2830+ struct squashfs_dir_index_2 index;
2831+
2832+ TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n",
2833+ i_count, (unsigned int) f_pos);
2834+
2835+ if (f_pos == 0)
2836+ goto finish;
2837+
2838+ for (i = 0; i < i_count; i++) {
2839+ if (msblk->swap) {
2840+ struct squashfs_dir_index_2 sindex;
2841+ squashfs_get_cached_block(s, (char *) &sindex,
2842+ index_start, index_offset,
2843+ sizeof(sindex), &index_start,
2844+ &index_offset);
2845+ SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex);
2846+ } else
2847+ squashfs_get_cached_block(s, (char *) &index,
2848+ index_start, index_offset,
2849+ sizeof(index), &index_start,
2850+ &index_offset);
2851+
2852+ if (index.index > f_pos)
2853+ break;
2854+
2855+ squashfs_get_cached_block(s, NULL, index_start, index_offset,
2856+ index.size + 1, &index_start,
2857+ &index_offset);
2858+
2859+ length = index.index;
2860+ *next_block = index.start_block + sblk->directory_table_start;
2861+ }
2862+
2863+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2864+
2865+finish:
2866+ return length;
2867+}
2868+
2869+
2870+static int get_dir_index_using_name(struct super_block *s, long long
2871+ *next_block, unsigned int *next_offset,
2872+ long long index_start,
2873+ unsigned int index_offset, int i_count,
2874+ const char *name, int size)
2875+{
2876+ struct squashfs_sb_info *msblk = s->s_fs_info;
2877+ struct squashfs_super_block *sblk = &msblk->sblk;
2878+ int i, length = 0;
2879+ struct squashfs_dir_index_2 *index;
2880+ char *str;
2881+
2882+ TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);
2883+
2884+ if (!(str = kmalloc(sizeof(struct squashfs_dir_index) +
2885+ (SQUASHFS_NAME_LEN + 1) * 2, GFP_KERNEL))) {
2886+ ERROR("Failed to allocate squashfs_dir_index\n");
2887+ goto failure;
2888+ }
2889+
2890+ index = (struct squashfs_dir_index_2 *) (str + SQUASHFS_NAME_LEN + 1);
2891+ strncpy(str, name, size);
2892+ str[size] = '\0';
2893+
2894+ for (i = 0; i < i_count; i++) {
2895+ if (msblk->swap) {
2896+ struct squashfs_dir_index_2 sindex;
2897+ squashfs_get_cached_block(s, (char *) &sindex,
2898+ index_start, index_offset,
2899+ sizeof(sindex), &index_start,
2900+ &index_offset);
2901+ SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex);
2902+ } else
2903+ squashfs_get_cached_block(s, (char *) index,
2904+ index_start, index_offset,
2905+ sizeof(struct squashfs_dir_index_2),
2906+ &index_start, &index_offset);
2907+
2908+ squashfs_get_cached_block(s, index->name, index_start,
2909+ index_offset, index->size + 1,
2910+ &index_start, &index_offset);
2911+
2912+ index->name[index->size + 1] = '\0';
2913+
2914+ if (strcmp(index->name, str) > 0)
2915+ break;
2916+
2917+ length = index->index;
2918+ *next_block = index->start_block + sblk->directory_table_start;
2919+ }
2920+
2921+ *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;
2922+ kfree(str);
2923+failure:
2924+ return length;
2925+}
2926+
2927+
2928+static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir)
2929+{
2930+ struct inode *i = file->f_dentry->d_inode;
2931+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
2932+ struct squashfs_super_block *sblk = &msblk->sblk;
2933+ long long next_block = SQUASHFS_I(i)->start_block +
2934+ sblk->directory_table_start;
2935+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
2936+ dir_count;
2937+ struct squashfs_dir_header_2 dirh;
2938+ struct squashfs_dir_entry_2 *dire;
2939+
2940+ TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset);
2941+
2942+ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
2943+ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
2944+ ERROR("Failed to allocate squashfs_dir_entry\n");
2945+ goto finish;
2946+ }
2947+
2948+ length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset,
2949+ SQUASHFS_I(i)->u.s2.directory_index_start,
2950+ SQUASHFS_I(i)->u.s2.directory_index_offset,
2951+ SQUASHFS_I(i)->u.s2.directory_index_count,
2952+ file->f_pos);
2953+
2954+ while (length < i_size_read(i)) {
2955+ /* read directory header */
2956+ if (msblk->swap) {
2957+ struct squashfs_dir_header_2 sdirh;
2958+
2959+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
2960+ next_block, next_offset, sizeof(sdirh),
2961+ &next_block, &next_offset))
2962+ goto failed_read;
2963+
2964+ length += sizeof(sdirh);
2965+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
2966+ } else {
2967+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
2968+ next_block, next_offset, sizeof(dirh),
2969+ &next_block, &next_offset))
2970+ goto failed_read;
2971+
2972+ length += sizeof(dirh);
2973+ }
2974+
2975+ dir_count = dirh.count + 1;
2976+ while (dir_count--) {
2977+ if (msblk->swap) {
2978+ struct squashfs_dir_entry_2 sdire;
2979+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2980+ &sdire, next_block, next_offset,
2981+ sizeof(sdire), &next_block,
2982+ &next_offset))
2983+ goto failed_read;
2984+
2985+ length += sizeof(sdire);
2986+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
2987+ } else {
2988+ if (!squashfs_get_cached_block(i->i_sb, (char *)
2989+ dire, next_block, next_offset,
2990+ sizeof(*dire), &next_block,
2991+ &next_offset))
2992+ goto failed_read;
2993+
2994+ length += sizeof(*dire);
2995+ }
2996+
2997+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
2998+ next_block, next_offset,
2999+ dire->size + 1, &next_block,
3000+ &next_offset))
3001+ goto failed_read;
3002+
3003+ length += dire->size + 1;
3004+
3005+ if (file->f_pos >= length)
3006+ continue;
3007+
3008+ dire->name[dire->size + 1] = '\0';
3009+
3010+ TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n",
3011+ (unsigned int) dirent, dire->name,
3012+ dire->size + 1, (int) file->f_pos,
3013+ dirh.start_block, dire->offset,
3014+ squashfs_filetype_table[dire->type]);
3015+
3016+ if (filldir(dirent, dire->name, dire->size + 1,
3017+ file->f_pos, SQUASHFS_MK_VFS_INODE(
3018+ dirh.start_block, dire->offset),
3019+ squashfs_filetype_table[dire->type])
3020+ < 0) {
3021+ TRACE("Filldir returned less than 0\n");
3022+ goto finish;
3023+ }
3024+ file->f_pos = length;
3025+ }
3026+ }
3027+
3028+finish:
3029+ kfree(dire);
3030+ return 0;
3031+
3032+failed_read:
3033+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
3034+ next_offset);
3035+ kfree(dire);
3036+ return 0;
3037+}
3038+
3039+
3040+static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry,
3041+ struct nameidata *nd)
3042+{
3043+ const unsigned char *name = dentry->d_name.name;
3044+ int len = dentry->d_name.len;
3045+ struct inode *inode = NULL;
3046+ struct squashfs_sb_info *msblk = i->i_sb->s_fs_info;
3047+ struct squashfs_super_block *sblk = &msblk->sblk;
3048+ long long next_block = SQUASHFS_I(i)->start_block +
3049+ sblk->directory_table_start;
3050+ int next_offset = SQUASHFS_I(i)->offset, length = 0,
3051+ dir_count;
3052+ struct squashfs_dir_header_2 dirh;
3053+ struct squashfs_dir_entry_2 *dire;
3054+ int sorted = sblk->s_major == 2 && sblk->s_minor >= 1;
3055+
3056+ TRACE("Entered squashfs_lookup_2 [%llx:%x]\n", next_block, next_offset);
3057+
3058+ if (!(dire = kmalloc(sizeof(struct squashfs_dir_entry) +
3059+ SQUASHFS_NAME_LEN + 1, GFP_KERNEL))) {
3060+ ERROR("Failed to allocate squashfs_dir_entry\n");
3061+ goto exit_loop;
3062+ }
3063+
3064+ if (len > SQUASHFS_NAME_LEN)
3065+ goto exit_loop;
3066+
3067+ length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset,
3068+ SQUASHFS_I(i)->u.s2.directory_index_start,
3069+ SQUASHFS_I(i)->u.s2.directory_index_offset,
3070+ SQUASHFS_I(i)->u.s2.directory_index_count, name,
3071+ len);
3072+
3073+ while (length < i_size_read(i)) {
3074+ /* read directory header */
3075+ if (msblk->swap) {
3076+ struct squashfs_dir_header_2 sdirh;
3077+ if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh,
3078+ next_block, next_offset, sizeof(sdirh),
3079+ &next_block, &next_offset))
3080+ goto failed_read;
3081+
3082+ length += sizeof(sdirh);
3083+ SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh);
3084+ } else {
3085+ if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh,
3086+ next_block, next_offset, sizeof(dirh),
3087+ &next_block, &next_offset))
3088+ goto failed_read;
3089+
3090+ length += sizeof(dirh);
3091+ }
3092+
3093+ dir_count = dirh.count + 1;
3094+ while (dir_count--) {
3095+ if (msblk->swap) {
3096+ struct squashfs_dir_entry_2 sdire;
3097+ if (!squashfs_get_cached_block(i->i_sb, (char *)
3098+ &sdire, next_block,next_offset,
3099+ sizeof(sdire), &next_block,
3100+ &next_offset))
3101+ goto failed_read;
3102+
3103+ length += sizeof(sdire);
3104+ SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire);
3105+ } else {
3106+ if (!squashfs_get_cached_block(i->i_sb, (char *)
3107+ dire, next_block,next_offset,
3108+ sizeof(*dire), &next_block,
3109+ &next_offset))
3110+ goto failed_read;
3111+
3112+ length += sizeof(*dire);
3113+ }
3114+
3115+ if (!squashfs_get_cached_block(i->i_sb, dire->name,
3116+ next_block, next_offset, dire->size + 1,
3117+ &next_block, &next_offset))
3118+ goto failed_read;
3119+
3120+ length += dire->size + 1;
3121+
3122+ if (sorted && name[0] < dire->name[0])
3123+ goto exit_loop;
3124+
3125+ if ((len == dire->size + 1) && !strncmp(name,
3126+ dire->name, len)) {
3127+ squashfs_inode_t ino =
3128+ SQUASHFS_MKINODE(dirh.start_block,
3129+ dire->offset);
3130+ unsigned int inode_number = SQUASHFS_MK_VFS_INODE(dirh.start_block,
3131+ dire->offset);
3132+
3133+ TRACE("calling squashfs_iget for directory "
3134+ "entry %s, inode %x:%x, %lld\n", name,
3135+ dirh.start_block, dire->offset, ino);
3136+
3137+ inode = squashfs_iget(i->i_sb, ino, inode_number);
3138+
3139+ goto exit_loop;
3140+ }
3141+ }
3142+ }
3143+
3144+exit_loop:
3145+ kfree(dire);
3146+ d_add(dentry, inode);
3147+ return ERR_PTR(0);
3148+
3149+failed_read:
3150+ ERROR("Unable to read directory block [%llx:%x]\n", next_block,
3151+ next_offset);
3152+ goto exit_loop;
3153+}
3154+
3155+
3156+int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
3157+{
3158+ struct squashfs_super_block *sblk = &msblk->sblk;
3159+
3160+ msblk->read_inode = squashfs_read_inode_2;
3161+ msblk->read_fragment_index_table = read_fragment_index_table_2;
3162+
3163+ sblk->bytes_used = sblk->bytes_used_2;
3164+ sblk->uid_start = sblk->uid_start_2;
3165+ sblk->guid_start = sblk->guid_start_2;
3166+ sblk->inode_table_start = sblk->inode_table_start_2;
3167+ sblk->directory_table_start = sblk->directory_table_start_2;
3168+ sblk->fragment_table_start = sblk->fragment_table_start_2;
3169+
3170+ return 1;
3171+}
3172--- /dev/null
3173+++ linux-2.6.24-rc1/fs/squashfs/squashfs.h
3174@@ -0,0 +1,87 @@
3175+/*
3176+ * Squashfs - a compressed read only filesystem for Linux
3177+ *
3178+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
3179+ * Phillip Lougher <phillip@lougher.org.uk>
3180+ *
3181+ * This program is free software; you can redistribute it and/or
3182+ * modify it under the terms of the GNU General Public License
3183+ * as published by the Free Software Foundation; either version 2,
3184+ * or (at your option) any later version.
3185+ *
3186+ * This program is distributed in the hope that it will be useful,
3187+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3188+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3189+ * GNU General Public License for more details.
3190+ *
3191+ * You should have received a copy of the GNU General Public License
3192+ * along with this program; if not, write to the Free Software
3193+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3194+ *
3195+ * squashfs.h
3196+ */
3197+
3198+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3199+#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3200+#endif
3201+
3202+#ifdef SQUASHFS_TRACE
3203+#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
3204+#else
3205+#define TRACE(s, args...) {}
3206+#endif
3207+
3208+#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args)
3209+
3210+#define SERROR(s, args...) do { \
3211+ if (!silent) \
3212+ printk(KERN_ERR "SQUASHFS error: "s, ## args);\
3213+ } while(0)
3214+
3215+#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args)
3216+
3217+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
3218+{
3219+ return list_entry(inode, struct squashfs_inode_info, vfs_inode);
3220+}
3221+
3222+#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY)
3223+#define SQSH_EXTERN
3224+extern unsigned int squashfs_read_data(struct super_block *s, char *buffer,
3225+ long long index, unsigned int length,
3226+ long long *next_index, int srclength);
3227+extern int squashfs_get_cached_block(struct super_block *s, char *buffer,
3228+ long long block, unsigned int offset,
3229+ int length, long long *next_block,
3230+ unsigned int *next_offset);
3231+extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct
3232+ squashfs_fragment_cache *fragment);
3233+extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block
3234+ *s, long long start_block,
3235+ int length);
3236+extern struct inode *squashfs_iget(struct super_block *s, squashfs_inode_t inode, unsigned int inode_number);
3237+extern const struct address_space_operations squashfs_symlink_aops;
3238+extern const struct address_space_operations squashfs_aops;
3239+extern const struct address_space_operations squashfs_aops_4K;
3240+extern struct inode_operations squashfs_dir_inode_ops;
3241+#else
3242+#define SQSH_EXTERN static
3243+#endif
3244+
3245+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3246+extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk);
3247+#else
3248+static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk)
3249+{
3250+ return 0;
3251+}
3252+#endif
3253+
3254+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3255+extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk);
3256+#else
3257+static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk)
3258+{
3259+ return 0;
3260+}
3261+#endif
3262--- /dev/null
3263+++ linux-2.6.24-rc1/include/linux/squashfs_fs.h
3264@@ -0,0 +1,934 @@
3265+#ifndef SQUASHFS_FS
3266+#define SQUASHFS_FS
3267+
3268+/*
3269+ * Squashfs
3270+ *
3271+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
3272+ * Phillip Lougher <phillip@lougher.org.uk>
3273+ *
3274+ * This program is free software; you can redistribute it and/or
3275+ * modify it under the terms of the GNU General Public License
3276+ * as published by the Free Software Foundation; either version 2,
3277+ * or (at your option) any later version.
3278+ *
3279+ * This program is distributed in the hope that it will be useful,
3280+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3281+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3282+ * GNU General Public License for more details.
3283+ *
3284+ * You should have received a copy of the GNU General Public License
3285+ * along with this program; if not, write to the Free Software
3286+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
3287+ *
3288+ * squashfs_fs.h
3289+ */
3290+
3291+#ifndef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3292+#define CONFIG_SQUASHFS_2_0_COMPATIBILITY
3293+#endif
3294+
3295+#ifdef CONFIG_SQUASHFS_VMALLOC
3296+#define SQUASHFS_ALLOC(a) vmalloc(a)
3297+#define SQUASHFS_FREE(a) vfree(a)
3298+#else
3299+#define SQUASHFS_ALLOC(a) kmalloc(a, GFP_KERNEL)
3300+#define SQUASHFS_FREE(a) kfree(a)
3301+#endif
3302+#define SQUASHFS_CACHED_FRAGMENTS CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE
3303+#define SQUASHFS_MAJOR 3
3304+#define SQUASHFS_MINOR 0
3305+#define SQUASHFS_MAGIC 0x73717368
3306+#define SQUASHFS_MAGIC_SWAP 0x68737173
3307+#define SQUASHFS_START 0
3308+
3309+/* size of metadata (inode and directory) blocks */
3310+#define SQUASHFS_METADATA_SIZE 8192
3311+#define SQUASHFS_METADATA_LOG 13
3312+
3313+/* default size of data blocks */
3314+#define SQUASHFS_FILE_SIZE 65536
3315+#define SQUASHFS_FILE_LOG 16
3316+
3317+#define SQUASHFS_FILE_MAX_SIZE 65536
3318+
3319+/* Max number of uids and gids */
3320+#define SQUASHFS_UIDS 256
3321+#define SQUASHFS_GUIDS 255
3322+
3323+/* Max length of filename (not 255) */
3324+#define SQUASHFS_NAME_LEN 256
3325+
3326+#define SQUASHFS_INVALID ((long long) 0xffffffffffff)
3327+#define SQUASHFS_INVALID_FRAG ((unsigned int) 0xffffffff)
3328+#define SQUASHFS_INVALID_BLK ((long long) -1)
3329+#define SQUASHFS_USED_BLK ((long long) -2)
3330+
3331+/* Filesystem flags */
3332+#define SQUASHFS_NOI 0
3333+#define SQUASHFS_NOD 1
3334+#define SQUASHFS_CHECK 2
3335+#define SQUASHFS_NOF 3
3336+#define SQUASHFS_NO_FRAG 4
3337+#define SQUASHFS_ALWAYS_FRAG 5
3338+#define SQUASHFS_DUPLICATE 6
3339+#define SQUASHFS_EXPORT 7
3340+
3341+#define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1)
3342+
3343+#define SQUASHFS_UNCOMPRESSED_INODES(flags) SQUASHFS_BIT(flags, \
3344+ SQUASHFS_NOI)
3345+
3346+#define SQUASHFS_UNCOMPRESSED_DATA(flags) SQUASHFS_BIT(flags, \
3347+ SQUASHFS_NOD)
3348+
3349+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3350+ SQUASHFS_NOF)
3351+
3352+#define SQUASHFS_NO_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3353+ SQUASHFS_NO_FRAG)
3354+
3355+#define SQUASHFS_ALWAYS_FRAGMENTS(flags) SQUASHFS_BIT(flags, \
3356+ SQUASHFS_ALWAYS_FRAG)
3357+
3358+#define SQUASHFS_DUPLICATES(flags) SQUASHFS_BIT(flags, \
3359+ SQUASHFS_DUPLICATE)
3360+
3361+#define SQUASHFS_EXPORTABLE(flags) SQUASHFS_BIT(flags, \
3362+ SQUASHFS_EXPORT)
3363+
3364+#define SQUASHFS_CHECK_DATA(flags) SQUASHFS_BIT(flags, \
3365+ SQUASHFS_CHECK)
3366+
3367+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, \
3368+ duplicate_checking, exortable) (noi | (nod << 1) | (check_data << 2) \
3369+ | (nof << 3) | (no_frag << 4) | (always_frag << 5) | \
3370+ (duplicate_checking << 6) | (exportable << 7))
3371+
3372+/* Max number of types and file types */
3373+#define SQUASHFS_DIR_TYPE 1
3374+#define SQUASHFS_FILE_TYPE 2
3375+#define SQUASHFS_SYMLINK_TYPE 3
3376+#define SQUASHFS_BLKDEV_TYPE 4
3377+#define SQUASHFS_CHRDEV_TYPE 5
3378+#define SQUASHFS_FIFO_TYPE 6
3379+#define SQUASHFS_SOCKET_TYPE 7
3380+#define SQUASHFS_LDIR_TYPE 8
3381+#define SQUASHFS_LREG_TYPE 9
3382+
3383+/* 1.0 filesystem type definitions */
3384+#define SQUASHFS_TYPES 5
3385+#define SQUASHFS_IPC_TYPE 0
3386+
3387+/* Flag whether block is compressed or uncompressed, bit is set if block is
3388+ * uncompressed */
3389+#define SQUASHFS_COMPRESSED_BIT (1 << 15)
3390+
3391+#define SQUASHFS_COMPRESSED_SIZE(B) (((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
3392+ (B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
3393+
3394+#define SQUASHFS_COMPRESSED(B) (!((B) & SQUASHFS_COMPRESSED_BIT))
3395+
3396+#define SQUASHFS_COMPRESSED_BIT_BLOCK (1 << 24)
3397+
3398+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B) (((B) & \
3399+ ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? (B) & \
3400+ ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
3401+
3402+#define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
3403+
3404+/*
3405+ * Inode number ops. Inodes consist of a compressed block number, and an
3406+ * uncompressed offset within that block
3407+ */
3408+#define SQUASHFS_INODE_BLK(a) ((unsigned int) ((a) >> 16))
3409+
3410+#define SQUASHFS_INODE_OFFSET(a) ((unsigned int) ((a) & 0xffff))
3411+
3412+#define SQUASHFS_MKINODE(A, B) ((squashfs_inode_t)(((squashfs_inode_t) (A)\
3413+ << 16) + (B)))
3414+
3415+/* Compute 32 bit VFS inode number from squashfs inode number */
3416+#define SQUASHFS_MK_VFS_INODE(a, b) ((unsigned int) (((a) << 8) + \
3417+ ((b) >> 2) + 1))
3418+/* XXX */
3419+
3420+/* Translate between VFS mode and squashfs mode */
3421+#define SQUASHFS_MODE(a) ((a) & 0xfff)
3422+
3423+/* fragment and fragment table defines */
3424+#define SQUASHFS_FRAGMENT_BYTES(A) ((A) * sizeof(struct squashfs_fragment_entry))
3425+
3426+#define SQUASHFS_FRAGMENT_INDEX(A) (SQUASHFS_FRAGMENT_BYTES(A) / \
3427+ SQUASHFS_METADATA_SIZE)
3428+
3429+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A) (SQUASHFS_FRAGMENT_BYTES(A) % \
3430+ SQUASHFS_METADATA_SIZE)
3431+
3432+#define SQUASHFS_FRAGMENT_INDEXES(A) ((SQUASHFS_FRAGMENT_BYTES(A) + \
3433+ SQUASHFS_METADATA_SIZE - 1) / \
3434+ SQUASHFS_METADATA_SIZE)
3435+
3436+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A) (SQUASHFS_FRAGMENT_INDEXES(A) *\
3437+ sizeof(long long))
3438+
3439+/* inode lookup table defines */
3440+#define SQUASHFS_LOOKUP_BYTES(A) ((A) * sizeof(squashfs_inode_t))
3441+
3442+#define SQUASHFS_LOOKUP_BLOCK(A) (SQUASHFS_LOOKUP_BYTES(A) / \
3443+ SQUASHFS_METADATA_SIZE)
3444+
3445+#define SQUASHFS_LOOKUP_BLOCK_OFFSET(A) (SQUASHFS_LOOKUP_BYTES(A) % \
3446+ SQUASHFS_METADATA_SIZE)
3447+
3448+#define SQUASHFS_LOOKUP_BLOCKS(A) ((SQUASHFS_LOOKUP_BYTES(A) + \
3449+ SQUASHFS_METADATA_SIZE - 1) / \
3450+ SQUASHFS_METADATA_SIZE)
3451+
3452+#define SQUASHFS_LOOKUP_BLOCK_BYTES(A) (SQUASHFS_LOOKUP_BLOCKS(A) *\
3453+ sizeof(long long))
3454+
3455+/* cached data constants for filesystem */
3456+#define SQUASHFS_CACHED_BLKS 8
3457+
3458+#define SQUASHFS_MAX_FILE_SIZE_LOG 64
3459+
3460+#define SQUASHFS_MAX_FILE_SIZE ((long long) 1 << \
3461+ (SQUASHFS_MAX_FILE_SIZE_LOG - 2))
3462+
3463+#define SQUASHFS_MARKER_BYTE 0xff
3464+
3465+/* meta index cache */
3466+#define SQUASHFS_META_INDEXES (SQUASHFS_METADATA_SIZE / sizeof(unsigned int))
3467+#define SQUASHFS_META_ENTRIES 31
3468+#define SQUASHFS_META_NUMBER 8
3469+#define SQUASHFS_SLOTS 4
3470+
3471+struct meta_entry {
3472+ long long data_block;
3473+ unsigned int index_block;
3474+ unsigned short offset;
3475+ unsigned short pad;
3476+};
3477+
3478+struct meta_index {
3479+ unsigned int inode_number;
3480+ unsigned int offset;
3481+ unsigned short entries;
3482+ unsigned short skip;
3483+ unsigned short locked;
3484+ unsigned short pad;
3485+ struct meta_entry meta_entry[SQUASHFS_META_ENTRIES];
3486+};
3487+
3488+
3489+/*
3490+ * definitions for structures on disk
3491+ */
3492+
3493+typedef long long squashfs_block_t;
3494+typedef long long squashfs_inode_t;
3495+
3496+struct squashfs_super_block {
3497+ unsigned int s_magic;
3498+ unsigned int inodes;
3499+ unsigned int bytes_used_2;
3500+ unsigned int uid_start_2;
3501+ unsigned int guid_start_2;
3502+ unsigned int inode_table_start_2;
3503+ unsigned int directory_table_start_2;
3504+ unsigned int s_major:16;
3505+ unsigned int s_minor:16;
3506+ unsigned int block_size_1:16;
3507+ unsigned int block_log:16;
3508+ unsigned int flags:8;
3509+ unsigned int no_uids:8;
3510+ unsigned int no_guids:8;
3511+ unsigned int mkfs_time /* time of filesystem creation */;
3512+ squashfs_inode_t root_inode;
3513+ unsigned int block_size;
3514+ unsigned int fragments;
3515+ unsigned int fragment_table_start_2;
3516+ long long bytes_used;
3517+ long long uid_start;
3518+ long long guid_start;
3519+ long long inode_table_start;
3520+ long long directory_table_start;
3521+ long long fragment_table_start;
3522+ long long lookup_table_start;
3523+} __attribute__ ((packed));
3524+
3525+struct squashfs_dir_index {
3526+ unsigned int index;
3527+ unsigned int start_block;
3528+ unsigned char size;
3529+ unsigned char name[0];
3530+} __attribute__ ((packed));
3531+
3532+#define SQUASHFS_BASE_INODE_HEADER \
3533+ unsigned int inode_type:4; \
3534+ unsigned int mode:12; \
3535+ unsigned int uid:8; \
3536+ unsigned int guid:8; \
3537+ unsigned int mtime; \
3538+ unsigned int inode_number;
3539+
3540+struct squashfs_base_inode_header {
3541+ SQUASHFS_BASE_INODE_HEADER;
3542+} __attribute__ ((packed));
3543+
3544+struct squashfs_ipc_inode_header {
3545+ SQUASHFS_BASE_INODE_HEADER;
3546+ unsigned int nlink;
3547+} __attribute__ ((packed));
3548+
3549+struct squashfs_dev_inode_header {
3550+ SQUASHFS_BASE_INODE_HEADER;
3551+ unsigned int nlink;
3552+ unsigned short rdev;
3553+} __attribute__ ((packed));
3554+
3555+struct squashfs_symlink_inode_header {
3556+ SQUASHFS_BASE_INODE_HEADER;
3557+ unsigned int nlink;
3558+ unsigned short symlink_size;
3559+ char symlink[0];
3560+} __attribute__ ((packed));
3561+
3562+struct squashfs_reg_inode_header {
3563+ SQUASHFS_BASE_INODE_HEADER;
3564+ squashfs_block_t start_block;
3565+ unsigned int fragment;
3566+ unsigned int offset;
3567+ unsigned int file_size;
3568+ unsigned short block_list[0];
3569+} __attribute__ ((packed));
3570+
3571+struct squashfs_lreg_inode_header {
3572+ SQUASHFS_BASE_INODE_HEADER;
3573+ unsigned int nlink;
3574+ squashfs_block_t start_block;
3575+ unsigned int fragment;
3576+ unsigned int offset;
3577+ long long file_size;
3578+ unsigned short block_list[0];
3579+} __attribute__ ((packed));
3580+
3581+struct squashfs_dir_inode_header {
3582+ SQUASHFS_BASE_INODE_HEADER;
3583+ unsigned int nlink;
3584+ unsigned int file_size:19;
3585+ unsigned int offset:13;
3586+ unsigned int start_block;
3587+ unsigned int parent_inode;
3588+} __attribute__ ((packed));
3589+
3590+struct squashfs_ldir_inode_header {
3591+ SQUASHFS_BASE_INODE_HEADER;
3592+ unsigned int nlink;
3593+ unsigned int file_size:27;
3594+ unsigned int offset:13;
3595+ unsigned int start_block;
3596+ unsigned int i_count:16;
3597+ unsigned int parent_inode;
3598+ struct squashfs_dir_index index[0];
3599+} __attribute__ ((packed));
3600+
3601+union squashfs_inode_header {
3602+ struct squashfs_base_inode_header base;
3603+ struct squashfs_dev_inode_header dev;
3604+ struct squashfs_symlink_inode_header symlink;
3605+ struct squashfs_reg_inode_header reg;
3606+ struct squashfs_lreg_inode_header lreg;
3607+ struct squashfs_dir_inode_header dir;
3608+ struct squashfs_ldir_inode_header ldir;
3609+ struct squashfs_ipc_inode_header ipc;
3610+};
3611+
3612+struct squashfs_dir_entry {
3613+ unsigned int offset:13;
3614+ unsigned int type:3;
3615+ unsigned int size:8;
3616+ int inode_number:16;
3617+ char name[0];
3618+} __attribute__ ((packed));
3619+
3620+struct squashfs_dir_header {
3621+ unsigned int count:8;
3622+ unsigned int start_block;
3623+ unsigned int inode_number;
3624+} __attribute__ ((packed));
3625+
3626+struct squashfs_fragment_entry {
3627+ long long start_block;
3628+ unsigned int size;
3629+ unsigned int pending;
3630+} __attribute__ ((packed));
3631+
3632+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
3633+extern int squashfs_uncompress_init(void);
3634+extern int squashfs_uncompress_exit(void);
3635+
3636+/*
3637+ * macros to convert each packed bitfield structure from little endian to big
3638+ * endian and vice versa. These are needed when creating or using a filesystem
3639+ * on a machine with different byte ordering to the target architecture.
3640+ *
3641+ */
3642+
3643+#define SQUASHFS_SWAP_START \
3644+ int bits;\
3645+ int b_pos;\
3646+ unsigned long long val;\
3647+ unsigned char *s;\
3648+ unsigned char *d;
3649+
3650+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
3651+ SQUASHFS_SWAP_START\
3652+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_super_block));\
3653+ SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
3654+ SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
3655+ SQUASHFS_SWAP((s)->bytes_used_2, d, 64, 32);\
3656+ SQUASHFS_SWAP((s)->uid_start_2, d, 96, 32);\
3657+ SQUASHFS_SWAP((s)->guid_start_2, d, 128, 32);\
3658+ SQUASHFS_SWAP((s)->inode_table_start_2, d, 160, 32);\
3659+ SQUASHFS_SWAP((s)->directory_table_start_2, d, 192, 32);\
3660+ SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
3661+ SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
3662+ SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
3663+ SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
3664+ SQUASHFS_SWAP((s)->flags, d, 288, 8);\
3665+ SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
3666+ SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
3667+ SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
3668+ SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
3669+ SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
3670+ SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
3671+ SQUASHFS_SWAP((s)->fragment_table_start_2, d, 472, 32);\
3672+ SQUASHFS_SWAP((s)->bytes_used, d, 504, 64);\
3673+ SQUASHFS_SWAP((s)->uid_start, d, 568, 64);\
3674+ SQUASHFS_SWAP((s)->guid_start, d, 632, 64);\
3675+ SQUASHFS_SWAP((s)->inode_table_start, d, 696, 64);\
3676+ SQUASHFS_SWAP((s)->directory_table_start, d, 760, 64);\
3677+ SQUASHFS_SWAP((s)->fragment_table_start, d, 824, 64);\
3678+ SQUASHFS_SWAP((s)->lookup_table_start, d, 888, 64);\
3679+}
3680+
3681+#define SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
3682+ SQUASHFS_MEMSET(s, d, n);\
3683+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
3684+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
3685+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
3686+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
3687+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
3688+ SQUASHFS_SWAP((s)->inode_number, d, 64, 32);
3689+
3690+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
3691+ SQUASHFS_SWAP_START\
3692+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, n)\
3693+}
3694+
3695+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) {\
3696+ SQUASHFS_SWAP_START\
3697+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3698+ sizeof(struct squashfs_ipc_inode_header))\
3699+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3700+}
3701+
3702+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
3703+ SQUASHFS_SWAP_START\
3704+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3705+ sizeof(struct squashfs_dev_inode_header)); \
3706+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3707+ SQUASHFS_SWAP((s)->rdev, d, 128, 16);\
3708+}
3709+
3710+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
3711+ SQUASHFS_SWAP_START\
3712+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3713+ sizeof(struct squashfs_symlink_inode_header));\
3714+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3715+ SQUASHFS_SWAP((s)->symlink_size, d, 128, 16);\
3716+}
3717+
3718+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
3719+ SQUASHFS_SWAP_START\
3720+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3721+ sizeof(struct squashfs_reg_inode_header));\
3722+ SQUASHFS_SWAP((s)->start_block, d, 96, 64);\
3723+ SQUASHFS_SWAP((s)->fragment, d, 160, 32);\
3724+ SQUASHFS_SWAP((s)->offset, d, 192, 32);\
3725+ SQUASHFS_SWAP((s)->file_size, d, 224, 32);\
3726+}
3727+
3728+#define SQUASHFS_SWAP_LREG_INODE_HEADER(s, d) {\
3729+ SQUASHFS_SWAP_START\
3730+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3731+ sizeof(struct squashfs_lreg_inode_header));\
3732+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3733+ SQUASHFS_SWAP((s)->start_block, d, 128, 64);\
3734+ SQUASHFS_SWAP((s)->fragment, d, 192, 32);\
3735+ SQUASHFS_SWAP((s)->offset, d, 224, 32);\
3736+ SQUASHFS_SWAP((s)->file_size, d, 256, 64);\
3737+}
3738+
3739+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
3740+ SQUASHFS_SWAP_START\
3741+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3742+ sizeof(struct squashfs_dir_inode_header));\
3743+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3744+ SQUASHFS_SWAP((s)->file_size, d, 128, 19);\
3745+ SQUASHFS_SWAP((s)->offset, d, 147, 13);\
3746+ SQUASHFS_SWAP((s)->start_block, d, 160, 32);\
3747+ SQUASHFS_SWAP((s)->parent_inode, d, 192, 32);\
3748+}
3749+
3750+#define SQUASHFS_SWAP_LDIR_INODE_HEADER(s, d) {\
3751+ SQUASHFS_SWAP_START\
3752+ SQUASHFS_SWAP_BASE_INODE_CORE(s, d, \
3753+ sizeof(struct squashfs_ldir_inode_header));\
3754+ SQUASHFS_SWAP((s)->nlink, d, 96, 32);\
3755+ SQUASHFS_SWAP((s)->file_size, d, 128, 27);\
3756+ SQUASHFS_SWAP((s)->offset, d, 155, 13);\
3757+ SQUASHFS_SWAP((s)->start_block, d, 168, 32);\
3758+ SQUASHFS_SWAP((s)->i_count, d, 200, 16);\
3759+ SQUASHFS_SWAP((s)->parent_inode, d, 216, 32);\
3760+}
3761+
3762+#define SQUASHFS_SWAP_DIR_INDEX(s, d) {\
3763+ SQUASHFS_SWAP_START\
3764+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index));\
3765+ SQUASHFS_SWAP((s)->index, d, 0, 32);\
3766+ SQUASHFS_SWAP((s)->start_block, d, 32, 32);\
3767+ SQUASHFS_SWAP((s)->size, d, 64, 8);\
3768+}
3769+
3770+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
3771+ SQUASHFS_SWAP_START\
3772+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header));\
3773+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
3774+ SQUASHFS_SWAP((s)->start_block, d, 8, 32);\
3775+ SQUASHFS_SWAP((s)->inode_number, d, 40, 32);\
3776+}
3777+
3778+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
3779+ SQUASHFS_SWAP_START\
3780+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry));\
3781+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
3782+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
3783+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
3784+ SQUASHFS_SWAP((s)->inode_number, d, 24, 16);\
3785+}
3786+
3787+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
3788+ SQUASHFS_SWAP_START\
3789+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry));\
3790+ SQUASHFS_SWAP((s)->start_block, d, 0, 64);\
3791+ SQUASHFS_SWAP((s)->size, d, 64, 32);\
3792+}
3793+
3794+#define SQUASHFS_SWAP_INODE_T(s, d) SQUASHFS_SWAP_LONG_LONGS(s, d, 1)
3795+
3796+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
3797+ int entry;\
3798+ int bit_position;\
3799+ SQUASHFS_SWAP_START\
3800+ SQUASHFS_MEMSET(s, d, n * 2);\
3801+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3802+ 16)\
3803+ SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
3804+}
3805+
3806+#define SQUASHFS_SWAP_INTS(s, d, n) {\
3807+ int entry;\
3808+ int bit_position;\
3809+ SQUASHFS_SWAP_START\
3810+ SQUASHFS_MEMSET(s, d, n * 4);\
3811+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3812+ 32)\
3813+ SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
3814+}
3815+
3816+#define SQUASHFS_SWAP_LONG_LONGS(s, d, n) {\
3817+ int entry;\
3818+ int bit_position;\
3819+ SQUASHFS_SWAP_START\
3820+ SQUASHFS_MEMSET(s, d, n * 8);\
3821+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3822+ 64)\
3823+ SQUASHFS_SWAP(s[entry], d, bit_position, 64);\
3824+}
3825+
3826+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
3827+ int entry;\
3828+ int bit_position;\
3829+ SQUASHFS_SWAP_START\
3830+ SQUASHFS_MEMSET(s, d, n * bits / 8);\
3831+ for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += \
3832+ bits)\
3833+ SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
3834+}
3835+
3836+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
3837+#define SQUASHFS_SWAP_LOOKUP_BLOCKS(s, d, n) SQUASHFS_SWAP_LONG_LONGS(s, d, n)
3838+
3839+#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
3840+
3841+struct squashfs_base_inode_header_1 {
3842+ unsigned int inode_type:4;
3843+ unsigned int mode:12; /* protection */
3844+ unsigned int uid:4; /* index into uid table */
3845+ unsigned int guid:4; /* index into guid table */
3846+} __attribute__ ((packed));
3847+
3848+struct squashfs_ipc_inode_header_1 {
3849+ unsigned int inode_type:4;
3850+ unsigned int mode:12; /* protection */
3851+ unsigned int uid:4; /* index into uid table */
3852+ unsigned int guid:4; /* index into guid table */
3853+ unsigned int type:4;
3854+ unsigned int offset:4;
3855+} __attribute__ ((packed));
3856+
3857+struct squashfs_dev_inode_header_1 {
3858+ unsigned int inode_type:4;
3859+ unsigned int mode:12; /* protection */
3860+ unsigned int uid:4; /* index into uid table */
3861+ unsigned int guid:4; /* index into guid table */
3862+ unsigned short rdev;
3863+} __attribute__ ((packed));
3864+
3865+struct squashfs_symlink_inode_header_1 {
3866+ unsigned int inode_type:4;
3867+ unsigned int mode:12; /* protection */
3868+ unsigned int uid:4; /* index into uid table */
3869+ unsigned int guid:4; /* index into guid table */
3870+ unsigned short symlink_size;
3871+ char symlink[0];
3872+} __attribute__ ((packed));
3873+
3874+struct squashfs_reg_inode_header_1 {
3875+ unsigned int inode_type:4;
3876+ unsigned int mode:12; /* protection */
3877+ unsigned int uid:4; /* index into uid table */
3878+ unsigned int guid:4; /* index into guid table */
3879+ unsigned int mtime;
3880+ unsigned int start_block;
3881+ unsigned int file_size:32;
3882+ unsigned short block_list[0];
3883+} __attribute__ ((packed));
3884+
3885+struct squashfs_dir_inode_header_1 {
3886+ unsigned int inode_type:4;
3887+ unsigned int mode:12; /* protection */
3888+ unsigned int uid:4; /* index into uid table */
3889+ unsigned int guid:4; /* index into guid table */
3890+ unsigned int file_size:19;
3891+ unsigned int offset:13;
3892+ unsigned int mtime;
3893+ unsigned int start_block:24;
3894+} __attribute__ ((packed));
3895+
3896+#define SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n) \
3897+ SQUASHFS_MEMSET(s, d, n);\
3898+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
3899+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
3900+ SQUASHFS_SWAP((s)->uid, d, 16, 4);\
3901+ SQUASHFS_SWAP((s)->guid, d, 20, 4);
3902+
3903+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
3904+ SQUASHFS_SWAP_START\
3905+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, n)\
3906+}
3907+
3908+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
3909+ SQUASHFS_SWAP_START\
3910+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3911+ sizeof(struct squashfs_ipc_inode_header_1));\
3912+ SQUASHFS_SWAP((s)->type, d, 24, 4);\
3913+ SQUASHFS_SWAP((s)->offset, d, 28, 4);\
3914+}
3915+
3916+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
3917+ SQUASHFS_SWAP_START\
3918+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3919+ sizeof(struct squashfs_dev_inode_header_1));\
3920+ SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
3921+}
3922+
3923+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
3924+ SQUASHFS_SWAP_START\
3925+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3926+ sizeof(struct squashfs_symlink_inode_header_1));\
3927+ SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
3928+}
3929+
3930+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
3931+ SQUASHFS_SWAP_START\
3932+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3933+ sizeof(struct squashfs_reg_inode_header_1));\
3934+ SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
3935+ SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
3936+ SQUASHFS_SWAP((s)->file_size, d, 88, 32);\
3937+}
3938+
3939+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
3940+ SQUASHFS_SWAP_START\
3941+ SQUASHFS_SWAP_BASE_INODE_CORE_1(s, d, \
3942+ sizeof(struct squashfs_dir_inode_header_1));\
3943+ SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
3944+ SQUASHFS_SWAP((s)->offset, d, 43, 13);\
3945+ SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
3946+ SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
3947+}
3948+
3949+#endif
3950+
3951+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
3952+
3953+struct squashfs_dir_index_2 {
3954+ unsigned int index:27;
3955+ unsigned int start_block:29;
3956+ unsigned char size;
3957+ unsigned char name[0];
3958+} __attribute__ ((packed));
3959+
3960+struct squashfs_base_inode_header_2 {
3961+ unsigned int inode_type:4;
3962+ unsigned int mode:12; /* protection */
3963+ unsigned int uid:8; /* index into uid table */
3964+ unsigned int guid:8; /* index into guid table */
3965+} __attribute__ ((packed));
3966+
3967+struct squashfs_ipc_inode_header_2 {
3968+ unsigned int inode_type:4;
3969+ unsigned int mode:12; /* protection */
3970+ unsigned int uid:8; /* index into uid table */
3971+ unsigned int guid:8; /* index into guid table */
3972+} __attribute__ ((packed));
3973+
3974+struct squashfs_dev_inode_header_2 {
3975+ unsigned int inode_type:4;
3976+ unsigned int mode:12; /* protection */
3977+ unsigned int uid:8; /* index into uid table */
3978+ unsigned int guid:8; /* index into guid table */
3979+ unsigned short rdev;
3980+} __attribute__ ((packed));
3981+
3982+struct squashfs_symlink_inode_header_2 {
3983+ unsigned int inode_type:4;
3984+ unsigned int mode:12; /* protection */
3985+ unsigned int uid:8; /* index into uid table */
3986+ unsigned int guid:8; /* index into guid table */
3987+ unsigned short symlink_size;
3988+ char symlink[0];
3989+} __attribute__ ((packed));
3990+
3991+struct squashfs_reg_inode_header_2 {
3992+ unsigned int inode_type:4;
3993+ unsigned int mode:12; /* protection */
3994+ unsigned int uid:8; /* index into uid table */
3995+ unsigned int guid:8; /* index into guid table */
3996+ unsigned int mtime;
3997+ unsigned int start_block;
3998+ unsigned int fragment;
3999+ unsigned int offset;
4000+ unsigned int file_size:32;
4001+ unsigned short block_list[0];
4002+} __attribute__ ((packed));
4003+
4004+struct squashfs_dir_inode_header_2 {
4005+ unsigned int inode_type:4;
4006+ unsigned int mode:12; /* protection */
4007+ unsigned int uid:8; /* index into uid table */
4008+ unsigned int guid:8; /* index into guid table */
4009+ unsigned int file_size:19;
4010+ unsigned int offset:13;
4011+ unsigned int mtime;
4012+ unsigned int start_block:24;
4013+} __attribute__ ((packed));
4014+
4015+struct squashfs_ldir_inode_header_2 {
4016+ unsigned int inode_type:4;
4017+ unsigned int mode:12; /* protection */
4018+ unsigned int uid:8; /* index into uid table */
4019+ unsigned int guid:8; /* index into guid table */
4020+ unsigned int file_size:27;
4021+ unsigned int offset:13;
4022+ unsigned int mtime;
4023+ unsigned int start_block:24;
4024+ unsigned int i_count:16;
4025+ struct squashfs_dir_index_2 index[0];
4026+} __attribute__ ((packed));
4027+
4028+union squashfs_inode_header_2 {
4029+ struct squashfs_base_inode_header_2 base;
4030+ struct squashfs_dev_inode_header_2 dev;
4031+ struct squashfs_symlink_inode_header_2 symlink;
4032+ struct squashfs_reg_inode_header_2 reg;
4033+ struct squashfs_dir_inode_header_2 dir;
4034+ struct squashfs_ldir_inode_header_2 ldir;
4035+ struct squashfs_ipc_inode_header_2 ipc;
4036+};
4037+
4038+struct squashfs_dir_header_2 {
4039+ unsigned int count:8;
4040+ unsigned int start_block:24;
4041+} __attribute__ ((packed));
4042+
4043+struct squashfs_dir_entry_2 {
4044+ unsigned int offset:13;
4045+ unsigned int type:3;
4046+ unsigned int size:8;
4047+ char name[0];
4048+} __attribute__ ((packed));
4049+
4050+struct squashfs_fragment_entry_2 {
4051+ unsigned int start_block;
4052+ unsigned int size;
4053+} __attribute__ ((packed));
4054+
4055+#define SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
4056+ SQUASHFS_MEMSET(s, d, n);\
4057+ SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
4058+ SQUASHFS_SWAP((s)->mode, d, 4, 12);\
4059+ SQUASHFS_SWAP((s)->uid, d, 16, 8);\
4060+ SQUASHFS_SWAP((s)->guid, d, 24, 8);\
4061+
4062+#define SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, n) {\
4063+ SQUASHFS_SWAP_START\
4064+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, n)\
4065+}
4066+
4067+#define SQUASHFS_SWAP_IPC_INODE_HEADER_2(s, d) \
4068+ SQUASHFS_SWAP_BASE_INODE_HEADER_2(s, d, sizeof(struct squashfs_ipc_inode_header_2))
4069+
4070+#define SQUASHFS_SWAP_DEV_INODE_HEADER_2(s, d) {\
4071+ SQUASHFS_SWAP_START\
4072+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
4073+ sizeof(struct squashfs_dev_inode_header_2)); \
4074+ SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
4075+}
4076+
4077+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(s, d) {\
4078+ SQUASHFS_SWAP_START\
4079+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
4080+ sizeof(struct squashfs_symlink_inode_header_2));\
4081+ SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
4082+}
4083+
4084+#define SQUASHFS_SWAP_REG_INODE_HEADER_2(s, d) {\
4085+ SQUASHFS_SWAP_START\
4086+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
4087+ sizeof(struct squashfs_reg_inode_header_2));\
4088+ SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
4089+ SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
4090+ SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
4091+ SQUASHFS_SWAP((s)->offset, d, 128, 32);\
4092+ SQUASHFS_SWAP((s)->file_size, d, 160, 32);\
4093+}
4094+
4095+#define SQUASHFS_SWAP_DIR_INODE_HEADER_2(s, d) {\
4096+ SQUASHFS_SWAP_START\
4097+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
4098+ sizeof(struct squashfs_dir_inode_header_2));\
4099+ SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
4100+ SQUASHFS_SWAP((s)->offset, d, 51, 13);\
4101+ SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
4102+ SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
4103+}
4104+
4105+#define SQUASHFS_SWAP_LDIR_INODE_HEADER_2(s, d) {\
4106+ SQUASHFS_SWAP_START\
4107+ SQUASHFS_SWAP_BASE_INODE_CORE_2(s, d, \
4108+ sizeof(struct squashfs_ldir_inode_header_2));\
4109+ SQUASHFS_SWAP((s)->file_size, d, 32, 27);\
4110+ SQUASHFS_SWAP((s)->offset, d, 59, 13);\
4111+ SQUASHFS_SWAP((s)->mtime, d, 72, 32);\
4112+ SQUASHFS_SWAP((s)->start_block, d, 104, 24);\
4113+ SQUASHFS_SWAP((s)->i_count, d, 128, 16);\
4114+}
4115+
4116+#define SQUASHFS_SWAP_DIR_INDEX_2(s, d) {\
4117+ SQUASHFS_SWAP_START\
4118+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_index_2));\
4119+ SQUASHFS_SWAP((s)->index, d, 0, 27);\
4120+ SQUASHFS_SWAP((s)->start_block, d, 27, 29);\
4121+ SQUASHFS_SWAP((s)->size, d, 56, 8);\
4122+}
4123+#define SQUASHFS_SWAP_DIR_HEADER_2(s, d) {\
4124+ SQUASHFS_SWAP_START\
4125+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_header_2));\
4126+ SQUASHFS_SWAP((s)->count, d, 0, 8);\
4127+ SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
4128+}
4129+
4130+#define SQUASHFS_SWAP_DIR_ENTRY_2(s, d) {\
4131+ SQUASHFS_SWAP_START\
4132+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_dir_entry_2));\
4133+ SQUASHFS_SWAP((s)->offset, d, 0, 13);\
4134+ SQUASHFS_SWAP((s)->type, d, 13, 3);\
4135+ SQUASHFS_SWAP((s)->size, d, 16, 8);\
4136+}
4137+
4138+#define SQUASHFS_SWAP_FRAGMENT_ENTRY_2(s, d) {\
4139+ SQUASHFS_SWAP_START\
4140+ SQUASHFS_MEMSET(s, d, sizeof(struct squashfs_fragment_entry_2));\
4141+ SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
4142+ SQUASHFS_SWAP((s)->size, d, 32, 32);\
4143+}
4144+
4145+#define SQUASHFS_SWAP_FRAGMENT_INDEXES_2(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
4146+
4147+/* fragment and fragment table defines */
4148+#define SQUASHFS_FRAGMENT_BYTES_2(A) (A * sizeof(struct squashfs_fragment_entry_2))
4149+
4150+#define SQUASHFS_FRAGMENT_INDEX_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) / \
4151+ SQUASHFS_METADATA_SIZE)
4152+
4153+#define SQUASHFS_FRAGMENT_INDEX_OFFSET_2(A) (SQUASHFS_FRAGMENT_BYTES_2(A) % \
4154+ SQUASHFS_METADATA_SIZE)
4155+
4156+#define SQUASHFS_FRAGMENT_INDEXES_2(A) ((SQUASHFS_FRAGMENT_BYTES_2(A) + \
4157+ SQUASHFS_METADATA_SIZE - 1) / \
4158+ SQUASHFS_METADATA_SIZE)
4159+
4160+#define SQUASHFS_FRAGMENT_INDEX_BYTES_2(A) (SQUASHFS_FRAGMENT_INDEXES_2(A) *\
4161+ sizeof(int))
4162+
4163+#endif
4164+
4165+#ifdef __KERNEL__
4166+
4167+/*
4168+ * macros used to swap each structure entry, taking into account
4169+ * bitfields and different bitfield placing conventions on differing
4170+ * architectures
4171+ */
4172+
4173+#include <asm/byteorder.h>
4174+
4175+#ifdef __BIG_ENDIAN
4176+ /* convert from little endian to big endian */
4177+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
4178+ tbits, b_pos)
4179+#else
4180+ /* convert from big endian to little endian */
4181+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, \
4182+ tbits, 64 - tbits - b_pos)
4183+#endif
4184+
4185+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
4186+ b_pos = pos % 8;\
4187+ val = 0;\
4188+ s = (unsigned char *)p + (pos / 8);\
4189+ d = ((unsigned char *) &val) + 7;\
4190+ for(bits = 0; bits < (tbits + b_pos); bits += 8) \
4191+ *d-- = *s++;\
4192+ value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
4193+}
4194+
4195+#define SQUASHFS_MEMSET(s, d, n) memset(s, 0, n);
4196+
4197+#endif
4198+#endif
4199--- /dev/null
4200+++ linux-2.6.24-rc1/include/linux/squashfs_fs_i.h
4201@@ -0,0 +1,45 @@
4202+#ifndef SQUASHFS_FS_I
4203+#define SQUASHFS_FS_I
4204+/*
4205+ * Squashfs
4206+ *
4207+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
4208+ * Phillip Lougher <phillip@lougher.org.uk>
4209+ *
4210+ * This program is free software; you can redistribute it and/or
4211+ * modify it under the terms of the GNU General Public License
4212+ * as published by the Free Software Foundation; either version 2,
4213+ * or (at your option) any later version.
4214+ *
4215+ * This program is distributed in the hope that it will be useful,
4216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4218+ * GNU General Public License for more details.
4219+ *
4220+ * You should have received a copy of the GNU General Public License
4221+ * along with this program; if not, write to the Free Software
4222+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4223+ *
4224+ * squashfs_fs_i.h
4225+ */
4226+
4227+struct squashfs_inode_info {
4228+ long long start_block;
4229+ unsigned int offset;
4230+ union {
4231+ struct {
4232+ long long fragment_start_block;
4233+ unsigned int fragment_size;
4234+ unsigned int fragment_offset;
4235+ long long block_list_start;
4236+ } s1;
4237+ struct {
4238+ long long directory_index_start;
4239+ unsigned int directory_index_offset;
4240+ unsigned int directory_index_count;
4241+ unsigned int parent_inode;
4242+ } s2;
4243+ } u;
4244+ struct inode vfs_inode;
4245+};
4246+#endif
4247--- /dev/null
4248+++ linux-2.6.24-rc1/include/linux/squashfs_fs_sb.h
4249@@ -0,0 +1,74 @@
4250+#ifndef SQUASHFS_FS_SB
4251+#define SQUASHFS_FS_SB
4252+/*
4253+ * Squashfs
4254+ *
4255+ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007
4256+ * Phillip Lougher <phillip@lougher.org.uk>
4257+ *
4258+ * This program is free software; you can redistribute it and/or
4259+ * modify it under the terms of the GNU General Public License
4260+ * as published by the Free Software Foundation; either version 2,
4261+ * or (at your option) any later version.
4262+ *
4263+ * This program is distributed in the hope that it will be useful,
4264+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4265+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4266+ * GNU General Public License for more details.
4267+ *
4268+ * You should have received a copy of the GNU General Public License
4269+ * along with this program; if not, write to the Free Software
4270+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4271+ *
4272+ * squashfs_fs_sb.h
4273+ */
4274+
4275+#include <linux/squashfs_fs.h>
4276+
4277+struct squashfs_cache {
4278+ long long block;
4279+ int length;
4280+ long long next_index;
4281+ char *data;
4282+};
4283+
4284+struct squashfs_fragment_cache {
4285+ long long block;
4286+ int length;
4287+ unsigned int locked;
4288+ char *data;
4289+};
4290+
4291+struct squashfs_sb_info {
4292+ struct squashfs_super_block sblk;
4293+ int devblksize;
4294+ int devblksize_log2;
4295+ int swap;
4296+ struct squashfs_cache *block_cache;
4297+ struct squashfs_fragment_cache *fragment;
4298+ int next_cache;
4299+ int next_fragment;
4300+ int next_meta_index;
4301+ unsigned int *uid;
4302+ unsigned int *guid;
4303+ long long *fragment_index;
4304+ unsigned int *fragment_index_2;
4305+ char *read_page;
4306+ struct mutex read_data_mutex;
4307+ struct mutex read_page_mutex;
4308+ struct mutex block_cache_mutex;
4309+ struct mutex fragment_mutex;
4310+ struct mutex meta_index_mutex;
4311+ wait_queue_head_t waitq;
4312+ wait_queue_head_t fragment_wait_queue;
4313+ struct meta_index *meta_index;
4314+ z_stream stream;
4315+ long long *inode_lookup_table;
4316+ int (*read_inode)(struct inode *i, squashfs_inode_t \
4317+ inode);
4318+ long long (*read_blocklist)(struct inode *inode, int \
4319+ index, int readahead_blks, char *block_list, \
4320+ unsigned short **block_p, unsigned int *bsize);
4321+ int (*read_fragment_index_table)(struct super_block *s);
4322+};
4323+#endif
4324--- linux-2.6.24-rc1.orig/init/do_mounts_rd.c
4325+++ linux-2.6.24-rc1/init/do_mounts_rd.c
4326@@ -5,6 +5,7 @@
4327 #include <linux/ext2_fs.h>
4328 #include <linux/romfs_fs.h>
4329 #include <linux/cramfs_fs.h>
4330+#include <linux/squashfs_fs.h>
4331 #include <linux/initrd.h>
4332 #include <linux/string.h>
4333
4334@@ -39,6 +40,7 @@
4335 * numbers could not be found.
4336 *
4337 * We currently check for the following magic numbers:
4338+ * squashfs
4339 * minix
4340 * ext2
4341 * romfs
4342@@ -53,6 +55,7 @@
4343 struct ext2_super_block *ext2sb;
4344 struct romfs_super_block *romfsb;
4345 struct cramfs_super *cramfsb;
4346+ struct squashfs_super_block *squashfsb;
4347 int nblocks = -1;
4348 unsigned char *buf;
4349
4350@@ -64,6 +67,7 @@
4351 ext2sb = (struct ext2_super_block *) buf;
4352 romfsb = (struct romfs_super_block *) buf;
4353 cramfsb = (struct cramfs_super *) buf;
4354+ squashfsb = (struct squashfs_super_block *) buf;
4355 memset(buf, 0xe5, size);
4356
4357 /*
4358@@ -101,6 +105,18 @@
4359 goto done;
4360 }
4361
4362+ /* squashfs is at block zero too */
4363+ if (squashfsb->s_magic == SQUASHFS_MAGIC) {
4364+ printk(KERN_NOTICE
4365+ "RAMDISK: squashfs filesystem found at block %d\n",
4366+ start_block);
4367+ if (squashfsb->s_major < 3)
4368+ nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
4369+ else
4370+ nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
4371+ goto done;
4372+ }
4373+
4374 /*
4375 * Read block 1 to test for minix and ext2 superblock
4376 */
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/uvesafb-0.1-rc3-2.6.22.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/uvesafb-0.1-rc3-2.6.22.patch
index 711375114f..711375114f 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/uvesafb-0.1-rc3-2.6.22.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/uvesafb-0.1-rc3-2.6.22.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/vt_ioctl_race.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/vt_ioctl_race.patch
index 5a51d1c3f5..5a51d1c3f5 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/vt_ioctl_race.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/vt_ioctl_race.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/w100fb-unused-var.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/w100fb-unused-var.patch
index 8cbbb6bd01..8cbbb6bd01 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/w100fb-unused-var.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/w100fb-unused-var.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/wm97xx-lcdnoise-r0.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/wm97xx-lcdnoise-r0.patch
index 191de3af22..191de3af22 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/wm97xx-lcdnoise-r0.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/wm97xx-lcdnoise-r0.patch
diff --git a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/zylonite-boot.patch b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/zylonite-boot.patch
index f41928eca5..f41928eca5 100644
--- a/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc0+git/zylonite-boot.patch
+++ b/meta/packages/linux/linux-rp-2.6.23+2.6.24-rc1/zylonite-boot.patch
diff --git a/meta/packages/linux/linux-rp_2.6.23+2.6.24-rc0+git.bb b/meta/packages/linux/linux-rp_2.6.23+2.6.24-rc1.bb
index 93ffe19b6e..d73f528892 100644
--- a/meta/packages/linux/linux-rp_2.6.23+2.6.24-rc0+git.bb
+++ b/meta/packages/linux/linux-rp_2.6.23+2.6.24-rc1.bb
@@ -1,7 +1,5 @@
1require linux-rp.inc 1require linux-rp.inc
2 2
3PR = "r1"
4
5DEFAULT_PREFERENCE = "-1" 3DEFAULT_PREFERENCE = "-1"
6 4
7# Handy URLs 5# Handy URLs
@@ -16,16 +14,16 @@ DEFAULT_PREFERENCE = "-1"
16# Patches submitted upstream are towards top of this list 14# Patches submitted upstream are towards top of this list
17# Hacks should clearly named and at the bottom 15# Hacks should clearly named and at the bottom
18SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 \ 16SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 \
19 http://www.kernel.org/pub/linux/kernel/v2.6/snapshots/patch-2.6.23-git9.bz2;patch=1 \ 17 http://www.kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.24-rc1.bz2;patch=1 \
20 ${RPSRC}/lzo_crypto-r2.patch;patch=1 \ 18 ${RPSRC}/lzo_crypto-r2.patch;patch=1 \
21 ${RPSRC}/lzo_jffs2_sysfs-r1.patch;patch=1 \ 19 ${RPSRC}/lzo_jffs2_sysfs-r1.patch;patch=1 \
22 ${RPSRC}/hx2750_base-r30.patch;patch=1 \ 20 file://hx2750_base-r31.patch;patch=1 \
23 ${RPSRC}/hx2750_bl-r9.patch;patch=1 \ 21 ${RPSRC}/hx2750_bl-r9.patch;patch=1 \
24 ${RPSRC}/hx2750_pcmcia-r3.patch;patch=1 \ 22 ${RPSRC}/hx2750_pcmcia-r3.patch;patch=1 \
25 ${RPSRC}/pxa_keys-r8.patch;patch=1 \ 23 ${RPSRC}/pxa_keys-r8.patch;patch=1 \
26 ${RPSRC}/tsc2101-r16.patch;patch=1 \ 24# ${RPSRC}/tsc2101-r16.patch;patch=1 \
27 ${RPSRC}/hx2750_test1-r7.patch;patch=1 \ 25 ${RPSRC}/hx2750_test1-r7.patch;patch=1 \
28 ${RPSRC}/input_power-r9.patch;patch=1 \ 26# ${RPSRC}/input_power-r9.patch;patch=1 \
29 ${RPSRC}/pxa25x_cpufreq-r2.patch;patch=1 \ 27 ${RPSRC}/pxa25x_cpufreq-r2.patch;patch=1 \
30 ${RPSRC}/sharpsl_pm_fixes1-r0.patch;patch=1 \ 28 ${RPSRC}/sharpsl_pm_fixes1-r0.patch;patch=1 \
31 ${RPSRC}/pm_changes-r1.patch;patch=1 \ 29 ${RPSRC}/pm_changes-r1.patch;patch=1 \
@@ -33,14 +31,13 @@ SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 \
33 ${RPSRC}/usb_pxa27x_udc-r7.patch;patch=1 \ 31 ${RPSRC}/usb_pxa27x_udc-r7.patch;patch=1 \
34 ${RPSRC}/locomo_kbd_tweak-r1.patch;patch=1 \ 32 ${RPSRC}/locomo_kbd_tweak-r1.patch;patch=1 \
35 ${RPSRC}/poodle_pm-r5.patch;patch=1 \ 33 ${RPSRC}/poodle_pm-r5.patch;patch=1 \
36 ${RPSRC}/pxa27x_overlay-r7.patch;patch=1 \ 34 file://pxa27x_overlay-r8.patch;patch=1 \
37 ${RPSRC}/w100_extaccel-r1.patch;patch=1 \ 35 ${RPSRC}/w100_extaccel-r1.patch;patch=1 \
38 ${RPSRC}/w100_extmem-r1.patch;patch=1 \ 36 ${RPSRC}/w100_extmem-r1.patch;patch=1 \
39 file://w100fb-unused-var.patch;patch=1 \ 37 file://w100fb-unused-var.patch;patch=1 \
40 file://hostap-monitor-mode.patch;patch=1 \ 38 file://hostap-monitor-mode.patch;patch=1 \
41 file://serial-add-support-for-non-standard-xtals-to-16c950-driver.patch;patch=1 \ 39 file://serial-add-support-for-non-standard-xtals-to-16c950-driver.patch;patch=1 \
42 ${RPSRC}/logo_oh-r1.patch.bz2;patch=1;status=unmergable \ 40 ${RPSRC}/logo_oh-r1.patch.bz2;patch=1;status=unmergable \
43 ${RPSRC}/logo_oz-r2.patch.bz2;patch=1;status=unmergable \
44 ${RPSRC}/pxa-linking-bug.patch;patch=1;status=unmergable \ 41 ${RPSRC}/pxa-linking-bug.patch;patch=1;status=unmergable \
45 ${RPSRC}/mmcsd_large_cards-r1.patch;patch=1;status=hack \ 42 ${RPSRC}/mmcsd_large_cards-r1.patch;patch=1;status=hack \
46 file://mmcsd_no_scr_check-r2.patch;patch=1 \ 43 file://mmcsd_no_scr_check-r2.patch;patch=1 \
@@ -49,9 +46,8 @@ SRC_URI = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2 \
49 ${RPSRC}/corgi_rearrange_lcd-r0.patch;patch=1 \ 46 ${RPSRC}/corgi_rearrange_lcd-r0.patch;patch=1 \
50 file://pxa-serial-hack.patch;patch=1;status=hack \ 47 file://pxa-serial-hack.patch;patch=1;status=hack \
51 file://connectplus-remove-ide-HACK.patch;patch=1;status=hack \ 48 file://connectplus-remove-ide-HACK.patch;patch=1;status=hack \
52 file://squashfs3.0-2.6.15.patch;patch=1;status=external \ 49# file://squashfs3.2-2.6.20-r0.patch;patch=1;status=external \
53 file://uvesafb-0.1-rc3-2.6.22.patch;patch=1;status=external \ 50# file://htcuni.patch;patch=1 \
54# file://htcuni.patch;patch=1 \
55 file://binutils-buildid-arm.patch;patch=1 \ 51 file://binutils-buildid-arm.patch;patch=1 \
56 file://defconfig-c7x0 \ 52 file://defconfig-c7x0 \
57 file://defconfig-hx2000 \ 53 file://defconfig-hx2000 \