Home | History | Annotate | Line # | Download | only in libsa
      1 /*	$NetBSD: sun3x.c,v 1.14 2020/06/20 18:46:14 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jeremy Cooper and Gordon Ross
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Standalone functions specific to the Sun3X.
     34  */
     35 
     36 #define _SUN3X_ XXX
     37 
     38 #include <sys/param.h>
     39 #include <machine/mon.h>
     40 
     41 #include <stand.h>
     42 
     43 #include "libsa.h"
     44 #include "dvma.h"
     45 #include "saio.h"	/* enum MAPTYPES */
     46 
     47 #include <arch/sun3/include/pte3x.h>
     48 #include <arch/sun3/sun3x/iommu.h>
     49 #include <arch/sun3/sun3x/vme.h>
     50 
     51 /* Names, names... */
     52 #define	MON_LOMEM_BASE	0
     53 #define	MON_LOMEM_SIZE	0x400000
     54 #define MON_LOMEM_END	(MON_LOMEM_BASE+MON_LOMEM_SIZE)
     55 #define MON_KDB_BASE	SUN3X_MON_KDB_BASE
     56 #define MON_KDB_SIZE	SUN3X_MON_KDB_SIZE
     57 #define MON_KDB_END 	(MON_KDB_BASE+MON_KDB_SIZE)
     58 #define MON_DVMA_BASE	SUN3X_MON_DVMA_BASE
     59 #define MON_DVMA_SIZE	SUN3X_MON_DVMA_SIZE
     60 
     61 static void mmu_atc_flush(vaddr_t);
     62 static void set_iommupte(vaddr_t, paddr_t);
     63 
     64 #ifdef	DEBUG_PROM
     65 static u_int	sun3x_get_pte(vaddr_t);
     66 #endif
     67 static void	sun3x_set_pte(vaddr_t, paddr_t);
     68 static void	dvma3x_init(void);
     69 static char *	dvma3x_alloc(int);
     70 static void	dvma3x_free(char *, int);
     71 static char *	dvma3x_mapin(char *, int);
     72 static void	dvma3x_mapout(char *, int);
     73 static char *	dev3x_mapin(int, u_long, int);
     74 
     75 struct mapinfo {
     76 	int maptype;
     77 	u_int base;
     78 	u_int mask;
     79 };
     80 
     81 struct mapinfo
     82 sun3x_mapinfo[MAP__NTYPES] = {
     83 	/* On-board memory, I/O */
     84 	{ MAP_MAINMEM,   0, ~0 },
     85 	{ MAP_OBIO,      0, ~0 },
     86 	/* Multibus adapter (A24,A16) */
     87 	{ MAP_MBMEM,     VME24D16_BASE, VME24_MASK },
     88 	{ MAP_MBIO,      VME16D16_BASE, VME16_MASK },
     89 	/* VME A16 */
     90 	{ MAP_VME16A16D, VME16D16_BASE, VME16_MASK },
     91 	{ MAP_VME16A32D, VME16D32_BASE, VME16_MASK },
     92 	/* VME A24 */
     93 	{ MAP_VME24A16D, VME24D16_BASE, VME24_MASK },
     94 	{ MAP_VME24A32D, VME24D32_BASE, VME24_MASK },
     95 	/* VME A32 */
     96 	{ MAP_VME32A16D, VME32D16_BASE, VME32_MASK },
     97 	{ MAP_VME32A32D, VME32D32_BASE, VME32_MASK },
     98 };
     99 
    100 /* The virtual address we will use for PROM device mappings. */
    101 u_int sun3x_devmap = MON_KDB_BASE;
    102 
    103 static char *
    104 dev3x_mapin(int maptype, u_long physaddr, int length)
    105 {
    106 	u_int i, pa, pte, pgva, va;
    107 
    108 	if ((sun3x_devmap + length) > (MON_KDB_BASE + MON_KDB_SIZE))
    109 		panic("dev3x_mapin: length=%d", length);
    110 
    111 	for (i = 0; i < MAP__NTYPES; i++)
    112 		if (sun3x_mapinfo[i].maptype == maptype)
    113 			goto found;
    114 	panic("dev3x_mapin: bad maptype");
    115 found:
    116 
    117 	if (physaddr & ~(sun3x_mapinfo[i].mask))
    118 		panic("dev3x_mapin: bad address");
    119 	pa = sun3x_mapinfo[i].base + physaddr;
    120 
    121 	pte = pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI;
    122 
    123 	va = pgva = sun3x_devmap;
    124 	do {
    125 		sun3x_set_pte(pgva, pte);
    126 		pgva += NBPG;
    127 		pte += NBPG;
    128 		length -= NBPG;
    129 	} while (length > 0);
    130 	sun3x_devmap = pgva;
    131 	va += (physaddr & PGOFSET);
    132 
    133 #ifdef	DEBUG_PROM
    134 	if (debug)
    135 		printf("dev3x_mapin: va=0x%x pte=0x%x\n",
    136 			   va, sun3x_get_pte(va));
    137 #endif
    138 	return ((char*)va);
    139 }
    140 
    141 /*****************************************************************
    142  * DVMA support
    143  */
    144 
    145 #define SA_MIN_VA	0x200000
    146 #define SA_MAX_VA	(SA_MIN_VA + MON_DVMA_SIZE - (8 * NBPG))
    147 
    148 #define	MON_DVMA_MAPLEN	(MON_DVMA_SIZE - NBPG)
    149 
    150 /* This points to the end of the free DVMA space. */
    151 u_int dvma3x_end = MON_DVMA_BASE + MON_DVMA_MAPLEN;
    152 
    153 static void
    154 dvma3x_init(void)
    155 {
    156 	u_int va, pa;
    157 
    158 	pa = SA_MIN_VA;
    159 	va = MON_DVMA_BASE;
    160 
    161 	while (pa < SA_MAX_VA) {
    162 		sun3x_set_pte(va, pa | MMU_DT_PAGE | MMU_SHORT_PTE_CI);
    163 		set_iommupte(va, pa | IOMMU_PDE_DT_VALID | IOMMU_PDE_CI);
    164 		va += NBPG;
    165 		pa += NBPG;
    166 	}
    167 }
    168 
    169 /* Convert a local address to a DVMA address. */
    170 char *
    171 dvma3x_mapin(char *addr, int len)
    172 {
    173 	int va = (int)addr;
    174 
    175 	/* Make sure the address is in the DVMA map. */
    176 	if ((va < SA_MIN_VA) || (va >= SA_MAX_VA))
    177 		panic("dvma3x_mapin");
    178 
    179 	va -= SA_MIN_VA;
    180 	va += MON_DVMA_BASE;
    181 
    182 	return ((char *) va);
    183 }
    184 
    185 /* Convert a DVMA address to a local address. */
    186 static void
    187 dvma3x_mapout(char *addr, int len)
    188 {
    189 	int va = (int)addr;
    190 
    191 	/* Make sure the address is in the DVMA map. */
    192 	if ((va < MON_DVMA_BASE) ||
    193 		(va >= (MON_DVMA_BASE + MON_DVMA_MAPLEN)))
    194 		panic("dvma3x_mapout");
    195 }
    196 
    197 static char *
    198 dvma3x_alloc(int len)
    199 {
    200 	len = m68k_round_page(len);
    201 	dvma3x_end -= len;
    202 	return((char *)dvma3x_end);
    203 }
    204 
    205 static void
    206 dvma3x_free(char *dvma, int len)
    207 {
    208 	/* not worth the trouble */
    209 }
    210 
    211 /*****************************************************************
    212  * MMU (and I/O MMU) support
    213  */
    214 
    215 #ifdef	DEBUG_PROM
    216 static u_int
    217 sun3x_get_pte(vaddr_t va)
    218 {
    219 	u_int	pn;
    220 	mmu_short_pte_t *tbl;
    221 
    222 	if (va >= MON_LOMEM_BASE && va < MON_LOMEM_END) {
    223 		tbl = (mmu_short_pte_t *) *romVectorPtr->lomemptaddr;
    224 	} else if (va >= MON_KDB_BASE && va < MON_KDB_END) {
    225 		va -= MON_KDB_BASE;
    226 		tbl = (mmu_short_pte_t *) *romVectorPtr->monptaddr;
    227 	} else if (va >= MON_DVMA_BASE) {
    228 		va -= MON_DVMA_BASE;
    229 		tbl = (mmu_short_pte_t *) *romVectorPtr->shadowpteaddr;
    230 	} else {
    231 		return 0;
    232 	}
    233 
    234 	/* Calculate the page number within the selected table. */
    235 	pn = (va >> MMU_PAGE_SHIFT);
    236 	/* Extract the PTE from the table. */
    237 	return tbl[pn].attr.raw;
    238 }
    239 #endif
    240 
    241 static void
    242 sun3x_set_pte(vaddr_t va, paddr_t pa)
    243 {
    244 	u_int	pn;
    245 	mmu_short_pte_t *tbl;
    246 
    247 	if (va >= MON_LOMEM_BASE && va < (MON_LOMEM_BASE + MON_LOMEM_SIZE)) {
    248 		/*
    249 		 * Main memory range.
    250 		 */
    251 		tbl = (mmu_short_pte_t *) *romVectorPtr->lomemptaddr;
    252 	} else if (va >= MON_KDB_BASE && va < (MON_KDB_BASE + MON_KDB_SIZE)) {
    253 		/*
    254 		 * Kernel Debugger range.
    255 		 */
    256 		va -= MON_KDB_BASE;
    257 		tbl = (mmu_short_pte_t *) *romVectorPtr->monptaddr;
    258 	} else if (va >= MON_DVMA_BASE) {
    259 		/*
    260 		 * DVMA range.
    261 		 */
    262 		va -= MON_DVMA_BASE;
    263 		tbl = (mmu_short_pte_t *) *romVectorPtr->shadowpteaddr;
    264 	} else {
    265 		/* invalid range */
    266 		return;
    267 	}
    268 
    269 	/* Calculate the page number within the selected table. */
    270 	pn = (va >> MMU_PAGE_SHIFT);
    271 	/* Enter the PTE into the table. */
    272 	tbl[pn].attr.raw = pa;
    273 	/* Flush the ATC of any cached entries for the va. */
    274 	mmu_atc_flush(va);
    275 }
    276 
    277 static void
    278 mmu_atc_flush(vaddr_t va)
    279 {
    280 
    281 	__asm volatile ("pflush	#0,#0,%0@" : : "a" (va));
    282 }
    283 
    284 static void
    285 set_iommupte(vaddr_t va, paddr_t pa)
    286 {
    287 	iommu_pde_t *iommu_va;
    288 	int pn;
    289 
    290 	iommu_va = (iommu_pde_t *) *romVectorPtr->dvmaptaddr;
    291 
    292 	/* Adjust the virtual address into an offset within the DVMA map. */
    293 	va -= MON_DVMA_BASE;
    294 
    295 	/* Convert the slave address into a page index. */
    296 	pn = IOMMU_BTOP(va);
    297 
    298 	iommu_va[pn].addr.raw = pa;
    299 }
    300 
    301 /*****************************************************************
    302  * Init our function pointers, etc.
    303  */
    304 
    305 void
    306 sun3x_init(void)
    307 {
    308 
    309 	/* Set the function pointers. */
    310 	dev_mapin_p   = dev3x_mapin;
    311 	dvma_alloc_p  = dvma3x_alloc;
    312 	dvma_free_p   = dvma3x_free;
    313 	dvma_mapin_p  = dvma3x_mapin;
    314 	dvma_mapout_p = dvma3x_mapout;
    315 
    316 	dvma3x_init();
    317 }
    318