Linux Kernel Patch v2.2, patch-2.2.9 (0/3)

1 view
Skip to first unread message

Thomas...@ciw.uni-karlsruhe.de

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Archive-name: v2.2/patch-2.2.9/part0

lines added deleted
linux/Makefile : 7 1 1
linux/arch/m68k/kernel/ints.c : 7 1 0
linux/arch/m68k/mm/kmap.c : 7 1 0
linux/arch/m68k/mvme147/config.c : 7 0 1
linux/arch/m68k/q40/config.c : 7 1 0
linux/arch/m68k/sun3x/time.c : 7 0 1
linux/arch/ppc/kernel/pmac_pic.c : 5 1 1
linux/drivers/block/ide-dma.c : 8 1 1
linux/drivers/block/ide.c : 32 19 0
linux/drivers/scsi/aha152x.c : 22 6 1
linux/drivers/video/Config.in : 77 17 10
linux/drivers/video/Makefile : 14 8 0
linux/drivers/video/acornfb.c : 2093 1735 221
linux/drivers/video/cyber2000fb.c : 1057 1057 0
linux/drivers/video/cyber2000fb.h : 78 78 0
linux/drivers/video/dummycon.c : 16 1 2
linux/drivers/video/fbmem.c : 41 13 1
linux/drivers/video/vgacon.c : 39 13 7
linux/fs/adfs/dir.c : 83 36 13
linux/fs/buffer.c : 397 174 136
linux/fs/hfs/ChangeLog : 19 16 0
linux/fs/hfs/file_hdr.c : 248 135 13
linux/fs/hfs/hfs.h : 27 18 3
linux/fs/hfs/inode.c : 45 6 5
linux/fs/hfs/super.c : 25 11 1
linux/fs/proc/array.c : 17 2 2
linux/include/asm-arm/arch-ebsa285/irq.h : 7 0 1
linux/include/asm-arm/arch-ebsa285/memory.h : 8 0 2
linux/include/asm-arm/arch-rpc/io.h : 71 37 14
linux/include/asm-arm/proc-fns.h : 8 1 1
linux/include/asm-arm/semaphore.h : 7 0 1
linux/include/asm-m68k/page.h : 8 2 0
linux/include/asm-m68k/q40_keyboard.h : 10 0 4
linux/include/asm-m68k/semaphore-helper.h : 8 2 0
linux/include/asm-m68k/semaphore.h : 7 0 1
linux/include/linux/hfs_fs.h : 132 46 45
linux/include/linux/hfs_fs_sb.h : 16 2 1
linux/include/linux/skbuff.h : 28 15 0
linux/include/net/tcp.h : 8 1 1
linux/net/ipv4/ip_masq_quake.c : 8 1 1
--
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.

Thomas...@ciw.uni-karlsruhe.de

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Archive-name: v2.2/patch-2.2.9/part3

#!/bin/sh
# this is part 3 of a 3 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.9 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.9'
else
echo 'x - continuing with patch-2.2.9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.9' &&
@@ -483,6 +551,32 @@
X limit = 4;
X break;
X
+ case HFS_HDR_DID:
+ /* if it's rootinfo, stick the next available did in
+ * the did slot. */
+ limit = 4;
+ if (entry->cnid == htonl(HFS_ROOT_CNID)) {
+ struct hfs_mdb *mdb = entry->mdb;
+ const struct hfs_name *reserved =
+ HFS_SB(mdb->sys_mdb)->s_reserved2;
+
+ while (reserved->Len) {
+ if (hfs_streq(reserved->Name,
+ reserved->Len,
+ entry->key.CName.Name,
+ entry->key.CName.Len)) {
+ hfs_put_hl(mdb->next_id, tmp);
+ p = tmp;
+ goto hfs_did_done;
+ }
+ reserved++;
+ }
+ }
+ p = (char *) &entry->cnid;
+hfs_did_done:
+ break;
+
+ case HFS_HDR_SNAME:
X default:
X limit = 0;
X }
@@ -724,6 +818,30 @@
X limit = 32;
X break;
X
+ case HFS_HDR_AFPI:
+ hfs_put_ns(0, tmp);
+ if ((entry->type == HFS_CDR_FIL) &&
+ (entry->u.file.flags & HFS_FIL_LOCK)) {
+ hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
+ } else {
+ hfs_put_ns(0, tmp + 2);
+ }
+ p = tmp;
+ limit = 4;
+ break;
+
+ case HFS_HDR_PRODOSI:
+ /* XXX: this needs to do mac->prodos translations */
+ memset(tmp, 0, 8);
+#if 0
+ hfs_put_ns(0, tmp); /* access */
+ hfs_put_ns(0, tmp); /* type */
+ hfs_put_nl(0, tmp); /* aux type */
+#endif
+ p = tmp;
+ limit = 8;
+ break;
+
X case HFS_HDR_MACI:
X hfs_put_ns(0, tmp);
X if (entry->type == HFS_CDR_FIL) {
@@ -736,6 +854,7 @@
X break;
X
X case HFS_HDR_FNAME: /* Can't rename a file this way */
+ case HFS_HDR_DID: /* can't specify a did this way */
X default:
X limit = 0;
X }
@@ -826,6 +945,9 @@
X break;
X
X case HFS_HDR_FNAME: /* Can't rename a file this way */
+ case HFS_HDR_DID: /* Can't specify a did this way */
+ case HFS_HDR_PRODOSI: /* not implemented yet */
+ case HFS_HDR_AFPI: /* ditto */
X default:
X break;
X }
diff -u --recursive --new-file v2.2.8/linux/fs/hfs/hfs.h linux/fs/hfs/hfs.h
--- v2.2.8/linux/fs/hfs/hfs.h Mon Dec 28 15:00:52 1998
+++ linux/fs/hfs/hfs.h Wed May 12 13:26:34 1999
@@ -80,9 +80,24 @@
X #define HFS_FK_RSRC 0xFF
X
X /* bits in hfs_fil_entry.Flags */
-#define HFS_FIL_LOCK 0x01
-#define HFS_FIL_THD 0x02
-#define HFS_FIL_USED 0x80
+#define HFS_FIL_LOCK 0x01 /* locked */
+#define HFS_FIL_THD 0x02 /* file thread */
+#define HFS_FIL_DOPEN 0x04 /* data fork open */
+#define HFS_FIL_ROPEN 0x08 /* resource fork open */
+#define HFS_FIL_DIR 0x10 /* directory (always clear) */
+#define HFS_FIL_RSRV1 0x20 /* reserved */
+#define HFS_FIL_NOCOPY 0x40 /* copy-protected file */
+#define HFS_FIL_USED 0x80 /* open */
+
+/* bits in hfs_dir_entry.Flags. dirflags is 16 bits. */
+#define HFS_DIR_LOCK 0x01 /* locked */
+#define HFS_DIR_THD 0x02 /* directory thread */
+#define HFS_DIR_INEXPFOLDER 0x04 /* in a shared area */
+#define HFS_DIR_MOUNTED 0x08 /* mounted */
+#define HFS_DIR_DIR 0x10 /* directory (always set) */
+#define HFS_DIR_EXPFOLDER 0x20 /* share point */
+#define HFS_DIR_RSRV1 0x40 /* reserved */
+#define HFS_DIR_RSRV2 0x80 /* reserved */
X
X /* Access types used when requesting access to a B-node */
X #define HFS_LOCK_NONE 0x0000 /* Illegal */
diff -u --recursive --new-file v2.2.8/linux/fs/hfs/inode.c linux/fs/hfs/inode.c
--- v2.2.8/linux/fs/hfs/inode.c Mon Dec 28 15:00:52 1998
+++ linux/fs/hfs/inode.c Wed May 12 13:26:34 1999
@@ -262,7 +262,7 @@
X HFS_I(inode)->entry = entry;
X HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
X
- hsb->s_ifill(inode, type);
+ hsb->s_ifill(inode, type, hsb->s_version);
X if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
X (entry->u.file.flags & HFS_FIL_LOCK)) {
X inode->i_mode &= ~S_IWUGO;
@@ -289,7 +289,7 @@
X * in other filesystems. It is called by __hfs_iget() to fill in
X * the missing fields of an uninitialized inode under the CAP scheme.
X */
-void hfs_cap_ifill(struct inode * inode, ino_t type)
+void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
X {
X struct hfs_cat_entry *entry = HFS_I(inode)->entry;
X
@@ -337,7 +337,7 @@
X * the missing fields of an uninitialized inode under the AppleDouble
X * scheme.
X */
-void hfs_dbl_ifill(struct inode * inode, ino_t type)
+void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
X {
X struct hfs_cat_entry *entry = HFS_I(inode)->entry;
X
@@ -378,7 +378,7 @@
X * the missing fields of an uninitialized inode under the Netatalk
X * scheme.
X */
-void hfs_nat_ifill(struct inode * inode, ino_t type)
+void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
X {
X struct hfs_cat_entry *entry = HFS_I(inode)->entry;
X
@@ -393,7 +393,8 @@
X inode->i_nlink = 1;
X }
X inode->i_op = &hfs_hdr_inode_operations;
- HFS_I(inode)->default_layout = &hfs_nat_hdr_layout;
+ HFS_I(inode)->default_layout = (version == 2) ?
+ &hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
X } else if (entry->type == HFS_CDR_FIL) {
X init_file_inode(inode, HFS_FK_DATA);
X inode->i_op = &hfs_file_inode_operations;
diff -u --recursive --new-file v2.2.8/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.2.8/linux/fs/hfs/super.c Sun Nov 8 14:03:06 1998
+++ linux/fs/hfs/super.c Wed May 12 13:26:34 1999
@@ -183,6 +183,8 @@
X hsb->s_lowercase = 0;
X hsb->s_quiet = 0;
X hsb->s_afpd = 0;
+ /* default version. 0 just selects the defaults */
+ hsb->s_version = 0;
X hsb->s_conv = 'b';
X names = '?';
X fork = '?';
@@ -197,7 +199,15 @@
X *value++ = 0;
X }
X /* Numeric-valued options */
- if (!strcmp(this_char,"uid")) {
+ if (!strcmp(this_char, "version")) {
+ if (!value || !*value) {
+ return 0;
+ }
+ hsb->s_version = simple_strtoul(value,&value,0);
+ if (*value) {
+ return 0;
+ }
+ } else if (!strcmp(this_char,"uid")) {
X if (!value || !*value) {
X return 0;
X }
diff -u --recursive --new-file v2.2.8/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.8/linux/fs/proc/array.c Tue May 11 13:10:31 1999
+++ linux/fs/proc/array.c Tue May 11 16:30:35 1999
@@ -567,7 +567,7 @@
X }
X } while (count++ < 16);
X }
-#elif defined (CONFIG_ARM)
+#elif defined(__arm__)
X {
X unsigned long fp, lr;
X unsigned long stack_page;
@@ -623,7 +623,7 @@
X # define KSTK_EIP(tsk) \
X (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
X # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
-#elif defined(CONFIG_ARM)
+#elif defined(__arm__)
X # define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
X # define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
X #elif defined(__mc68000__)
diff -u --recursive --new-file v2.2.8/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.2.8/linux/include/asm-arm/arch-ebsa285/irq.h Tue May 11 13:10:31 1999
+++ linux/include/asm-arm/arch-ebsa285/irq.h Tue May 11 16:30:36 1999
@@ -10,7 +10,6 @@
X * 26-Jan-1999 PJB Don't use IACK on CATS
X * 16-Mar-1999 RMK Added autodetect of ISA PICs
X */
-#include <linux/config.h>
X #include <asm/hardware.h>
X #include <asm/dec21285.h>
X #include <asm/irq.h>
diff -u --recursive --new-file v2.2.8/linux/include/asm-arm/arch-ebsa285/memory.h linux/include/asm-arm/arch-ebsa285/memory.h
--- v2.2.8/linux/include/asm-arm/arch-ebsa285/memory.h Tue May 11 13:10:31 1999
+++ linux/include/asm-arm/arch-ebsa285/memory.h Tue May 11 16:30:36 1999
@@ -15,8 +15,6 @@
X #ifndef __ASM_ARCH_MMU_H
X #define __ASM_ARCH_MMU_H
X
-#include <linux/config.h>
-
X #if defined(CONFIG_HOST_FOOTBRIDGE)
X
X /*
diff -u --recursive --new-file v2.2.8/linux/include/asm-arm/arch-rpc/io.h linux/include/asm-arm/arch-rpc/io.h
--- v2.2.8/linux/include/asm-arm/arch-rpc/io.h Fri Jan 8 22:36:22 1999
+++ linux/include/asm-arm/arch-rpc/io.h Tue May 11 16:30:36 1999
@@ -28,18 +28,43 @@
X * Dynamic IO functions - let the compiler
X * optimize the expressions
X */
-#define DECLARE_DYN_OUT(fnsuffix,instr) \
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
-{ \
- unsigned long temp; \
- __asm__ __volatile__( \
- "tst %2, #0x80000000\n\t" \
- "mov %0, %4\n\t" \
- "addeq %0, %0, %3\n\t" \
- "str" ##instr## " %1, [%0, %2, lsl #2] @ out"###fnsuffix \
- : "=&r" (temp) \
- : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
- : "cc"); \
+extern __inline__ void __outb (unsigned int value, unsigned int port)
+{
+ unsigned long temp;
+ __asm__ __volatile__(
+ "tst %2, #0x80000000\n\t"
+ "mov %0, %4\n\t"
+ "addeq %0, %0, %3\n\t"
+ "strb %1, [%0, %2, lsl #2] @ outb"
+ : "=&r" (temp)
+ : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+ : "cc");
+}
+
+extern __inline__ void __outw (unsigned int value, unsigned int port)
+{
+ unsigned long temp;
+ __asm__ __volatile__(
+ "tst %2, #0x80000000\n\t"
+ "mov %0, %4\n\t"
+ "addeq %0, %0, %3\n\t"
+ "str %1, [%0, %2, lsl #2] @ outw"
+ : "=&r" (temp)
+ : "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+ : "cc");
+}
+
+extern __inline__ void __outl (unsigned int value, unsigned int port)
+{
+ unsigned long temp;
+ __asm__ __volatile__(
+ "tst %2, #0x80000000\n\t"
+ "mov %0, %4\n\t"
+ "addeq %0, %0, %3\n\t"
+ "str %1, [%0, %2, lsl #2] @ outl"
+ : "=&r" (temp)
+ : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+ : "cc");
X }
X
X #define DECLARE_DYN_IN(sz,fnsuffix,instr) \
@@ -66,7 +91,6 @@
X }
X
X #define DECLARE_IO(sz,fnsuffix,instr) \
- DECLARE_DYN_OUT(fnsuffix,instr) \
X DECLARE_DYN_IN(sz,fnsuffix,instr)
X
X DECLARE_IO(char,b,"b")
@@ -74,7 +98,6 @@
X DECLARE_IO(long,l,"")
X
X #undef DECLARE_IO
-#undef DECLARE_DYN_OUT
X #undef DECLARE_DYN_IN
X
X /*
diff -u --recursive --new-file v2.2.8/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h
--- v2.2.8/linux/include/asm-arm/proc-fns.h Tue May 11 13:10:32 1999
+++ linux/include/asm-arm/proc-fns.h Tue May 11 16:30:36 1999
@@ -10,7 +10,7 @@
X
X #ifdef __KERNEL__
X
-/* forward-decare task_struct */
+/* forward-declare task_struct */
X struct task_struct;
X
X /*
diff -u --recursive --new-file v2.2.8/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.2.8/linux/include/asm-arm/semaphore.h Tue May 11 13:10:32 1999
+++ linux/include/asm-arm/semaphore.h Tue May 11 16:30:36 1999
@@ -5,7 +5,6 @@
X #define __ASM_ARM_SEMAPHORE_H
X
X #include <linux/linkage.h>
-#include <asm/system.h>
X #include <asm/atomic.h>
X
X struct semaphore {
diff -u --recursive --new-file v2.2.8/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.2.8/linux/include/asm-m68k/page.h Tue May 11 13:10:32 1999
+++ linux/include/asm-m68k/page.h Wed May 12 08:50:08 1999
@@ -1,6 +1,8 @@
X #ifndef _M68K_PAGE_H
X #define _M68K_PAGE_H
X
+#include <linux/config.h>
+
X /* PAGE_SHIFT determines the page size */
X #define PAGE_SHIFT 12
X #define PAGE_SIZE (1UL << PAGE_SHIFT)
diff -u --recursive --new-file v2.2.8/linux/include/asm-m68k/q40_keyboard.h linux/include/asm-m68k/q40_keyboard.h
--- v2.2.8/linux/include/asm-m68k/q40_keyboard.h Tue May 11 13:10:32 1999
+++ linux/include/asm-m68k/q40_keyboard.h Wed May 12 08:50:08 1999
@@ -9,10 +9,6 @@
X */
X
X
-#include <linux/config.h> /* CONFIG_MAGIC_SYSRQ */
-
-
-
X #ifdef __KERNEL__
X
X
diff -u --recursive --new-file v2.2.8/linux/include/asm-m68k/semaphore-helper.h linux/include/asm-m68k/semaphore-helper.h
--- v2.2.8/linux/include/asm-m68k/semaphore-helper.h Tue May 11 13:10:32 1999
+++ linux/include/asm-m68k/semaphore-helper.h Wed May 12 08:50:08 1999
@@ -9,6 +9,8 @@
X * m68k version by Andreas Schwab
X */
X
+#include <linux/config.h>
+
X /*
X * These two _must_ execute atomically wrt each other.
X */
diff -u --recursive --new-file v2.2.8/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.2.8/linux/include/asm-m68k/semaphore.h Tue May 11 13:10:32 1999
+++ linux/include/asm-m68k/semaphore.h Wed May 12 08:50:08 1999
@@ -1,7 +1,6 @@
X #ifndef _M68K_SEMAPHORE_H
X #define _M68K_SEMAPHORE_H
X
-#include <linux/config.h>
X #include <linux/linkage.h>
X
X #include <asm/system.h>
diff -u --recursive --new-file v2.2.8/linux/include/linux/hfs_fs.h linux/include/linux/hfs_fs.h
--- v2.2.8/linux/include/linux/hfs_fs.h Fri Nov 27 13:09:29 1998
+++ linux/include/linux/hfs_fs.h Wed May 12 13:26:34 1999
@@ -82,17 +82,22 @@
X #define HFS_SGL_DINF HFS_ITYPE_1 /* %DirInfo for directory */
X
X /* IDs for elements of an AppleDouble or AppleSingle header */
-#define HFS_HDR_DATA 1
-#define HFS_HDR_RSRC 2
-#define HFS_HDR_FNAME 3
-#define HFS_HDR_COMNT 4
-#define HFS_HDR_BWICN 5
-#define HFS_HDR_CICON 6
-#define HFS_HDR_OLDI 7
-#define HFS_HDR_DATES 8
-#define HFS_HDR_FINFO 9
-#define HFS_HDR_MACI 10
-#define HFS_HDR_MAX 10
+#define HFS_HDR_DATA 1 /* data fork */
+#define HFS_HDR_RSRC 2 /* resource fork */
+#define HFS_HDR_FNAME 3 /* full (31-character) name */
+#define HFS_HDR_COMNT 4 /* comment */
+#define HFS_HDR_BWICN 5 /* b/w icon */
+#define HFS_HDR_CICON 6 /* color icon info */
+#define HFS_HDR_OLDI 7 /* old file info */
+#define HFS_HDR_DATES 8 /* file dates info */
+#define HFS_HDR_FINFO 9 /* Finder info */
+#define HFS_HDR_MACI 10 /* Macintosh info */
+#define HFS_HDR_PRODOSI 11 /* ProDOS info */
+#define HFS_HDR_MSDOSI 12 /* MSDOS info */
+#define HFS_HDR_SNAME 13 /* short name */
+#define HFS_HDR_AFPI 14 /* AFP file info */
+#define HFS_HDR_DID 15 /* directory id */
+#define HFS_HDR_MAX 16
X
X /*
X * There are three time systems. All three are based on seconds since
@@ -136,26 +141,7 @@
X };
X
X /*
- * Default header layout for Netatalk
- */
-struct hfs_nat_hdr {
- hfs_lword_t magic;
- hfs_lword_t version;
- hfs_byte_t homefs[16];
- hfs_word_t entries;
- hfs_byte_t descrs[60];
- hfs_byte_t real_name[255]; /* id=3 */
- hfs_byte_t comment[200]; /* id=4 XXX: not yet implemented */
- hfs_lword_t create_time; /* \ */
- hfs_lword_t modify_time; /* | */
- hfs_lword_t backup_time; /* | id=7 */
- hfs_word_t filler; /* | */
- hfs_word_t attr; /* / */
- hfs_byte_t finderinfo[32]; /* id=9 */
-};
-
-/*
- * Default header layout for AppleDouble
+ * Default header layout for Netatalk and AppleDouble
X */
X struct hfs_dbl_hdr {
X hfs_lword_t magic;
@@ -163,23 +149,37 @@
X hfs_byte_t filler[16];
X hfs_word_t entries;
X hfs_byte_t descrs[12*HFS_HDR_MAX];
- hfs_u32 create_time; /* \ */
- hfs_u32 modify_time; /* | id=8 */
- hfs_u32 backup_time; /* | */
- hfs_u32 access_time; /* / */
+ hfs_byte_t real_name[255]; /* id=3 */
+ hfs_byte_t comment[200]; /* id=4 XXX: not yet implemented */
+ hfs_u32 create_time; /* \ */
+ hfs_u32 modify_time; /* | id=8 (or 7) */
+ hfs_u32 backup_time; /* | */
+ hfs_u32 access_time; /* / (attributes with id=7) */
X hfs_u8 finderinfo[32]; /* id=9 */
X hfs_u32 fileinfo; /* id=10 */
- hfs_u8 real_name[32]; /* id=3 */
- hfs_u8 comment[200]; /* id=4 XXX: not yet implemented */
+ hfs_u32 cnid; /* id=15 */
+ hfs_u8 short_name[12]; /* id=13 */
+ hfs_u8 prodosi[8]; /* id=11 */
X };
X
+
X /* finder metadata for CAP */
X struct hfs_cap_info {
X hfs_byte_t fi_fndr[32]; /* Finder's info */
- hfs_word_t fi_attr; /* AFP attributes */
-#define HFS_AFP_WRI 0x020 /* Write inhibit bit */
-#define HFS_AFP_RNI 0x080 /* Rename inhibit bit (AFP >= 2.0) */
-#define HFS_AFP_DEI 0x100 /* Delete inhibit bit (AFP >= 2.0) */
+ hfs_word_t fi_attr; /* AFP attributes (f=file/d=dir) */
+#define HFS_AFP_INV 0x001 /* Invisible bit (f/d) */
+#define HFS_AFP_EXPFOLDER 0x002 /* exported folder (d) */
+#define HFS_AFP_MULTI 0x002 /* Multiuser bit (f) */
+#define HFS_AFP_SYS 0x004 /* System bit (f/d) */
+#define HFS_AFP_DOPEN 0x008 /* data fork already open (f) */
+#define HFS_AFP_MOUNTED 0x008 /* mounted folder (d) */
+#define HFS_AFP_ROPEN 0x010 /* resource fork already open (f) */
+#define HFS_AFP_INEXPFOLDER 0x010 /* folder in shared area (d) */
+#define HFS_AFP_WRI 0x020 /* Write inhibit bit (readonly) (f) */
+#define HFS_AFP_BACKUP 0x040 /* backup needed bit (f/d) */
+#define HFS_AFP_RNI 0x080 /* Rename inhibit bit (f/d) */
+#define HFS_AFP_DEI 0x100 /* Delete inhibit bit (f/d) */
+#define HFS_AFP_NOCOPY 0x400 /* Copy protect bit (f) */
X #define HFS_AFP_RDONLY ( HFS_AFP_WRI|HFS_AFP_RNI|HFS_AFP_DEI)
X hfs_byte_t fi_magic1; /* Magic number: */
X #define HFS_CAP_MAGIC1 0xFF
@@ -273,6 +273,7 @@
X extern const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout;
X extern const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout;
X extern const struct hfs_hdr_layout hfs_nat_hdr_layout;
+extern const struct hfs_hdr_layout hfs_nat2_hdr_layout;
X extern const struct hfs_hdr_layout hfs_sngl_hdr_layout;
X
X /* inode.c */
@@ -280,10 +281,10 @@
X extern int hfs_notify_change(struct dentry *, struct iattr *);
X extern struct inode *hfs_iget(struct hfs_cat_entry *, ino_t, struct dentry *);
X
-extern void hfs_cap_ifill(struct inode *, ino_t);
-extern void hfs_dbl_ifill(struct inode *, ino_t);
-extern void hfs_nat_ifill(struct inode *, ino_t);
-extern void hfs_sngl_ifill(struct inode *, ino_t);
+extern void hfs_cap_ifill(struct inode *, ino_t, const int);
+extern void hfs_dbl_ifill(struct inode *, ino_t, const int);
+extern void hfs_nat_ifill(struct inode *, ino_t, const int);
+extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
X
X /* super.c */
X extern struct super_block *hfs_read_super(struct super_block *,void *,int);
diff -u --recursive --new-file v2.2.8/linux/include/linux/hfs_fs_sb.h linux/include/linux/hfs_fs_sb.h
--- v2.2.8/linux/include/linux/hfs_fs_sb.h Sun Jan 4 10:40:17 1998
+++ linux/include/linux/hfs_fs_sb.h Wed May 12 13:26:34 1999
@@ -16,7 +16,7 @@
X
X typedef int (*hfs_namein_fn) (char *, const struct hfs_name *);
X typedef void (*hfs_nameout_fn) (struct hfs_name *, const char *, int);
-typedef void (*hfs_ifill_fn) (struct inode *, ino_t);
+typedef void (*hfs_ifill_fn) (struct inode *, ino_t, const int);
X
X /*
X * struct hfs_sb_info
@@ -30,6 +30,7 @@
X changing owner or mode? */
X int s_lowercase; /* Map names to lowercase? */
X int s_afpd; /* AFPD compatible mode? */
+ int s_version; /* version info */
X hfs_namein_fn s_namein; /* The function used to
X map Mac filenames to
X Linux filenames */
diff -u --recursive --new-file v2.2.8/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.2.8/linux/include/linux/skbuff.h Fri Oct 9 13:27:16 1998
+++ linux/include/linux/skbuff.h Thu May 13 10:33:17 1999
@@ -449,6 +449,14 @@
X * Add data to an sk_buff
X */
X
+extern __inline__ unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+{
+ unsigned char *tmp=skb->tail;
+ skb->tail+=len;
+ skb->len+=len;
+ return tmp;
+}
+
X extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
X {
X unsigned char *tmp=skb->tail;
@@ -461,6 +469,13 @@
X here: ;
X }
X return tmp;
+}
+
+extern __inline__ unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+{
+ skb->data-=len;
+ skb->len+=len;
+ return skb->data;
X }
X
X extern __inline__ unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
diff -u --recursive --new-file v2.2.8/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.2.8/linux/include/net/tcp.h Tue May 11 13:10:32 1999
+++ linux/include/net/tcp.h Thu May 13 10:33:17 1999
@@ -728,7 +728,7 @@
X */
X extern __inline__ __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
X {
- __u32 snd_wnd_packets = tp->snd_wnd / tp->mss_cache;
+ __u32 snd_wnd_packets = tp->snd_wnd / max(tp->mss_cache, 1);
X
X return max(min(snd_wnd_packets, tp->snd_cwnd) >> 1, 2);
X }
diff -u --recursive --new-file v2.2.8/linux/net/ipv4/ip_masq_quake.c linux/net/ipv4/ip_masq_quake.c
--- v2.2.8/linux/net/ipv4/ip_masq_quake.c Mon Feb 23 18:12:12 1998
+++ linux/net/ipv4/ip_masq_quake.c Tue May 11 16:30:35 1999
@@ -44,7 +44,7 @@
X
X struct quake_priv_data {
X /* Have we seen a client connect message */
- char cl_connect;
+ signed char cl_connect;
X };
X
X static int
SHAR_EOF
true || echo 'restore of patch-2.2.9 failed'
echo 'File patch-2.2.9 is complete' &&
chmod 644 patch-2.2.9 ||
echo 'restore of patch-2.2.9 failed'
Cksum="`cksum < 'patch-2.2.9'`"
if ! test "1049105884 135622" = "$Cksum"
then
echo 'patch-2.2.9: original Checksum 1049105884 135622, current one' "$Cksum"
rm -f _shar_wnt_.tmp
rm -f _shar_seq_.tmp
exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'
exit 0

Thomas...@ciw.uni-karlsruhe.de

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Archive-name: v2.2/patch-2.2.9/part1

#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a 3 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh
#

if test -r _shar_seq_.tmp; then
echo 'Must unpack archives in sequence!'
echo Please unpack part `cat _shar_seq_.tmp` next
exit 1
fi
# ============= patch-2.2.9 ==============
if test -f 'patch-2.2.9' -a X"$1" != X"-c"; then
echo 'x - skipping patch-2.2.9 (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.9 (Text)'


sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.9' &&

diff -u --recursive --new-file v2.2.8/linux/Makefile linux/Makefile
--- v2.2.8/linux/Makefile Tue May 11 13:10:27 1999
+++ linux/Makefile Wed May 12 08:50:12 1999
@@ -1,6 +1,6 @@
X VERSION = 2
X PATCHLEVEL = 2
-SUBLEVEL = 8
+SUBLEVEL = 9
X EXTRAVERSION =
X
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.2.8/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.2.8/linux/arch/m68k/kernel/ints.c Tue May 11 13:10:27 1999
+++ linux/arch/m68k/kernel/ints.c Wed May 12 08:50:08 1999
@@ -25,6 +25,7 @@
X * which must be served /Roman Zippel


X */
X
+#include <linux/config.h>

X #include <linux/types.h>
X #include <linux/sched.h>
X #include <linux/kernel_stat.h>
diff -u --recursive --new-file v2.2.8/linux/arch/m68k/mm/kmap.c linux/arch/m68k/mm/kmap.c
--- v2.2.8/linux/arch/m68k/mm/kmap.c Tue May 11 13:10:27 1999
+++ linux/arch/m68k/mm/kmap.c Wed May 12 08:50:08 1999
@@ -7,6 +7,7 @@
X * used by other architectures /Roman Zippel


X */
X
+#include <linux/config.h>

X #include <linux/mm.h>
X #include <linux/kernel.h>
X #include <linux/string.h>
diff -u --recursive --new-file v2.2.8/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.2.8/linux/arch/m68k/mvme147/config.c Tue May 11 13:10:27 1999
+++ linux/arch/m68k/mvme147/config.c Wed May 12 08:50:08 1999
@@ -13,7 +13,6 @@
X * for more details.
X */
X
-#include <linux/config.h>
X #include <stdarg.h>
X #include <linux/types.h>
X #include <linux/kernel.h>
diff -u --recursive --new-file v2.2.8/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.2.8/linux/arch/m68k/q40/config.c Tue May 11 13:10:27 1999
+++ linux/arch/m68k/q40/config.c Wed May 12 08:50:08 1999
@@ -13,6 +13,7 @@
X */
X
X #include <stdarg.h>
+#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/kernel.h>
X #include <linux/mm.h>
diff -u --recursive --new-file v2.2.8/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c
--- v2.2.8/linux/arch/m68k/sun3x/time.c Tue May 11 13:10:27 1999
+++ linux/arch/m68k/sun3x/time.c Wed May 12 08:50:08 1999
@@ -4,7 +4,6 @@
X * Sun3x-specific time handling
X */
X
-#include <linux/config.h>
X #include <linux/types.h>
X #include <linux/init.h>
X #include <linux/sched.h>
diff -u --recursive --new-file v2.2.8/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.2.8/linux/arch/ppc/kernel/pmac_pic.c Tue May 11 13:10:28 1999
+++ linux/arch/ppc/kernel/pmac_pic.c Wed May 12 08:50:08 1999
@@ -1,4 +1,4 @@
-
+#include <linux/config.h>
X #include <linux/stddef.h>
X #include <linux/init.h>
X #include <linux/sched.h>
diff -u --recursive --new-file v2.2.8/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.2.8/linux/drivers/block/ide-dma.c Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide-dma.c Tue May 11 14:58:46 1999
@@ -425,7 +425,7 @@
X } else {
X dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
X if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) {
- printk("%s: dma_base is invalid (0x%04lx, BIOS problem), please report to <m...@ucw.cz>\n", name, dma_base);
+ printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);
X dma_base = 0;
X }
X }
diff -u --recursive --new-file v2.2.8/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.2.8/linux/drivers/block/ide.c Tue May 11 13:10:28 1999
+++ linux/drivers/block/ide.c Wed May 12 13:19:32 1999
@@ -1696,6 +1696,7 @@
X ide_hwgroup_t *hwgroup;
X int irq_count = 0, unit, i;
X unsigned long flags;
+ unsigned int p, minor;
X
X if (index >= MAX_HWIFS)
X return;
@@ -1714,6 +1715,24 @@
X goto abort;
X }
X hwif->present = 0;
+
+ /*
+ * All clear? Then blow away the buffer cache
+ */
+ sti();
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ drive = &hwif->drives[unit];
+ minor = drive->select.b.unit << PARTN_BITS;
+ for (p = 0; p < (1<<PARTN_BITS); ++p) {
+ if (drive->part[p].nr_sects > 0) {
+ kdev_t devp = MKDEV(hwif->major, minor+p);
+ struct super_block * sb = get_super(devp);
+ if (sb) invalidate_inodes(sb);
+ invalidate_buffers (devp);
+ }
+ }
+ }
+ cli();
X hwgroup = hwif->hwgroup;
X
X /*
diff -u --recursive --new-file v2.2.8/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.2.8/linux/drivers/scsi/aha152x.c Fri Apr 16 14:47:30 1999
+++ linux/drivers/scsi/aha152x.c Wed May 12 13:19:32 1999
@@ -414,8 +414,13 @@
X #define P_PARITY 2
X
X /* possible irq range */
+#ifdef PCMCIA
+#define IRQ_MIN 0
+#define IRQ_MAX 16
+#else
X #define IRQ_MIN 9
X #define IRQ_MAX 12
+#endif
X #define IRQS IRQ_MAX-IRQ_MIN+1
X
X enum {
@@ -746,7 +751,7 @@
X if(!aha152x_porttest(setup->io_port))
X return 0;
X
- if(setup->irq<IRQ_MIN && setup->irq>IRQ_MAX)
+ if((setup->irq<IRQ_MIN) || (setup->irq>IRQ_MAX))
X return 0;
X
X if((setup->scsiid < 0) || (setup->scsiid > 7))
diff -u --recursive --new-file v2.2.8/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.2.8/linux/drivers/video/Config.in Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/Config.in Tue May 11 16:30:36 1999
@@ -21,6 +21,9 @@
X if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
X bool 'Acorn VIDC support' CONFIG_FB_ACORN
X fi
+ if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
+ tristate 'Cyber2000 support' CONFIG_FB_CYBER2000
+ fi
X if [ "$CONFIG_APOLLO" = "y" ]; then
X define_bool CONFIG_FB_APOLLO y
X fi
@@ -177,8 +180,8 @@
X "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
X "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
X "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
- "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
- "$CONFIG_FB_SGIVW" = "y" ]; then
+ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+ "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" ]; then
X define_bool CONFIG_FBCON_CFB8 y
X else
X if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -191,8 +194,8 @@
X "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
X "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
X "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
- "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
- "$CONFIG_FB_SGIVW" = "m" ]; then
+ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+ "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then
X define_bool CONFIG_FBCON_CFB8 m
X fi
X fi
@@ -204,7 +207,8 @@
X "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
X "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
X "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
- "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then
+ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
+ "$CONFIG_FB_CYBER2000" = "y" ]; then
X define_bool CONFIG_FBCON_CFB16 y
X else
X if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -214,19 +218,22 @@
X "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
X "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
X "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
- "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" ]; then
+ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+ "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "m" -o \
+ "$CONFIG_FB_CYBER2000" = "m" ]; then
X define_bool CONFIG_FBCON_CFB16 m
X fi
X fi
X if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
X "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
- "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
+ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+ "$CONFIG_FB_CYBER2000" = "y" ]; then
X define_bool CONFIG_FBCON_CFB24 y
X else
X if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
X "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
- "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
+ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+ "$CONFIG_FB_CYBER2000" = "m" ]; then
X define_bool CONFIG_FBCON_CFB24 m
X fi
X fi
@@ -323,7 +330,7 @@
X if [ "$CONFIG_AMIGA" = "y" ]; then
X define_bool CONFIG_FONT_PEARL_8x8 y
X fi
- if [ "$CONFIG_ARM" = "y" ]; then
+ if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
X define_bool CONFIG_FONT_ACORN_8x8 y
X fi
X fi
diff -u --recursive --new-file v2.2.8/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.2.8/linux/drivers/video/Makefile Tue Mar 23 14:35:48 1999
+++ linux/drivers/video/Makefile Tue May 11 16:30:36 1999
@@ -132,6 +132,14 @@
X endif
X endif
X
+ifeq ($(CONFIG_FB_CYBER2000),y)
+L_OBJS += cyber2000fb.o
+else
+ ifeq ($(CONFIG_FB_CYBER2000),m)
+ M_OBJS += cyber2000fb.o
+ endif
+endif
+
X ifeq ($(CONFIG_FB_SGIVW),y)
X L_OBJS += sgivwfb.o
X else
diff -u --recursive --new-file v2.2.8/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.2.8/linux/drivers/video/acornfb.c Mon Oct 5 13:13:41 1998
+++ linux/drivers/video/acornfb.c Tue May 11 16:30:36 1999
@@ -1,15 +1,22 @@
X /*
X * linux/drivers/video/acorn.c
X *
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998,1999 Russell King
X *
X * Frame buffer code for Acorn platforms
+ *
+ * NOTE: Most of the modes with X!=640 will disappear shortly.
+ * NOTE: Startup setting of HS & VS polarity not supported.
+ * (do we need to support it if we're coming up in 640x480?)
X */
+
+#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/kernel.h>
X #include <linux/sched.h>
X #include <linux/errno.h>
X #include <linux/string.h>
+#include <linux/ctype.h>
X #include <linux/mm.h>
X #include <linux/tty.h>
X #include <linux/malloc.h>
@@ -21,245 +28,898 @@
X #include <asm/irq.h>
X #include <asm/uaccess.h>
X
+#include <video/fbcon.h>
X #include <video/fbcon-mfb.h>
X #include <video/fbcon-cfb2.h>
X #include <video/fbcon-cfb4.h>
X #include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+
+/*
+ * Default resolution.
+ * NOTE that it has to be supported in the table towards
+ * the end of this file.
+ */
+#define DEFAULT_XRES 640
+#define DEFAULT_YRES 480
+
+/*
+ * define this to debug the video mode selection
+ */
+#undef DEBUG_MODE_SELECTION
+
+#if defined(HAS_VIDC20)
+#define VIDC_PALETTE_SIZE 256
+#define VIDC_NAME "VIDC20"
+#elif defined(HAS_VIDC)
+#include <asm/memc.h>
+#define VIDC_PALETTE_SIZE 16
+#define VIDC_NAME "VIDC"
+#endif
X
-#define MAX_VIDC20_PALETTE 256
-#define MAX_VIDC_PALETTE 16
+#define EXTEND8(x) ((x)|(x)<<8)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<16)
+
+struct vidc20_palette {
+ u_int red:8;
+ u_int green:8;
+ u_int blue:8;
+ u_int ext:4;
+ u_int unused:4;
+};
+
+struct vidc_palette {
+ u_int red:4;
+ u_int green:4;
+ u_int blue:4;
+ u_int trans:1;
+ u_int sbz1:13;
+ u_int reg:4;
+ u_int sbz2:2;
+};
+
+union palette {
+ struct vidc20_palette vidc20;
+ struct vidc_palette vidc;
+ u_int p;
+};
X
X struct acornfb_par {
- unsigned long screen_base;
- unsigned int xres;
- unsigned int yres;
- unsigned char bits_per_pixel;
- unsigned int palette_size;
+ unsigned long screen_base;
+ unsigned long screen_base_p;
+ unsigned long screen_end;
+ unsigned long screen_size;
+ unsigned int dram_size;
+ unsigned int vram_half_sam;
+ unsigned int palette_size;
+ signed int montype;
+ signed int currcon;
+ unsigned int allow_modeset : 1;
+ unsigned int using_vram : 1;
+ unsigned int dpms : 1;
+
+ union palette palette[VIDC_PALETTE_SIZE];
X
X union {
- union {
- struct {
- unsigned long red:8;
- unsigned long green:8;
- unsigned long blue:8;
- unsigned long ext:4;
- unsigned long unused:4;
- } d;
- unsigned long p;
- } vidc20[MAX_VIDC20_PALETTE];
- union {
- struct {
- unsigned long red:4;
- unsigned long green:4;
- unsigned long blue:4;
- unsigned long trans:1;
- unsigned long unused:19;
- } d;
- unsigned long p;
- } vidc[MAX_VIDC_PALETTE];
- } palette;
+ unsigned short cfb16[16];
+ unsigned long cfb32[16];
+ } cmap;
X };
X
-static int currcon = 0;
-static struct display disp;
+/*
+ * Translation from RISC OS monitor types to actual
+ * HSYNC and VSYNC frequency ranges. These are
+ * probably not right...
+ */
+#define NR_MONTYPES 6
+static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
+ { 15625, 15625, 50, 50, 0 }, /* TV */
+ { 0, 99999, 0, 99, 0 }, /* Multi Freq */
+ { 58608, 58608, 64, 64, 0 }, /* Hi-res mono */
+ { 30000, 70000, 60, 60, 0 }, /* VGA */
+ { 30000, 70000, 56, 75, 0 }, /* SVGA */
+ { 30000, 70000, 60, 60, 0 }
+};
+
+static struct display global_disp;
X static struct fb_info fb_info;
X static struct acornfb_par current_par;
+static struct fb_var_screeninfo __initdata init_var = {};
X
-static int
-acornfb_open(struct fb_info *info, int user)
+extern int acornfb_depth; /* set by setup.c */
+extern unsigned int vram_size; /* set by setup.c */
+
+
+static struct vidc_timing {
+ u_int h_cycle;
+ u_int h_sync_width;
+ u_int h_border_start;
+ u_int h_display_start;
+ u_int h_display_end;
+ u_int h_border_end;
+ u_int h_interlace;
+
+ u_int v_cycle;
+ u_int v_sync_width;
+ u_int v_border_start;
+ u_int v_display_start;
+ u_int v_display_end;
+ u_int v_border_end;
+
+ u_int control;
+
+ /* VIDC20 only */
+ u_int pll_ctl;
+} current_vidc;
+
+#ifdef HAS_VIDC
+
+#define VID_CTL_VS_NVSYNC (1 << 3)
+#define VID_CTL_HS_NHSYNC (1 << 2)
+#define VID_CTL_24MHz (0)
+#define VID_CTL_25MHz (1)
+#define VID_CTL_36MHz (2)
+
+#define VIDC_CTRL_INTERLACE (1 << 6)
+#define VIDC_CTRL_FIFO_0_4 (0 << 4)
+#define VIDC_CTRL_FIFO_1_5 (1 << 4)
+#define VIDC_CTRL_FIFO_2_6 (2 << 4)
+#define VIDC_CTRL_FIFO_3_7 (3 << 4)
+#define VIDC_CTRL_1BPP (0 << 2)
+#define VIDC_CTRL_2BPP (1 << 2)
+#define VIDC_CTRL_4BPP (2 << 2)
+#define VIDC_CTRL_8BPP (3 << 2)
+#define VIDC_CTRL_DIV3 (0 << 0)
+#define VIDC_CTRL_DIV2 (1 << 0)
+#define VIDC_CTRL_DIV1_5 (2 << 0)
+#define VIDC_CTRL_DIV1 (3 << 0)
+
+/* CTL VIDC Actual
+ * 24.000 0 8.000
+ * 25.175 0 8.392
+ * 36.000 0 12.000
+ * 24.000 1 12.000
+ * 25.175 1 12.588
+ * 24.000 2 16.000
+ * 25.175 2 16.783
+ * 36.000 1 18.000
+ * 24.000 3 24.000
+ * 36.000 2 24.000
+ * 25.175 3 25.175
+ * 36.000 3 36.000
+ */
+static struct pixclock {
+ u_long min_clock;
+ u_long max_clock;
+ u_int vidc_ctl;
+ u_int vid_ctl;
+} pixclocks[] = {
+ /* we allow +/-1% on these */
+ { 123750, 126250, VIDC_CTRL_DIV3, VID_CTL_24MHz }, /* 8.000MHz */
+ { 82500, 84167, VIDC_CTRL_DIV2, VID_CTL_24MHz }, /* 12.000MHz */
+ { 61875, 63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz }, /* 16.000MHz */
+ { 41250, 42083, VIDC_CTRL_DIV1, VID_CTL_24MHz }, /* 24.000MHz */
+#ifdef CONFIG_ARCH_A5K
+ { 117974, 120357, VIDC_CTRL_DIV3, VID_CTL_25MHz }, /* 8.392MHz */
+ { 78649, 80238, VIDC_CTRL_DIV2, VID_CTL_25MHz }, /* 12.588MHz */
+ { 58987, 60178, VIDC_CTRL_DIV1_5, VID_CTL_25MHz }, /* 16.588MHz */
+ { 55000, 56111, VIDC_CTRL_DIV2, VID_CTL_36MHz }, /* 18.000MHz */
+ { 39325, 40119, VIDC_CTRL_DIV1, VID_CTL_25MHz }, /* 25.175MHz */
+ { 27500, 28055, VIDC_CTRL_DIV1, VID_CTL_36MHz }, /* 36.000MHz */
+#endif
+ { 0, }
+};
+
+static struct pixclock *
+acornfb_valid_pixrate(u_long pixclock)
X {
- MOD_INC_USE_COUNT;
- return 0;
+ u_int i;
+
+ for (i = 0; pixclocks[i].min_clock; i++)
+ if (pixclock > pixclocks[i].min_clock &&
+ pixclock < pixclocks[i].max_clock)
+ return pixclocks + i;
+
+ return NULL;
X }
X
-static int
-acornfb_release(struct fb_info *info, int user)
+/* VIDC Rules:
+ * hcr : must be even (interlace, hcr/2 must be even)
+ * hswr : must be even
+ * hdsr : must be odd
+ * hder : must be odd
+ *
+ * vcr : must be odd
+ * vswr : >= 1
+ * vdsr : >= 1
+ * vder : >= vdsr
+ * if interlaced, then hcr/2 must be even
+ */
+static void
+acornfb_set_timing(struct fb_var_screeninfo *var)
X {
- MOD_DEC_USE_COUNT;
- return 0;
+ struct pixclock *pclk;
+ struct vidc_timing vidc;
+ u_int horiz_correction;
+ u_int sync_len, display_start, display_end, cycle;
+ u_int is_interlaced;
+ u_int vid_ctl, vidc_ctl;
+ u_int bandwidth;
+
+ memset(&vidc, 0, sizeof(vidc));
+
+ pclk = acornfb_valid_pixrate(var->pixclock);
+ vidc_ctl = pclk->vidc_ctl;
+ vid_ctl = pclk->vid_ctl;
+
+ bandwidth = var->pixclock * 8 / var->bits_per_pixel;
+ /* 25.175, 4bpp = 79.444ns per byte, 317.776ns per word: fifo = 2,6 */
+ if (bandwidth > 71750)
+ vidc_ctl |= VIDC_CTRL_FIFO_2_6;
+ else if (bandwidth > 35875)
+ vidc_ctl |= VIDC_CTRL_FIFO_1_5;
+ else
+ vidc_ctl |= VIDC_CTRL_FIFO_0_4;
+
+ switch (var->bits_per_pixel) {
+ case 1:
+ horiz_correction = 19;
+ vidc_ctl |= VIDC_CTRL_1BPP;
+ break;
+
+ case 2:
+ horiz_correction = 11;
+ vidc_ctl |= VIDC_CTRL_2BPP;
+ break;
+
+ case 4:
+ horiz_correction = 7;
+ vidc_ctl |= VIDC_CTRL_4BPP;
+ break;
+
+ default:
+ case 8:
+ horiz_correction = 5;
+ vidc_ctl |= VIDC_CTRL_8BPP;
+ break;
+ }
+
+ if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+ vid_ctl |= VID_CTL_HS_NHSYNC;
+
+ if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+ vid_ctl |= VID_CTL_VS_NVSYNC;
+
+ sync_len = var->hsync_len;
+ display_start = sync_len + var->left_margin;
+ display_end = display_start + var->xres;
+ cycle = display_end + var->right_margin;
+
+ /* if interlaced, then hcr/2 must be even */
+ is_interlaced = (var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
+
+ if (is_interlaced) {
+ vidc_ctl |= VIDC_CTRL_INTERLACE;
+ if (cycle & 2) {
+ cycle += 2;
+ var->right_margin += 2;
+ }
+ }
+
+ vidc.h_cycle = (cycle - 2) / 2;
+ vidc.h_sync_width = (sync_len - 2) / 2;
+ vidc.h_border_start = (display_start - 1) / 2;
+ vidc.h_display_start = (display_start - horiz_correction) / 2;
+ vidc.h_display_end = (display_end - horiz_correction) / 2;
+ vidc.h_border_end = (display_end - 1) / 2;
+ vidc.h_interlace = (vidc.h_cycle + 1) / 2;
+
+ sync_len = var->vsync_len;
+ display_start = sync_len + var->upper_margin;
+ display_end = display_start + var->yres;
+ cycle = display_end + var->lower_margin;
+
+ if (is_interlaced)
+ cycle = (cycle - 3) / 2;
+ else
+ cycle = cycle - 1;
+
+ vidc.v_cycle = cycle;
+ vidc.v_sync_width = sync_len - 1;
+ vidc.v_border_start = display_start - 1;
+ vidc.v_display_start = vidc.v_border_start;
+ vidc.v_display_end = display_end - 1;
+ vidc.v_border_end = vidc.v_display_end;
+
+#ifdef CONFIG_ARCH_A5K
+ outb(vid_ctl, IOEB_VID_CTL);
+#endif
+ if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
+ current_vidc = vidc;
+
+ outl(0xe0000000 | vidc_ctl, IO_VIDC_BASE);
+ outl(0x80000000 | (vidc.h_cycle << 14), IO_VIDC_BASE);
+ outl(0x84000000 | (vidc.h_sync_width << 14), IO_VIDC_BASE);
+ outl(0x88000000 | (vidc.h_border_start << 14), IO_VIDC_BASE);
+ outl(0x8c000000 | (vidc.h_display_start << 14), IO_VIDC_BASE);
+ outl(0x90000000 | (vidc.h_display_end << 14), IO_VIDC_BASE);
+ outl(0x94000000 | (vidc.h_border_end << 14), IO_VIDC_BASE);
+ outl(0x98000000, IO_VIDC_BASE);
+ outl(0x9c000000 | (vidc.h_interlace << 14), IO_VIDC_BASE);
+ outl(0xa0000000 | (vidc.v_cycle << 14), IO_VIDC_BASE);
+ outl(0xa4000000 | (vidc.v_sync_width << 14), IO_VIDC_BASE);
+ outl(0xa8000000 | (vidc.v_border_start << 14), IO_VIDC_BASE);
+ outl(0xac000000 | (vidc.v_display_start << 14), IO_VIDC_BASE);
+ outl(0xb0000000 | (vidc.v_display_end << 14), IO_VIDC_BASE);
+ outl(0xb4000000 | (vidc.v_border_end << 14), IO_VIDC_BASE);
+ outl(0xb8000000, IO_VIDC_BASE);
+ outl(0xbc000000, IO_VIDC_BASE);
+ }
+#ifdef DEBUG_MODE_SELECTION
+ printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
+ var->yres, var->bits_per_pixel);
+ printk(KERN_DEBUG " H-cycle : %d\n", vidc.h_cycle);
+ printk(KERN_DEBUG " H-sync-width : %d\n", vidc.h_sync_width);
+ printk(KERN_DEBUG " H-border-start : %d\n", vidc.h_border_start);
+ printk(KERN_DEBUG " H-display-start : %d\n", vidc.h_display_start);
+ printk(KERN_DEBUG " H-display-end : %d\n", vidc.h_display_end);
+ printk(KERN_DEBUG " H-border-end : %d\n", vidc.h_border_end);
+ printk(KERN_DEBUG " H-interlace : %d\n", vidc.h_interlace);
+ printk(KERN_DEBUG " V-cycle : %d\n", vidc.v_cycle);
+ printk(KERN_DEBUG " V-sync-width : %d\n", vidc.v_sync_width);
+ printk(KERN_DEBUG " V-border-start : %d\n", vidc.v_border_start);
+ printk(KERN_DEBUG " V-display-start : %d\n", vidc.v_display_start);
+ printk(KERN_DEBUG " V-display-end : %d\n", vidc.v_display_end);
+ printk(KERN_DEBUG " V-border-end : %d\n", vidc.v_border_end);
+ printk(KERN_DEBUG " VIDC Ctrl (E) : 0x%08X\n", vidc_ctl);
+ printk(KERN_DEBUG " IOEB Ctrl : 0x%08X\n", vid_ctl);
+#endif
+}
+
+static inline void
+acornfb_palette_write(u_int regno, union palette pal)
+{
+ outl(pal.p, IO_VIDC_BASE);
+}
+
+static inline union palette
+acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
+ u_int trans)
+{
+ union palette pal;
+
+ pal.p = 0;
+ pal.vidc.reg = regno;
+ pal.vidc.red = red >> 12;
+ pal.vidc.green = green >> 12;
+ pal.vidc.blue = blue >> 12;
+ return pal;
X }
X
X static void
-acornfb_encode_var(struct fb_var_screeninfo *var, struct acornfb_par *par)
+acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *trans)
X {
- var->xres = par->xres;
- var->yres = par->yres;
- var->xres_virtual = par->xres;
- var->yres_virtual = par->yres;
- var->xoffset = 0;
- var->yoffset = 0;
- var->bits_per_pixel = par->bits_per_pixel;
- var->grayscale = 0;
- var->red.offset = 0;
- var->red.length = 8;
- var->red.msb_right = 0;
- var->green.offset = 0;
- var->green.length = 8;
- var->green.msb_right = 0;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->blue.msb_right = 0;
- var->transp.offset = 0;
- var->transp.length = 4;
- var->transp.msb_right = 0;
- var->nonstd = 0;
- var->activate = FB_ACTIVATE_NOW;
- var->height = -1;
- var->width = -1;
- var->vmode = FB_VMODE_NONINTERLACED;
- var->pixclock = 1;
- var->sync = 0;
- var->left_margin = 0;
- var->right_margin = 0;
- var->upper_margin = 0;
- var->lower_margin = 0;
- var->hsync_len = 0;
- var->vsync_len = 0;
+ *red = EXTEND4(current_par.palette[regno].vidc.red);
+ *green = EXTEND4(current_par.palette[regno].vidc.green);
+ *blue = EXTEND4(current_par.palette[regno].vidc.blue);
+ *trans = current_par.palette[regno].vidc.trans ? -1 : 0;
X }
+#endif
X
-static int
-acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+#ifdef HAS_VIDC20
+/*
+ * VIDC20 registers
+ */
+#define VIDC20_CTRL 0xe0000000
+#define VIDC20_CTRL_PIX_VCLK (0 << 0)
+#define VIDC20_CTRL_PIX_HCLK (1 << 0)
+#define VIDC20_CTRL_PIX_RCLK (2 << 0)
+#define VIDC20_CTRL_PIX_CK (0 << 2)
+#define VIDC20_CTRL_PIX_CK2 (1 << 2)
+#define VIDC20_CTRL_PIX_CK3 (2 << 2)
+#define VIDC20_CTRL_PIX_CK4 (3 << 2)
+#define VIDC20_CTRL_PIX_CK5 (4 << 2)
+#define VIDC20_CTRL_PIX_CK6 (5 << 2)
+#define VIDC20_CTRL_PIX_CK7 (6 << 2)
+#define VIDC20_CTRL_PIX_CK8 (7 << 2)
+#define VIDC20_CTRL_1BPP (0 << 5)
+#define VIDC20_CTRL_2BPP (1 << 5)
+#define VIDC20_CTRL_4BPP (2 << 5)
+#define VIDC20_CTRL_8BPP (3 << 5)
+#define VIDC20_CTRL_16BPP (4 << 5)
+#define VIDC20_CTRL_32BPP (6 << 5)
+#define VIDC20_CTRL_FIFO_NS (0 << 8)
+#define VIDC20_CTRL_FIFO_4 (1 << 8)
+#define VIDC20_CTRL_FIFO_8 (2 << 8)
+#define VIDC20_CTRL_FIFO_12 (3 << 8)
+#define VIDC20_CTRL_FIFO_16 (4 << 8)
+#define VIDC20_CTRL_FIFO_20 (5 << 8)
+#define VIDC20_CTRL_FIFO_24 (6 << 8)
+#define VIDC20_CTRL_FIFO_28 (7 << 8)
+#define VIDC20_CTRL_INT (1 << 12)
+#define VIDC20_CTRL_DUP (1 << 13)
+#define VIDC20_CTRL_PDOWN (1 << 14)
+
+#define VIDC20_ECTL 0xc0000000
+#define VIDC20_ECTL_REG(x) ((x) & 0xf3)
+#define VIDC20_ECTL_ECK (1 << 2)
+#define VIDC20_ECTL_REDPED (1 << 8)
+#define VIDC20_ECTL_GREENPED (1 << 9)
+#define VIDC20_ECTL_BLUEPED (1 << 10)
+#define VIDC20_ECTL_DAC (1 << 12)
+#define VIDC20_ECTL_LCDGS (1 << 13)
+#define VIDC20_ECTL_HRM (1 << 14)
+
+#define VIDC20_ECTL_HS_MASK (3 << 16)
+#define VIDC20_ECTL_HS_HSYNC (0 << 16)
+#define VIDC20_ECTL_HS_NHSYNC (1 << 16)
+#define VIDC20_ECTL_HS_CSYNC (2 << 16)
+#define VIDC20_ECTL_HS_NCSYNC (3 << 16)
+
+#define VIDC20_ECTL_VS_MASK (3 << 18)
+#define VIDC20_ECTL_VS_VSYNC (0 << 18)
+#define VIDC20_ECTL_VS_NVSYNC (1 << 18)
+#define VIDC20_ECTL_VS_CSYNC (2 << 18)
+#define VIDC20_ECTL_VS_NCSYNC (3 << 18)
+
+#define VIDC20_DCTL 0xf0000000
+/* 0-9 = number of words in scanline */
+#define VIDC20_DCTL_SNA (1 << 12)
+#define VIDC20_DCTL_HDIS (1 << 13)
+#define VIDC20_DCTL_BUS_NS (0 << 16)
+#define VIDC20_DCTL_BUS_D31_0 (1 << 16)
+#define VIDC20_DCTL_BUS_D63_32 (2 << 16)
+#define VIDC20_DCTL_BUS_D63_0 (3 << 16)
+#define VIDC20_DCTL_VRAM_DIS (0 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK (1 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK2 (2 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK4 (3 << 18)
+
+#define acornfb_valid_pixrate(rate) (1)
+
+/*
+ * Try to find the best PLL parameters for the pixel clock.
+ * This algorithm seems to give best predictable results,
+ * and produces the same values as detailed in the VIDC20
+ * data sheet.
+ */
+static inline u_int
+acornfb_vidc20_find_pll(u_int pixclk)
X {
- struct acornfb_par *par = &current_par;
- unsigned int line_length;
+ u_int r, best_r = 2, best_v = 2;
+ int best_d = 0x7fffffff;
X
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, "Acorn");
+ for (r = 2; r <= 32; r++) {
+ u_int rr, v, p;
+ int d;
X
- line_length = par->xres * par->bits_per_pixel / 8;
+ rr = 41667 * r;
X
- fix->smem_start = (char *)SCREEN2_BASE;
- fix->smem_len = (((line_length * par->yres) - 1) | (PAGE_SIZE - 1)) + 1;
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- fix->xpanstep = 0;
- fix->ypanstep = 0;
- fix->ywrapstep = 1;
- fix->line_length = line_length;
- fix->accel = FB_ACCEL_NONE;
+ v = (rr + pixclk / 2) / pixclk;
X
- return 0;
+ if (v > 32 || v < 2)
+ continue;
+
+ p = (rr + v / 2) / v;
+
+ d = pixclk - p;
+
+ if (d < 0)
+ d = -d;
+
+ if (d < best_d) {
+ best_d = d;
+ best_v = v - 1;
+ best_r = r - 1;
+ }
+
+ if (d == 0)
+ break;
+ }
+
+ return best_v << 8 | best_r;
X }
X
-static int
-acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static inline void
+acornfb_vidc20_find_rates(struct vidc_timing *vidc,
+ struct fb_var_screeninfo *var)
X {
- if (con == -1) {
- acornfb_encode_var(var, &current_par);
+ u_int div, bandwidth;
+
+ /* Select pixel-clock divisor to keep PLL in range */
+ div = var->pixclock / 9090; /*9921*/
+
+ /* Limit divisor */
+ if (div == 0)
+ div = 1;
+ if (div > 8)
+ div = 8;
+
+ /* Encode divisor to VIDC20 setting */
+ switch (div) {
+ case 1: vidc->control |= VIDC20_CTRL_PIX_CK; break;
+ case 2: vidc->control |= VIDC20_CTRL_PIX_CK2; break;
+ case 3: vidc->control |= VIDC20_CTRL_PIX_CK3; break;
+ case 4: vidc->control |= VIDC20_CTRL_PIX_CK4; break;
+ case 5: vidc->control |= VIDC20_CTRL_PIX_CK5; break;
+ case 6: vidc->control |= VIDC20_CTRL_PIX_CK6; break;
+ case 7: vidc->control |= VIDC20_CTRL_PIX_CK7; break;
+ case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
+ }
+
+ /* Calculate bandwidth */
+ bandwidth = var->pixclock * 8 / var->bits_per_pixel;
+
+ /* Encode bandwidth as VIDC20 setting */
+ if (bandwidth > 16667*2)
+ vidc->control |= VIDC20_CTRL_FIFO_16;
+ else if (bandwidth > 13333*2)
+ vidc->control |= VIDC20_CTRL_FIFO_20;
+ else if (bandwidth > 11111*2)
+ vidc->control |= VIDC20_CTRL_FIFO_24;
+ else
+ vidc->control |= VIDC20_CTRL_FIFO_28;
+
+ /* Find the PLL values */
+ vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
+}
+
+/* VIDC20 has a different set of rules from the VIDC:
+ * hcr : must be multiple of 4
+ * hswr : must be even
+ * hdsr : must be even
+ * hder : must be even
+ * vcr : >= 2, (interlace, must be odd)
+ * vswr : >= 1
+ * vdsr : >= 1
+ * vder : >= vdsr
+ */
+static void
+acornfb_set_timing(struct fb_var_screeninfo *var)
+{
+ struct vidc_timing vidc;
+ u_int vcr, fsize;
+ u_int ext_ctl, dat_ctl;
+ u_int words_per_line;
+
+ memset(&vidc, 0, sizeof(vidc));
+
+ vidc.h_sync_width = var->hsync_len - 8;
+ vidc.h_border_start = vidc.h_sync_width + var->left_margin + 8 - 12;
+ vidc.h_display_start = vidc.h_border_start + 12 - 18;
+ vidc.h_display_end = vidc.h_display_start + var->xres;
+ vidc.h_border_end = vidc.h_display_end + 18 - 12;
+ vidc.h_cycle = vidc.h_border_end + var->right_margin + 12 - 8;
+ vidc.h_interlace = vidc.h_cycle / 2;
+ vidc.v_sync_width = var->vsync_len - 1;
+ vidc.v_border_start = vidc.v_sync_width + var->upper_margin;
+ vidc.v_display_start = vidc.v_border_start;
+ vidc.v_display_end = vidc.v_display_start + var->yres;
+ vidc.v_border_end = vidc.v_display_end;
+ vidc.control = VIDC20_CTRL_PIX_VCLK;
+
+ vcr = var->vsync_len + var->upper_margin + var->yres +
+ var->lower_margin;
+
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+ vidc.v_cycle = (vcr - 3) / 2;
+ vidc.control |= VIDC20_CTRL_INT;
X } else
- *var = fb_display[con].var;
- return 0;
+ vidc.v_cycle = vcr - 2;
+
+ switch (var->bits_per_pixel) {
+ case 1: vidc.control |= VIDC20_CTRL_1BPP; break;
+ case 2: vidc.control |= VIDC20_CTRL_2BPP; break;
+ case 4: vidc.control |= VIDC20_CTRL_4BPP; break;
+ default:
+ case 8: vidc.control |= VIDC20_CTRL_8BPP; break;
+ case 16: vidc.control |= VIDC20_CTRL_16BPP; break;
+ case 32: vidc.control |= VIDC20_CTRL_32BPP; break;
+ }
+
+ acornfb_vidc20_find_rates(&vidc, var);
+ fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;
+
+ if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
+ current_vidc = vidc;
+
+ outl(VIDC20_CTRL| vidc.control, IO_VIDC_BASE);
+ outl(0xd0000000 | vidc.pll_ctl, IO_VIDC_BASE);
+ outl(0x80000000 | vidc.h_cycle, IO_VIDC_BASE);
+ outl(0x81000000 | vidc.h_sync_width, IO_VIDC_BASE);
+ outl(0x82000000 | vidc.h_border_start, IO_VIDC_BASE);
+ outl(0x83000000 | vidc.h_display_start, IO_VIDC_BASE);
+ outl(0x84000000 | vidc.h_display_end, IO_VIDC_BASE);
+ outl(0x85000000 | vidc.h_border_end, IO_VIDC_BASE);
+ outl(0x86000000, IO_VIDC_BASE);
+ outl(0x87000000 | vidc.h_interlace, IO_VIDC_BASE);
+ outl(0x90000000 | vidc.v_cycle, IO_VIDC_BASE);
+ outl(0x91000000 | vidc.v_sync_width, IO_VIDC_BASE);
+ outl(0x92000000 | vidc.v_border_start, IO_VIDC_BASE);
+ outl(0x93000000 | vidc.v_display_start, IO_VIDC_BASE);
+ outl(0x94000000 | vidc.v_display_end, IO_VIDC_BASE);
+ outl(0x95000000 | vidc.v_border_end, IO_VIDC_BASE);
+ outl(0x96000000, IO_VIDC_BASE);
+ outl(0x97000000, IO_VIDC_BASE);
+ }
+
+ outl(fsize, IOMD_FSIZE);
+
+ ext_ctl = VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3);
+
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ ext_ctl |= VIDC20_ECTL_HS_HSYNC;
+ else
+ ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
+
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ ext_ctl |= VIDC20_ECTL_VS_VSYNC;
+ else
+ ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
+
+ outl(VIDC20_ECTL | ext_ctl, IO_VIDC_BASE);
+
+ words_per_line = var->xres * var->bits_per_pixel / 32;
+
+ if (current_par.using_vram && current_par.screen_size == 2048*1024)
+ words_per_line /= 2;
+
+ /* RiscPC doesn't use the VIDC's VRAM control. */
+ dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
+
+ /* The data bus width is dependent on both the type
+ * and amount of video memory.
+ * DRAM 32bit low
+ * 1MB VRAM 32bit
+ * 2MB VRAM 64bit
+ */
+ if (current_par.using_vram && current_par.vram_half_sam == 2048) {
+ dat_ctl |= VIDC20_DCTL_BUS_D63_0;
+ } else
+ dat_ctl |= VIDC20_DCTL_BUS_D31_0;
+
+ outl(VIDC20_DCTL | dat_ctl, IO_VIDC_BASE);
+
+#ifdef DEBUG_MODE_SELECTION
+ printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
+ var->yres, var->bits_per_pixel);
+ printk(KERN_DEBUG " H-cycle : %d\n", vidc.h_cycle);
+ printk(KERN_DEBUG " H-sync-width : %d\n", vidc.h_sync_width);
+ printk(KERN_DEBUG " H-border-start : %d\n", vidc.h_border_start);
+ printk(KERN_DEBUG " H-display-start : %d\n", vidc.h_display_start);
+ printk(KERN_DEBUG " H-display-end : %d\n", vidc.h_display_end);
+ printk(KERN_DEBUG " H-border-end : %d\n", vidc.h_border_end);
+ printk(KERN_DEBUG " H-interlace : %d\n", vidc.h_interlace);
+ printk(KERN_DEBUG " V-cycle : %d\n", vidc.v_cycle);
+ printk(KERN_DEBUG " V-sync-width : %d\n", vidc.v_sync_width);
+ printk(KERN_DEBUG " V-border-start : %d\n", vidc.v_border_start);
+ printk(KERN_DEBUG " V-display-start : %d\n", vidc.v_display_start);
+ printk(KERN_DEBUG " V-display-end : %d\n", vidc.v_display_end);
+ printk(KERN_DEBUG " V-border-end : %d\n", vidc.v_border_end);
+ printk(KERN_DEBUG " Ext Ctrl (C) : 0x%08X\n", ext_ctl);
+ printk(KERN_DEBUG " PLL Ctrl (D) : 0x%08X\n", vidc.pll_ctl);
+ printk(KERN_DEBUG " Ctrl (E) : 0x%08X\n", vidc.control);
+ printk(KERN_DEBUG " Data Ctrl (F) : 0x%08X\n", dat_ctl);
+ printk(KERN_DEBUG " Fsize : 0x%08X\n", fsize);
+#endif
X }
X
-static int
-acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static inline void
+acornfb_palette_write(u_int regno, union palette pal)
X {
- return 0;
+ outl(0x10000000 | regno, IO_VIDC_BASE);
+ outl(pal.p, IO_VIDC_BASE);
+}
+
+static inline union palette
+acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
+ u_int trans)
+{
+ union palette pal;
+
+ pal.p = 0;
+ pal.vidc20.red = red >> 8;
+ pal.vidc20.green = green >> 8;
+ pal.vidc20.blue = blue >> 8;
+ return pal;
X }
X
X static void
-acornfb_set_disp(int con)
+acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *trans)
X {
- struct fb_fix_screeninfo fix;
- struct display *display;
+ *red = EXTEND8(current_par.palette[regno].vidc20.red);
+ *green = EXTEND8(current_par.palette[regno].vidc20.green);
+ *blue = EXTEND8(current_par.palette[regno].vidc20.blue);
+ *trans = EXTEND4(current_par.palette[regno].vidc20.ext);
+}
+#endif
X
- if (con >= 0)
- display = &fb_display[con];
+/*
+ * Before selecting the timing parameters, adjust
+ * the resolution to fit the rules.
+ */
+static void
+acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
+{
+ u_int font_line_len;
+ u_int fontht;
+ u_int sam_size, min_size, size;
+ u_int nr_y;
+
+ /* xres must be even */
+ var->xres = (var->xres + 1) & ~1;
+
+ /*
+ * We don't allow xres_virtual to differ from xres
+ */
+ var->xres_virtual = var->xres;
+ var->xoffset = 0;
+
+ /*
+ * Find the font height
+ */
+ if (con == -1)
+ fontht = fontheight(&global_disp);
X else
- display = &disp;
+ fontht = fontheight(fb_display + con);
X
- current_par.xres = 8 * ORIG_VIDEO_COLS;
- current_par.yres = 8 * ORIG_VIDEO_LINES;
- current_par.bits_per_pixel = 8;
- current_par.palette_size = MAX_VIDC20_PALETTE;
-
- acornfb_get_fix(&fix, con, 0);
-
- acornfb_get_var(&display->var, con, 0);
-
- display->cmap.start = 0;
- display->cmap.len = 0;
- display->cmap.red = NULL;
- display->cmap.green = NULL;
- display->cmap.blue = NULL;
- display->cmap.transp = NULL;
- display->screen_base = fix.smem_start;
- display->visual = fix.visual;
- display->type = fix.type;
- display->type_aux = fix.type_aux;
- display->ypanstep = fix.ypanstep;
- display->ywrapstep = fix.ywrapstep;
- display->line_length = fix.line_length;
- display->can_soft_blank = 0;
- display->inverse = 0;
+ if (fontht == 0)
+ fontht = 8;
X
- outl(SCREEN_START, VDMA_START);
- outl(SCREEN_START + fix.smem_len - VDMA_XFERSIZE, VDMA_END);
- outl(SCREEN_START, VDMA_INIT);
+ if (current_par.using_vram)
+ sam_size = current_par.vram_half_sam * 2;
+ else
+ sam_size = 16;
X
- switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
- case 1:
- display->dispsw = &fbcon_mfb;
- break;
-#endif
-#ifdef FBCON_HAS_CFB2
- case 2:
- display->dispsw = &fbcon_cfb2;
- break;
-#endif
-#ifdef FBCON_HAS_CFB4
- case 4:
- display->dispsw = &fbcon_cfb4;
- break;
+ /*
+ * Now, find a value for yres_virtual which allows
+ * us to do ywrap scrolling. The value of
+ * yres_virtual must be such that the end of the
+ * displayable frame buffer must be aligned with
+ * the start of a font line.
+ */
+ font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
+ min_size = var->xres * var->yres * var->bits_per_pixel / 8;
+
+ /* Find int 'y', such that y * fll == s * sam < maxsize
+ * y = s * sam / fll; s = maxsize / sam
+ */
+ for (size = current_par.screen_size; min_size <= size;
+ size -= sam_size) {
+ nr_y = size / font_line_len;
+
+ if (nr_y * font_line_len == size)
+ break;
+ }
+
+ if (min_size > size) {
+ /*
+ * failed, use ypan
+ */
+ size = current_par.screen_size;
+ var->yres_virtual = size / (font_line_len / fontht);
+ } else
+ var->yres_virtual = nr_y * fontht;
+
+ current_par.screen_end = current_par.screen_base_p + size;
+
+ /*
+ * Fix yres & yoffset if needed.
+ */
+ if (var->yres > var->yres_virtual)
+ var->yres = var->yres_virtual;
+
+ if (var->vmode & FB_VMODE_YWRAP) {
+ if (var->yoffset > var->yres_virtual)
+ var->yoffset = var->yres_virtual;
+ } else {
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+ }
+}
+
+/*
+ * After selecting the timing parameters, adjust
+ * the timing to suit the chip.
+ * NOTE! Only minor adjustments should be made here.
+ */
+static void
+acornfb_post_adjust_timing(struct fb_var_screeninfo *var)
+{
+ /* hsync_len must be even */
+ var->hsync_len = (var->hsync_len + 1) & ~1;
+
+#ifdef HAS_VIDC
+ /* left_margin must be odd */
+ if ((var->left_margin & 1) == 0) {
+ var->left_margin -= 1;
+ var->right_margin += 1;
+ }
+
+ /* right_margin must be odd */
+ var->right_margin |= 1;
+#elif defined(HAS_VIDC20)
+ /* left_margin must be even */
+ if (var->left_margin & 1) {
+ var->left_margin += 1;
+ var->right_margin -= 1;
+ }
+
+ /* right_margin must be even */
+ if (var->right_margin & 1)
+ var->right_margin += 1;
X #endif
-#ifdef FBCON_HAS_CFB8
- case 8:
- display->dispsw = &fbcon_cfb8;
- break;
+
+ if (var->vsync_len < 1)
+ var->vsync_len = 1;
+}
+
+static inline void
+acornfb_update_dma(struct fb_var_screeninfo *var)
+{
+ int off = (var->yoffset * var->xres_virtual *
+ var->bits_per_pixel) >> 3;
+
+#if defined(HAS_MEMC)
+ memc_write(VDMA_INIT, off >> 2);
+#elif defined(HAS_IOMD)
+ outl(current_par.screen_base_p + off, IOMD_VIDINIT);
X #endif
- default:
- display->dispsw = &fbcon_dummy;
- break;
- }


