patch-2.1.44 linux/drivers/sbus/char/cgsix.c

Next file: linux/drivers/sbus/char/cgthree.c
Previous file: linux/drivers/sbus/char/cgfourteen.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.43/linux/drivers/sbus/char/cgsix.c linux/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.33 1997/07/01 09:12:05 jj Exp $
  * cgsix.c: cgsix frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -233,12 +233,33 @@
 	  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 @@
 		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 @@
 			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:
@@ -449,14 +477,22 @@
 		 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) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov