1/*-
2 * Copyright (c) 2008 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Coyote Point Systems, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*-
31 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
32 * All rights reserved.
33 *
34 * NBMK Encryption Technologies provides no support of any kind for
35 * this software.  Questions or concerns about it may be addressed to
36 * the members of the relevant open-source community at
37 * <tech-crypto@netbsd.org>.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions are
41 * met:
42 *
43 * 1. Redistributions of source code must retain the above copyright
44 *    notice, this list of conditions and the following disclaimer.
45 *
46 * 2. Redistributions in binary form must reproduce the above
47 *    copyright notice, this list of conditions and the following
48 *    disclaimer in the documentation and/or other materials provided
49 *    with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63
64static char const n8_id[] = "$Id: n8_memory_bsd.c,v 1.4 2009/05/12 08:23:01 cegger Exp $";
65/*****************************************************************************/
66/** @file n8_memory_bsd.c
67 *  @brief NetOctaveMemory Services - FreeBSD-specific support routines.
68 *
69 * This file contains all FreeBSD-specific support routines for the large
70 * allocation services used by the driver. The cross-platform memory management
71 * code uses these routines.
72 *****************************************************************************/
73
74/*****************************************************************************
75 * Revision history:
76 * 05/12/03 brr   Modified user pools to take advantage of the support for
77 *                multiple memory banks.
78 * 05/08/03 brr   Dimension arrays to allow of multiple user pools.
79 * 05/05/03 brr   Moved memory functions here from helper.c.
80 * 04/22/03 brr   Change wait flag passed to contigmalloc to M_WAITOK.
81 * 04/22/03 brr   Clean up comments & add debug statements.
82 *                Removed redundant parameter from n8_FreeLargeAllocation.
83 * 04/21/03 brr   Added support for multiple memory banks.
84 * 11/01/02 brr   Correctly deallocate memory resources.
85 * 10/25/02 brr   Temporarily comment out call to contigfree().
86 * 10/22/02 brr   File created.
87 ****************************************************************************/
88/** @defgroup NSP2000Driver NSP2000 Device Driver - FreeBSD version.
89 */
90
91
92#include "helper.h"
93#include "n8_malloc_common.h"
94#include "n8_OS_intf.h"
95#include "n8_memory.h"
96#include "n8_driver_parms.h"
97#include <uvm/uvm.h>
98#include <machine/pmap.h>
99#include "nsp.h"
100
101extern NspInstance_t NSPDeviceTable_g[];
102static unsigned long  MemBaseAddress_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
103static unsigned long  MemTopAddress_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
104static unsigned long  MemSize_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
105static          void *BasePointer_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
106static bus_dmamap_t   DmaMap_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
107static int            Rseg_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
108static bus_dma_segment_t Seg_g[N8_MEMBANK_MAX + DEF_USER_POOL_BANKS];
109
110/*****************************************************************************
111 * n8_vmalloc
112 *****************************************************************************/
113/** @ingroup NSP2000Driver
114 * @brief n8_memory - Allocates and clears a buffer.
115 *
116 * This routine abstracts memory allocation for the functions in the driver.
117 *
118 * @param size   RO:  Specifies the desired allocation size
119 *
120 * @return
121 *    Virtual address of the memory allocation, NULL if failed.
122 *
123 *
124 * @par Errors:
125 *    See return section for error information.
126 *****************************************************************************/
127
128void *
129n8_vmalloc(unsigned long size)
130{
131    N8_UmallocHdr_t *m;
132
133    if (size) {
134	m = malloc(size, M_DEVBUF, M_WAITOK);
135
136	if (m) {
137	    memset(m, 0, sizeof (*m));
138
139	    return m+1;
140	}
141    }
142
143    return 0;
144}
145
146/*****************************************************************************
147 * n8_vfree
148 *****************************************************************************/
149/** @ingroup NSP2000Driver
150 * @brief n8_memory - Frees a buffer allocated by n8_vmalloc.
151 *
152 * This routine abstracts memory allocation for the functions in the driver.
153 *
154 * @param a   RO:  Specifies the address to free.
155 *
156 * @return
157 *    None.
158 *
159 *
160 * @par Errors:
161 *    See return section for error information.
162 *****************************************************************************/
163
164void
165n8_vfree(void *a)
166{
167    N8_UmallocHdr_t *m	= a;
168
169    if (m) {
170	free(m-1, M_DEVBUF);
171    }
172}
173
174/*****************************************************************************
175 * N8_PhysToVirt
176 *****************************************************************************/
177/** @ingroup NSP2000Driver
178 * @brief N8_PhysToVirt - Converts a physical address to it virtual address
179 *
180 * @param phys   RO:  Physical address to convert.
181 *
182 * @return
183 *    Virtual address of phys
184 *
185 *
186 * @par Errors:
187 *****************************************************************************/
188
189void *
190N8_PhysToVirt(unsigned long phys)
191{
192    unsigned long offset;
193    int bankIndex = N8_MEMBANK_QUEUE;
194    int ctr;
195    void *virtaddr;
196
197    for (ctr = 0; ctr < (N8_MEMBANK_MAX + DEF_USER_POOL_BANKS); ctr++)
198    {
199       if ((phys >= MemBaseAddress_g[ctr]) &&
200           (phys < MemTopAddress_g[ctr]))
201       {
202	   bankIndex = ctr;
203           break;
204       }
205    }
206    if (ctr >= (N8_MEMBANK_MAX + DEF_USER_POOL_BANKS)) {
207	printf("N8_PhysToVirt(0x%lx) ran out of banks\n", phys);
208    }
209
210    offset = phys - MemBaseAddress_g[bankIndex];
211
212    virtaddr = (void *)(offset + (unsigned long)BasePointer_g[bankIndex]);
213    return virtaddr;
214}
215
216
217
218/*****************************************************************************
219 * N8_VirtToPhys
220 *****************************************************************************/
221/** @ingroup NSP2000Driver
222 * @brief Convert a virtual address to a physical address.
223 *
224 * This routine abstracts the Linux system call to convert a virtual address
225 * to a physical address.
226 *
227 * @param virtaddr   RO:  Specifies the physical address.
228 *
229 * @par Externals:
230 *    N/A
231 *
232 * @return
233 *    Returns the corresponding physical address.
234 *
235 * @par Errors:
236 *    See return section for error information.
237 *****************************************************************************/
238
239unsigned long N8_VirtToPhys(void *virtaddr)
240{
241     paddr_t phys_addr;
242     pmap_extract(pmap_kernel(), (unsigned long)virtaddr, &phys_addr);
243     return phys_addr;
244}
245
246
247/*****************************************************************************
248 * n8_GetLargeAllocation
249 *****************************************************************************/
250/** @ingroup NSP2000Driver
251 * @brief n8_memory - Allocates a large physically contiguous memory range.
252 *
253 * This routine allocates the requested large allocation with a call
254 * to contigmalloc.
255 *
256 * @param bankIndex  RO:  Bank type for the memory allocation.
257 * @param size       RO:  The allocation size.
258 * @param debug      RO:  Dump debug information.
259 *
260 * @return
261 *    Physical address of the memory pool. NULL if failed.
262 *
263 *
264 * @par Errors:
265 *    See return section for error information.
266 *****************************************************************************/
267
268unsigned long
269n8_GetLargeAllocation(N8_MemoryType_t bankIndex,
270		      unsigned long size, unsigned char debug)
271{
272
273	NspInstance_t	*nip  = &NSPDeviceTable_g[0];	/* can only attach once */
274	struct nsp_softc *sc = device_private(nip->dev);
275
276	bus_dma_segment_t seg;
277	int rseg;
278	void *kva = NULL;
279
280#if 0
281	/* Replacement for: */
282	m = contigmalloc(size, M_DEVBUF, M_WAITOK,
283		     0, 		/* lower acceptible phys addr	*/
284		     0xffffffff,	/* upper acceptible phys addr	*/
285		     PAGE_SIZE,		/* alignment			*/
286		     0);		/* boundary			*/
287#endif
288	if (bus_dmamem_alloc(sc->dma_tag, size, PAGE_SIZE, 0,
289	    &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
290		printf("%s: can't alloc DMA buffer\n",
291		    device_xname(&sc->device));
292		return 0;
293        }
294	if (bus_dmamem_map(sc->dma_tag, &seg, rseg, size, &kva,
295	    BUS_DMA_NOWAIT)) {
296		printf("%s: can't map DMA buffers (%lu bytes)\n",
297		    device_xname(&sc->device), size);
298		bus_dmamem_free(sc->dma_tag, &seg, rseg);
299		return 0;
300	}
301	if (bus_dmamap_create(sc->dma_tag, size, 1,
302	    size, 0, BUS_DMA_NOWAIT, &DmaMap_g[bankIndex])) {
303		printf("%s: can't create DMA map\n", device_xname(&sc->device));
304		bus_dmamem_unmap(sc->dma_tag, kva, size);
305		bus_dmamem_free(sc->dma_tag, &seg, rseg);
306		return 0;
307	}
308	if (bus_dmamap_load(sc->dma_tag, DmaMap_g[bankIndex], kva, size,
309	    NULL, BUS_DMA_NOWAIT)) {
310		printf("%s: can't load DMA map\n", device_xname(&sc->device));
311		bus_dmamap_destroy(sc->dma_tag, DmaMap_g[bankIndex]);
312		bus_dmamem_unmap(sc->dma_tag, kva, size);
313		bus_dmamem_free(sc->dma_tag, &seg, rseg);
314		return 0;
315	}
316	if (kva) {
317	    /* memset(kva, 0, size) */
318	    BasePointer_g[bankIndex]    = kva;
319	    MemSize_g[bankIndex]        = size;
320	    Seg_g[bankIndex]            = seg;
321	    Rseg_g[bankIndex]           = rseg;
322	    MemBaseAddress_g[bankIndex] = vtophys((u_int)kva);
323	    MemTopAddress_g[bankIndex]  = MemBaseAddress_g[bankIndex] + size;
324	}
325
326	if (debug)
327	{
328	   printf("n8_GetLargeAllocation: %p (0x%08lx) allocated for bankIndex %d\n",
329		   BasePointer_g[bankIndex], MemBaseAddress_g[bankIndex], bankIndex);
330	}
331
332	return MemBaseAddress_g[bankIndex];
333}
334
335/*****************************************************************************
336 * n8_FreeLargeAllocation
337 *****************************************************************************/
338/** @ingroup NSP2000Driver
339 * @brief n8_memory - Releases a large physically contiguous memory range.
340 *
341 * This routine deallocates the large allocation with a call to contigfree.
342 *
343 * @param bankIndex  RO:  Bank type for the memory free.
344 * @param debug      RO:  Dump debug information.
345 *
346 * @return
347 *    N/A
348 *
349 * @par Errors:
350 *    See return section for error information.
351 *****************************************************************************/
352
353
354void
355n8_FreeLargeAllocation(N8_MemoryType_t bankIndex,
356		       unsigned char   debug)
357{
358	NspInstance_t	*nip  = &NSPDeviceTable_g[0];	/* can only attach once */
359	struct nsp_softc *sc = device_private(nip->dev);
360
361        printf("n8_FreeLargeAllocation: freeing %p for bankIndex %d\n",
362		  BasePointer_g[bankIndex], bankIndex);
363	if (debug) {
364	  printf("n8_FreeLargeAllocation: freeing %p for bankIndex %d\n",
365		  BasePointer_g[bankIndex], bankIndex);
366	}
367
368	if (BasePointer_g[bankIndex]) {
369	    /* contigfree(BasePointer_g[bankIndex], MemSize_g[bankIndex], M_DEVBUF); */
370	    printf("n8_FreeLargeAllocation: bus_dmamap_unload(bank %d) (kva=%p)\n",
371		    bankIndex, BasePointer_g[bankIndex]);
372	    bus_dmamap_unload(sc->dma_tag, DmaMap_g[bankIndex]);
373	    printf("n8_FreeLargeAllocation: bus_dmamap_destroy()\n");
374	    bus_dmamap_destroy(sc->dma_tag, DmaMap_g[bankIndex]);
375	    printf("n8_FreeLargeAllocation: bus_dmamap_unmap()\n");
376	    bus_dmamem_unmap(sc->dma_tag, BasePointer_g[bankIndex],
377		    MemSize_g[bankIndex]);
378	    printf("n8_FreeLargeAllocation: bus_dmamap_unmap()\n");
379	    bus_dmamem_free(sc->dma_tag, &Seg_g[bankIndex], Rseg_g[bankIndex]);
380	}
381	BasePointer_g[bankIndex] = NULL;
382}
383
384/*****************************************************************************
385 * n8_bounds_check
386 *****************************************************************************/
387/** @ingroup NSP2000Driver
388 * @brief n8_bounds_check - Validates address passed to mmap
389 *
390 * This routine validates address passed to mmap
391 *
392 * @param phys       RO:  Address of mmap request.
393 *
394 * @return
395 *    N/A
396 *
397 * @par Errors:
398 *    See return section for error information.
399 *****************************************************************************/
400
401int
402n8_bounds_check(unsigned long phys)
403{
404    int ctr;
405
406    for (ctr = 1; ctr < (N8_MEMBANK_MAX + DEF_USER_POOL_BANKS); ctr++)
407    {
408        if ((MemBaseAddress_g[ctr] <= phys) &&
409            (phys < (MemBaseAddress_g[ctr] + MemSize_g[ctr])))
410        {
411            /* Valid mmap request */
412            return 1;
413        }
414    }
415
416    return 0;
417}
418
419
420