Commit e49255e0 authored by Geert Uytterhoeven's avatar Geert Uytterhoeven Committed by Linus Torvalds

[PATCH] Sun-3 ioremap()

Add ioremap() support for Sun-3 and modify the Sun-3 LANCE and i82586 OBIO
Ethernet drivers to use it (from Sam Creasey)
parent fbcd20a8
......@@ -7,7 +7,7 @@ obj-y := init.o fault.o extable.o hwtest.o
ifndef CONFIG_SUN3
obj-y += kmap.o memory.o motorola.o
else
obj-y += sun3mmu.o
obj-y += sun3kmap.o sun3mmu.o
endif
......
/*
* linux/arch/m68k/mm/sun3kmap.c
*
* Copyright (C) 2002 Sam Creasey <sammy@sammy.net>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/sun3mmu.h>
#undef SUN3_KMAP_DEBUG
#ifdef SUN3_KMAP_DEBUG
extern void print_pte_vaddr(unsigned long vaddr);
#endif
extern void mmu_emu_map_pmeg (int context, int vaddr);
static inline void do_page_mapin(unsigned long phys, unsigned long virt,
unsigned long type)
{
unsigned long pte;
pte_t ptep;
ptep = pfn_pte(phys >> PAGE_SHIFT, PAGE_KERNEL);
pte = pte_val(ptep);
pte |= type;
sun3_put_pte(virt, pte);
#ifdef SUN3_KMAP_DEBUG
print_pte_vaddr(virt);
#endif
}
static inline void do_pmeg_mapin(unsigned long phys, unsigned long virt,
unsigned long type, int pages)
{
if(sun3_get_segmap(virt & ~SUN3_PMEG_MASK) == SUN3_INVALID_PMEG)
mmu_emu_map_pmeg(sun3_get_context(), virt);
while(pages) {
do_page_mapin(phys, virt, type);
phys += PAGE_SIZE;
virt += PAGE_SIZE;
pages--;
}
}
void *sun3_ioremap(unsigned long phys, unsigned long size,
unsigned long type)
{
struct vm_struct *area;
unsigned long offset, virt, ret;
int pages;
if(!size)
return NULL;
/* page align */
offset = phys & (PAGE_SIZE-1);
phys &= ~(PAGE_SIZE-1);
size += offset;
size = PAGE_ALIGN(size);
if((area = get_vm_area(size, VM_IOREMAP)) == NULL)
return NULL;
#ifdef SUN3_KMAP_DEBUG
printk("ioremap: got virt %p size %lx(%lx)\n",
area->addr, size, area->size);
#endif
pages = size / PAGE_SIZE;
virt = (unsigned long)area->addr;
ret = virt + offset;
while(pages) {
int seg_pages;
seg_pages = (SUN3_PMEG_SIZE - (virt & SUN3_PMEG_MASK)) / PAGE_SIZE;
if(seg_pages > pages)
seg_pages = pages;
do_pmeg_mapin(phys, virt, type, seg_pages);
pages -= seg_pages;
phys += seg_pages * PAGE_SIZE;
virt += seg_pages * PAGE_SIZE;
}
return (void *)ret;
}
void *__ioremap(unsigned long phys, unsigned long size, int cache)
{
return sun3_ioremap(phys, size, SUN3_PAGE_TYPE_IO);
}
void iounmap(void *addr)
{
vfree((void *)(PAGE_MASK & (unsigned long)addr));
}
......@@ -177,7 +177,6 @@ void mmu_emu_init(unsigned long bootmem_end)
pmeg_alloc[sun3_get_segmap(seg)] = 2;
}
}
dvma_init();
......@@ -276,7 +275,7 @@ unsigned long get_free_context(struct mm_struct *mm)
//todo: better allocation scheme? but is extra complexity worthwhile?
//todo: only clear old entries if necessary? how to tell?
static inline void mmu_emu_map_pmeg (int context, int vaddr)
inline void mmu_emu_map_pmeg (int context, int vaddr)
{
static unsigned char curr_pmeg = 128;
int i;
......
......@@ -279,14 +279,14 @@ static void alloc586(struct net_device *dev)
int __init sun3_82586_probe(struct net_device *dev)
{
unsigned long ioaddr, iopte;
unsigned long ioaddr;
static int found = 0;
/* check that this machine has an onboard lance */
/* check that this machine has an onboard 82586 */
switch(idprom->id_machtype) {
case SM_SUN3|SM_3_160:
case SM_SUN3|SM_3_260:
/* these machines have lance */
/* these machines have 82586 */
break;
default:
......@@ -296,22 +296,8 @@ int __init sun3_82586_probe(struct net_device *dev)
if(found)
return -ENODEV;
for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
SUN3_PMEG_SIZE); ioaddr += SUN3_PTE_SIZE) {
iopte = sun3_get_pte(ioaddr);
if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
continue;
if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
IE_OBIO) {
found = 1;
break;
}
}
if(!found)
return 0;
ioaddr = (unsigned long)ioremap(IE_OBIO, PAGE_SIZE);
found = 1;
SET_MODULE_OWNER(dev);
......
......@@ -279,33 +279,16 @@ int __init sun3lance_probe( struct net_device *dev )
static int __init lance_probe( struct net_device *dev)
{
unsigned long ioaddr, iopte;
unsigned long ioaddr;
struct lance_private *lp;
int i;
static int did_version;
int found = 0;
volatile unsigned short *ioaddr_probe;
unsigned short tmp1, tmp2;
#ifdef CONFIG_SUN3
/* LANCE_OBIO can be found within the IO pmeg with some effort */
for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
SUN3_PMEG_SIZE); ioaddr += SUN3_PTE_SIZE) {
iopte = sun3_get_pte(ioaddr);
if(!(iopte & SUN3_PAGE_TYPE_IO)) /* this an io page? */
continue;
if(((iopte & SUN3_PAGE_PGNUM_MASK) << PAGE_SHIFT) ==
LANCE_OBIO) {
found = 1;
break;
}
}
if(!found)
return 0;
ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE);
#else
ioaddr = SUN3X_LANCE;
#endif
......
......@@ -161,6 +161,9 @@ extern __inline__ void sun3_put_context(unsigned char c)
return;
}
extern void *sun3_ioremap(unsigned long phys, unsigned long size,
unsigned long type);
#endif /* !__ASSEMBLY__ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment