1/* 2 * Copyright (c) 2007-2013 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <stdlib.h> 11#include <stdio.h> 12#include <string.h> 13#include <barrelfish/barrelfish.h> 14 15#include <usb/usb.h> 16 17#include <usb_memory.h> 18 19#include "usb_ohci.h" 20#include "usb_ohci_memory.h" 21 22static struct usb_ohci_td *free_tds = NULL; 23static struct usb_ohci_ed *free_eds = NULL; 24 25static struct usb_page *free_pages = NULL; 26 27static struct usb_ohci_hcca *hcca = NULL; 28static usb_paddr_t hcca_phys = 0; 29 30struct usb_ohci_hcca *usb_ohci_hcca_alloc(void) 31{ 32 if (hcca != NULL) { 33 return hcca; 34 } 35 36 // we do not have any free page anymore 37 if (free_pages == NULL) { 38 free_pages = usb_mem_page_alloc(); 39 } 40 41 uint32_t ret_size; 42 struct usb_memory_block mem; 43 44 // allocate a new memory block in the usb page 45 ret_size = usb_mem_next_block(USB_OHCI_HCCA_SIZE, USB_OHCI_HCCA_ALIGN, 46 free_pages, &mem); 47 48 /* 49 * check if we have enough space, this may occur when we have just a few 50 * bytes left in the page, allocate new page and try again 51 */ 52 if (ret_size < USB_OHCI_HCCA_SIZE) { 53 if (free_pages->free.size < sizeof(struct usb_ohci_ed)) { 54 /* 55 * TODO: memory waste 56 */ 57 } else if (free_pages->free.size < 64) { 58 /* 59 * we can allocate a endpoint descriptor instead and store it 60 */ 61 struct usb_ohci_ed *ed = usb_ohci_ed_alloc(); 62 ed->obj_next = free_eds; 63 free_eds = ed; 64 } 65 // get a new page; 66 free_pages = usb_mem_page_alloc(); 67 } 68 69 /* 70 * retry allocating a new hcca in the given block 71 */ 72 ret_size = usb_mem_next_block(USB_OHCI_HCCA_SIZE, USB_OHCI_HCCA_ALIGN, 73 free_pages, &mem); 74 75 assert(ret_size >= USB_OHCI_HCCA_SIZE); 76 77 hcca = (struct usb_ohci_hcca *) mem.buffer; 78 hcca_phys = mem.phys_addr; 79 80 return hcca; 81} 82 83usb_paddr_t usb_ohci_hcca_physaddr(void) 84{ 85 if (hcca_phys != 0) { 86 return hcca_phys; 87 } 88 usb_ohci_hcca_alloc(); 89 return hcca_phys; 90} 91 92/** 93 * \brief this function allocates a td descriptor used for the usb transfers 94 * 95 * \return pointer to a usb_ohci_td struct 96 */ 97struct usb_ohci_td *usb_ohci_td_alloc(void) 98{ 99 struct usb_ohci_td * ret = NULL; 100 101 /* 102 * check if we have a free td left 103 */ 104 if (free_tds != NULL) { 105 ret = free_tds; 106 free_tds = free_tds->obj_next; 107 ret->obj_next = NULL; 108 return ret; 109 } 110 111 uint32_t min_size = sizeof(struct usb_ohci_td); 112 113 // we do not have any free page anymore 114 if (free_pages == NULL) { 115 free_pages = usb_mem_page_alloc(); 116 } 117 118 uint32_t ret_size; 119 struct usb_memory_block mem; 120 121 // allocate a new memory block in the usb page 122 ret_size = usb_mem_next_block(sizeof(struct usb_ohci_td), USB_OHCI_TD_ALIGN, 123 free_pages, &mem); 124 125 /* 126 * check if we have enough space, this may occur when we have just a few 127 * bytes left in the page, allocate new page and try again 128 */ 129 if (ret_size < min_size) { 130 if (free_pages->free.size < 32) { 131 /* 132 * TODO: memory waste 133 */ 134 } else if (free_pages->free.size < 64) { 135 /* 136 * we can allocate a endpoint descriptor instead and store it 137 */ 138 struct usb_ohci_ed *ed = usb_ohci_ed_alloc(); 139 ed->obj_next = free_eds; 140 free_eds = ed; 141 } 142 // get a new page; 143 free_pages = usb_mem_page_alloc(); 144 } 145 146 /* 147 * retry allocating a new td descriptor in the given block 148 */ 149 ret_size = usb_mem_next_block(sizeof(struct usb_ohci_td), USB_OHCI_TD_ALIGN, 150 free_pages, &mem); 151 152 assert(ret_size >= min_size); 153 154 // now we have memory for the td descriptor and we can set it up 155 156 ret = (struct usb_ohci_td *) mem.buffer; 157 ret->td_self = mem.phys_addr; 158 ret->td_current_buffer = mem.phys_addr + USB_OHCI_TD_BUFFER_OFFSET; 159 ret->td_buffer_end = ret->td_current_buffer + USB_OHCI_TD_BUFFER_SIZE; 160 ret->obj_next = NULL; 161 162 return ret; 163} 164 165void usb_ohci_td_free(struct usb_ohci_td *td) 166{ 167 td->td_current_buffer = td->td_self + USB_OHCI_TD_BUFFER_OFFSET; 168 td->td_buffer_end = td->td_current_buffer + USB_OHCI_TD_BUFFER_SIZE; 169 td->td_nextTD = 0; 170 td->alt_next = NULL; 171 td->len = 0; 172 td->obj_next = free_tds; 173 free_tds = td; 174} 175 176struct usb_ohci_ed *usb_ohci_ed_alloc(void) 177{ 178 struct usb_ohci_ed * ret = NULL; 179 180 /* 181 * check if we have a free td left 182 */ 183 if (free_tds != NULL) { 184 ret = free_eds; 185 free_eds = free_eds->obj_next; 186 ret->obj_next = NULL; 187 return ret; 188 } 189 190 uint32_t min_size = sizeof(struct usb_ohci_ed); 191 192 // we do not have any free page anymore 193 if (free_pages == NULL) { 194 free_pages = usb_mem_page_alloc(); 195 } 196 197 uint32_t ret_size; 198 struct usb_memory_block mem; 199 200 // allocate a new memory block in the usb page 201 ret_size = usb_mem_next_block(sizeof(struct usb_ohci_ed), USB_OHCI_ED_ALIGN, 202 free_pages, &mem); 203 204 /* 205 * check if we have enough space, this may occur when we have just a few 206 * bytes left in the page, allocate new page and try again 207 */ 208 if (ret_size < min_size) { 209 if (free_pages->free.size < 32) { 210 /* 211 * TODO: memory waste 212 */ 213 } 214 // get a new page; 215 free_pages = usb_mem_page_alloc(); 216 /* 217 * retry allocating a new td descriptor in the given block 218 */ 219 ret_size = usb_mem_next_block(sizeof(struct usb_ohci_ed), 220 USB_OHCI_ED_ALIGN, free_pages, &mem); 221 } 222 223 assert(ret_size >= min_size); 224 225 // now we have memory for the td descriptor and we can set it up 226 227 ret = (struct usb_ohci_ed *) mem.buffer; 228 memset(ret, 0, sizeof(struct usb_ohci_ed)); 229 230 ret->ed_self = mem.phys_addr; 231 232 return ret; 233 234} 235 236void usb_ohci_ed_free(struct usb_ohci_ed *ed) 237{ 238 /* 239 * delete the hardware part of the descriptor 240 */ 241 memset(ed, 0, USB_OHCI_ED_HW_SIZE); 242 ed->obj_next = free_eds; 243 ed->prev = NULL; 244 ed->next = NULL; 245 free_eds = ed; 246} 247 248struct usb_ohci_itd *usb_ohci_itd_alloc(void) 249{ 250 assert(!"NYI: allocating itd is not implemented. "); 251 return NULL; 252} 253 254void usb_ohci_itd_free(struct usb_ohci_itd *td) 255{ 256 assert(!"NYI: freeing itd is not implemented. "); 257} 258 259usb_paddr_t usb_ohci_buffer_alloc(uint32_t size, uint32_t align) 260{ 261 return 0; 262} 263 264void usb_ohci_buffer_free(usb_paddr_t buf) 265{ 266 267} 268