X }
X
X static int

-acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
+acornfb_open(struct fb_info *info, int user)
X {
- int t;
+ MOD_INC_USE_COUNT;


+ return 0;
+}
+

+static int
+acornfb_release(struct fb_info *info, int user)
+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
X
+static int
+acornfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+ u_int *trans, struct fb_info *info)
+{
X if (regno >= current_par.palette_size)
X return 1;
- t = current_par.palette.vidc20[regno].d.red;
- *red = (t << 8) | t;
- t = current_par.palette.vidc20[regno].d.green;
- *green = (t << 8) | t;
- t = current_par.palette.vidc20[regno].d.blue;
- *blue = (t << 8) | t;
- t = current_par.palette.vidc20[regno].d.ext;
- t |= t << 4;
- *transp = (t << 8) | t;
+
+ acornfb_palette_decode(regno, red, green, blue, trans);
+
X return 0;


X }
X
X static int

-acornfb_vidc20_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info)
+acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int trans, struct fb_info *info)
X {
+ union palette pal;
+
X if (regno >= current_par.palette_size)
X return 1;
X
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- current_par.palette.vidc20[regno].p = 0;
- current_par.palette.vidc20[regno].d.red = red;
- current_par.palette.vidc20[regno].d.green = green;
- current_par.palette.vidc20[regno].d.blue = blue;
+ pal = acornfb_palette_encode(regno, red, green, blue, trans);
+ acornfb_palette_write(regno, pal);
+ current_par.palette[regno] = pal;
+
+ if (regno < 16) {
+ switch (info->disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+ case 16: /* RGB555 */
+ current_par.cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+ break;
+#endif
X
- outl(0x10000000 | regno, VIDC_BASE);
- outl(current_par.palette.vidc20[regno].p, VIDC_BASE);
+ default:
+ break;
+ }
+ }
X
X return 0;
X }
@@ -270,8 +930,8 @@
X {
X int err = 0;
X
- if (con == currcon)
- err = fb_get_cmap(cmap, kspc, acornfb_vidc20_getcolreg, info);
+ if (con == current_par.currcon)
+ err = fb_get_cmap(cmap, kspc, acornfb_getcolreg, info);
X else if (fb_display[con].cmap.len)
X fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
X else
@@ -290,8 +950,8 @@
X err = fb_alloc_cmap(&fb_display[con].cmap,
X current_par.palette_size, 0);
X if (!err) {
- if (con == currcon)
- err = fb_set_cmap(cmap, kspc, acornfb_vidc20_setcolreg,
+ if (con == current_par.currcon)
+ err = fb_set_cmap(cmap, kspc, acornfb_setcolreg,
X info);
X else
X fb_copy_cmap(cmap, &fb_display[con].cmap,
@@ -301,13 +961,279 @@


X }
X
X static int

+acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+{
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+ case 1:
+ *visual = FB_VISUAL_MONO10;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+#ifdef HAS_VIDC
+ *visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+#else
+ *visual = FB_VISUAL_PSEUDOCOLOR;
+#endif
+ break;
+#endif
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ *visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB2
+ case 2:
+ *visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+#endif
+ case 16:
+ case 24:
+ case 32:
+ *visual = FB_VISUAL_TRUECOLOR;
+ default:
+ return -EINVAL;
+ }
+
+ if (!acornfb_valid_pixrate(var->pixclock))
+ return -EINVAL;
+
+ /*
+ * Adjust the resolution before using it.
+ */
+ acornfb_pre_adjust_timing(var, con);
+
+#if defined(HAS_VIDC20)
+ var->red.length = 8;
+ var->transp.length = 4;
+#elif defined(HAS_VIDC)
+ var->red.length = 4;
+ var->transp.length = 1;
+#endif
+ var->green = var->red;
+ var->blue = var->red;
+
+ /*
+ * Now adjust the timing parameters
+ */
+ acornfb_post_adjust_timing(var);
+


+ return 0;
+}
+

+static int
+acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct display *display;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ strcpy(fix->id, "Acorn");
+
+ if (con >= 0)
+ display = fb_display + con;
+ else
+ display = &global_disp;
+
+ fix->smem_start = (char *)current_par.screen_base_p;
+ fix->smem_len = current_par.screen_size;
+ fix->type = display->type;
+ fix->type_aux = display->type_aux;
+ fix->xpanstep = 0;
+ fix->ypanstep = display->ypanstep;
+ fix->ywrapstep = display->ywrapstep;
+ fix->visual = display->visual;
+ fix->line_length = display->line_length;
+ fix->accel = FB_ACCEL_NONE;
+


+ return 0;
+}
+

+static int
+acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ if (con == -1) {
+ *var = global_disp.var;
+ } else
+ *var = fb_display[con].var;
+


+ return 0;
+}
+

