summaryrefslogtreecommitdiffstats
path: root/drivers/sbus/char/cgsix.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-07-20 14:56:40 +0000
commite308faf24f68e262d92d294a01ddca7a17e76762 (patch)
tree22c47cb315811834861f013067878ff664e95abd /drivers/sbus/char/cgsix.c
parent30c6397ce63178fcb3e7963ac247f0a03132aca9 (diff)
Sync with Linux 2.1.46.
Diffstat (limited to 'drivers/sbus/char/cgsix.c')
-rw-r--r--drivers/sbus/char/cgsix.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/sbus/char/cgsix.c b/drivers/sbus/char/cgsix.c
index e53fcf09e..825d49b4a 100644
--- a/drivers/sbus/char/cgsix.c
+++ b/drivers/sbus/char/cgsix.c
@@ -1,4 +1,4 @@
-/* $Id: cgsix.c,v 1.30 1997/06/04 08:27:28 davem Exp $
+/* $Id: cgsix.c,v 1.35 1997/07/17 02:21:45 davem Exp $
* cgsix.c: cgsix frame buffer driver
*
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -233,12 +233,33 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
long base, fbinfo_t *fb)
{
uint size, page, r, map_size;
- uint map_offset = 0;
-
+ unsigned long map_offset = 0;
+
size = vma->vm_end - vma->vm_start;
if (vma->vm_offset & ~PAGE_MASK)
return -ENXIO;
+#ifdef __sparc_v9__
+ /* Try to align RAM */
+#define ALIGNMENT 0x80000
+ map_offset = vma->vm_offset + size;
+ if (vma->vm_offset <= CG6_RAM && map_offset >= CG6_RAM + fb->type.fb_size) {
+ struct vm_area_struct *vmm = find_vma(current->mm, vma->vm_start);
+ int alignment = ALIGNMENT - ((vma->vm_start + CG6_RAM - vma->vm_offset) & (ALIGNMENT - 1));
+ int sz = 0, fbsz;
+
+ if (alignment == ALIGNMENT) alignment = 0;
+ fbsz = ((fb->type.fb_size + ALIGNMENT - 1) & ~(ALIGNMENT - 1));
+ if (map_offset < CG6_RAM + fbsz)
+ sz = fbsz - map_offset + CG6_RAM;
+ if ((sz || alignment) && (!vmm || vmm->vm_start >= vma->vm_end + sz + alignment)) {
+ vma->vm_start += alignment;
+ vma->vm_end += alignment + sz;
+ }
+ }
+#undef ALIGNMENT
+#endif
+
/* To stop the swapper from even considering these pages */
vma->vm_flags |= FB_MMAP_VM_FLAGS;
@@ -247,7 +268,7 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
switch (vma->vm_offset+page){
case CG6_TEC:
map_size = PAGE_SIZE;
- map_offset = get_phys ((unsigned long)fb->info.cg6.tec);
+ map_offset = get_phys ((unsigned long)fb->info.cg6.tec) & PAGE_MASK;
break;
case CG6_FBC:
map_size = PAGE_SIZE;
@@ -259,18 +280,25 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
break;
case CG6_THC:
map_size = PAGE_SIZE;
- map_offset = get_phys ((unsigned long)fb->info.cg6.thc);
+ map_offset = get_phys ((unsigned long)fb->info.cg6.thc) & PAGE_MASK;
break;
case CG6_BTREGS:
map_size = PAGE_SIZE;
map_offset = get_phys ((unsigned long)fb->info.cg6.bt);
break;
+
+ /* For Ultra, make sure the following two are right.
+ * The above two happen to work out (for example FBC and
+ * TEC will get mapped by one I/O page mapping because
+ * of the 8192 byte page size, same for FHC/THC. -DaveM
+ */
+
case CG6_DHC:
- map_size = PAGE_SIZE * 40;
+ map_size = /* PAGE_SIZE * 40 */ (4096 * 40);
map_offset = get_phys ((unsigned long)fb->info.cg6.dhc);
break;
case CG6_ROM:
- map_size = PAGE_SIZE * 16;
+ map_size = /* PAGE_SIZE * 16 */ (4096 * 16);
map_offset = get_phys ((unsigned long)fb->info.cg6.rom);
break;
case CG6_RAM:
@@ -293,11 +321,12 @@ cg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma,
map_offset,
map_size, vma->vm_page_prot,
fb->space);
- if (r) return -EAGAIN;
+ if (r)
+ return -EAGAIN;
page += map_size;
}
- vma->vm_inode = inode;
- atomic_inc(&inode->i_count);
+
+ vma->vm_dentry = dget(file->f_dentry);
return 0;
}
@@ -449,14 +478,22 @@ __initfunc(void cg6_setup (fbinfo_t *fb, int slot, u32 cg6, int cg6_io))
sizeof (struct bt_regs), "cgsix_dac", cg6_io, 0);
cg6info->fhc = sparc_alloc_io (cg6+CG6_FHC_OFFSET, 0,
sizeof (int), "cgsix_fhc", cg6_io, 0);
+#if PAGE_SHIFT <= 12
cg6info->thc = sparc_alloc_io (cg6+CG6_THC_OFFSET, 0,
sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0);
+#else
+ cg6info->thc = (struct cg6_thc *)(((char *)cg6info->fhc)+0x1000);
+#endif
+ cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
+ 0x1000, "cgsix_fbc", cg6_io, 0);
+#if PAGE_SHIFT <= 12
cg6info->tec = sparc_alloc_io (cg6+CG6_TEC_OFFSET, 0,
sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0);
+#else
+ cg6info->tec = (struct cg6_tec *)(((char *)cg6info->fbc)+0x1000);
+#endif
cg6info->dhc = sparc_alloc_io (cg6+CG6_DHC_OFFSET, 0,
0x40000, "cgsix_dhc", cg6_io, 0);
- cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
- 0x1000, "cgsix_fbc", cg6_io, 0);
cg6info->rom = sparc_alloc_io (cg6+CG6_ROM_OFFSET, 0,
0x10000, "cgsix_rom", cg6_io, 0);
if (!fb->base) {
@@ -477,6 +514,10 @@ __initfunc(void cg6_setup (fbinfo_t *fb, int slot, u32 cg6, int cg6_io))
cg6info->bt->addr = 0x07 << 24;
cg6info->bt->control = 0x00 << 24;
+#ifdef __sparc_v9__
+ printk("VA %016lx ", fb->base);
+#endif
+
printk("TEC Rev %x ",
(cg6info->thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) &
CG6_THC_MISC_REV_MASK);