ohci.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301
  1. /**************************************************************************//**
  2. * @file ohci.c
  3. * @version V1.10
  4. * $Revision: 11 $
  5. * $Date: 14/10/03 1:54p $
  6. * @brief USB Host library OHCI (USB 1.1) host controller driver.
  7. *
  8. * @note
  9. * SPDX-License-Identifier: Apache-2.0
  10. * Copyright (C) 2017 Nuvoton Technology Corp. All rights reserved.
  11. *****************************************************************************/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "nuc980.h"
  16. #include "usb.h"
  17. #include "hub.h"
  18. #include "ohci.h"
  19. /// @cond HIDDEN_SYMBOLS
  20. //#define TD_debug rt_kprintf
  21. #define TD_debug(...)
  22. //#define ED_debug rt_kprintf
  23. #define ED_debug(...)
  24. uint8_t _hcca_mem[256] __attribute__((aligned(256)));
  25. HCCA_T *_hcca;
  26. ED_T *_Ied[6];
  27. static ED_T *ed_remove_list;
  28. static void add_to_ED_remove_list(ED_T *ed)
  29. {
  30. ED_T *p;
  31. ED_debug("add_to_ED_remove_list - 0x%x (0x%x)\n", (int)ed, ed->Info);
  32. DISABLE_OHCI_IRQ();
  33. /* check if this ED found in ed_remove_list */
  34. p = ed_remove_list;
  35. while (p)
  36. {
  37. if (p == ed)
  38. {
  39. ENABLE_OHCI_IRQ(); /* This ED found in ed_remove_list */
  40. return; /* do nothing */
  41. }
  42. p = p->next;
  43. }
  44. ed->Info |= ED_SKIP; /* ask OHCI controller skip this ED */
  45. ed->next = ed_remove_list;
  46. ed_remove_list = ed; /* insert to the head of ed_remove_list */
  47. ENABLE_OHCI_IRQ();
  48. _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk;
  49. _ohci->HcInterruptEnable |= USBH_HcInterruptEnable_SF_Msk;
  50. usbh_delay_ms(2); /* Full speed wait 2 ms is enough */
  51. }
  52. static int ohci_reset(void)
  53. {
  54. volatile int t0;
  55. /* Disable HC interrupts */
  56. _ohci->HcInterruptDisable = USBH_HcInterruptDisable_MIE_Msk;
  57. /* HC Reset requires max 10 ms delay */
  58. _ohci->HcControl = 0;
  59. _ohci->HcCommandStatus = USBH_HcCommandStatus_HCR_Msk;
  60. usbh_delay_ms(10);
  61. /* Check if OHCI reset completed? */
  62. if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0)
  63. {
  64. USB_error("Error! - USB OHCI reset timed out!\n");
  65. return -1;
  66. }
  67. USBH->HcRhStatus = USBH_HcRhStatus_OCI_Msk | USBH_HcRhStatus_LPS_Msk;
  68. USBH->HcControl = HCFS_RESET;
  69. usbh_delay_ms(10);
  70. /* Check if OHCI reset completed? */
  71. if ((USBH->HcCommandStatus & USBH_HcCommandStatus_HCR_Msk) != 0)
  72. {
  73. USB_error("Error! - USB HC reset timed out!\n");
  74. return -1;
  75. }
  76. return 0;
  77. }
  78. static void init_hcca_int_table()
  79. {
  80. ED_T *ed_p;
  81. int i, idx, interval;
  82. memset(_hcca->int_table, 0, sizeof(_hcca->int_table));
  83. for (i = 5; i >= 0; i--) /* interval = i^2 */
  84. {
  85. _Ied[i] = alloc_ohci_ED();
  86. _Ied[i]->Info = ED_SKIP;
  87. interval = 0x1 << i;
  88. for (idx = interval - 1; idx < 32; idx += interval)
  89. {
  90. if (_hcca->int_table[idx] == 0) /* is empty list, insert directly */
  91. {
  92. _hcca->int_table[idx] = (uint32_t)_Ied[i];
  93. }
  94. else
  95. {
  96. ed_p = (ED_T *)_hcca->int_table[idx];
  97. while (1)
  98. {
  99. if (ed_p == _Ied[i])
  100. break; /* already chained by previous visit */
  101. if (ed_p->NextED == 0) /* reach end of list? */
  102. {
  103. ed_p->NextED = (uint32_t)_Ied[i];
  104. break;
  105. }
  106. ed_p = (ED_T *)ed_p->NextED;
  107. }
  108. }
  109. }
  110. }
  111. }
  112. static ED_T *get_int_tree_head_node(int interval)
  113. {
  114. int i;
  115. for (i = 0; i < 5; i++)
  116. {
  117. interval >>= 1;
  118. if (interval == 0)
  119. return _Ied[i];
  120. }
  121. return _Ied[5]; /* for interval >= 32 */
  122. }
  123. static int get_ohci_interval(int interval)
  124. {
  125. int i, bInterval = 1;
  126. for (i = 0; i < 5; i++)
  127. {
  128. interval >>= 1;
  129. if (interval == 0)
  130. return bInterval;
  131. bInterval *= 2;
  132. }
  133. return 32; /* for interval >= 32 */
  134. }
  135. static int ohci_init(void)
  136. {
  137. uint32_t fminterval;
  138. volatile int i;
  139. _hcca = (HCCA_T *)((uint32_t)_hcca_mem | NON_CACHE_MASK);
  140. if (ohci_reset() < 0)
  141. return -1;
  142. ed_remove_list = NULL;
  143. init_hcca_int_table();
  144. /* Tell the controller where the control and bulk lists are
  145. * The lists are empty now. */
  146. _ohci->HcControlHeadED = 0; /* control ED list head */
  147. _ohci->HcBulkHeadED = 0; /* bulk ED list head */
  148. _ohci->HcHCCA = (uint32_t)_hcca; /* HCCA area */
  149. /* periodic start 90% of frame interval */
  150. fminterval = 0x2edf; /* 11,999 */
  151. _ohci->HcPeriodicStart = (fminterval * 9) / 10;
  152. /* set FSLargestDataPacket, 10,104 for 0x2edf frame interval */
  153. fminterval |= ((((fminterval - 210) * 6) / 7) << 16);
  154. _ohci->HcFmInterval = fminterval;
  155. _ohci->HcLSThreshold = 0x628;
  156. /* start controller operations */
  157. _ohci->HcControl = HCFS_OPER | (0x3 << USBH_HcControl_CBSR_Pos);
  158. #ifdef OHCI_PER_PORT_POWER
  159. _ohci->HcRhDescriptorB = 0x60000;
  160. for (i = 0; i < OHCI_PORT_CNT; i++)
  161. _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_PPS_Msk;
  162. #else
  163. _ohci->HcRhDescriptorA = (USBH->HcRhDescriptorA | (1 << 9)) & ~USBH_HcRhDescriptorA_PSM_Msk;
  164. _ohci->HcRhStatus = USBH_HcRhStatus_LPSC_Msk;
  165. #endif
  166. _ohci->HcInterruptEnable = USBH_HcInterruptEnable_MIE_Msk | USBH_HcInterruptEnable_WDH_Msk | USBH_HcInterruptEnable_SF_Msk;
  167. /* POTPGT delay is bits 24-31, in 20 ms units. */
  168. usbh_delay_ms(20);
  169. return 0;
  170. }
  171. static void ohci_suspend(void)
  172. {
  173. int i;
  174. for (i = 0; i < OHCI_PORT_CNT; i++)
  175. {
  176. /* set port suspend if connected */
  177. if (_ohci->HcRhPortStatus[i] & 0x1)
  178. _ohci->HcRhPortStatus[i] = 0x4;
  179. }
  180. /* enable Device Remote Wakeup */
  181. _ohci->HcRhStatus |= USBH_HcRhStatus_DRWE_Msk;
  182. /* enable USBH RHSC interrupt for system wakeup */
  183. _ohci->HcInterruptEnable |= USBH_HcInterruptEnable_RHSC_Msk | USBH_HcInterruptEnable_RD_Msk;
  184. /* set Host Controller enter suspend state */
  185. _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos);
  186. }
  187. static void ohci_resume(void)
  188. {
  189. int i;
  190. _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos);
  191. _ohci->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos);
  192. for (i = 0; i < OHCI_PORT_CNT; i++)
  193. {
  194. if (_ohci->HcRhPortStatus[i] & 0x4)
  195. _ohci->HcRhPortStatus[i] = 0x8;
  196. }
  197. }
  198. static void ohci_shutdown(void)
  199. {
  200. ohci_suspend();
  201. DISABLE_OHCI_IRQ();
  202. #ifndef OHCI_PER_PORT_POWER
  203. _ohci->HcRhStatus = USBH_HcRhStatus_LPS_Msk;
  204. #endif
  205. }
  206. /*
  207. * Quit current trasnfer via UTR or hardware EP.
  208. */
  209. static int ohci_quit_xfer(UTR_T *utr, EP_INFO_T *ep)
  210. {
  211. ED_T *ed;
  212. if (utr != NULL)
  213. {
  214. if (utr->ep == NULL)
  215. return USBH_ERR_NOT_FOUND;
  216. ed = (ED_T *)(utr->ep->hw_pipe);
  217. if (!ed)
  218. return USBH_ERR_NOT_FOUND;
  219. /* add the endpoint to remove list, it will be removed on the next start of frame */
  220. add_to_ED_remove_list(ed);
  221. utr->ep->hw_pipe = NULL;
  222. }
  223. if ((ep != NULL) && (ep->hw_pipe != NULL))
  224. {
  225. ed = (ED_T *)(ep->hw_pipe);
  226. /* add the endpoint to remove list, it will be removed on the next start of frame */
  227. add_to_ED_remove_list(ed);
  228. ep->hw_pipe = NULL;
  229. }
  230. return 0;
  231. }
  232. uint32_t ed_make_info(UDEV_T *udev, EP_INFO_T *ep)
  233. {
  234. uint32_t info;
  235. if (ep == NULL) /* is a control endpoint */
  236. {
  237. /* control endpoint direction is from TD */
  238. if (udev->descriptor.bMaxPacketSize0 == 0) /* is 0 if device descriptor still not obtained. */
  239. {
  240. if (udev->speed == SPEED_LOW) /* give a default maximum packet size */
  241. udev->descriptor.bMaxPacketSize0 = 8;
  242. else
  243. udev->descriptor.bMaxPacketSize0 = 64;
  244. }
  245. info = (udev->descriptor.bMaxPacketSize0 << 16) /* Control endpoint Maximum Packet Size from device descriptor */
  246. | ED_DIR_BY_TD /* Direction (Get direction From TD) */
  247. | ED_FORMAT_GENERAL /* General format */
  248. | (0 << ED_CTRL_EN_Pos); /* Endpoint address 0 */
  249. }
  250. else /* Other endpoint direction is from endpoint descriptor */
  251. {
  252. info = (ep->wMaxPacketSize << 16); /* Maximum Packet Size from endpoint */
  253. info |= ((ep->bEndpointAddress & 0xf) << ED_CTRL_EN_Pos); /* Endpoint Number */
  254. if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN)
  255. info |= ED_DIR_IN;
  256. else
  257. info |= ED_DIR_OUT;
  258. if ((ep->bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_ISO)
  259. info |= ED_FORMAT_ISO;
  260. else
  261. info |= ED_FORMAT_GENERAL;
  262. }
  263. info |= ((udev->speed == SPEED_LOW) ? ED_SPEED_LOW : ED_SPEED_FULL); /* Speed */
  264. info |= (udev->dev_num); /* Function Address */
  265. return info;
  266. }
  267. static void write_td(TD_T *td, uint32_t info, uint8_t *buff, uint32_t data_len)
  268. {
  269. td->Info = info;
  270. td->CBP = (uint32_t)((!buff || !data_len) ? 0 : buff);
  271. td->BE = (uint32_t)((!buff || !data_len) ? 0 : (uint32_t)buff + data_len - 1);
  272. td->buff_start = td->CBP;
  273. // TD_debug("TD [0x%x]: 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->BE);
  274. }
  275. static int ohci_ctrl_xfer(UTR_T *utr)
  276. {
  277. UDEV_T *udev;
  278. ED_T *ed;
  279. TD_T *td_setup, *td_data, *td_status;
  280. uint32_t info;
  281. udev = utr->udev;
  282. /*------------------------------------------------------------------------------------*/
  283. /* Allocate ED and TDs */
  284. /*------------------------------------------------------------------------------------*/
  285. td_setup = alloc_ohci_TD(utr);
  286. if (utr->data_len > 0)
  287. td_data = alloc_ohci_TD(utr);
  288. else
  289. td_data = NULL;
  290. td_status = alloc_ohci_TD(utr);
  291. if (td_status == NULL)
  292. {
  293. free_ohci_TD(td_setup);
  294. if (utr->data_len > 0)
  295. free_ohci_TD(td_data);
  296. return USBH_ERR_MEMORY_OUT;
  297. }
  298. /* Check if there's any transfer pending on this endpoint... */
  299. if (udev->ep0.hw_pipe == NULL)
  300. {
  301. ed = alloc_ohci_ED();
  302. if (ed == NULL)
  303. {
  304. free_ohci_TD(td_setup);
  305. free_ohci_TD(td_status);
  306. if (utr->data_len > 0)
  307. free_ohci_TD(td_data);
  308. return USBH_ERR_MEMORY_OUT;
  309. }
  310. }
  311. else
  312. ed = (ED_T *)udev->ep0.hw_pipe;
  313. /*------------------------------------------------------------------------------------*/
  314. /* prepare SETUP stage TD */
  315. /*------------------------------------------------------------------------------------*/
  316. info = TD_CC | TD_T_DATA0 | TD_TYPE_CTRL;
  317. write_td(td_setup, info, (uint8_t *)&utr->setup, 8);
  318. td_setup->ed = ed;
  319. /*------------------------------------------------------------------------------------*/
  320. /* prepare DATA stage TD */
  321. /*------------------------------------------------------------------------------------*/
  322. if (utr->data_len > 0)
  323. {
  324. if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT)
  325. info = (TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA);
  326. else
  327. info = (TD_CC | TD_R | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL | TD_CTRL_DATA);
  328. write_td(td_data, info, utr->buff, utr->data_len);
  329. td_data->ed = ed;
  330. td_setup->NextTD = (uint32_t)td_data;
  331. td_setup->next = td_data;
  332. td_data->NextTD = (uint32_t)td_status;
  333. td_data->next = td_status;
  334. }
  335. else
  336. {
  337. td_setup->NextTD = (uint32_t)td_status;
  338. td_setup->next = td_status;
  339. }
  340. /*------------------------------------------------------------------------------------*/
  341. /* prepare STATUS stage TD */
  342. /*------------------------------------------------------------------------------------*/
  343. ed->Info = ed_make_info(udev, NULL);
  344. if ((utr->setup.bmRequestType & 0x80) == REQ_TYPE_OUT)
  345. info = (TD_CC | TD_DP_IN | TD_T_DATA1 | TD_TYPE_CTRL);
  346. else
  347. info = (TD_CC | TD_DP_OUT | TD_T_DATA1 | TD_TYPE_CTRL);
  348. write_td(td_status, info, NULL, 0);
  349. td_status->ed = ed;
  350. td_status->NextTD = 0;
  351. td_status->next = 0;
  352. /*------------------------------------------------------------------------------------*/
  353. /* prepare ED */
  354. /*------------------------------------------------------------------------------------*/
  355. ed->TailP = 0;
  356. ed->HeadP = (uint32_t)td_setup;
  357. ed->Info = ed_make_info(udev, NULL);
  358. ed->NextED = 0;
  359. //TD_debug("TD SETUP [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_setup, td_setup->Info, td_setup->CBP, td_setup->BE, td_setup->NextTD);
  360. //if (td_data)
  361. // TD_debug("TD DATA [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_data, td_data->Info, td_data->CBP, td_data->BE, td_data->NextTD);
  362. //TD_debug("TD STATUS [0x%x]: 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td_status, td_status->Info, td_status->CBP, td_status->BE, td_status->NextTD);
  363. ED_debug("Xfer ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
  364. if (utr->data_len > 0)
  365. utr->td_cnt = 3;
  366. else
  367. utr->td_cnt = 2;
  368. utr->ep = &udev->ep0; /* driver can find EP from UTR */
  369. udev->ep0.hw_pipe = (void *)ed; /* driver can find ED from EP */
  370. /*------------------------------------------------------------------------------------*/
  371. /* Start transfer */
  372. /*------------------------------------------------------------------------------------*/
  373. DISABLE_OHCI_IRQ();
  374. _ohci->HcControlHeadED = (uint32_t)ed; /* Link ED to OHCI */
  375. _ohci->HcControl |= USBH_HcControl_CLE_Msk; /* enable control list */
  376. ENABLE_OHCI_IRQ();
  377. _ohci->HcCommandStatus = USBH_HcCommandStatus_CLF_Msk; /* start Control list */
  378. return 0;
  379. }
  380. static int ohci_bulk_xfer(UTR_T *utr)
  381. {
  382. UDEV_T *udev = utr->udev;
  383. EP_INFO_T *ep = utr->ep;
  384. ED_T *ed;
  385. TD_T *td, *td_p, *td_list = NULL;
  386. uint32_t info;
  387. uint32_t data_len, xfer_len;
  388. int8_t bIsNewED = 0;
  389. uint8_t *buff;
  390. /*------------------------------------------------------------------------------------*/
  391. /* Check if there's uncompleted transfer on this endpoint... */
  392. /* Prepare ED */
  393. /*------------------------------------------------------------------------------------*/
  394. info = ed_make_info(udev, ep);
  395. /* Check if there's any transfer pending on this endpoint... */
  396. ed = (ED_T *)_ohci->HcBulkHeadED; /* get the head of bulk endpoint list */
  397. while (ed != NULL)
  398. {
  399. if (ed->Info == info) /* have transfer of this EP not completed? */
  400. {
  401. if ((ed->HeadP & 0xFFFFFFF0) != (ed->TailP & 0xFFFFFFF0))
  402. return USBH_ERR_OHCI_EP_BUSY; /* endpoint is busy */
  403. else
  404. break; /* ED already there... */
  405. }
  406. ed = (ED_T *)ed->NextED;
  407. }
  408. if (ed == NULL)
  409. {
  410. bIsNewED = 1;
  411. ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
  412. if (ed == NULL)
  413. return USBH_ERR_MEMORY_OUT;
  414. ed->Info = info;
  415. ed->HeadP = 0;
  416. ED_debug("Link BULK ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
  417. }
  418. ep->hw_pipe = (void *)ed;
  419. /*------------------------------------------------------------------------------------*/
  420. /* Prepare TDs */
  421. /*------------------------------------------------------------------------------------*/
  422. utr->td_cnt = 0;
  423. data_len = utr->data_len;
  424. buff = utr->buff;
  425. do
  426. {
  427. if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT)
  428. info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_BULK);
  429. else
  430. info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_BULK);
  431. info &= ~(1 << 25); /* Data toggle from ED toggleCarry bit */
  432. if (data_len > 4096) /* maximum transfer length is 4K for each TD */
  433. xfer_len = 4096;
  434. else
  435. xfer_len = data_len; /* remaining data length < 4K */
  436. td = alloc_ohci_TD(utr); /* allocate a TD */
  437. if (td == NULL)
  438. goto mem_out;
  439. /* fill this TD */
  440. write_td(td, info, buff, xfer_len);
  441. td->ed = ed;
  442. utr->td_cnt++; /* increase TD count, for recalim counter */
  443. buff += xfer_len; /* advanced buffer pointer */
  444. data_len -= xfer_len;
  445. /* chain to end of TD list */
  446. if (td_list == NULL)
  447. {
  448. td_list = td;
  449. }
  450. else
  451. {
  452. td_p = td_list;
  453. while (td_p->NextTD != 0)
  454. td_p = (TD_T *)td_p->NextTD;
  455. td_p->NextTD = (uint32_t)td;
  456. }
  457. }
  458. while (data_len > 0);
  459. /*------------------------------------------------------------------------------------*/
  460. /* Start transfer */
  461. /*------------------------------------------------------------------------------------*/
  462. utr->status = 0;
  463. DISABLE_OHCI_IRQ();
  464. ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */
  465. if (bIsNewED)
  466. {
  467. ed->HeadP = (uint32_t)td_list;
  468. /* Link ED to OHCI Bulk List */
  469. ed->NextED = _ohci->HcBulkHeadED;
  470. _ohci->HcBulkHeadED = (uint32_t)ed;
  471. }
  472. ENABLE_OHCI_IRQ();
  473. _ohci->HcControl |= USBH_HcControl_BLE_Msk; /* enable bulk list */
  474. _ohci->HcCommandStatus = USBH_HcCommandStatus_BLF_Msk; /* start bulk list */
  475. return 0;
  476. mem_out:
  477. while (td_list != NULL)
  478. {
  479. td = td_list;
  480. td_list = (TD_T *)td_list->NextTD;
  481. free_ohci_TD(td);
  482. }
  483. free_ohci_ED(ed);
  484. return USBH_ERR_MEMORY_OUT;
  485. }
  486. static int ohci_int_xfer(UTR_T *utr)
  487. {
  488. UDEV_T *udev = utr->udev;
  489. EP_INFO_T *ep = utr->ep;
  490. ED_T *ed, *ied;
  491. TD_T *td, *td_new;
  492. uint32_t info;
  493. int8_t bIsNewED = 0;
  494. if (utr->data_len > 64) /* USB 1.1 interrupt transfer maximum packet size is 64 */
  495. return USBH_ERR_INVALID_PARAM;
  496. td_new = alloc_ohci_TD(utr); /* allocate a TD for dummy TD */
  497. if (td_new == NULL)
  498. return USBH_ERR_MEMORY_OUT;
  499. ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */
  500. /*------------------------------------------------------------------------------------*/
  501. /* Find if this ED was already in the list */
  502. /*------------------------------------------------------------------------------------*/
  503. info = ed_make_info(udev, ep);
  504. ed = ied;
  505. while (ed != NULL)
  506. {
  507. if (ed->Info == info)
  508. break; /* Endpoint found */
  509. ed = (ED_T *)ed->NextED;
  510. }
  511. if (ed == NULL) /* ED not found, create it */
  512. {
  513. bIsNewED = 1;
  514. ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
  515. if (ed == NULL)
  516. return USBH_ERR_MEMORY_OUT;
  517. ed->Info = info;
  518. ed->HeadP = 0;
  519. ed->bInterval = ep->bInterval;
  520. td = alloc_ohci_TD(NULL); /* allocate the initial dummy TD for ED */
  521. if (td == NULL)
  522. {
  523. free_ohci_ED(ed);
  524. free_ohci_TD(td_new);
  525. return USBH_ERR_MEMORY_OUT;
  526. }
  527. ed->HeadP = (uint32_t)td; /* Let both HeadP and TailP point to dummy TD */
  528. ed->TailP = ed->HeadP;
  529. }
  530. else
  531. {
  532. td = (TD_T *)(ed->TailP & ~0xf); /* TailP always point to the dummy TD */
  533. }
  534. ep->hw_pipe = (void *)ed;
  535. /*------------------------------------------------------------------------------------*/
  536. /* Prepare TD */
  537. /*------------------------------------------------------------------------------------*/
  538. if ((ep->bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_OUT)
  539. info = (TD_CC | TD_R | TD_DP_OUT | TD_TYPE_INT);
  540. else
  541. info = (TD_CC | TD_R | TD_DP_IN | TD_TYPE_INT);
  542. /* Keep data toggle */
  543. info = (info & ~(1 << 25)) | (td->Info & (1 << 25));
  544. /* fill this TD */
  545. write_td(td, info, utr->buff, utr->data_len);
  546. td->ed = ed;
  547. td->NextTD = (uint32_t)td_new;
  548. td->utr = utr;
  549. utr->td_cnt = 1; /* increase TD count, for recalim counter */
  550. utr->status = 0;
  551. /*------------------------------------------------------------------------------------*/
  552. /* Hook ED and TD list to HCCA interrupt table */
  553. /*------------------------------------------------------------------------------------*/
  554. DISABLE_OHCI_IRQ();
  555. ed->TailP = (uint32_t)td_new;
  556. if (bIsNewED)
  557. {
  558. /* Add to list of the same interval */
  559. ed->NextED = ied->NextED;
  560. ied->NextED = (uint32_t)ed;
  561. }
  562. ENABLE_OHCI_IRQ();
  563. //printf("Link INT ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
  564. _ohci->HcControl |= USBH_HcControl_PLE_Msk; /* periodic list enable */
  565. return 0;
  566. }
  567. static int ohci_iso_xfer(UTR_T *utr)
  568. {
  569. UDEV_T *udev = utr->udev;
  570. EP_INFO_T *ep = utr->ep;
  571. ED_T *ed, *ied;
  572. TD_T *td, *td_list, *last_td;
  573. int i;
  574. uint32_t info;
  575. uint32_t buff_addr;
  576. int8_t bIsNewED = 0;
  577. ied = get_int_tree_head_node(ep->bInterval); /* get head node of this interval */
  578. /*------------------------------------------------------------------------------------*/
  579. /* Find if this ED was already in the list */
  580. /*------------------------------------------------------------------------------------*/
  581. info = ed_make_info(udev, ep);
  582. ed = ied;
  583. while (ed != NULL)
  584. {
  585. if (ed->Info == info)
  586. break; /* Endpoint found */
  587. ed = (ED_T *)ed->NextED;
  588. }
  589. if (ed == NULL) /* ED not found, create it */
  590. {
  591. bIsNewED = 1;
  592. ed = alloc_ohci_ED(); /* allocate an Endpoint Descriptor */
  593. if (ed == NULL)
  594. return USBH_ERR_MEMORY_OUT;
  595. ed->Info = info;
  596. ed->HeadP = 0;
  597. ed->bInterval = ep->bInterval;
  598. }
  599. else
  600. ep->hw_pipe = (void *)ed;
  601. /*------------------------------------------------------------------------------------*/
  602. /* Prepare TDs */
  603. /*------------------------------------------------------------------------------------*/
  604. if (utr->bIsoNewSched) /* Is the starting of isochronous streaming? */
  605. ed->next_sf = _hcca->frame_no + OHCI_ISO_DELAY;
  606. utr->td_cnt = 0;
  607. utr->iso_sf = ed->next_sf;
  608. last_td = NULL;
  609. td_list = NULL;
  610. for (i = 0; i < IF_PER_UTR; i++)
  611. {
  612. utr->iso_status[i] = USBH_ERR_NOT_ACCESS1;
  613. td = alloc_ohci_TD(utr); /* allocate a TD */
  614. if (td == NULL)
  615. goto mem_out;
  616. /* fill this TD */
  617. buff_addr = (uint32_t)(utr->iso_buff[i]);
  618. td->Info = (TD_CC | TD_TYPE_ISO) | ed->next_sf;
  619. ed->next_sf += get_ohci_interval(ed->bInterval);
  620. td->CBP = buff_addr & ~0xFFF;
  621. td->BE = buff_addr + utr->iso_xlen[i] - 1;
  622. td->PSW[0] = 0xE000 | (buff_addr & 0xFFF);
  623. td->ed = ed;
  624. utr->td_cnt++; /* increase TD count, for recalim counter */
  625. /* chain to end of TD list */
  626. if (td_list == NULL)
  627. td_list = td;
  628. else
  629. last_td->NextTD = (uint32_t)td;
  630. last_td = td;
  631. };
  632. /*------------------------------------------------------------------------------------*/
  633. /* Hook ED and TD list to HCCA interrupt table */
  634. /*------------------------------------------------------------------------------------*/
  635. utr->status = 0;
  636. DISABLE_OHCI_IRQ();
  637. if ((ed->HeadP & ~0x3) == 0)
  638. ed->HeadP = (ed->HeadP & 0x2) | (uint32_t)td_list; /* keep toggleCarry bit */
  639. else
  640. {
  641. /* find the tail of TDs under this ED */
  642. td = (TD_T *)(ed->HeadP & ~0x3);
  643. while (td->NextTD != 0)
  644. {
  645. td = (TD_T *)td->NextTD;
  646. }
  647. td->NextTD = (uint32_t)td_list;
  648. }
  649. if (bIsNewED)
  650. {
  651. /* Add to list of the same interval */
  652. ed->NextED = ied->NextED;
  653. ied->NextED = (uint32_t)ed;
  654. }
  655. ENABLE_OHCI_IRQ();
  656. ED_debug("Link ISO ED 0x%x: 0x%x 0x%x 0x%x 0x%x\n", (int)ed, ed->Info, ed->TailP, ed->HeadP, ed->NextED);
  657. _ohci->HcControl |= USBH_HcControl_PLE_Msk | USBH_HcControl_IE_Msk; /* enable periodic list and isochronous transfer */
  658. return 0;
  659. mem_out:
  660. while (td_list != NULL)
  661. {
  662. td = td_list;
  663. td_list = (TD_T *)td_list->NextTD;
  664. free_ohci_TD(td);
  665. }
  666. free_ohci_ED(ed);
  667. return USBH_ERR_MEMORY_OUT;
  668. }
  669. static UDEV_T *ohci_find_device_by_port(int port)
  670. {
  671. UDEV_T *udev;
  672. udev = g_udev_list;
  673. while (udev != NULL)
  674. {
  675. if ((udev->parent == NULL) && (udev->port_num == port) &&
  676. ((udev->speed == SPEED_LOW) || (udev->speed == SPEED_FULL)))
  677. return udev;
  678. udev = udev->next;
  679. }
  680. return NULL;
  681. }
  682. static int ohci_rh_port_reset(int port)
  683. {
  684. int retry;
  685. int reset_time;
  686. uint32_t t0;
  687. reset_time = usbh_tick_from_millisecond(PORT_RESET_TIME_MS);
  688. for (retry = 0; retry < PORT_RESET_RETRY; retry++)
  689. {
  690. _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_PRS_Msk;
  691. t0 = usbh_get_ticks();
  692. while (usbh_get_ticks() - t0 < (reset_time) + 1)
  693. {
  694. /*
  695. * If device is disconnected or port enabled, we can stop port reset.
  696. */
  697. if (((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) ||
  698. ((_ohci->HcRhPortStatus[port] & (USBH_HcRhPortStatus_PES_Msk | USBH_HcRhPortStatus_CCS_Msk)) == (USBH_HcRhPortStatus_PES_Msk | USBH_HcRhPortStatus_CCS_Msk)))
  699. goto port_reset_done;
  700. }
  701. reset_time += PORT_RESET_RETRY_INC_MS;
  702. }
  703. USB_debug("OHCI port %d - port reset failed!\n", port + 1);
  704. return USBH_ERR_PORT_RESET;
  705. port_reset_done:
  706. if ((_ohci->HcRhPortStatus[port] & USBH_HcRhPortStatus_CCS_Msk) == 0) /* check again if device disconnected */
  707. {
  708. _ohci->HcRhPortStatus[port] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */
  709. return USBH_ERR_DISCONNECTED;
  710. }
  711. return USBH_OK; /* port reset success */
  712. }
  713. static int ohci_rh_polling(void)
  714. {
  715. int i, change = 0;
  716. UDEV_T *udev;
  717. int ret;
  718. for (i = 0; i < OHCI_PORT_CNT; i++)
  719. {
  720. /* clear unwanted port change status */
  721. _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_OCIC_Msk | USBH_HcRhPortStatus_PRSC_Msk |
  722. USBH_HcRhPortStatus_PSSC_Msk | USBH_HcRhPortStatus_PESC_Msk;
  723. if ((_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CSC_Msk) == 0)
  724. continue;
  725. rt_kprintf("OHCI port%d status change: 0x%x\n", i + 1, _ohci->HcRhPortStatus[i]);
  726. /*--------------------------------------------------------------------------------*/
  727. /* connect status change */
  728. /*--------------------------------------------------------------------------------*/
  729. _ohci->HcRhPortStatus[i] = USBH_HcRhPortStatus_CSC_Msk; /* clear CSC */
  730. if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_CCS_Msk)
  731. {
  732. /*----------------------------------------------------------------------------*/
  733. /* First of all, check if there's any previously connected device. */
  734. /*----------------------------------------------------------------------------*/
  735. while (1)
  736. {
  737. udev = ohci_find_device_by_port(i + 1);
  738. if (udev == NULL)
  739. break;
  740. usbh_disconnect_device(udev);
  741. }
  742. rt_kprintf("OHCI connect device.\n");
  743. if (ohci_rh_port_reset(i) != USBH_OK)
  744. continue;
  745. /*
  746. * Port reset success...
  747. */
  748. udev = alloc_device();
  749. if (udev == NULL)
  750. continue;
  751. udev->parent = NULL;
  752. udev->port_num = i + 1;
  753. if (_ohci->HcRhPortStatus[i] & USBH_HcRhPortStatus_LSDA_Msk)
  754. udev->speed = SPEED_LOW;
  755. else
  756. udev->speed = SPEED_FULL;
  757. udev->hc_driver = &ohci_driver;
  758. ret = usbh_connect_device(udev);
  759. if (ret < 0)
  760. {
  761. USB_error("connect_device error! [%d]\n", ret);
  762. free_device(udev);
  763. }
  764. change = 1;
  765. }
  766. else
  767. {
  768. /*
  769. * Device disconnected
  770. */
  771. rt_kprintf("OHCI disconnect device.\n");
  772. while (1)
  773. {
  774. udev = ohci_find_device_by_port(i + 1);
  775. if (udev == NULL)
  776. break;
  777. usbh_disconnect_device(udev);
  778. }
  779. change = 1;
  780. }
  781. }
  782. return change;
  783. }
  784. void td_done(TD_T *td)
  785. {
  786. UTR_T *utr = td->utr;
  787. uint32_t info;
  788. int cc;
  789. info = td->Info;
  790. TD_debug("td_done: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", (int)td, td->Info, td->CBP, td->NextTD, td->BE);
  791. /* ISO ... drivers see per-TD length/status */
  792. if ((info & TD_TYPE_Msk) == TD_TYPE_ISO)
  793. {
  794. uint16_t sf;
  795. int idx;
  796. sf = info & 0xFFFF;
  797. idx = ((sf + 0x10000 - utr->iso_sf) & 0xFFFF) / get_ohci_interval(td->ed->bInterval);
  798. if (idx >= IF_PER_UTR)
  799. {
  800. USB_error("ISO invalid index!! %d, %d\n", sf, utr->iso_sf);
  801. goto td_out;
  802. }
  803. cc = (td->PSW[0] >> 12) & 0xF;
  804. if (cc == 0xF) /* this frame was not transferred */
  805. {
  806. USB_debug("ISO F %d N/A!\n", sf);
  807. utr->iso_status[idx] = USBH_ERR_SCH_OVERRUN;
  808. goto td_out;
  809. }
  810. if ((cc != 0) && (cc != CC_DATA_UNDERRUN))
  811. {
  812. utr->iso_status[idx] = USBH_ERR_CC_NO_ERR - cc;
  813. goto td_out;
  814. }
  815. utr->iso_status[idx] = 0;
  816. utr->iso_xlen[idx] = td->PSW[0] & 0x7FF;
  817. }
  818. else
  819. {
  820. cc = TD_CC_GET(info);
  821. /* short packet is fine */
  822. if ((cc != CC_NOERROR) && (cc != CC_DATA_UNDERRUN))
  823. {
  824. USB_error("TD error, CC = 0x%x\n", cc);
  825. if (cc == CC_STALL)
  826. utr->status = USBH_ERR_STALL;
  827. else
  828. utr->status = USBH_ERR_TRANSFER;
  829. }
  830. switch (info & TD_TYPE_Msk)
  831. {
  832. case TD_TYPE_CTRL:
  833. if (info & TD_CTRL_DATA)
  834. {
  835. if (td->CBP == 0)
  836. utr->xfer_len += td->BE - td->buff_start + 1;
  837. else
  838. utr->xfer_len += td->CBP - td->buff_start;
  839. }
  840. break;
  841. case TD_TYPE_BULK:
  842. case TD_TYPE_INT:
  843. if (td->CBP == 0)
  844. utr->xfer_len += td->BE - td->buff_start + 1;
  845. else
  846. utr->xfer_len += td->CBP - td->buff_start;
  847. break;
  848. }
  849. }
  850. td_out:
  851. utr->td_cnt--;
  852. /* If all TDs are done, call-back to requester. */
  853. if (utr->td_cnt == 0)
  854. {
  855. utr->bIsTransferDone = 1;
  856. if (utr->func)
  857. utr->func(utr);
  858. }
  859. }
  860. /* in IRQ context */
  861. static void remove_ed()
  862. {
  863. ED_T *ed, *ed_p, *ied;
  864. TD_T *td, *td_next;
  865. UTR_T *utr;
  866. int found;
  867. while (ed_remove_list != NULL)
  868. {
  869. ED_debug("Remove ED: 0x%x, %d\n", (int)ed_remove_list, ed_remove_list->bInterval);
  870. ed_p = ed_remove_list;
  871. found = 0;
  872. /*--------------------------------------------------------------------------------*/
  873. /* Remove endpoint from Control List if found */
  874. /*--------------------------------------------------------------------------------*/
  875. if ((ed_p->Info & ED_EP_ADDR_Msk) == 0)
  876. {
  877. if (_ohci->HcControlHeadED == (uint32_t)ed_p)
  878. {
  879. _ohci->HcControlHeadED = (uint32_t)ed_p->NextED;
  880. found = 1;
  881. }
  882. else
  883. {
  884. ed = (ED_T *)_ohci->HcControlHeadED;
  885. while (ed != NULL)
  886. {
  887. if (ed->NextED == (uint32_t)ed_p)
  888. {
  889. ed->NextED = ed_p->NextED;
  890. found = 1;
  891. }
  892. ed = (ED_T *)ed->NextED;
  893. }
  894. }
  895. }
  896. /*--------------------------------------------------------------------------------*/
  897. /* Remove INT or ISO endpoint from HCCA interrupt table */
  898. /*--------------------------------------------------------------------------------*/
  899. else if (ed_p->bInterval > 0)
  900. {
  901. ied = get_int_tree_head_node(ed_p->bInterval);
  902. ed = ied;
  903. while (ed != NULL)
  904. {
  905. if (ed->NextED == (uint32_t)ed_p)
  906. {
  907. ed->NextED = ed_p->NextED;
  908. found = 1;
  909. break;
  910. }
  911. ed = (ED_T *)ed->NextED;
  912. }
  913. }
  914. /*--------------------------------------------------------------------------------*/
  915. /* Remove endpoint from Bulk List if found */
  916. /*--------------------------------------------------------------------------------*/
  917. else
  918. {
  919. if (_ohci->HcBulkHeadED == (uint32_t)ed_p)
  920. {
  921. ed = (ED_T *)ed_p;
  922. _ohci->HcBulkHeadED = ed_p->NextED;
  923. found = 1;
  924. }
  925. else
  926. {
  927. ed = (ED_T *)_ohci->HcBulkHeadED;
  928. while (ed != NULL)
  929. {
  930. if (ed->NextED == (uint32_t)ed_p)
  931. {
  932. ed->NextED = ed_p->NextED;
  933. found = 1;
  934. }
  935. ed = (ED_T *)ed->NextED;
  936. }
  937. }
  938. }
  939. /*--------------------------------------------------------------------------------*/
  940. /* Remove and free all TDs under this endpoint */
  941. /*--------------------------------------------------------------------------------*/
  942. if (found)
  943. {
  944. td = (TD_T *)(ed_p->HeadP & ~0x3);
  945. if (td != NULL)
  946. {
  947. while (td != NULL)
  948. {
  949. utr = td->utr;
  950. td_next = (TD_T *)td->NextTD;
  951. free_ohci_TD(td);
  952. td = td_next;
  953. utr->td_cnt--;
  954. if (utr->td_cnt == 0)
  955. {
  956. utr->status = USBH_ERR_ABORT;
  957. utr->bIsTransferDone = 1;
  958. if (utr->func)
  959. utr->func(utr);
  960. }
  961. }
  962. }
  963. }
  964. /*
  965. * Done. Remove this ED from [ed_remove_list] and free it.
  966. */
  967. ed_remove_list = ed_p->next;
  968. free_ohci_ED(ed_p);
  969. }
  970. }
  971. //static irqreturn_t ohci_irq (struct usb_hcd *hcd)
  972. //void OHCI_IRQHandler(void)
  973. void nu_ohci_isr(int vector, void *param)
  974. {
  975. TD_T *td, *td_prev, *td_next;
  976. uint32_t int_sts;
  977. //if ( nu_sys_usb0_role() != USB0_ID_HOST ) return;
  978. int_sts = _ohci->HcInterruptStatus;
  979. //USB_debug("ohci int_sts = 0x%x\n", int_sts);
  980. if ((_ohci->HcInterruptEnable & USBH_HcInterruptEnable_SF_Msk) &&
  981. (int_sts & USBH_HcInterruptStatus_SF_Msk))
  982. {
  983. int_sts &= ~USBH_HcInterruptStatus_SF_Msk;
  984. _ohci->HcInterruptDisable = USBH_HcInterruptDisable_SF_Msk;
  985. remove_ed();
  986. _ohci->HcInterruptStatus = USBH_HcInterruptStatus_SF_Msk;
  987. }
  988. if (int_sts & USBH_HcInterruptStatus_WDH_Msk)
  989. {
  990. int_sts &= ~USBH_HcInterruptStatus_WDH_Msk;
  991. /*
  992. * reverse done list
  993. */
  994. td = (TD_T *)(_hcca->done_head & TD_ADDR_MASK);
  995. _hcca->done_head = 0;
  996. td_prev = NULL;
  997. _ohci->HcInterruptStatus = USBH_HcInterruptStatus_WDH_Msk;
  998. while (td != NULL)
  999. {
  1000. //TD_debug("Done list TD 0x%x => 0x%x\n", (int)td, (int)td->NextTD);
  1001. td_next = (TD_T *)(td->NextTD & TD_ADDR_MASK);
  1002. td->NextTD = (uint32_t)td_prev;
  1003. td_prev = td;
  1004. td = td_next;
  1005. }
  1006. td = td_prev; /* first TD of the reversed done list */
  1007. /*
  1008. * reclaim TDs
  1009. */
  1010. while (td != NULL)
  1011. {
  1012. TD_debug("Reclaim TD 0x%x, next 0x%x\n", (int)td, td->NextTD);
  1013. td_next = (TD_T *)td->NextTD;
  1014. td_done(td);
  1015. free_ohci_TD(td);
  1016. td = td_next;
  1017. }
  1018. }
  1019. if (int_sts & USBH_HcInterruptStatus_RHSC_Msk)
  1020. {
  1021. _ohci->HcInterruptDisable = USBH_HcInterruptDisable_RHSC_Msk;
  1022. }
  1023. _ohci->HcInterruptStatus = int_sts;
  1024. }
  1025. #ifdef ENABLE_DEBUG_MSG
  1026. void dump_ohci_int_table()
  1027. {
  1028. int i;
  1029. ED_T *ed;
  1030. for (i = 0; i < 32; i++)
  1031. // for (i = 0; i < 1; i++)
  1032. {
  1033. USB_debug("%02d: ", i);
  1034. ed = (ED_T *)_hcca->int_table[i];
  1035. while (ed != NULL)
  1036. {
  1037. USB_debug("0x%x (0x%x) => ", (int)ed, ed->HeadP);
  1038. ed = (ED_T *)ed->NextED;
  1039. }
  1040. rt_kprintf("0\n");
  1041. }
  1042. }
  1043. void dump_ohci_regs()
  1044. {
  1045. USB_debug("Dump OCHI registers:\n");
  1046. USB_debug(" HcRevision = 0x%x\n", _ohci->HcRevision);
  1047. USB_debug(" HcControl = 0x%x\n", _ohci->HcControl);
  1048. USB_debug(" HcCommandStatus = 0x%x\n", _ohci->HcCommandStatus);
  1049. USB_debug(" HcInterruptStatus = 0x%x\n", _ohci->HcInterruptStatus);
  1050. USB_debug(" HcInterruptEnable = 0x%x\n", _ohci->HcInterruptEnable);
  1051. USB_debug(" HcInterruptDisable = 0x%x\n", _ohci->HcInterruptDisable);
  1052. USB_debug(" HcHCCA = 0x%x\n", _ohci->HcHCCA);
  1053. USB_debug(" HcPeriodCurrentED = 0x%x\n", _ohci->HcPeriodCurrentED);
  1054. USB_debug(" HcControlHeadED = 0x%x\n", _ohci->HcControlHeadED);
  1055. USB_debug(" HcControlCurrentED = 0x%x\n", _ohci->HcControlCurrentED);
  1056. USB_debug(" HcBulkHeadED = 0x%x\n", _ohci->HcBulkHeadED);
  1057. USB_debug(" HcBulkCurrentED = 0x%x\n", _ohci->HcBulkCurrentED);
  1058. USB_debug(" HcDoneHead = 0x%x\n", _ohci->HcDoneHead);
  1059. USB_debug(" HcFmInterval = 0x%x\n", _ohci->HcFmInterval);
  1060. USB_debug(" HcFmRemaining = 0x%x\n", _ohci->HcFmRemaining);
  1061. USB_debug(" HcFmNumber = 0x%x\n", _ohci->HcFmNumber);
  1062. USB_debug(" HcPeriodicStart = 0x%x\n", _ohci->HcPeriodicStart);
  1063. USB_debug(" HcLSThreshold = 0x%x\n", _ohci->HcLSThreshold);
  1064. USB_debug(" HcRhDescriptorA = 0x%x\n", _ohci->HcRhDescriptorA);
  1065. USB_debug(" HcRhDescriptorB = 0x%x\n", _ohci->HcRhDescriptorB);
  1066. USB_debug(" HcRhStatus = 0x%x\n", _ohci->HcRhStatus);
  1067. USB_debug(" HcRhPortStatus0 = 0x%x\n", _ohci->HcRhPortStatus[0]);
  1068. USB_debug(" HcRhPortStatus1 = 0x%x\n", _ohci->HcRhPortStatus[1]);
  1069. USB_debug(" HcPhyControl = 0x%x\n", _ohci->HcPhyControl);
  1070. USB_debug(" HcMiscControl = 0x%x\n", _ohci->HcMiscControl);
  1071. }
  1072. void dump_ohci_ports()
  1073. {
  1074. USB_debug("_ohci port0=0x%x, port1=0x%x\n", _ohci->HcRhPortStatus[0], _ohci->HcRhPortStatus[1]);
  1075. }
  1076. #endif // ENABLE_DEBUG_MSG
  1077. HC_DRV_T ohci_driver =
  1078. {
  1079. ohci_init, /* init */
  1080. ohci_shutdown, /* shutdown */
  1081. ohci_suspend, /* suspend */
  1082. ohci_resume, /* resume */
  1083. ohci_ctrl_xfer, /* ctrl_xfer */
  1084. ohci_bulk_xfer, /* bulk_xfer */
  1085. ohci_int_xfer, /* int_xfer */
  1086. ohci_iso_xfer, /* iso_xfer */
  1087. ohci_quit_xfer, /* quit_xfer */
  1088. ohci_rh_port_reset, /* rthub_port_reset */
  1089. ohci_rh_polling /* rthub_polling */
  1090. };
  1091. /// @endcond HIDDEN_SYMBOLS
  1092. /*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/