+static int
+acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ struct display *display;
+ int err, chgvar = 0, visual;
+
+ if (con >= 0)
+ display = fb_display + con;
+ else
+ display = &global_disp;
+
+ if (!current_par.allow_modeset && con != -1)
+ return -EINVAL;
+
+ err = acornfb_decode_var(var, con, &visual);
+ if (err)
+ return err;
+
+ switch (var->activate & FB_ACTIVATE_MASK) {
+ case FB_ACTIVATE_TEST:
+ return 0;
+
+ case FB_ACTIVATE_NXTOPEN:
+ case FB_ACTIVATE_NOW:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (con >= 0) {
+ if (display->var.xres != var->xres)
+ chgvar = 1;
+ if (display->var.yres != var->yres)
+ chgvar = 1;
+ if (display->var.xres_virtual != var->xres_virtual)
+ chgvar = 1;
+ if (display->var.yres_virtual != var->yres_virtual)
+ chgvar = 1;
+ if (memcmp(&display->var.red, &var->red, sizeof(var->red)))
+ chgvar = 1;
+ if (memcmp(&display->var.green, &var->green, sizeof(var->green)))
+ chgvar = 1;
+ if (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))
+ chgvar = 1;
+ }
+
+ display->var = *var;
+ display->var.activate &= ~FB_ACTIVATE_ALL;
+
+ if (var->activate & FB_ACTIVATE_ALL)
+ global_disp.var = display->var;
+
+ display->screen_base = (char *)current_par.screen_base;
+ display->visual = visual;
+ display->type = FB_TYPE_PACKED_PIXELS;
+ display->type_aux = 0;
+ display->ypanstep = 1;
+ display->ywrapstep = 1;
+ display->line_length =
+ display->next_line = (var->xres * var->bits_per_pixel) / 8;
+ display->can_soft_blank = visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
+ display->inverse = 0;
+
+ switch (display->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+ case 1:
+ current_par.palette_size = 2;
+ display->dispsw = &fbcon_mfb;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB2
+ case 2:
+ current_par.palette_size = 4;
+ display->dispsw = &fbcon_cfb2;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB4
+ case 4:
+ current_par.palette_size = 16;
+ display->dispsw = &fbcon_cfb4;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ current_par.palette_size = VIDC_PALETTE_SIZE;
+ display->dispsw = &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ current_par.palette_size = VIDC_PALETTE_SIZE;
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = current_par.cmap.cfb16;
+ break;
+#endif
+ default:
+ display->dispsw = &fbcon_dummy;
+ break;
+ }
+
+ if (chgvar && info && info->changevar)
+ info->changevar(con);
+
+ if (con == current_par.currcon) {
+ struct fb_cmap *cmap;
+ unsigned long start, size;
+ int control;
+
+#if defined(HAS_MEMC)
+ start = 0;
+ size = current_par.screen_size - VDMA_XFERSIZE;
+ control = 0;
+
+ memc_write(VDMA_START, start);
+ memc_write(VDMA_END, size >> 2);
+#elif defined(HAS_IOMD)
+
+ start = current_par.screen_base_p;
+ size = current_par.screen_end;
+
+ if (current_par.using_vram) {
+ size -= current_par.vram_half_sam;
+ control = DMA_CR_E | (current_par.vram_half_sam / 256);
+ } else {
+ size -= 16;
+ control = DMA_CR_E | DMA_CR_D | 16;
+ }
+
+ outl(start, IOMD_VIDSTART);
+ outl(size, IOMD_VIDEND);
+ outl(control, IOMD_VIDCR);
+#endif
+ acornfb_update_dma(var);
+
+ if (current_par.allow_modeset)
+ acornfb_set_timing(var);
+
+ if (display->cmap.len)
+ cmap = &display->cmap;
+ else
+ cmap = fb_default_cmap(current_par.palette_size);
+
+ fb_set_cmap(cmap, 1, acornfb_setcolreg, info);
+ }


