Linux Audio

Check our new training course

Loading...
v6.2
  1/*
  2 * linux/arch/m68k/mm/sun3kmap.c
  3 *
  4 * Copyright (C) 2002 Sam Creasey <sammy@sammy.net>
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file COPYING in the main directory of this archive
  8 * for more details.
  9 */
 10
 11#include <linux/module.h>
 12#include <linux/types.h>
 13#include <linux/kernel.h>
 14#include <linux/mm.h>
 15#include <linux/vmalloc.h>
 16
 17#include <asm/page.h>
 
 18#include <asm/io.h>
 19#include <asm/sun3mmu.h>
 20
 21#undef SUN3_KMAP_DEBUG
 22
 23#ifdef SUN3_KMAP_DEBUG
 24extern void print_pte_vaddr(unsigned long vaddr);
 25#endif
 26
 27extern void mmu_emu_map_pmeg (int context, int vaddr);
 28
 29static inline void do_page_mapin(unsigned long phys, unsigned long virt,
 30				 unsigned long type)
 31{
 32	unsigned long pte;
 33	pte_t ptep;
 34
 35	ptep = pfn_pte(phys >> PAGE_SHIFT, PAGE_KERNEL);
 36	pte = pte_val(ptep);
 37	pte |= type;
 38
 39	sun3_put_pte(virt, pte);
 40
 41#ifdef SUN3_KMAP_DEBUG
 42	pr_info("mapin:");
 43	print_pte_vaddr(virt);
 44#endif
 45
 46}
 47
 48static inline void do_pmeg_mapin(unsigned long phys, unsigned long virt,
 49				 unsigned long type, int pages)
 50{
 51
 52	if(sun3_get_segmap(virt & ~SUN3_PMEG_MASK) == SUN3_INVALID_PMEG)
 53		mmu_emu_map_pmeg(sun3_get_context(), virt);
 54
 55	while(pages) {
 56		do_page_mapin(phys, virt, type);
 57		phys += PAGE_SIZE;
 58		virt += PAGE_SIZE;
 59		pages--;
 60	}
 61}
 62
 63void __iomem *sun3_ioremap(unsigned long phys, unsigned long size,
 64		   unsigned long type)
 65{
 66	struct vm_struct *area;
 67	unsigned long offset, virt, ret;
 68	int pages;
 69
 70	if(!size)
 71		return NULL;
 72
 73	/* page align */
 74	offset = phys & (PAGE_SIZE-1);
 75	phys &= ~(PAGE_SIZE-1);
 76
 77	size += offset;
 78	size = PAGE_ALIGN(size);
 79	if((area = get_vm_area(size, VM_IOREMAP)) == NULL)
 80		return NULL;
 81
 82#ifdef SUN3_KMAP_DEBUG
 83	pr_info("ioremap: got virt %p size %lx(%lx)\n", area->addr, size,
 84		area->size);
 85#endif
 86
 87	pages = size / PAGE_SIZE;
 88	virt = (unsigned long)area->addr;
 89	ret = virt + offset;
 90
 91	while(pages) {
 92		int seg_pages;
 93
 94		seg_pages = (SUN3_PMEG_SIZE - (virt & SUN3_PMEG_MASK)) / PAGE_SIZE;
 95		if(seg_pages > pages)
 96			seg_pages = pages;
 97
 98		do_pmeg_mapin(phys, virt, type, seg_pages);
 99
100		pages -= seg_pages;
101		phys += seg_pages * PAGE_SIZE;
102		virt += seg_pages * PAGE_SIZE;
103	}
104
105	return (void __iomem *)ret;
106
107}
108EXPORT_SYMBOL(sun3_ioremap);
109
110
111void __iomem *__ioremap(unsigned long phys, unsigned long size, int cache)
112{
113
114	return sun3_ioremap(phys, size, SUN3_PAGE_TYPE_IO);
115
116}
117EXPORT_SYMBOL(__ioremap);
118
119void iounmap(void __iomem *addr)
120{
121	vfree((void *)(PAGE_MASK & (unsigned long)addr));
122}
123EXPORT_SYMBOL(iounmap);
124
125/* sun3_map_test(addr, val) -- Reads a byte from addr, storing to val,
126 * trapping the potential read fault.  Returns 0 if the access faulted,
127 * 1 on success.
128 *
129 * This function is primarily used to check addresses on the VME bus.
130 *
131 * Mucking with the page fault handler seems a little hackish to me, but
132 * SunOS, NetBSD, and Mach all implemented this check in such a manner,
133 * so I figure we're allowed.
134 */
135int sun3_map_test(unsigned long addr, char *val)
136{
137	int ret = 0;
138
139	__asm__ __volatile__
140		(".globl _sun3_map_test_start\n"
141		 "_sun3_map_test_start:\n"
142		 "1: moveb (%2), (%0)\n"
143		 "   moveq #1, %1\n"
144		 "2:\n"
145		 ".section .fixup,\"ax\"\n"
146		 ".even\n"
147		 "3: moveq #0, %1\n"
148		 "   jmp 2b\n"
149		 ".previous\n"
150		 ".section __ex_table,\"a\"\n"
151		 ".align 4\n"
152		 ".long 1b,3b\n"
153		 ".previous\n"
154		 ".globl _sun3_map_test_end\n"
155		 "_sun3_map_test_end:\n"
156		 : "=a"(val), "=r"(ret)
157		 : "a"(addr));
158
159	return ret;
160}
161EXPORT_SYMBOL(sun3_map_test);
v5.4
  1/*
  2 * linux/arch/m68k/mm/sun3kmap.c
  3 *
  4 * Copyright (C) 2002 Sam Creasey <sammy@sammy.net>
  5 *
  6 * This file is subject to the terms and conditions of the GNU General Public
  7 * License.  See the file COPYING in the main directory of this archive
  8 * for more details.
  9 */
 10
 11#include <linux/module.h>
 12#include <linux/types.h>
 13#include <linux/kernel.h>
 14#include <linux/mm.h>
 15#include <linux/vmalloc.h>
 16
 17#include <asm/page.h>
 18#include <asm/pgtable.h>
 19#include <asm/io.h>
 20#include <asm/sun3mmu.h>
 21
 22#undef SUN3_KMAP_DEBUG
 23
 24#ifdef SUN3_KMAP_DEBUG
 25extern void print_pte_vaddr(unsigned long vaddr);
 26#endif
 27
 28extern void mmu_emu_map_pmeg (int context, int vaddr);
 29
 30static inline void do_page_mapin(unsigned long phys, unsigned long virt,
 31				 unsigned long type)
 32{
 33	unsigned long pte;
 34	pte_t ptep;
 35
 36	ptep = pfn_pte(phys >> PAGE_SHIFT, PAGE_KERNEL);
 37	pte = pte_val(ptep);
 38	pte |= type;
 39
 40	sun3_put_pte(virt, pte);
 41
 42#ifdef SUN3_KMAP_DEBUG
 43	pr_info("mapin:");
 44	print_pte_vaddr(virt);
 45#endif
 46
 47}
 48
 49static inline void do_pmeg_mapin(unsigned long phys, unsigned long virt,
 50				 unsigned long type, int pages)
 51{
 52
 53	if(sun3_get_segmap(virt & ~SUN3_PMEG_MASK) == SUN3_INVALID_PMEG)
 54		mmu_emu_map_pmeg(sun3_get_context(), virt);
 55
 56	while(pages) {
 57		do_page_mapin(phys, virt, type);
 58		phys += PAGE_SIZE;
 59		virt += PAGE_SIZE;
 60		pages--;
 61	}
 62}
 63
 64void __iomem *sun3_ioremap(unsigned long phys, unsigned long size,
 65		   unsigned long type)
 66{
 67	struct vm_struct *area;
 68	unsigned long offset, virt, ret;
 69	int pages;
 70
 71	if(!size)
 72		return NULL;
 73
 74	/* page align */
 75	offset = phys & (PAGE_SIZE-1);
 76	phys &= ~(PAGE_SIZE-1);
 77
 78	size += offset;
 79	size = PAGE_ALIGN(size);
 80	if((area = get_vm_area(size, VM_IOREMAP)) == NULL)
 81		return NULL;
 82
 83#ifdef SUN3_KMAP_DEBUG
 84	pr_info("ioremap: got virt %p size %lx(%lx)\n", area->addr, size,
 85		area->size);
 86#endif
 87
 88	pages = size / PAGE_SIZE;
 89	virt = (unsigned long)area->addr;
 90	ret = virt + offset;
 91
 92	while(pages) {
 93		int seg_pages;
 94
 95		seg_pages = (SUN3_PMEG_SIZE - (virt & SUN3_PMEG_MASK)) / PAGE_SIZE;
 96		if(seg_pages > pages)
 97			seg_pages = pages;
 98
 99		do_pmeg_mapin(phys, virt, type, seg_pages);
100
101		pages -= seg_pages;
102		phys += seg_pages * PAGE_SIZE;
103		virt += seg_pages * PAGE_SIZE;
104	}
105
106	return (void __iomem *)ret;
107
108}
109EXPORT_SYMBOL(sun3_ioremap);
110
111
112void __iomem *__ioremap(unsigned long phys, unsigned long size, int cache)
113{
114
115	return sun3_ioremap(phys, size, SUN3_PAGE_TYPE_IO);
116
117}
118EXPORT_SYMBOL(__ioremap);
119
120void iounmap(void __iomem *addr)
121{
122	vfree((void *)(PAGE_MASK & (unsigned long)addr));
123}
124EXPORT_SYMBOL(iounmap);
125
126/* sun3_map_test(addr, val) -- Reads a byte from addr, storing to val,
127 * trapping the potential read fault.  Returns 0 if the access faulted,
128 * 1 on success.
129 *
130 * This function is primarily used to check addresses on the VME bus.
131 *
132 * Mucking with the page fault handler seems a little hackish to me, but
133 * SunOS, NetBSD, and Mach all implemented this check in such a manner,
134 * so I figure we're allowed.
135 */
136int sun3_map_test(unsigned long addr, char *val)
137{
138	int ret = 0;
139
140	__asm__ __volatile__
141		(".globl _sun3_map_test_start\n"
142		 "_sun3_map_test_start:\n"
143		 "1: moveb (%2), (%0)\n"
144		 "   moveq #1, %1\n"
145		 "2:\n"
146		 ".section .fixup,\"ax\"\n"
147		 ".even\n"
148		 "3: moveq #0, %1\n"
149		 "   jmp 2b\n"
150		 ".previous\n"
151		 ".section __ex_table,\"a\"\n"
152		 ".align 4\n"
153		 ".long 1b,3b\n"
154		 ".previous\n"
155		 ".globl _sun3_map_test_end\n"
156		 "_sun3_map_test_end:\n"
157		 : "=a"(val), "=r"(ret)
158		 : "a"(addr));
159
160	return ret;
161}
162EXPORT_SYMBOL(sun3_map_test);