diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-07-20 14:56:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-07-20 14:56:40 +0000 |
commit | e308faf24f68e262d92d294a01ddca7a17e76762 (patch) | |
tree | 22c47cb315811834861f013067878ff664e95abd /drivers/sbus/char/cgsix.c | |
parent | 30c6397ce63178fcb3e7963ac247f0a03132aca9 (diff) |
Sync with Linux 2.1.46.
Diffstat (limited to 'drivers/sbus/char/cgsix.c')
-rw-r--r-- | drivers/sbus/char/cgsix.c | 65 |
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); |