+ return 0;
+}
+

+static int
X acornfb_pan_display(struct fb_var_screeninfo *var, int con,
X struct fb_info *info)
X {
- if (var->xoffset || var->yoffset)
+ u_int y_bottom;
+
+ if (var->xoffset)
X return -EINVAL;
+
+ y_bottom = var->yoffset;
+
+ if (!(var->vmode & FB_VMODE_YWRAP))
+ y_bottom += var->yres;
+
+ if (y_bottom > fb_display[con].var.yres_virtual)
+ return -EINVAL;
+
+ acornfb_update_dma(var);
+
+ fb_display[con].var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ fb_display[con].var.vmode |= FB_VMODE_YWRAP;
X else
- return 0;
+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+
+ return 0;


X }
X
X static int

@@ -329,64 +1255,652 @@
X acornfb_ioctl
X };
X
-void
-acornfb_setup(char *options, int *ints)
+static int
+acornfb_updatevar(int con, struct fb_info *info)
X {
+ if (con == current_par.currcon)
+ acornfb_update_dma(&fb_display[con].var);
+
+ return 0;


X }
X
X static int

-acornfb_update_var(int con, struct fb_info *info)
+acornfb_switch(int con, struct fb_info *info)
X {
- if (con == currcon) {
- int off = fb_display[con].var.yoffset *
- fb_display[con].var.xres_virtual *
- fb_display[con].var.bits_per_pixel >> 3;
- unsigned long base;
+ struct fb_cmap *cmap;
X
- base = current_par.screen_base = SCREEN_START + off;
+ if (current_par.currcon >= 0) {
+ cmap = &fb_display[current_par.currcon].cmap;
X
- outl (SCREEN_START + base, VDMA_INIT);
+ if (cmap->len)
+ fb_get_cmap(cmap, 1, acornfb_getcolreg, info);
X }
X
- return 0;
-}
+ current_par.currcon = con;
+
+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
+
+ acornfb_set_var(&fb_display[con].var, con, info);
X
-static int
-acornfb_switch(int con, struct fb_info *info)
-{
- currcon = con;
- acornfb_update_var(con, info);
X return 0;
X }
X
X static void
X acornfb_blank(int blank, struct fb_info *info)
X {
+ int i;
+
+ if (blank)
+ for (i = 0; i < current_par.palette_size; i++) {
+ union palette p;
+
+ p = acornfb_palette_encode(i, 0, 0, 0, 0);
+
+ acornfb_palette_write(i, p);
+ }
+ else
+ for (i = 0; i < current_par.palette_size; i++)
+ acornfb_palette_write(i, current_par.palette[i]);
+}
+
+/*
+ * Everything after here is initialisation!!!
+ */
+struct modey_params {
+ u_int y_res;
+ u_int u_margin;
+ u_int b_margin;
+ u_int vsync_len;
+ u_int vf;
+};
+
+struct modex_params {
+ u_int x_res;
+ u_int l_margin;
+ u_int r_margin;
+ u_int hsync_len;
+ u_int clock;
+ u_int hf;
+ const struct modey_params *modey;
+};
+
+static const struct modey_params modey_640_15600[] __initdata = {
+ { 250, 38, 21, 3, 50 }, /* 640x 250, 50Hz */
+ { 256, 35, 18, 3, 50 }, /* 640x 256, 50Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_640_26800[] __initdata = {
+ { 512, 18, 1, 3, 50 }, /* 640x 512, 50Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_640_31500[] __initdata = {
+ { 250, 109, 88, 2, 70 }, /* 640x 250, 70Hz */
+ { 256, 106, 85, 2, 70 }, /* 640x 256, 70Hz */
+ { 352, 58, 37, 2, 70 }, /* 640x 352, 70Hz */
+ { 480, 32, 11, 2, 60 }, /* 640x 480, 60Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_800_35200[] __initdata = {
+ { 600, 22, 1, 2, 56 }, /* 800x 600, 56Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_896_21800[] __initdata = {
+ { 352, 9, 0, 3, 60 }, /* 896x 352, 60Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+/* everything after here is not supported */
+static const struct modey_params modey_1024_uk[] __initdata = {
+ { 768, 0, 0, 0, 0 }, /* 1024x 768 */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_1056_uk[] __initdata = {
+ { 250, 0, 0, 0, 0 }, /* 1056x 250 */
+ { 256, 0, 0, 0, 0 }, /* 1056x 256 */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_1152_uk[] __initdata = {
+ { 896, 0, 0, 0, 0 }, /* 1152x 896 */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_1280_63600[] __initdata = {
+ { 1024, 0, 0, 0, 60 }, /* 1280x1024, 60Hz */
+ { 0, 0, 0, 0, 0 }
+};
+
+static const struct modey_params modey_1600_uk[] __initdata = {
+ { 1280, 0, 0, 0, 0 }, /* 1600x1280 */
+ { 0, 0, 0, 0, 0 }
+};
+
+/*
+ * Horizontal video programming requirements.
+ * This table is searched for the required horizontal
+ * and required frequency, and then the tables above
+ * are then searched for the required vertical
+ * resolution.
+ *
+ * NOTE! we can match multiple entries, so we search
+ * all horizontal entries for which the hfreq is within
+ * the monitor's range.
+ */
+static const struct modex_params modex_params[] __initdata = {
+ { /* X: 640, 15.6kHz */
+ 640, 185, 123, 76, 16000, 15625, modey_640_15600
+ },
+ { /* X: 640, 26.8kHz */
+ 640, 113, 87, 56, 24000, 26800, modey_640_26800
+ },
+ { /* X: 640, 31.5kHz */
+ 640, 48, 16, 96, 25175, 31500, modey_640_31500
+ },
+ { /* X: 800, 35.2kHz */
+ 800, 101, 23, 100, 36000, 35200, modey_800_35200
+ },
+ { /* X: 896, 21.8kHz */
+ 896, 59, 27, 118, 24000, 21800, modey_896_21800
+ },
+ { /* X: 1024 */
+ 1024, 0, 0, 0, 0, 0, modey_1024_uk
+ },
+ { /* X: 1056 */
+ 1056, 0, 0, 0, 0, 0, modey_1056_uk
+ },
+ { /* X: 1152 */
+ 1152, 0, 0, 0, 0, 0, modey_1152_uk
+ },
+ { /* X: 1280, 63.6kHz */
+ 1280, 0, 0, 0, 0, 63600, modey_1280_63600
+ },
+ { /* X: 1600 */
+ 1600, 0, 0, 0, 0, 0, modey_1600_uk
+ },
+ {
+ 0,
+ }
+};
+
+__initfunc(static int
+acornfb_lookup_timing(struct fb_var_screeninfo *var))
+{
+ const struct modex_params *x;
+ const struct modey_params *y;
+
+ /*
+ * We must adjust the resolution parameters
+ * before selecting the timing parameters.
+ */
+ acornfb_pre_adjust_timing(var, -1);
+
+ for (x = modex_params; x->x_res; x++) {
+
+ /*
+ * Is this resolution one we're looking for?
+ */
+ if (x->x_res != var->xres)
+ continue;
+
+ /*
+ * Is the hsync frequency ok for our monitor?
+ */
+ if (x->hf > fb_info.monspecs.hfmax ||
+ x->hf < fb_info.monspecs.hfmin)
+ continue;
+
+ /*
+ * Try to find a vertical resolution
+ */
+ for (y = x->modey; y->y_res; y++) {
+ /*
+ * Is this resolution one we're looking for?
+ */
+ if (y->y_res != var->yres)
+ continue;
+
+ /*
+ * Is the vsync frequency ok for our monitor?
+ */
+ if (y->vf > fb_info.monspecs.vfmax ||
+ y->vf < fb_info.monspecs.vfmin)
+ continue;
+
+ goto found;
+ }
+ }
+
+ var->pixclock = 0;
+
+ return -EINVAL;
+
+found:
+ /*
+ * Why is pixclock in picoseconds?
+ */
+ switch (x->clock) {
+ case 36000: var->pixclock = 27778; break;
+ case 25175: var->pixclock = 39722; break;
+ case 24000: var->pixclock = 41667; break;
+ case 16000: var->pixclock = 62500; break;
+ case 12000: var->pixclock = 83333; break;
+ case 8000: var->pixclock = 125000; break;
+ default: var->pixclock = 0; break;
+ }
+
+#ifdef DEBUG_MODE_SELECTION
+ printk(KERN_DEBUG "Found %dx%d at %d.%3dkHz, %dHz, pix %d\n",
+ x->x_res, y->y_res,
+ x->hf / 1000, x->hf % 1000,
+ y->vf, var->pixclock);
+#endif
+
+ var->left_margin = x->l_margin;
+ var->right_margin = x->r_margin;
+ var->upper_margin = y->u_margin;
+ var->lower_margin = y->b_margin;
+ var->hsync_len = x->hsync_len;
+ var->vsync_len = y->vsync_len;
+ var->sync = 0;
+
+ /*
+ * Now adjust the parameters we found
+ */
+ acornfb_post_adjust_timing(var);
+
+ return 0;
X }
X
-__initfunc(unsigned long
-acornfb_init(unsigned long mem_start))
+__initfunc(static void
+acornfb_init_fbinfo(void))
X {
+ static int first = 1;
+
+ if (!first)
+ return;
+ first = 0;
+
X strcpy(fb_info.modename, "Acorn");
- fb_info.node = -1;
- fb_info.fbops = &acornfb_ops;
- fb_info.disp = &disp;
- fb_info.monspecs.hfmin = 0;
- fb_info.monspecs.hfmax = 0;
- fb_info.monspecs.vfmin = 0;
- fb_info.monspecs.vfmax = 0;
- fb_info.monspecs.dpms = 0;
X strcpy(fb_info.fontname, "Acorn8x8");
- fb_info.changevar = NULL;
- fb_info.switch_con = acornfb_switch;
- fb_info.updatevar = acornfb_update_var;
- fb_info.blank = acornfb_blank;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
-
- acornfb_set_disp(-1);
- fb_set_cmap(fb_default_cmap(current_par.palette_size),
- 1, acornfb_vidc20_setcolreg, &fb_info);
- register_framebuffer(&fb_info);
X
- return mem_start;
+ fb_info.node = -1;
+ fb_info.fbops = &acornfb_ops;
+ fb_info.disp = &global_disp;
+ fb_info.changevar = NULL;
+ fb_info.switch_con = acornfb_switch;
+ fb_info.updatevar = acornfb_updatevar;
+ fb_info.blank = acornfb_blank;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ global_disp.dispsw = &fbcon_dummy;
+
+ /*
+ * setup initial parameters
+ */
+ memset(&init_var, 0, sizeof(init_var));
+ init_var.xres = DEFAULT_XRES;
+ init_var.yres = DEFAULT_YRES;
+
+#if defined(FBCON_HAS_CFB4)
+ init_var.bits_per_pixel = 4;
+#elif defined(FBCON_HAS_CFB8)
+ init_var.bits_per_pixel = 8;
+#elif defined(FBCON_HAS_CFB2)
+ init_var.bits_per_pixel = 2;
+#elif defined(FBCON_HAS_MFB)
+ init_var.bits_per_pixel = 1;
+#else
+#error No suitable framebuffers configured
+#endif
+
+#if defined(HAS_VIDC20)
+ init_var.red.length = 8;
+ init_var.transp.length = 4;
+#elif defined(HAS_VIDC)
+ init_var.red.length = 4;
+ init_var.transp.length = 1;
+#endif
+ init_var.green = init_var.red;
+ init_var.blue = init_var.red;
+ init_var.nonstd = 0;
+ init_var.activate = FB_ACTIVATE_NOW;
+ init_var.height = -1;
+ init_var.width = -1;
+ init_var.vmode = FB_VMODE_NONINTERLACED;
+
+ current_par.dram_size = 0;
+ current_par.montype = -1;
+ current_par.dpms = 0;
+}
+
+/*
+ * setup acornfb options:
+ *
+ * font:fontname
+ * Set fontname
+ *
+ * mon:hmin-hmax:vmin-vmax:dpms:width:height
+ * Set monitor parameters:
+ * hmin = horizontal minimum frequency (Hz)
+ * hmax = horizontal maximum frequency (Hz) (optional)
+ * vmin = vertical minimum frequency (Hz)
+ * vmax = vertical maximum frequency (Hz) (optional)
+ * dpms = DPMS supported? (optional)
+ * width = width of picture in mm. (optional)
+ * height = height of picture in mm. (optional)
+ *
+ * montype:type
+ * Set RISC-OS style monitor type:
+ * 0 (or tv) - TV frequency
+ * 1 (or multi) - Multi frequency
+ * 2 (or hires) - Hi-res monochrome
+ * 3 (or vga) - VGA
+ * 4 (or svga) - SVGA
+ * auto, or option missing
+ * - try hardware detect
+ *
+ * dram:size
+ * Set the amount of DRAM to use for the frame buffer
+ * (even if you have VRAM).
+ * size can optionally be followed by 'M' or 'K' for
+ * MB or KB respectively.
+ */
+__initfunc(static void
+acornfb_parse_font(char *opt))
+{
+ strcpy(fb_info.fontname, opt);
+}
+
+__initfunc(static void
+acornfb_parse_mon(char *opt))
+{
+ fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0);
+ if (*opt == '-')
+ fb_info.monspecs.hfmax = simple_strtoul(opt + 1, &opt, 0);
+ else
+ fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;
+
+ if (*opt != ':')
+ return;
+
+ fb_info.monspecs.vfmin = simple_strtoul(opt + 1, &opt, 0);
+ if (*opt == '-')
+ fb_info.monspecs.vfmax = simple_strtoul(opt + 1, &opt, 0);
+ else
+ fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;


SHAR_EOF
true || echo 'restore of patch-2.2.9 failed'

fi
echo 'End of part 1'
echo 'File patch-2.2.9 is continued in part 2'
echo 2 > _shar_seq_.tmp

Thomas...@ciw.uni-karlsruhe.de

unread,
May 14, 1999, 3:00:00 AM5/14/99
to
Archive-name: v2.2/patch-2.2.9/part2

#!/bin/sh
# this is part 2 of a 3 - part archive


# do not concatenate these parts, unpack them in order with /bin/sh

# file patch-2.2.9 continued
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck

if test "$Scheck" != 2; then


echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.9'
else
echo 'x - continuing with patch-2.2.9'

sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.9' &&

+
+ if (*opt != ':')
+ return;
+

+ fb_info.monspecs.dpms = simple_strtoul(opt + 1, &opt, 0);
+


+ if (*opt != ':')
+ return;
+

+ init_var.width = simple_strtoul(opt + 1, &opt, 0);
+


+ if (*opt != ':')
+ return;
+

+ init_var.height = simple_strtoul(opt + 1, NULL, 0);
+}
+
+__initfunc(static void
+acornfb_parse_montype(char *opt))
+{
+ current_par.montype = -2;
+
+ if (strncmp(opt, "tv", 2) == 0) {
+ opt += 2;
+ current_par.montype = 0;
+ } else if (strncmp(opt, "multi", 5) == 0) {
+ opt += 5;
+ current_par.montype = 1;
+ } else if (strncmp(opt, "hires", 5) == 0) {
+ opt += 5;
+ current_par.montype = 2;
+ } else if (strncmp(opt, "vga", 3) == 0) {
+ opt += 3;
+ current_par.montype = 3;
+ } else if (strncmp(opt, "svga", 4) == 0) {
+ opt += 4;
+ current_par.montype = 4;
+ } else if (strncmp(opt, "auto", 4) == 0) {
+ opt += 4;
+ current_par.montype = -1;
+ } else if (isdigit(*opt))
+ current_par.montype = simple_strtoul(opt, &opt, 0);
+
+ if (current_par.montype == -2 ||
+ current_par.montype > NR_MONTYPES) {
+ printk(KERN_ERR "acornfb: unknown monitor type: %s\n",
+ opt);
+ current_par.montype = -1;
+ } else
+ if (opt && *opt) {
+ if (strcmp(opt, ",dpms") == 0)
+ current_par.dpms = 1;
+ else
+ printk(KERN_ERR
+ "acornfb: unknown monitor option: %s\n",
+ opt);
+ }
+}
+
+__initfunc(static void
+acornfb_parse_dram(char *opt))
+{
+ unsigned int size;
+
+ size = simple_strtoul(opt, &opt, 0);
+
+ if (opt) {
+ switch (*opt) {
+ case 'M':
+ case 'm':
+ size *= 1024;
+ case 'K':
+ case 'k':
+ size *= 1024;


+ default:
+ break;
+ }
+ }

+
+ current_par.dram_size = size;
+}
+
+static struct options {
+ char *name;
+ void (*parse)(char *opt);
+} opt_table[] __initdata = {
+ { "font", acornfb_parse_font },
+ { "mon", acornfb_parse_mon },
+ { "montype", acornfb_parse_montype },
+ { "dram", acornfb_parse_dram },
+ { NULL, NULL }
+};
+
+__initfunc(void
+acornfb_setup(char *options, int *ints))
+{
+ struct options *optp;
+ char *opt;
+
+ if (!options || !*options)
+ return;
+
+ acornfb_init_fbinfo();
+
+ for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
+ if (!*opt)
+ continue;
+
+ for (optp = opt_table; optp->name; optp++) {
+ int optlen;
+
+ optlen = strlen(optp->name);
+
+ if (strncmp(opt, optp->name, optlen) == 0 &&
+ opt[optlen] == ':') {
+ optp->parse(opt + optlen + 1);


+ break;
+ }
+ }
+

+ if (!optp->name)
+ printk(KERN_ERR "acornfb: unknown parameter: %s\n",
+ opt);
+ }
+}
+
+/*
+ * Detect type of monitor connected
+ * For now, we just assume SVGA
+ */
+__initfunc(static int
+acornfb_detect_monitortype(void))
+{
+ return 4;
+}
+
+/*
+ * This enables the unused memory to be freed on older Acorn machines.
+ */
+static inline void
+free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
+{
+ int mb_freed = 0;
+
+ /*
+ * Align addresses
+ */
+ virtual_start = PAGE_ALIGN(virtual_start);
+ virtual_end = PAGE_ALIGN(virtual_end);
+
+ while (virtual_start < virtual_end) {
+ /*
+ * Clear page reserved bit,
+ * set count to 1, and free
+ * the page.
+ */
+ clear_bit(PG_reserved, &mem_map[MAP_NR(virtual_start)].flags);
+ atomic_set(&mem_map[MAP_NR(virtual_start)].count, 1);
+ free_page(virtual_start);
+
+ virtual_start += PAGE_SIZE;
+ mb_freed += PAGE_SIZE / 1024;
+ }
+
+ printk("acornfb: freed %dK memory\n", mb_freed);
+}
+
+__initfunc(void
+acornfb_init(void))
+{
+ unsigned long size;
+ u_int h_sync, v_sync;
+
+ acornfb_init_fbinfo();
+
+ if (current_par.montype == -1)
+ current_par.montype = acornfb_detect_monitortype();
+
+ if (current_par.montype < 0 || current_par.montype > NR_MONTYPES)
+ current_par.montype = 4;
+
+ fb_info.monspecs = monspecs[current_par.montype];
+ fb_info.monspecs.dpms = current_par.dpms;
+
+ current_par.currcon = -1;
+ current_par.screen_base = SCREEN2_BASE;
+ current_par.screen_base_p = SCREEN_START;
+ current_par.using_vram = 0;
+
+ /*
+ * If vram_size is set, we are using VRAM in
+ * a Risc PC. However, if the user has specified
+ * an amount of DRAM then use that instead.
+ */
+ if (vram_size && !current_par.dram_size) {
+ size = vram_size;
+ current_par.vram_half_sam = vram_size / 1024;
+ current_par.using_vram = 1;
+ } else if (current_par.dram_size)
+ size = current_par.dram_size;
+ else
+ size = (init_var.xres * init_var.yres *
+ init_var.bits_per_pixel) / 8;
+
+ size = PAGE_ALIGN(size);
+
+#ifdef CONFIG_ARCH_RPC
+ if (!current_par.using_vram) {
+ /*
+ * RiscPC needs to allocate the DRAM memory
+ * for the framebuffer if we are not using
+ * VRAM. Archimedes/A5000 machines use a
+ * fixed address for their framebuffers.
+ */
+ current_par.screen_base = (unsigned long)kmalloc(size, GFP_KERNEL);
+ if (current_par.screen_base == 0) {
+ printk(KERN_ERR "acornfb: unable to allocate screen "
+ "memory\n");
+ return;
+ }
+ current_par.screen_base_p =
+ virt_to_phys(current_par.screen_base);
+ }
+#endif
+#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_ARC)
+#define MAX_SIZE 480*1024
+ /*
+ * Limit maximum screen size.
+ */
+ if (size > MAX_SIZE)
+ size = MAX_SIZE;
+
+ /*
+ * Free unused pages
+ */
+ free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
+#endif
+
+ current_par.screen_size = size;
+ current_par.palette_size = VIDC_PALETTE_SIZE;
+ current_par.allow_modeset = 1;
+
+ /*
+ * Lookup the timing for this resolution. If we can't
+ * find it, then we can't restore it if we change
+ * the resolution, so we disable this feature.
+ */
+ if (acornfb_lookup_timing(&init_var))
+ current_par.allow_modeset = 0;
+
+ /*
+ * Again, if this does not succeed, then we disallow
+ * changes to the resolution parameters.
+ */
+ if (acornfb_set_var(&init_var, -1, &fb_info))
+ current_par.allow_modeset = 0;
+
+ h_sync = 1953125000 / init_var.pixclock;
+ h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +
+ init_var.right_margin + init_var.hsync_len);
+ v_sync = h_sync / (init_var.yres + init_var.upper_margin +
+ init_var.lower_margin + init_var.vsync_len);
+
+ printk("Acornfb: %ldkB %cRAM, %s, using %dx%d, %d.%03dkHz, %dHz\n",
+ current_par.screen_size / 1024,
+ current_par.using_vram ? 'V' : 'D',
+ VIDC_NAME, init_var.xres, init_var.yres,
+ h_sync / 1000, h_sync % 1000, v_sync);
+
+ register_framebuffer(&fb_info);
X }
diff -u --recursive --new-file v2.2.8/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.2.8/linux/drivers/video/cyber2000fb.c Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cyber2000fb.c Tue May 11 16:30:36 1999
@@ -0,0 +1,1057 @@
+/*
+ * linux/drivers/video/cyber2000fb.c
+ *
+ * Integraphics Cyber2000 frame buffer device
+ *
+ * Based on cyberfb.c
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+
+/*
+ * Some defaults


+ */
+#define DEFAULT_XRES 640
+#define DEFAULT_YRES 480

+#define DEFAULT_BPP 8
+
+static volatile unsigned char *CyberRegs;
+
+#include "cyber2000fb.h"


+
+static struct display global_disp;

+static struct fb_info fb_info;
+static struct cyber2000fb_par current_par;
+static struct display_switch *dispsw;


+static struct fb_var_screeninfo __initdata init_var = {};

+
+#ifdef DEBUG
+static void debug_printf(char *fmt, ...)
+{
+ char buffer[128];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsprintf(buffer, fmt, ap);
+ va_end(ap);
+
+ printascii(buffer);
+}
+#else
+#define debug_printf(x...) do { } while (0)
+#endif
+
+/*
+ * Predefined Video Modes
+ */
+static const struct res cyber2000_res[] = {
+ {
+ 640, 480,
+ {
+ 0x5f, 0x4f, 0x50, 0x80, 0x52, 0x9d, 0x0b, 0x3e,
+ 0x00, 0x40,
+ 0xe9, 0x8b, 0xdf, 0x50, 0x00, 0xe6, 0x04, 0xc3
+ },
+ 0x00,
+ { 0xd2, 0xce, 0xdb, 0x54 }
+ },
+
+ {
+ 800, 600,
+ {
+ 0x7f, 0x63, 0x64, 0x00, 0x66, 0x10, 0x6f, 0xf0,
+ 0x00, 0x60,
+ 0x5b, 0x8f, 0x57, 0x64, 0x00, 0x59, 0x6e, 0xe3
+ },
+ 0x00,
+ { 0x52, 0x85, 0xdb, 0x54 }
+ },
+
+ {
+ 1024, 768,
+ {
+ 0x9f, 0x7f, 0x80, 0x80, 0x8b, 0x94, 0x1e, 0xfd,
+ 0x00, 0x60,
+ 0x03, 0x86, 0xff, 0x80, 0x0f, 0x00, 0x1e, 0xe3
+ },
+ 0x00,
+ { 0xd0, 0x52, 0xdb, 0x54 }
+ },
+#if 0
+ {
+ 1152, 886,
+ {
+ },
+ {
+ }
+ },
+#endif
+ {
+ 1280, 1024,
+ {
+ 0xce, 0x9f, 0xa0, 0x8f, 0xa2, 0x1f, 0x28, 0x52,
+ 0x00, 0x40,
+ 0x08, 0x8f, 0xff, 0xa0, 0x00, 0x03, 0x27, 0xe3
+ },
+ 0x1d,
+ { 0xb4, 0x4b, 0xdb, 0x54 }
+ },
+
+ {
+ 1600, 1200,
+ {
+ 0xff, 0xc7, 0xc9, 0x9f, 0xcf, 0xa0, 0xfe, 0x10,
+ 0x00, 0x40,
+ 0xcf, 0x89, 0xaf, 0xc8, 0x00, 0xbc, 0xf1, 0xe3
+ },
+ 0x1f,
+ { 0xbd, 0x10, 0xdb, 0x54 }
+ }
+};
+
+#define NUM_TOTAL_MODES arraysize(cyber2000_res)
+
+static const char igs_regs[] = {
+ 0x10, 0x10, 0x12, 0x00, 0x13, 0x00,
+ 0x30, 0x21, 0x31, 0x00, 0x32, 0x00, 0x33, 0x01,
+ 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00,
+ 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01,
+ 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00,
+ 0x70, 0x0b, 0x71, 0x10, 0x72, 0x45, 0x73, 0x30,
+ 0x74, 0x1b, 0x75, 0x1e, 0x76, 0x00, 0x7a, 0xc8
+};
+
+static const char crtc_idx[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+};
+
+static void cyber2000_init_hw(const struct res *res)
+{
+ int i;
+
+ debug_printf("init vga hw for %dx%d\n", res->xres, res->yres);
+
+ cyber2000_outb(0xef, 0x3c2);
+ cyber2000_crtcw(0x0b, 0x11);
+ cyber2000_attrw(0x00, 0x11);
+
+ cyber2000_seqw(0x01, 0x00);
+ cyber2000_seqw(0x01, 0x01);
+ cyber2000_seqw(0x0f, 0x02);
+ cyber2000_seqw(0x00, 0x03);
+ cyber2000_seqw(0x0e, 0x04);
+ cyber2000_seqw(0x03, 0x00);
+
+ for (i = 0; i < sizeof(crtc_idx); i++)
+ cyber2000_crtcw(res->crtc_regs[i], crtc_idx[i]);
+
+ for (i = 0x0a; i < 0x10; i++)
+ cyber2000_crtcw(0, i);
+
+ cyber2000_crtcw(0xff, 0x18);
+
+ cyber2000_grphw(0x00, 0x00);
+ cyber2000_grphw(0x00, 0x01);
+ cyber2000_grphw(0x00, 0x02);
+ cyber2000_grphw(0x00, 0x03);
+ cyber2000_grphw(0x00, 0x04);
+ cyber2000_grphw(0x60, 0x05);
+ cyber2000_grphw(0x05, 0x06);
+ cyber2000_grphw(0x0f, 0x07);
+ cyber2000_grphw(0xff, 0x08);
+
+ for (i = 0; i < 16; i++)
+ cyber2000_attrw(i, i);
+
+ cyber2000_attrw(0x01, 0x10);
+ cyber2000_attrw(0x00, 0x11);
+ cyber2000_attrw(0x0f, 0x12);
+ cyber2000_attrw(0x00, 0x13);
+ cyber2000_attrw(0x00, 0x14);
+
+ for (i = 0; i < sizeof(igs_regs); i += 2)
+ cyber2000_grphw(igs_regs[i+1], igs_regs[i]);
+
+ cyber2000_grphw(res->crtc_ofl, 0x11);
+
+ for (i = 0; i < 4; i += 1)
+ cyber2000_grphw(res->clk_regs[i], 0xb0 + i);
+
+ cyber2000_grphw(0x01, 0x90);
+ cyber2000_grphw(0x80, 0xb9);
+ cyber2000_grphw(0x00, 0xb9);
+
+ cyber2000_outb(0x56, 0x3ce);
+ i = cyber2000_inb(0x3cf);
+ cyber2000_outb(i | 4, 0x3cf);
+ cyber2000_outb(0x04, 0x3c6);
+ cyber2000_outb(i, 0x3cf);
+
+ cyber2000_outb(0x20, 0x3c0);
+ cyber2000_outb(0xff, 0x3c6);
+
+ for (i = 0; i < 256; i++) {
+ cyber2000_outb(i, 0x3c8);
+ cyber2000_outb(0, 0x3c9);
+ cyber2000_outb(0, 0x3c9);
+ cyber2000_outb(0, 0x3c9);
+ }
+}
+
+
+static struct fb_ops cyber2000fb_ops;
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Cyber2000 Acceleration
+ */
+static void cyber2000_accel_wait(void)
+{
+ int count = 10000;
+
+ while (cyber2000_inb(0xbf011) & 0x80) {
+ if (!count--) {
+ debug_printf("accel_wait timed out\n");
+ cyber2000_outb(0, 0xbf011);
+ return;
+ }
+ udelay(10);
+ }
+}
+
+static void
+cyber2000_accel_setup(struct display *p)
+{
+ dispsw->setup(p);
+}
+
+static void
+cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ unsigned long src, dst, chwidth = p->var.xres_virtual * fontheight(p);
+ int v = 0x8000;
+
+ if (sx < dx) {
+ sx += width - 1;
+ dx += width - 1;
+ v |= 4;
+ }
+
+ if (sy < dy) {
+ sy += height - 1;
+ dy += height - 1;
+ v |= 2;
+ }
+
+ sx *= fontwidth(p);
+ dx *= fontwidth(p);
+ src = sx + sy * chwidth;
+ dst = dx + dy * chwidth;
+ width = width * fontwidth(p) - 1;
+ height = height * fontheight(p) - 1;
+
+ cyber2000_accel_wait();
+ cyber2000_outb(0x00, 0xbf011);
+ cyber2000_outb(0x03, 0xbf048);
+ cyber2000_outw(width, 0xbf060);
+
+ if (p->var.bits_per_pixel != 24) {
+ cyber2000_outl(dst, 0xbf178);
+ cyber2000_outl(src, 0xbf170);
+ } else {
+ cyber2000_outl(dst * 3, 0xbf178);
+ cyber2000_outb(dst, 0xbf078);
+ cyber2000_outl(src * 3, 0xbf170);
+ }
+
+ cyber2000_outw(height, 0xbf062);
+ cyber2000_outw(v, 0xbf07c);
+ cyber2000_outw(0x2800, 0xbf07e);
+}
+
+static void
+cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ unsigned long dst;
+ u32 bgx = attr_bgcol_ec(p, conp);
+
+ dst = sx * fontwidth(p) + sy * p->var.xres_virtual * fontheight(p);
+ width = width * fontwidth(p) - 1;
+ height = height * fontheight(p) - 1;
+
+ cyber2000_accel_wait();
+ cyber2000_outb(0x00, 0xbf011);
+ cyber2000_outb(0x03, 0xbf048);
+ cyber2000_outw(width, 0xbf060);
+ cyber2000_outw(height, 0xbf062);
+
+ switch (p->var.bits_per_pixel) {
+ case 16:
+ bgx = ((u16 *)p->dispsw_data)[bgx];
+ case 8:
+ cyber2000_outl(dst, 0xbf178);
+ break;
+
+ case 24:
+ cyber2000_outl(dst * 3, 0xbf178);
+ cyber2000_outb(dst, 0xbf078);
+ bgx = ((u32 *)p->dispsw_data)[bgx];
+ break;
+ }
+
+ cyber2000_outl(bgx, 0xbf058);
+ cyber2000_outw(0x8000, 0xbf07c);
+ cyber2000_outw(0x0800, 0xbf07e);
+}
+
+static void
+cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+ cyber2000_accel_wait();
+ dispsw->putc(conp, p, c, yy, xx);
+}
+
+static void
+cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count, int yy, int xx)
+{
+ cyber2000_accel_wait();
+ dispsw->putcs(conp, p, s, count, yy, xx);
+}
+
+static void
+cyber2000_accel_revc(struct display *p, int xx, int yy)
+{
+ cyber2000_accel_wait();
+ dispsw->revc(p, xx, yy);
+}
+
+static void
+cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p, int bottom_only)
+{
+ dispsw->clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_cyber_accel = {
+ cyber2000_accel_setup,
+ cyber2000_accel_bmove,
+ cyber2000_accel_clear,
+ cyber2000_accel_putc,
+ cyber2000_accel_putcs,
+ cyber2000_accel_revc,
+ NULL,
+ NULL,
+ cyber2000_accel_clear_margins,
+ FONTWIDTH(8)|FONTWIDTH(16)
+};
+
+/*
+ * Palette
+ */
+static int
+cyber2000_getcolreg(u_int regno, u_int * red, u_int * green, u_int * blue,
+ u_int * transp, struct fb_info *fb_info)
+{
+ int t;
+
+ if (regno >= 256)
+ return 1;
+
+ t = current_par.palette[regno].red;
+ *red = t << 10 | t << 4 | t >> 2;
+
+ t = current_par.palette[regno].green;
+ *green = t << 10 | t << 4 | t >> 2;
+
+ t = current_par.palette[regno].blue;
+ *blue = t << 10 | t << 4 | t >> 2;
+
+ *transp = 0;
+
+ return 0;
+}
+
+/*
+ * Set a single color register. Return != 0 for invalid regno.
+ */
+static int
+cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *fb_info)
+{
+ if (regno > 255)
+ return 1;
+
+ red >>= 10;
+ green >>= 10;
+ blue >>= 10;
+
+ current_par.palette[regno].red = red;
+ current_par.palette[regno].green = green;
+ current_par.palette[regno].blue = blue;
+
+ switch (fb_display[current_par.currcon].var.bits_per_pixel) {
+ case 8:
+ cyber2000_outb(regno, 0x3c8);
+ cyber2000_outb(red, 0x3c9);
+ cyber2000_outb(green, 0x3c9);
+ cyber2000_outb(blue, 0x3c9);
+ break;
+


+#ifdef FBCON_HAS_CFB16
+ case 16:

+ if (regno < 64) {
+ /* write green */
+ cyber2000_outb(regno << 2, 0x3c8);
+ cyber2000_outb(current_par.palette[regno >> 1].red, 0x3c9);
+ cyber2000_outb(green, 0x3c9);
+ cyber2000_outb(current_par.palette[regno >> 1].blue, 0x3c9);
+ }
+
+ if (regno < 32) {
+ /* write red,blue */
+ cyber2000_outb(regno << 3, 0x3c8);
+ cyber2000_outb(red, 0x3c9);
+ cyber2000_outb(current_par.palette[regno << 1].green, 0x3c9);
+ cyber2000_outb(blue, 0x3c9);
+ }


+
+ if (regno < 16)

+ current_par.c_table.cfb16[regno] = regno | regno << 5 | regno << 11;
+ break;
+#endif
+
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ cyber2000_outb(regno, 0x3c8);
+ cyber2000_outb(red, 0x3c9);
+ cyber2000_outb(green, 0x3c9);
+ cyber2000_outb(blue, 0x3c9);


+
+ if (regno < 16)

+ current_par.c_table.cfb24[regno] = regno | regno << 8 | regno << 16;
+ break;
+#endif
+
+ default:
+ return 1;
+ }


+
+ return 0;
+}
+

