source: mainline/uspace/lib/usb/src/usbmem.c@ 103a3626

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 103a3626 was 103a3626, checked in by Matus Dekanek <smekideki@…>, 14 years ago

a bit of codelifting, dprintf correctly used in usb hub driver

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2011 Matus Dekanek
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file implementation of special memory management, used mostly in usb stack
33 */
34
35#include <adt/hash_table.h>
36#include <adt/list.h>
37#include <as.h>
38#include <errno.h>
39#include <malloc.h>
40
41#include "usb/usbmem.h"
42
43#define ADDR_BUCKETS 1537
44
45//address translation tables
46static hash_table_t * pa2va_table = NULL;
47static hash_table_t * va2pa_table = NULL;
48
49/**
50 * address translation hashtable item
51 */
52typedef struct{
53 unsigned long addr;
54 unsigned long translation;
55 link_t link;
56
57}addr_node_t;
58
59static hash_index_t addr_hash(unsigned long key[])
60{
61 return (3*key[0]<<4) % ADDR_BUCKETS;
62}
63
64static int addr_compare(unsigned long key[], hash_count_t keys,
65 link_t *item)
66{
67 addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
68 return (addr_node->addr == key[0]);
69}
70
71static void addr_remove_callback(link_t * item)
72{
73 //delete item
74 addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
75 free(addr_node);
76}
77
78
79static hash_table_operations_t addr_devices_ops = {
80 .hash = addr_hash,
81 .compare = addr_compare,
82 .remove_callback = addr_remove_callback
83};
84
85/**
86 * create node for address translation hashtable
87 * @param addr
88 * @param translation
89 * @return
90 */
91static addr_node_t * create_addr_node(void * addr, void * translation){
92 addr_node_t * node = (addr_node_t*)malloc(sizeof(addr_node_t));
93 node->addr = (unsigned long)addr;
94 node->translation = (unsigned long)translation;
95 return node;
96}
97
98/**
99 * allocate size on heap and register it`s pa<->va translation
100 *
101 * If physical address + size is 2GB or higher, nothing is allocated and NULL
102 * is returned.
103 * @param size
104 * @param alignment
105 * @return
106 */
107void * mman_malloc(
108 size_t size,
109 size_t alignment,
110 unsigned long max_physical_address)
111{
112 if (size == 0)
113 return NULL;
114 if (alignment == 0)
115 return NULL;
116 //check if tables were initialized
117 if(!pa2va_table){
118 pa2va_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
119 va2pa_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
120 hash_table_create(pa2va_table, ADDR_BUCKETS, 1,
121 &addr_devices_ops);
122 hash_table_create(va2pa_table, ADDR_BUCKETS, 1,
123 &addr_devices_ops);
124 }
125 //allocate
126 void * vaddr = memalign(alignment, size);
127
128 //get translation
129 void * paddr = NULL;
130 int opResult = as_get_physical_mapping(vaddr,(uintptr_t*)&paddr);
131 if(opResult != EOK){
132 //something went wrong
133 free(vaddr);
134 return NULL;
135 }
136 if((unsigned long)paddr + size > max_physical_address){
137 //unusable address for usb
138 free(vaddr);
139 return NULL;
140 }
141 //store translation
142 addr_node_t * pa2vaNode = create_addr_node(paddr,vaddr);
143 addr_node_t * va2paNode = create_addr_node(vaddr,paddr);
144
145 unsigned long keypaddr = (unsigned long)paddr;
146 unsigned long keyvaddr = (unsigned long)vaddr;
147 hash_table_insert(pa2va_table, (&keypaddr), &pa2vaNode->link);
148 hash_table_insert(va2pa_table, (&keyvaddr), &va2paNode->link);
149 //return
150 return vaddr;
151
152}
153
154/**
155 * get virtual address from physical
156 * @param addr
157 * @return translated virtual address or null
158 */
159void * mman_getVA(void * addr){
160 unsigned long keypaddr = (unsigned long)addr;
161 link_t * link = hash_table_find(pa2va_table, &keypaddr);
162 if(!link) return NULL;
163 addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
164 return (void*)node->translation;
165}
166
167/**
168 * get physical address from virtual
169 * @param addr
170 * @return physical address or null
171 */
172void * mman_getPA(void * addr){
173 unsigned long keyvaddr = (unsigned long)addr;
174 link_t * link = hash_table_find(va2pa_table, &keyvaddr);
175 if(!link) return NULL;
176 addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
177 return (void*)node->translation;
178}
179
180/**
181 * free the address and deregister it from pa<->va translation
182 * @param vaddr if NULL, nothing happens
183 */
184void mman_free(void * vaddr){
185 if(!vaddr)
186 return;
187 //get paddress
188 void * paddr = mman_getPA(vaddr);
189 unsigned long keypaddr = (unsigned long)paddr;
190 unsigned long keyvaddr = (unsigned long)vaddr;
191 //remove mapping
192 hash_table_remove(pa2va_table,&keypaddr, 1);
193 hash_table_remove(va2pa_table,&keyvaddr, 1);
194 //free address
195 free(vaddr);
196}
197
198
199
200/** @}
201 */
Note: See TracBrowser for help on using the repository browser.