M4521_BSP V3.02.000
The Board Support Package for M4521
usbh_support.c
Go to the documentation of this file.
1/******************************************************************************
2 * @file usbh_ohci.c
3 * @version V1.00
4 * $Revision: 8 $
5 * $Date: 15/09/02 10:02a $
6 * @brief M4521 MCU USB Host OHCI driver
7 *
8 * @note
9 * SPDX-License-Identifier: Apache-2.0
10 * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
11*****************************************************************************/
12#include <stdio.h>
13#include <string.h>
14
15#include "M4521.h"
16#include "usbh_core.h"
17#include "usbh_hub.h"
18#include "usbh_ohci.h"
19
21
22#ifdef __ICCARM__
23#pragma data_alignment=32
24static ED_T g_ed_pool[ED_MAX_NUM];
25#pragma data_alignment=32
26static TD_T g_td_pool[TD_MAX_NUM];
27static URB_T g_urb_pool[URB_MAX_NUM];
28#else
29static ED_T g_ed_pool[ED_MAX_NUM] __attribute__((aligned(32)));
30static TD_T g_td_pool[TD_MAX_NUM] __attribute__((aligned(32)));
31static URB_T g_urb_pool[URB_MAX_NUM] __attribute__((aligned(32)));
32#endif
33
34USB_DEV_T g_dev_pool[DEV_MAX_NUM];
35static USB_HUB_T g_hub_pool[MAX_HUB_DEVICE];
36
37static uint8_t ed_alloc_mark[ED_MAX_NUM];
38static uint8_t td_alloc_mark[TD_MAX_NUM];
39USB_DEV_T * td_alloc_dev[TD_MAX_NUM];
40uint8_t dev_alloc_mark[DEV_MAX_NUM];
41static uint8_t urb_alloc_mark[URB_MAX_NUM];
42static uint8_t hub_alloc_mark[MAX_HUB_DEVICE];
43
44int _td_cnt, _ed_cnt;
45
47
49{
50 int i;
51
52 for(i = 0; i < ED_MAX_NUM; i++)
53 ed_alloc_mark[i] = 0;
54 _ed_cnt = ED_MAX_NUM;
55
56 for(i = 0; i < TD_MAX_NUM; i++)
57 td_alloc_mark[i] = 0;
58 _td_cnt = TD_MAX_NUM;
59
60 for(i = 0; i < DEV_MAX_NUM; i++)
61 dev_alloc_mark[i] = 0;
62
63 for(i = 0; i < URB_MAX_NUM; i++)
64 urb_alloc_mark[i] = 0;
65
66 for(i = 0; i < MAX_HUB_DEVICE; i++)
67 hub_alloc_mark[i] = 0;
68}
69
70
77{
78 int i;
79
80 for(i = 0; i < URB_MAX_NUM; i++)
81 {
82 if(urb_alloc_mark[i] == 0)
83 {
84 urb_alloc_mark[i] = 1;
85 memset((char *)&g_urb_pool[i], 0, sizeof(URB_T));
86 return &g_urb_pool[i];
87 }
88 }
89 USB_error("USBH_AllocUrb failed!\n");
90 return NULL;
91}
92
93
100{
101 int i;
102
103 for(i = 0; i < URB_MAX_NUM; i++)
104 {
105 if(&g_urb_pool[i] == urb)
106 {
107 urb_alloc_mark[i] = 0;
108 return;
109 }
110 }
111 USB_error("USBH_FreeUrb - missed!\n");
112}
113
114
116{
117 int i;
118
119 for(i = 0; i < URB_MAX_NUM; i++)
120 {
121 if(urb_alloc_mark[i])
122 {
123 if(g_urb_pool[i].dev == dev)
124 {
125 USBH_UnlinkUrb(&g_urb_pool[i]);
126 urb_alloc_mark[i] = 0;
127 }
128 }
129 }
130}
131
132
134{
135 int i;
136
137 for(i = 0; i < ED_MAX_NUM; i++)
138 {
139 if(ed_alloc_mark[i] == 0)
140 {
141 ed_alloc_mark[i] = 1;
142 memset((char *)&g_ed_pool[i], 0, sizeof(ED_T));
143 _ed_cnt--;
144 return &g_ed_pool[i];
145 }
146 }
147 USB_error("ohci_alloc_ed failed!\n");
148 return NULL;
149}
150
151
152void ohci_free_ed(ED_T *ed_p)
153{
154 int i;
155
156 for(i = 0; i < ED_MAX_NUM; i++)
157 {
158 if(&g_ed_pool[i] == ed_p)
159 {
160 ed_alloc_mark[i] = 0;
161 _ed_cnt++;
162 return;
163 }
164 }
165 USB_error("ohci_free_ed - missed!\n");
166}
167
168
170{
171 int i;
172
173 for(i = 0; i < TD_MAX_NUM; i++)
174 {
175 if(td_alloc_mark[i] == 0)
176 {
177 td_alloc_mark[i] = 1;
178 td_alloc_dev[i] = dev;
179 memset((char *)&g_td_pool[i], 0, sizeof(TD_T));
180 _td_cnt--;
181 return &g_td_pool[i];
182 }
183 }
184 USB_error("ohci_alloc_td failed!\n");
185 return NULL;
186}
187
188
189void ohci_free_td(TD_T *td_p)
190{
191 int i;
192
193 for(i = 0; i < TD_MAX_NUM; i++)
194 {
195 if((&g_td_pool[i] == td_p) && (td_alloc_mark[i]))
196 {
197 _td_cnt++;
198 td_alloc_mark[i] = 0;
199 return;
200 }
201 }
202}
203
204
206{
207 int i;
208 for(i = 0; i < TD_MAX_NUM; i++)
209 {
210 if((td_alloc_mark[i]) && (td_alloc_dev[i] == dev))
211 {
212 _td_cnt++;
213 td_alloc_mark[i] = 0;
214 return;
215 }
216 }
217}
218
219
220/*
221 * Only HC's should call usbh_alloc_device and usbh_free_device directly
222 * Anybody may use USB_IncreaseDeviceUser or usb_dec_dev_use
223 */
224USB_DEV_T *usbh_alloc_device(USB_DEV_T *parent, USB_BUS_T *bus)
225{
226 int i;
227 USB_DEV_T *dev;
228
229 for(i = 0; i < DEV_MAX_NUM; i++)
230 {
231 if(dev_alloc_mark[i] == 0)
232 {
233 dev_alloc_mark[i] = 1;
234 dev = &g_dev_pool[i];
235 memset((char *)dev, 0, sizeof(*dev));
236 dev->act_config = -1;
237 dev->parent = parent;
238 dev->bus = bus;
239 if(dev->bus->op->allocate(dev) != 0)
240 {
241 dev_alloc_mark[i] = 0;
242 return NULL;
243 }
244 return dev;
245 }
246 }
247 USB_error("usbh_alloc_device failed!\n");
248 return NULL;
249}
250
251
253{
254 int i, j;
255 OHCI_DEVICE_T *ohcidev;
256
257 dev->bus->op->deallocate(dev);
258 for(i = 0; i < DEV_MAX_NUM; i++)
259 {
260 if(&g_dev_pool[i] == dev)
261 {
262 ohcidev = usb_to_ohci(dev);
263 for(j = 0; j < NUM_EDS; j++)
264 {
265 if(ohcidev->edp[j] != NULL)
266 ohci_free_ed(ohcidev->edp[j]);
267 }
268 dev_alloc_mark[i] = 0;
269 return;
270 }
271 }
272 USB_error("usbh_free_device - missed!\n");
273}
274
275
276USB_HUB_T * usbh_alloc_hubdev()
277{
278 int i;
279
280 for(i = 0; i < MAX_HUB_DEVICE; i++)
281 {
282 if(hub_alloc_mark[i] == 0)
283 {
284 hub_alloc_mark[i] = 1;
285 memset((char *)&g_hub_pool[i], 0, sizeof(USB_HUB_T));
286 return &g_hub_pool[i];
287 }
288 }
289 USB_error("usbh_alloc_hubdev failed!\n");
290 return NULL;
291}
292
293
294void usbh_free_hubdev(USB_HUB_T *hub)
295{
296 int i;
297
298 for(i = 0; i < MAX_HUB_DEVICE; i++)
299 {
300 if(&g_hub_pool[i] == hub)
301 {
302 hub_alloc_mark[i] = 0;
303 return;
304 }
305 }
306 USB_error("ohci_free_ed - missed!\n");
307}
308
309
311{
312 int i;
313
314 for(i = 0; i < MAX_HUB_DEVICE; i++)
315 {
316 if(hub_alloc_mark[i])
317 {
318 if(g_hub_pool[i].dev == dev)
319 return &g_hub_pool[i];
320 }
321 }
322 return NULL;
323}
324
325
326/*-------------------------------------------------------------------------
327 * Millisecond delay
328 *-------------------------------------------------------------------------*/
329
330void usbh_mdelay(uint32_t msec)
331{
332 volatile uint32_t t0;
333 volatile uint32_t frame_no;
334
335 if((USBH->HcControl & 0xC0) == 0x40)
336 {
337 /* OHCI in operational state */
338 for(t0 = 0; t0 < msec; t0++)
339 {
340 frame_no = USBH->HcFmNumber;
341 while(USBH->HcFmNumber == frame_no) ;
342 }
343 }
344 else
345 {
346 for(t0 = 0; t0 < msec * 0x1000; t0++) ;
347 }
348}
349
350
void *__dso_handle __attribute__((weak))
Definition: _syscalls.c:35
#define NULL
Definition: M4521.h:13912
#define USBH
Definition: M4521.h:13831
URB_T * USBH_AllocUrb()
Allocate an URB from USB Core driver internal URB pool.
Definition: usbh_support.c:76
int32_t USBH_UnlinkUrb(URB_T *urb)
Cancel an URB which has been submit to USB core.
Definition: usbh_core.c:237
void USBH_FreeUrb(URB_T *urb)
Free the URB allocated from USBH_AllocUrb()
Definition: usbh_support.c:99
#define DEV_MAX_NUM
Definition: usbh_config.h:32
#define MAX_HUB_DEVICE
Definition: usbh_config.h:40
#define URB_MAX_NUM
Definition: usbh_config.h:33
#define ED_MAX_NUM
Definition: usbh_config.h:34
#define TD_MAX_NUM
Definition: usbh_config.h:35
USB Host core driver header file.
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
USB_HUB_T * usbh_alloc_hubdev()
Definition: usbh_support.c:276
void usbh_free_device(USB_DEV_T *dev)
Definition: usbh_support.c:252
void ohci_free_td(TD_T *td_p)
Definition: usbh_support.c:189
TD_T * ohci_alloc_td(USB_DEV_T *dev)
Definition: usbh_support.c:169
USB_HUB_T * usbh_get_hub_by_dev(USB_DEV_T *dev)
Definition: usbh_support.c:310
HIDDEN_SYMBOLS void usbh_init_memory()
Definition: usbh_support.c:48
void ohci_free_ed(ED_T *ed_p)
Definition: usbh_support.c:152
void usbh_free_hubdev(USB_HUB_T *hub)
Definition: usbh_support.c:294
USB_DEV_T * usbh_alloc_device(USB_DEV_T *parent, USB_BUS_T *bus)
Definition: usbh_support.c:224
void usbh_mdelay(uint32_t msec)
Definition: usbh_support.c:330
void usbh_free_dev_urbs(USB_DEV_T *dev)
Definition: usbh_support.c:115
void ohci_free_dev_td(USB_DEV_T *dev)
Definition: usbh_support.c:205
ED_T * ohci_alloc_ed()
Definition: usbh_support.c:133