+static int cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+{
+ int width = var->xres_virtual;
+ int scr_pitch, fetchrow;
+ int i;
+ char b, col;


+
+ switch (var->bits_per_pixel) {

+ case 8: /* PSEUDOCOLOUR, 256 */
+ b = 0;
+ col = 1;
+ scr_pitch = var->xres_virtual / 8;
+ break;
+
+ case 16:/* DIRECTCOLOUR, 64k */
+ b = 1;
+ col = 2;
+ scr_pitch = var->xres_virtual / 8 * 2;
+ break;
+ case 24:/* TRUECOLOUR, 16m */
+ b = 2;
+ col = 4;
+ scr_pitch = var->xres_virtual / 8 * 3;
+ width *= 3;


+ break;
+
+ default:

+ return 1;
+ }
+
+ for (i = 0; i < NUM_TOTAL_MODES; i++)
+ if (var->xres == cyber2000_res[i].xres &&
+ var->yres == cyber2000_res[i].yres)
+ break;
+
+ if (i < NUM_TOTAL_MODES)
+ cyber2000_init_hw(cyber2000_res + i);
+
+ fetchrow = scr_pitch + 1;
+
+ debug_printf("Setting regs: pitch=%X, fetchrow=%X, col=%X, b=%X\n",
+ scr_pitch, fetchrow, col, b);
+
+ cyber2000_outb(0x13, 0x3d4);
+ cyber2000_outb(scr_pitch, 0x3d5);
+ cyber2000_outb(0x14, 0x3ce);
+ cyber2000_outb(fetchrow, 0x3cf);
+ cyber2000_outb(0x15, 0x3ce);
+ /* FIXME: is this the right way round? */
+ cyber2000_outb(((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f), 0x3cf);
+ cyber2000_outb(0x77, 0x3ce);
+ cyber2000_outb(col, 0x3cf);
+
+
+ cyber2000_outb(0x33, 0x3ce);
+ cyber2000_outb(0x1c, 0x3cf);
+
+ cyber2000_outw(width - 1, 0xbf018);
+ cyber2000_outw(width - 1, 0xbf218);
+ cyber2000_outb(b, 0xbf01c);


+
+ return 0;
+}
+

+static inline void
+cyber2000fb_update_start(struct fb_var_screeninfo *var)
+{
+#if 0
+ unsigned int base;
+
+ base = var->yoffset * var->xres_virtual + var->xoffset;
+
+ cyber2000_outb(0x0c, 0x3d4);
+ cyber2000_outb(base, 0x3d5);
+ cyber2000_outb(0x0d, 0x3d4);
+ cyber2000_outb(base >> 8, 0x3d5);
+ /* FIXME: need the upper bits of the start offset */
+/* cyber2000_outb(0x??, 0x3d4);
+ cyber2000_outb(base >> 16, 0x3d5);*/
+#endif
+}
+
+/*
+ * Open/Release the frame buffer device
+ */
+static int cyber2000fb_open(struct fb_info *info, int user)
+{


+ MOD_INC_USE_COUNT;
+ return 0;
+}
+

+static int cyber2000fb_release(struct fb_info *info, int user)


+{
+ MOD_DEC_USE_COUNT;
+ return 0;
+}

+
+/*
+ * Get the Colormap
+ */
+static int
+cyber2000fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ int err = 0;
+
+ if (con == current_par.currcon) /* current console? */
+ err = fb_get_cmap(cmap, kspc, cyber2000_getcolreg, info);
+ else if (fb_display[con].cmap.len) /* non default colormap? */
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);


+ return err;
+}
+

+
+/*
+ * Set the Colormap
+ */
+static int
+cyber2000fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ struct display *disp = &fb_display[con];
+ int err = 0;
+
+ if (!disp->cmap.len) { /* no colormap allocated? */
+ int size;
+
+ if (disp->var.bits_per_pixel == 16)
+ size = 32;
+ else
+ size = 256;
+
+ err = fb_alloc_cmap(&disp->cmap, size, 0);
+ }
+ if (!err) {
+ if (con == current_par.currcon) /* current console? */
+ err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg,
+ info);
+ else
+ fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+ }
+


+ return err;
+}
+

+static int
+cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)


+{
+ switch (var->bits_per_pixel) {

+#ifdef FBCON_HAS_CFB8
+ case 8:

+ *visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+#endif

+#ifdef FBCON_HAS_CFB16
+ case 16:

+ *visual = FB_VISUAL_DIRECTCOLOR;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ *visual = FB_VISUAL_TRUECOLOR;


+ break;
+#endif
+ default:

+ return -EINVAL;
+ }
+

+ return 0;
+}
+
+/*
+ * Get the Fixed Part of the Display
+ */
+static int
+cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *fb_info)


+{
+ struct display *display;
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));

+ strcpy(fix->id, "Cyber2000");


+
+ if (con >= 0)
+ display = fb_display + con;
+ else
+ display = &global_disp;
+
+ fix->smem_start = (char *)current_par.screen_base_p;
+ fix->smem_len = current_par.screen_size;

+ fix->mmio_start = (char *)current_par.regs_base_p;
+ fix->mmio_len = 0x000c0000;


+ fix->type = display->type;
+ fix->type_aux = display->type_aux;
+ fix->xpanstep = 0;
+ fix->ypanstep = display->ypanstep;
+ fix->ywrapstep = display->ywrapstep;
+ fix->visual = display->visual;
+ fix->line_length = display->line_length;

+ fix->accel = 22; /*FB_ACCEL_IGS_CYBER2000*/


+
+ return 0;
+}
+
+

+/*
+ * Get the User Defined Part of the Display
+ */
+static int
+cyber2000fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *fb_info)


+{
+ if (con == -1)
+ *var = global_disp.var;
+ else
+ *var = fb_display[con].var;
+
+ return 0;
+}
+

+/*
+ * Set the User Defined Part of the Display
+ */
+static int
+cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)


+{
+ struct display *display;
+ int err, chgvar = 0, visual;
+
+ if (con >= 0)
+ display = fb_display + con;
+ else
+ display = &global_disp;
+

+ err = cyber2000fb_decode_var(var, con, &visual);


+ if (err)
+ return err;
+
+ switch (var->activate & FB_ACTIVATE_MASK) {
+ case FB_ACTIVATE_TEST:
+ return 0;
+
+ case FB_ACTIVATE_NXTOPEN:
+ case FB_ACTIVATE_NOW:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (con >= 0) {
+ if (display->var.xres != var->xres)
+ chgvar = 1;
+ if (display->var.yres != var->yres)
+ chgvar = 1;
+ if (display->var.xres_virtual != var->xres_virtual)
+ chgvar = 1;
+ if (display->var.yres_virtual != var->yres_virtual)
+ chgvar = 1;

+ if (display->var.accel_flags != var->accel_flags)


+ chgvar = 1;
+ if (memcmp(&display->var.red, &var->red, sizeof(var->red)))
+ chgvar = 1;
+ if (memcmp(&display->var.green, &var->green, sizeof(var->green)))
+ chgvar = 1;

+ if (memcmp(&display->var.blue, &var->blue, sizeof(var->green)))


+ chgvar = 1;
+ }

+
+ display->var = *var;
+

+ display->screen_base = (char *)current_par.screen_base;
+ display->visual = visual;
+ display->type = FB_TYPE_PACKED_PIXELS;
+ display->type_aux = 0;

+ display->ypanstep = 0;
+ display->ywrapstep = 0;
+ display->line_length =
+ display->next_line = (var->xres_virtual * var->bits_per_pixel) / 8;
+ display->can_soft_blank = 1;


+ display->inverse = 0;
+
+ switch (display->var.bits_per_pixel) {

+#ifdef FBCON_HAS_CFB8
+ case 8:

+ dispsw = &fbcon_cfb8;
+ display->dispsw_data = NULL;


+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:

+ dispsw = &fbcon_cfb16;
+ display->dispsw_data = current_par.c_table.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ dispsw = &fbcon_cfb24;
+ display->dispsw_data = current_par.c_table.cfb24;


+ break;
+#endif
+ default:

+ printk(KERN_WARNING "cyber2000: no support for %dbpp\n",
+ display->var.bits_per_pixel);
+ dispsw = &fbcon_dummy;
+ break;
+ }
+
+ if (display->var.accel_flags & FB_ACCELF_TEXT &&
+ dispsw != &fbcon_dummy)
+ display->dispsw = &fbcon_cyber_accel;
+ else
+ display->dispsw = dispsw;


+
+ if (chgvar && info && info->changevar)
+ info->changevar(con);
+
+ if (con == current_par.currcon) {
+ struct fb_cmap *cmap;
+

+ cyber2000fb_update_start(var);
+ cyber2000fb_set_timing(var);


+
+ if (display->cmap.len)
+ cmap = &display->cmap;
+ else
+ cmap = fb_default_cmap(current_par.palette_size);
+

+ fb_set_cmap(cmap, 1, cyber2000_setcolreg, info);


+ }
+ return 0;
+}
+
+

+/*
+ * Pan or Wrap the Display
+ */
+static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ u_int y_bottom;


+
+ y_bottom = var->yoffset;
+
+ if (!(var->vmode & FB_VMODE_YWRAP))
+ y_bottom += var->yres;
+

+ if (var->xoffset > (var->xres_virtual - var->xres))
+ return -EINVAL;


+ if (y_bottom > fb_display[con].var.yres_virtual)
+ return -EINVAL;

+return -EINVAL;
+
+ cyber2000fb_update_start(var);
+
+ fb_display[con].var.xoffset = var->xoffset;


+ fb_display[con].var.yoffset = var->yoffset;
+ if (var->vmode & FB_VMODE_YWRAP)
+ fb_display[con].var.vmode |= FB_VMODE_YWRAP;

+ else


+ fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+
+ return 0;

+}
+
+
+static int cyber2000fb_ioctl(struct inode *inode, struct file *file,
+ u_int cmd, u_long arg, int con, struct fb_info *info)
+{


+ return -EINVAL;
+}
+
+

+/*
+ * Update the `var' structure (called by fbcon.c)
+ *
+ * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ * Since it's called by a kernel driver, no range checking is done.
+ */
+static int
+cyber2000fb_updatevar(int con, struct fb_info *info)
+{
+ if (con == current_par.currcon)
+ cyber2000fb_update_start(&fb_display[con].var);


+ return 0;
+}
+
+static int

+cyber2000fb_switch(int con, struct fb_info *info)
+{
+ struct fb_cmap *cmap;
+


+ if (current_par.currcon >= 0) {
+ cmap = &fb_display[current_par.currcon].cmap;

+
+ if (cmap->len)
+ fb_get_cmap(cmap, 1, cyber2000_getcolreg, info);
+ }
+


+ current_par.currcon = con;
+
+ fb_display[con].var.activate = FB_ACTIVATE_NOW;
+

+ cyber2000fb_set_var(&fb_display[con].var, con, info);


+
+ return 0;
+}
+

+/*
+ * (Un)Blank the display.
+ */
+static void cyber2000fb_blank(int blank, struct fb_info *fb_info)
+{


+ int i;
+
+ if (blank) {

+ for (i = 0; i < 256; i++) {
+ cyber2000_outb(i, 0x3c8);
+ cyber2000_outb(0, 0x3c9);
+ cyber2000_outb(0, 0x3c9);
+ cyber2000_outb(0, 0x3c9);
+ }
+ } else {
+ for (i = 0; i < 256; i++) {
+ cyber2000_outb(i, 0x3c8);
+ cyber2000_outb(current_par.palette[i].red, 0x3c9);
+ cyber2000_outb(current_par.palette[i].green, 0x3c9);
+ cyber2000_outb(current_par.palette[i].blue, 0x3c9);
+ }
+ }
+}
+
+__initfunc(void cyber2000fb_setup(char *options, int *ints))
+{
+}
+
+static struct fb_ops cyber2000fb_ops =
+{
+ cyber2000fb_open,
+ cyber2000fb_release,
+ cyber2000fb_get_fix,
+ cyber2000fb_get_var,
+ cyber2000fb_set_var,
+ cyber2000fb_get_cmap,
+ cyber2000fb_set_cmap,
+ cyber2000fb_pan_display,
+ cyber2000fb_ioctl
+};
+
+__initfunc(static void
+cyber2000fb_init_fbinfo(void))
+{


+ static int first = 1;
+
+ if (!first)
+ return;
+ first = 0;
+

+ strcpy(fb_info.modename, "Cyber2000");
+ strcpy(fb_info.fontname, "Acorn8x8");
+
+ fb_info.node = -1;
+ fb_info.fbops = &cyber2000fb_ops;


+ fb_info.disp = &global_disp;
+ fb_info.changevar = NULL;

+ fb_info.switch_con = cyber2000fb_switch;
+ fb_info.updatevar = cyber2000fb_updatevar;
+ fb_info.blank = cyber2000fb_blank;


+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+

+ /*
+ * setup initial parameters
+ */
+ memset(&init_var, 0, sizeof(init_var));

+ init_var.xres_virtual =
+ init_var.xres = DEFAULT_XRES;
+ init_var.yres_virtual =
+ init_var.yres = DEFAULT_YRES;
+ init_var.bits_per_pixel = DEFAULT_BPP;
+
+ init_var.red.msb_right = 0;
+ init_var.green.msb_right = 0;
+ init_var.blue.msb_right = 0;
+
+ switch(init_var.bits_per_pixel) {
+ case 8:
+ init_var.bits_per_pixel = 8;
+ init_var.red.offset = 0;
+ init_var.red.length = 8;
+ init_var.green.offset = 0;
+ init_var.green.length = 8;
+ init_var.blue.offset = 0;
+ init_var.blue.length = 8;
+ break;
+
+ case 16:
+ init_var.bits_per_pixel = 16;
+ init_var.red.offset = 11;
+ init_var.red.length = 5;
+ init_var.green.offset = 5;
+ init_var.green.length = 6;
+ init_var.blue.offset = 0;
+ init_var.blue.length = 5;
+ break;
+
+ case 24:
+ init_var.bits_per_pixel = 24;
+ init_var.red.offset = 16;
+ init_var.red.length = 8;
+ init_var.green.offset = 8;
+ init_var.green.length = 8;
+ init_var.blue.offset = 0;
+ init_var.blue.length = 8;
+ break;
+ }
+


+ init_var.nonstd = 0;
+ init_var.activate = FB_ACTIVATE_NOW;
+ init_var.height = -1;
+ init_var.width = -1;

+ init_var.accel_flags = FB_ACCELF_TEXT;
+ init_var.sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;


+ init_var.vmode = FB_VMODE_NONINTERLACED;
+}
+

+/*
+ * Initialization
+ */
+__initfunc(void cyber2000fb_init(void))
+{
+ struct pci_dev *dev;
+ u_int h_sync, v_sync;
+
+ dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
+ if (!dev)
+ return;
+
+ CyberRegs = bus_to_virt(dev->base_address[0]) + 0x00800000;/*FIXME*/
+
+ cyber2000_outb(0x18, 0x46e8);
+ cyber2000_outb(0x01, 0x102);
+ cyber2000_outb(0x08, 0x46e8);
+
+ cyber2000fb_init_fbinfo();
+
+ current_par.currcon = -1;
+ current_par.screen_base_p = 0x80000000 + dev->base_address[0];
+ current_par.screen_base = (u_int)bus_to_virt(dev->base_address[0]);
+ current_par.screen_size = 0x00200000;
+ current_par.regs_base_p = 0x80800000 + dev->base_address[0];
+
+ cyber2000fb_set_var(&init_var, -1, &fb_info);
+
+ h_sync = 1953125000 / init_var.pixclock;
+ h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +
+ init_var.right_margin + init_var.hsync_len);
+ v_sync = h_sync / (init_var.yres + init_var.upper_margin +
+ init_var.lower_margin + init_var.vsync_len);
+
+ printk("Cyber2000: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+ current_par.screen_size >> 10,
+ init_var.xres, init_var.yres,
+ h_sync / 1000, h_sync % 1000, v_sync);
+
+ if (register_framebuffer(&fb_info) < 0)
+ return;
+
+ MOD_INC_USE_COUNT; /* TODO: This driver cannot be unloaded yet */
+}
+
+
+
+#ifdef MODULE
+int init_module(void)
+{
+ cyber2000fb_init();


+ return 0;
+}
+

+void cleanup_module(void)
+{
+ /* Not reached because the usecount will never be
+ decremented to zero */
+ unregister_framebuffer(&fb_info);
+ /* TODO: clean up ... */
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.8/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h
--- v2.2.8/linux/drivers/video/cyber2000fb.h Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cyber2000fb.h Tue May 11 16:30:36 1999
@@ -0,0 +1,78 @@
+/*
+ * linux/drivers/video/cyber2000fb.h
+ *
+ * Integraphics Cyber2000 frame buffer device
+ */
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+#define cyber2000_outb(dat,reg) (CyberRegs[reg] = dat)
+#define cyber2000_outw(dat,reg) (*(unsigned short *)&CyberRegs[reg] = dat)
+#define cyber2000_outl(dat,reg) (*(unsigned long *)&CyberRegs[reg] = dat)
+
+#define cyber2000_inb(reg) (CyberRegs[reg])
+#define cyber2000_inw(reg) (*(unsigned short *)&CyberRegs[reg])
+#define cyber2000_inl(reg) (*(unsigned long *)&CyberRegs[reg])
+
+static inline void cyber2000_crtcw(int val, int reg)
+{
+ cyber2000_outb(reg, 0x3d4);
+ cyber2000_outb(val, 0x3d5);
+}
+
+static inline void cyber2000_grphw(int val, int reg)
+{
+ cyber2000_outb(reg, 0x3ce);
+ cyber2000_outb(val, 0x3cf);
+}
+
+static inline void cyber2000_attrw(int val, int reg)
+{
+ cyber2000_inb(0x3da);
+ cyber2000_outb(reg, 0x3c0);
+ cyber2000_inb(0x3c1);
+ cyber2000_outb(val, 0x3c0);
+}
+
+static inline void cyber2000_seqw(int val, int reg)
+{
+ cyber2000_outb(reg, 0x3c4);
+ cyber2000_outb(val, 0x3c5);
+}
+
+struct cyber2000fb_par {


+ unsigned long screen_base;
+ unsigned long screen_base_p;

+ unsigned long regs_base;
+ unsigned long regs_base_p;


+ unsigned long screen_end;
+ unsigned long screen_size;

+ unsigned int palette_size;
+ signed int currcon;
+ /*
+ * palette
+ */
+ struct {
+ u8 red;
+ u8 green;
+ u8 blue;
+ } palette[256];
+ /*
+ * colour mapping table
+ */
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+ } c_table;
+};
+
+struct res {
+ int xres;
+ int yres;
+ unsigned char crtc_regs[18];
+ unsigned char crtc_ofl;
+ unsigned char clk_regs[4];
+};
diff -u --recursive --new-file v2.2.8/linux/drivers/video/dummycon.c linux/drivers/video/dummycon.c
--- v2.2.8/linux/drivers/video/dummycon.c Mon Aug 3 12:45:46 1998
+++ linux/drivers/video/dummycon.c Tue May 11 16:30:36 1999
@@ -5,7 +5,6 @@
X * available, usually until fbcon takes console over.


X */
X
-#include <linux/config.h>
X #include <linux/types.h>

X #include <linux/kdev_t.h>
X #include <linux/tty.h>
@@ -18,7 +17,7 @@
X * Dummy console driver
X */
X
-#if defined(CONFIG_ARM)
+#if defined(__arm__)
X #define DUMMY_COLUMNS ORIG_VIDEO_COLS
X #define DUMMY_ROWS ORIG_VIDEO_LINES
X #else
diff -u --recursive --new-file v2.2.8/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.2.8/linux/drivers/video/fbmem.c Wed Apr 28 11:37:30 1999
+++ linux/drivers/video/fbmem.c Tue May 11 16:30:36 1999
@@ -44,7 +44,7 @@
X * Frame buffer device initialization and setup routines
X */
X
-extern unsigned long acornfb_init(void);
+extern void acornfb_init(void);
X extern void acornfb_setup(char *options, int *ints);
X extern void amifb_init(void);
X extern void amifb_setup(char *options, int *ints);
@@ -56,6 +56,8 @@
X extern void cyberfb_setup(char *options, int *ints);
X extern void pm2fb_init(void);
X extern void pm2fb_setup(char *options, int *ints);
+extern void cyber2000fb_init(void);
+extern void cyber2000fb_setup(char *options, int *ints);
X extern void retz3fb_init(void);
X extern void retz3fb_setup(char *options, int *ints);
X extern void clgenfb_init(void);
@@ -120,6 +122,9 @@
X #ifdef CONFIG_FB_CYBER
X { "cyber", cyberfb_init, cyberfb_setup },
X #endif
+#ifdef CONFIG_FB_CYBER2000
+ { "cyber2000", cyber2000fb_init, cyber2000fb_setup },
+#endif
X #ifdef CONFIG_FB_PM2
X { "pm2fb", pm2fb_init, pm2fb_setup },
X #endif
@@ -501,6 +506,13 @@
X #elif defined(__mips__)
X pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
X pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+#elif defined(__arm__)
+#if defined(CONFIG_CPU_32) && !defined(CONFIG_ARCH_ACORN)
+ /* On Acorn architectures, we want to keep the framebuffer
+ * cached.
+ */
+ pgprot_val(vma->vm_page_prot) &= ~(PTE_CACHEABLE | PTE_BUFFERABLE);
+#endif
X #else
X #warning What do we have to do here??
X #endif
diff -u --recursive --new-file v2.2.8/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.2.8/linux/drivers/video/vgacon.c Mon Sep 28 10:51:34 1998
+++ linux/drivers/video/vgacon.c Tue May 11 16:30:36 1999
@@ -153,7 +153,7 @@
X __initfunc(static const char *vgacon_startup(void))
X {
X const char *display_desc = NULL;
- u16 saved;
+ u16 saved1, saved2;
X u16 *p;
X
X if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
@@ -267,18 +267,24 @@
X * Are there smarter methods around?
X */
X p = (u16 *)vga_vram_base;
- saved = scr_readw(p);
+ saved1 = scr_readw(p);
+ saved2 = scr_readw(p + 1);
X scr_writew(0xAA55, p);
- if (scr_readw(p) != 0xAA55) {
- scr_writew(saved, p);
+ scr_writew(0x55AA, p + 1);
+ if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
+ scr_writew(saved1, p);
+ scr_writew(saved2, p + 1);
X goto no_vga;
X }
X scr_writew(0x55AA, p);
- if (scr_readw(p) != 0x55AA) {
- scr_writew(saved, p);
+ scr_writew(0xAA55, p + 1);
+ if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
+ scr_writew(saved1, p);
+ scr_writew(saved2, p + 1);
X goto no_vga;
X }
- scr_writew(saved, p);
+ scr_writew(saved1, p);
+ scr_writew(saved2, p + 1);
X
X if (vga_video_type == VIDEO_TYPE_EGAC
X || vga_video_type == VIDEO_TYPE_VGAC
diff -u --recursive --new-file v2.2.8/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.2.8/linux/fs/adfs/dir.c Wed Apr 28 11:37:30 1999
+++ linux/fs/adfs/dir.c Tue May 11 16:30:36 1999
@@ -76,13 +76,34 @@
X return val;
X }
X
+static unsigned int adfs_filetype (unsigned int load)
+{
+ if ((load & 0xfff00000) != 0xfff00000)
+ return (unsigned int) -1;
+ return (load >> 8) & 0xfff;
+}
+
X static unsigned int adfs_time (unsigned int load, unsigned int exec)
X {
X unsigned int high, low;
X
- high = ((load << 24) | (exec >> 8)) - 0x336e996a;
+ /* Check for unstamped files. */
+ if ((load & 0xfff00000) != 0xfff00000)
+ return 0;
+
+ high = ((load << 24) | (exec >> 8));
X low = exec & 255;
X
+ /* Files dated pre 1970. */
+ if (high < 0x336e996a)
+ return 0;
+
+ high -= 0x336e996a;
+
+ /* Files dated post 2038 ish. */
+ if (high > 0x31ffffff)
+ return 0x7fffffff;
+
X /* 65537 = h256,l1
X * (h256 % 100) = 56 h256 / 100 = 2
X * 56 << 8 = 14336 2 * 256 = 512
@@ -204,6 +225,18 @@
X brelse (bhp[i]);
X }
X
+/* convert a disk-based directory entry to a Linux ADFS directory entry */
+static inline void
+adfs_dirent_to_idirent(struct adfs_idir_entry *ide, struct adfs_direntry *de)
+{
+ ide->name_len = adfs_readname(ide->name, de->dirobname, ADFS_NAME_LEN);
+ ide->file_id = adfs_val(de->dirinddiscadd, 3);
+ ide->size = adfs_val(de->dirlen, 4);
+ ide->mode = de->newdiratts;
+ ide->mtime = adfs_time(adfs_val(de->dirload, 4), adfs_val(de->direxec, 4));
+ ide->filetype = adfs_filetype(adfs_val(de->dirload, 4));
+}
+
X int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp,
X int buffers, int pos, unsigned long parent_object_id,
X struct adfs_idir_entry *ide)
@@ -228,13 +261,8 @@
X if (!de.dirobname[0])
X return 0;
X
- ide->name_len = adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN);
X ide->inode_no = adfs_inode_generate (parent_object_id, pos);
- ide->file_id = adfs_val (de.dirinddiscadd, 3);
- ide->size = adfs_val (de.dirlen, 4);
- ide->mode = de.newdiratts;
- ide->mtime = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4));
- ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff;
+ adfs_dirent_to_idirent(ide, &de);
X return 1;
X }
X
@@ -262,12 +290,7 @@
X if (!de.dirobname[0])
X return 0;
X
- ide->name_len = adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN);
- ide->size = adfs_val (de.dirlen, 4);
- ide->mode = de.newdiratts;
- ide->file_id = adfs_val (de.dirinddiscadd, 3);
- ide->mtime = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4));
- ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff;
+ adfs_dirent_to_idirent(ide, &de);
X return 1;
X }
X
diff -u --recursive --new-file v2.2.8/linux/fs/buffer.c linux/fs/buffer.c
--- v2.2.8/linux/fs/buffer.c Tue May 11 13:10:30 1999
+++ linux/fs/buffer.c Thu May 13 13:14:04 1999
@@ -100,8 +100,7 @@
X each time we call refill */
X int nref_dirt; /* Dirty buffer threshold for activating bdflush
X when trying to refill buffers. */
- int interval; /* Interval (seconds) between spontaneous
- bdflush runs */
+ int dummy1; /* unused */
X int age_buffer; /* Time for normal buffer to age before
X we flush it */
X int age_super; /* Time for superblock to age before we
@@ -110,10 +109,10 @@
X int dummy3; /* unused */
X } b_un;
X unsigned int data[N_PARAM];
-} bdf_prm = {{40, 500, 64, 256, 5, 30*HZ, 5*HZ, 1884, 2}};
+} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
X
X /* These are the min and max parameter values that we will allow to be assigned */
-int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 1, 1*HZ, 1*HZ, 1, 1};
+int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 1*HZ, 1*HZ, 1, 1};
X int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 600*HZ, 600*HZ, 2047, 5};
X
X void wakeup_bdflush(int);
@@ -1554,6 +1553,7 @@
X * response to dirty buffers. Once this process is activated, we write back
X * a limited number of buffers to the disks and then go back to sleep again.
X */
+static struct wait_queue * bdflush_wait = NULL;
X static struct wait_queue * bdflush_done = NULL;
X struct task_struct *bdflush_tsk = 0;
X
@@ -1561,7 +1561,7 @@
X {
X if (current == bdflush_tsk)
X return;
- wake_up_process(bdflush_tsk);
+ wake_up(&bdflush_wait);
X if (wait) {
X run_task_queue(&tq_disk);
X sleep_on(&bdflush_done);
@@ -1570,107 +1570,82 @@
X
X
X /*
- * Here we attempt to write back old buffers.
- * To prevent deadlocks for a loop device:
- * 1) Do non-blocking writes to loop (avoids deadlock with running
- * out of request blocks).
- * 2) But do a blocking write if the only dirty buffers are loop buffers
- * (otherwise we go into an infinite busy-loop).
- * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
- * with running out of free buffers for loop's "real" device).
-*/
+ * Here we attempt to write back old buffers. We also try to flush inodes
+ * and supers as well, since this function is essentially "update", and
+ * otherwise there would be no way of ensuring that these quantities ever
+ * get written back. Ideally, we would have a timestamp on the inodes
+ * and superblocks so that we could write back only the old ones as well
+ */
X
-static inline void sync_old_buffers(void)
+static int sync_old_buffers(void)
X {
X int i;
- int ndirty = 0;
- int wrta_cmd = WRITEA;
-#ifdef DEBUG
- int ncount = 0, nwritten = 0;
-#endif
+ int ndirty, nwritten;
+ int nlist;
+ int ncount;
X struct buffer_head * bh, *next;
X
-#ifdef DEBUG
- bh = lru_list[BUF_CLEAN];
- if(bh)
- for(i = nr_buffers_type[BUF_CLEAN]; --i > 0; bh = next) {
- next = bh->b_next_free;
+ sync_supers(0);
+ sync_inodes(0);
X
- /* Dirty/locked buffer on clean list? Refile it */
- if (buffer_locked(bh) || buffer_dirty(bh)) {
- ncount++;
- refile_buffer(bh);
- }
- }
+ ncount = 0;
+#ifdef DEBUG
+ for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+ for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
X #endif
+ {
+ ndirty = 0;
+ nwritten = 0;
+ repeat:
X
- bh = lru_list[BUF_LOCKED];
- if(bh)
- for(i = nr_buffers_type[BUF_LOCKED]; --i > 0; bh = next) {
- next = bh->b_next_free;
-
- /* Unlocked buffer on locked list? Refile it */
- if (!buffer_locked(bh))
- refile_buffer(bh);
- }
-
- restart:
- bh = lru_list[BUF_DIRTY];
- if(bh)
- for (i = nr_buffers_type[BUF_DIRTY];
- i-- > 0 && ndirty < bdf_prm.b_un.ndirty;
- bh = next) {
- /* We may have stalled while waiting for
- I/O to complete. */
- if(bh->b_list != BUF_DIRTY)
- goto restart;
- next = bh->b_next_free;
- if(!lru_list[BUF_DIRTY]) {
- printk("Dirty list empty %d\n", i);
- break;
- }
-
- /* Clean buffer on dirty list? Refile it */
- if (!buffer_dirty(bh)) {
- refile_buffer(bh);
- continue;
- }
-
- if (buffer_locked(bh))
- continue;
- /* Should we write back buffers that are
- shared or not?? Currently dirty buffers
- are not shared, so it does not matter */
- next->b_count++;
- bh->b_count++;
- ndirty++;
- bh->b_flushtime = 0;
- if (MAJOR(bh->b_dev) == LOOP_MAJOR) {
- ll_rw_block(wrta_cmd,1, &bh);
- wrta_cmd = WRITEA;
- if (buffer_dirty(bh))
- --ndirty;
- }
- else
- ll_rw_block(WRITE, 1, &bh);
- bh->b_count--;
- next->b_count--;
- }
- /* If we didn't write anything, but there are still
- * dirty buffers, then make the next write to a
- * loop device to be a blocking write.
- * This lets us block--which we _must_ do! */
- if (ndirty == 0
- && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
- wrta_cmd = WRITE;
- goto restart;
+ bh = lru_list[nlist];
+ if(bh)
+ for (i = nr_buffers_type[nlist]; i-- > 0; bh = next) {
+ /* We may have stalled while waiting for I/O to complete. */
+ if(bh->b_list != nlist) goto repeat;
+ next = bh->b_next_free;
+ if(!lru_list[nlist]) {
+ printk("Dirty list empty %d\n", i);
+ break;
+ }
+
+ /* Clean buffer on dirty list? Refile it */
+ if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ /* Unlocked buffer on locked list? Refile it */
+ if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ if (buffer_locked(bh) || !buffer_dirty(bh))
+ continue;
+ ndirty++;
+ if(time_before(jiffies, bh->b_flushtime))
+ continue;
+ nwritten++;
+ next->b_count++;
+ bh->b_count++;
+ bh->b_flushtime = 0;
+#ifdef DEBUG
+ if(nlist != BUF_DIRTY) ncount++;
+#endif
+ ll_rw_block(WRITE, 1, &bh);
+ bh->b_count--;
+ next->b_count--;
+ }
X }
-
+ run_task_queue(&tq_disk);
X #ifdef DEBUG
X if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
- printk("wrote %d/%d buffers...", nwritten, ndirty);
+ printk("Wrote %d/%d buffers\n", nwritten, ndirty);
X #endif
X run_task_queue(&tq_disk);


+ return 0;
X }
X
X

@@ -1687,12 +1662,10 @@
X if (!capable(CAP_SYS_ADMIN))
X goto out;
X
- if (func == 1)
- /* Func 1 used to call sync_old_buffers; a user space
- daemon would call it periodically. This is no
- longer necessary. Returning -EPERM here makes the
- daemon silently exit. */
- goto out;
+ if (func == 1) {
+ error = sync_old_buffers();
+ goto out;
+ }
X
X /* Basically func 1 means read param 1, 2 means write param 1, etc */
X if (func >= 2) {
@@ -1721,17 +1694,27 @@
X return error;
X }
X
-/* This is the actual bdflush daemon itself. It used to be started
- * from the syscall above, but now we launch it ourselves internally
- * with kernel_thread(...) directly after the first thread in
- * init/main.c. Every so often, or when woken up by another task that
- * needs memory, we call sync_old_buffers to partially clear the dirty list.
- */
+/* This is the actual bdflush daemon itself. It used to be started from
+ * the syscall above, but now we launch it ourselves internally with
+ * kernel_thread(...) directly after the first thread in init/main.c */
X
+/* To prevent deadlocks for a loop device:
+ * 1) Do non-blocking writes to loop (avoids deadlock with running
+ * out of request blocks).
+ * 2) But do a blocking write if the only dirty buffers are loop buffers
+ * (otherwise we go into an infinite busy-loop).
+ * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
+ * with running out of free buffers for loop's "real" device).
+*/
X int bdflush(void * unused)
X {
- long remaining = HZ * bdf_prm.b_un.interval;
- struct task_struct *tsk = current;
+ int i;
+ int ndirty;
+ int nlist;
+ int ncount;
+ struct buffer_head * bh, *next;
+ int major;
+ int wrta_cmd = WRITEA; /* non-blocking write for LOOP */
X
X /*
X * We have a bare-bones task_struct, and really should fill
@@ -1739,12 +1722,10 @@
X * display semi-sane things. Not real crucial though...
X */
X
- tsk->session = 1;
- tsk->pgrp = 1;
- tsk->dumpable = 0; /* inhibit ptrace() */
- strcpy(tsk->comm, "kflushd");
- sigfillset(&tsk->blocked);
- bdflush_tsk = tsk;
+ current->session = 1;
+ current->pgrp = 1;
+ sprintf(current->comm, "kflushd");
+ bdflush_tsk = current;
X
X /*
X * As a kernel thread we want to tamper with system buffers
@@ -1754,36 +1735,93 @@
X lock_kernel();
X
X for (;;) {
- tsk->state = TASK_INTERRUPTIBLE;
- remaining = schedule_timeout(remaining);
-
X #ifdef DEBUG
X printk("bdflush() activated...");
X #endif
- CHECK_EMERGENCY_SYNC
X
- if (remaining == 0) {
- /*
- * Also try to flush inodes and supers, since
- * otherwise there would be no way of ensuring
- * that these quantities ever get written
- * back. Ideally, we would have a timestamp
- * on the inodes and superblocks so that we
- * could write back only the old ones.
- */
- sync_supers(0);
- sync_inodes(0);
- remaining = HZ * bdf_prm.b_un.interval;
- }
-
- /* Keep flushing till there aren't very many dirty buffers */
- do {
- sync_old_buffers();
- } while(nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100);
+ CHECK_EMERGENCY_SYNC
X
- wake_up(&bdflush_done);
+ ncount = 0;
X #ifdef DEBUG
+ for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+ for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
+#endif
+ {
+ ndirty = 0;
+ repeat:
+
+ bh = lru_list[nlist];
+ if(bh)
+ for (i = nr_buffers_type[nlist]; i-- > 0 && ndirty < bdf_prm.b_un.ndirty;
+ bh = next) {
+ /* We may have stalled while waiting for I/O to complete. */
+ if(bh->b_list != nlist) goto repeat;
+ next = bh->b_next_free;
+ if(!lru_list[nlist]) {
+ printk("Dirty list empty %d\n", i);
+ break;
+ }
+
+ /* Clean buffer on dirty list? Refile it */
+ if (nlist == BUF_DIRTY && !buffer_dirty(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ /* Unlocked buffer on locked list? Refile it */
+ if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
+ refile_buffer(bh);
+ continue;
+ }
+
+ if (buffer_locked(bh) || !buffer_dirty(bh))
+ continue;
+ major = MAJOR(bh->b_dev);
+ /* Should we write back buffers that are shared or not??
+ currently dirty buffers are not shared, so it does not matter */
+ next->b_count++;
+ bh->b_count++;
+ ndirty++;
+ bh->b_flushtime = 0;
+ if (major == LOOP_MAJOR) {
+ ll_rw_block(wrta_cmd,1, &bh);
+ wrta_cmd = WRITEA;
+ if (buffer_dirty(bh))
+ --ndirty;
+ }
+ else
+ ll_rw_block(WRITE, 1, &bh);
+#ifdef DEBUG
+ if(nlist != BUF_DIRTY) ncount++;
+#endif
+ bh->b_count--;
+ next->b_count--;
+ }
+ }
+#ifdef DEBUG
+ if (ncount) printk("sys_bdflush: %d dirty buffers not on dirty list\n", ncount);
X printk("sleeping again.\n");
X #endif
+ /* If we didn't write anything, but there are still
+ * dirty buffers, then make the next write to a
+ * loop device to be a blocking write.
+ * This lets us block--which we _must_ do! */
+ if (ndirty == 0 && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
+ wrta_cmd = WRITE;
+ continue;
+ }
+ run_task_queue(&tq_disk);
+ wake_up(&bdflush_done);
+
+ /* If there are still a lot of dirty buffers around, skip the sleep
+ and flush some more */
+ if(ndirty == 0 || nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
+ spin_lock_irq(&current->sigmask_lock);
+ flush_signals(current);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ interruptible_sleep_on(&bdflush_wait);
+ }
X }
X }
diff -u --recursive --new-file v2.2.8/linux/fs/hfs/ChangeLog linux/fs/hfs/ChangeLog
--- v2.2.8/linux/fs/hfs/ChangeLog Tue Feb 23 15:21:34 1999
+++ linux/fs/hfs/ChangeLog Wed May 12 13:26:34 1999
@@ -1,3 +1,19 @@
+1999-04-12 a sun <as...@hecate.darksunrising.blah>
+
+ * file_hdr.c (hdr_read): added rootinfo behaviour for DID header.
+
+1999-04-11 a sun <as...@hecate.darksunrising.blah>
+
+ * super.c (parse_options): added s_version so that we can select
+ between different versions of the same layout.
+
+1999-04-05 a sun <as...@hecate.darksunrising.blah>
+
+ * linux/hfs_fs.h: unified netatalk and appledouble header format.
+ added in all of the AFP attribute bits.
+
+ * file_hdr.c: added netatalk appledouble v2 compatible headers.
+
X 1999-01-30 a sun <as...@hecate.darksunrising.blah>
X
X * catalog.c (hfs_cat_move): fixed corruption problem with
diff -u --recursive --new-file v2.2.8/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.2.8/linux/fs/hfs/file_hdr.c Tue Feb 23 15:21:34 1999
+++ linux/fs/hfs/file_hdr.c Wed May 12 13:26:34 1999
@@ -30,6 +30,14 @@
X #include <linux/hfs_fs_i.h>
X #include <linux/hfs_fs.h>
X
+/* prodos types */
+#define PRODOSI_FTYPE_DIR 0x0F
+#define PRODOSI_FTYPE_TEXT 0x04
+#define PRODOSI_FTYPE_8BIT 0xFF
+#define PRODOSI_FTYPE_16BIT 0xB3
+
+#define PRODOSI_AUXTYPE_DIR 0x0200
+
X /*================ Forward declarations ================*/
X
X static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);
@@ -84,13 +92,14 @@
X const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
X __constant_htonl(HFS_DBL_MAGIC), /* magic */
X __constant_htonl(HFS_HDR_VERSION_2), /* version */
- 5, /* entries */
+ 6, /* entries */
X { /* descr[] */
+ {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
X {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
X {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
- {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
- {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
- {HFS_HDR_RSRC, HFS_DBL_HDR_LEN, ~0},
+ {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
+ {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4},
+ {HFS_HDR_RSRC, HFS_DBL_HDR_LEN, ~0}
X },
X { /* order[] */
X (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],
@@ -98,24 +107,55 @@
X (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],
X (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],
X (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],
+ (struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]
X }
X };
X
X const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
X __constant_htonl(HFS_DBL_MAGIC), /* magic */
X __constant_htonl(HFS_HDR_VERSION_2), /* version */
- 4, /* entries */
+ 5, /* entries */
X { /* descr[] */
+ {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
X {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
X {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
- {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
- {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
+ {HFS_HDR_MACI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
+ {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4}
X },
X { /* order[] */
X (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],
X (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],
X (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],
X (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],
+ (struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]
+ }
+};
+
+const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
+ __constant_htonl(HFS_DBL_MAGIC), /* magic */
+ __constant_htonl(HFS_HDR_VERSION_2), /* version */
+ 9, /* entries */
+ { /* descr[] */
+ {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
+ {HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment), 0},
+ {HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
+ {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
+ {HFS_HDR_AFPI, offsetof(struct hfs_dbl_hdr, fileinfo), 4},
+ {HFS_HDR_DID, offsetof(struct hfs_dbl_hdr, cnid), 4},
+ {HFS_HDR_SNAME, offsetof(struct hfs_dbl_hdr, short_name), ~0},
+ {HFS_HDR_PRODOSI, offsetof(struct hfs_dbl_hdr, prodosi), 8},
+ {HFS_HDR_RSRC, HFS_NAT_HDR_LEN, ~0}
+ },
+ { /* order[] */
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]
X }
X };
X
@@ -124,18 +164,18 @@
X __constant_htonl(HFS_HDR_VERSION_1), /* version */
X 5, /* entries */
X { /* descr[] */
+ {HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name), ~0},
+ {HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment), 0},
+ {HFS_HDR_OLDI, offsetof(struct hfs_dbl_hdr, create_time), 16},
+ {HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo), 32},
X {HFS_HDR_RSRC, HFS_NAT_HDR_LEN, ~0},
- {HFS_HDR_FNAME, offsetof(struct hfs_nat_hdr, real_name), ~0},
- {HFS_HDR_COMNT, offsetof(struct hfs_nat_hdr, comment), 0},
- {HFS_HDR_OLDI, offsetof(struct hfs_nat_hdr, create_time), 16},
- {HFS_HDR_FINFO, offsetof(struct hfs_nat_hdr, finderinfo), 32},
X },
X { /* order[] */
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
X (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
X (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
X (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
- (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
- (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
+ (struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]
X }
X };
X
@@ -187,6 +227,7 @@
X length = entry->key.CName.Len;
X break;
X
+ case HFS_HDR_SNAME:
X default:
X length = 0;
X }
@@ -456,6 +497,8 @@
X case HFS_HDR_DATES:
X get_dates(entry, inode, (hfs_u32 *)tmp);
X if (descr->id == HFS_HDR_DATES) {
+ /* XXX: access date. hfsplus actually
+ has this. */
X memcpy(tmp + 12, tmp + 4, 4);
X } else if ((entry->type == HFS_CDR_FIL) &&


X (entry->u.file.flags & HFS_FIL_LOCK)) {

@@ -472,6 +515,31 @@


X limit = 32;
X break;
X
+ case HFS_HDR_AFPI:

+ /* XXX: this needs to do more mac->afp mappings */


+ hfs_put_ns(0, tmp);
+ if ((entry->type == HFS_CDR_FIL) &&
+ (entry->u.file.flags & HFS_FIL_LOCK)) {
+ hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
+ } else {
+ hfs_put_ns(0, tmp + 2);
+ }
+ p = tmp;
+ limit = 4;

+ break;
+


+ case HFS_HDR_PRODOSI:
+ /* XXX: this needs to do mac->prodos translations */
+ memset(tmp, 0, 8);
+#if 0
+ hfs_put_ns(0, tmp); /* access */
+ hfs_put_ns(0, tmp); /* type */
+ hfs_put_nl(0, tmp); /* aux type */
+#endif
+ p = tmp;
+ limit = 8;
+ break;
+
X case HFS_HDR_MACI:
X hfs_put_ns(0, tmp);
X if (entry->type == HFS_CDR_FIL) {

SHAR_EOF
true || echo 'restore of patch-2.2.9 failed'
fi

echo 'End of part 2'
echo 'File patch-2.2.9 is continued in part 3'
echo 3 > _shar_seq_.tmp

Reply all
Reply to author
Forward
0 new messages