uhci.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  1. /* uhci.c - UHCI Support. */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2008 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/dl.h>
  20. #include <grub/mm.h>
  21. #include <grub/misc.h>
  22. #include <grub/usb.h>
  23. #include <grub/usbtrans.h>
  24. #include <grub/pci.h>
  25. #include <grub/cpu/io.h>
  26. #include <grub/time.h>
  27. #include <grub/cpu/pci.h>
  28. #include <grub/disk.h>
  29. GRUB_MOD_LICENSE ("GPLv3+");
  30. #define GRUB_UHCI_IOMASK (0x7FF << 5)
  31. #define N_QH 256
  32. #define N_TD 640
  33. typedef enum
  34. {
  35. GRUB_UHCI_REG_USBCMD = 0x00,
  36. GRUB_UHCI_REG_USBINTR = 0x04,
  37. GRUB_UHCI_REG_FLBASEADD = 0x08,
  38. GRUB_UHCI_REG_PORTSC1 = 0x10,
  39. GRUB_UHCI_REG_PORTSC2 = 0x12,
  40. GRUB_UHCI_REG_USBLEGSUP = 0xc0
  41. } grub_uhci_reg_t;
  42. enum
  43. {
  44. GRUB_UHCI_DETECT_CHANGED = (1 << 1),
  45. GRUB_UHCI_DETECT_HAVE_DEVICE = 1,
  46. GRUB_UHCI_DETECT_LOW_SPEED = (1 << 8)
  47. };
  48. /* R/WC legacy support bits */
  49. enum
  50. {
  51. GRUB_UHCI_LEGSUP_END_A20GATE = (1 << 15),
  52. GRUB_UHCI_TRAP_BY_64H_WSTAT = (1 << 11),
  53. GRUB_UHCI_TRAP_BY_64H_RSTAT = (1 << 10),
  54. GRUB_UHCI_TRAP_BY_60H_WSTAT = (1 << 9),
  55. GRUB_UHCI_TRAP_BY_60H_RSTAT = (1 << 8)
  56. };
  57. /* Reset all legacy support - clear all R/WC bits and all R/W bits */
  58. #define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
  59. | GRUB_UHCI_TRAP_BY_64H_WSTAT \
  60. | GRUB_UHCI_TRAP_BY_64H_RSTAT \
  61. | GRUB_UHCI_TRAP_BY_60H_WSTAT \
  62. | GRUB_UHCI_TRAP_BY_60H_RSTAT )
  63. /* Some UHCI commands */
  64. #define GRUB_UHCI_CMD_RUN_STOP (1 << 0)
  65. #define GRUB_UHCI_CMD_HCRESET (1 << 1)
  66. #define GRUB_UHCI_CMD_MAXP (1 << 7)
  67. /* Important bits in structures */
  68. #define GRUB_UHCI_LINK_TERMINATE 1
  69. #define GRUB_UHCI_LINK_QUEUE_HEAD 2
  70. enum
  71. {
  72. GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002,
  73. GRUB_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004,
  74. GRUB_UHCI_REG_PORTSC_RESUME = 0x0040,
  75. GRUB_UHCI_REG_PORTSC_RESET = 0x0200,
  76. GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000,
  77. GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED
  78. | GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET
  79. | GRUB_UHCI_REG_PORTSC_SUSPEND,
  80. /* These bits should not be written as 1 unless we really need it */
  81. GRUB_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13))
  82. };
  83. /* UHCI Queue Head. */
  84. struct grub_uhci_qh
  85. {
  86. /* Queue head link pointer which points to the next queue head. */
  87. grub_uint32_t linkptr;
  88. /* Queue element link pointer which points to the first data object
  89. within the queue. */
  90. grub_uint32_t elinkptr;
  91. /* Queue heads are aligned on 16 bytes, pad so a queue head is 16
  92. bytes so we can store many in a 4K page. */
  93. grub_uint8_t pad[8];
  94. } GRUB_PACKED;
  95. /* UHCI Transfer Descriptor. */
  96. struct grub_uhci_td
  97. {
  98. /* Pointer to the next TD in the list. */
  99. grub_uint32_t linkptr;
  100. /* Control and status bits. */
  101. grub_uint32_t ctrl_status;
  102. /* All information required to transfer the Token packet. */
  103. grub_uint32_t token;
  104. /* A pointer to the data buffer, UHCI requires this pointer to be 32
  105. bits. */
  106. grub_uint32_t buffer;
  107. /* Another linkptr that is not overwritten by the Host Controller.
  108. This is GRUB specific. */
  109. grub_uint32_t linkptr2;
  110. /* 3 additional 32 bits words reserved for the Host Controller Driver. */
  111. grub_uint32_t data[3];
  112. } GRUB_PACKED;
  113. typedef volatile struct grub_uhci_td *grub_uhci_td_t;
  114. typedef volatile struct grub_uhci_qh *grub_uhci_qh_t;
  115. struct grub_uhci
  116. {
  117. grub_port_t iobase;
  118. volatile grub_uint32_t *framelist_virt;
  119. grub_uint32_t framelist_phys;
  120. struct grub_pci_dma_chunk *framelist_chunk;
  121. /* N_QH Queue Heads. */
  122. struct grub_pci_dma_chunk *qh_chunk;
  123. volatile grub_uhci_qh_t qh_virt;
  124. grub_uint32_t qh_phys;
  125. /* N_TD Transfer Descriptors. */
  126. struct grub_pci_dma_chunk *td_chunk;
  127. volatile grub_uhci_td_t td_virt;
  128. grub_uint32_t td_phys;
  129. /* Free Transfer Descriptors. */
  130. grub_uhci_td_t tdfree;
  131. int qh_busy[N_QH];
  132. struct grub_uhci *next;
  133. };
  134. static struct grub_uhci *uhci;
  135. static grub_uint16_t
  136. grub_uhci_readreg16 (struct grub_uhci *u, grub_uhci_reg_t reg)
  137. {
  138. return grub_inw (u->iobase + reg);
  139. }
  140. #if 0
  141. static grub_uint32_t
  142. grub_uhci_readreg32 (struct grub_uhci *u, grub_uhci_reg_t reg)
  143. {
  144. return grub_inl (u->iobase + reg);
  145. }
  146. #endif
  147. static void
  148. grub_uhci_writereg16 (struct grub_uhci *u,
  149. grub_uhci_reg_t reg, grub_uint16_t val)
  150. {
  151. grub_outw (val, u->iobase + reg);
  152. }
  153. static void
  154. grub_uhci_writereg32 (struct grub_uhci *u,
  155. grub_uhci_reg_t reg, grub_uint32_t val)
  156. {
  157. grub_outl (val, u->iobase + reg);
  158. }
  159. /* Iterate over all PCI devices. Determine if a device is an UHCI
  160. controller. If this is the case, initialize it. */
  161. static int
  162. grub_uhci_pci_iter (grub_pci_device_t dev,
  163. grub_pci_id_t pciid __attribute__((unused)),
  164. void *data __attribute__ ((unused)))
  165. {
  166. grub_uint32_t class_code;
  167. grub_uint32_t class;
  168. grub_uint32_t subclass;
  169. grub_uint32_t interf;
  170. grub_uint32_t base;
  171. grub_uint32_t fp;
  172. grub_pci_address_t addr;
  173. struct grub_uhci *u;
  174. int i;
  175. addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
  176. class_code = grub_pci_read (addr) >> 8;
  177. interf = class_code & 0xFF;
  178. subclass = (class_code >> 8) & 0xFF;
  179. class = class_code >> 16;
  180. /* If this is not an UHCI controller, just return. */
  181. if (class != 0x0c || subclass != 0x03 || interf != 0x00)
  182. return 0;
  183. /* Determine IO base address. */
  184. addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
  185. base = grub_pci_read (addr);
  186. /* Stop if there is no IO space base address defined. */
  187. if ((base & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO)
  188. return 0;
  189. if ((base & GRUB_UHCI_IOMASK) == 0)
  190. return 0;
  191. /* Set bus master - needed for coreboot or broken BIOSes */
  192. addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
  193. grub_pci_write_word(addr, GRUB_PCI_COMMAND_IO_ENABLED
  194. | GRUB_PCI_COMMAND_BUS_MASTER
  195. | GRUB_PCI_COMMAND_MEM_ENABLED
  196. | grub_pci_read_word (addr));
  197. grub_dprintf ("uhci", "base = %x\n", base);
  198. /* Allocate memory for the controller and register it. */
  199. u = grub_zalloc (sizeof (*u));
  200. if (! u)
  201. return 1;
  202. u->iobase = (base & GRUB_UHCI_IOMASK) + GRUB_MACHINE_PCI_IO_BASE;
  203. /* Reset PIRQ and SMI */
  204. addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);
  205. grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI);
  206. /* Reset the HC */
  207. grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET);
  208. grub_millisleep(5);
  209. /* Disable interrupts and commands (just to be safe) */
  210. grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0);
  211. /* Finish HC reset, HC remains disabled */
  212. grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0);
  213. /* Read back to be sure PCI write is done */
  214. grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
  215. /* Reserve a page for the frame list. */
  216. u->framelist_chunk = grub_memalign_dma32 (4096, 4096);
  217. if (! u->framelist_chunk)
  218. goto fail;
  219. u->framelist_virt = grub_dma_get_virt (u->framelist_chunk);
  220. u->framelist_phys = grub_dma_get_phys (u->framelist_chunk);
  221. grub_dprintf ("uhci",
  222. "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n",
  223. class, subclass, interf, u->iobase, u->framelist_virt);
  224. /* The QH pointer of UHCI is only 32 bits, make sure this
  225. code works on on 64 bits architectures. */
  226. u->qh_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_qh) * N_QH);
  227. if (! u->qh_chunk)
  228. goto fail;
  229. u->qh_virt = grub_dma_get_virt (u->qh_chunk);
  230. u->qh_phys = grub_dma_get_phys (u->qh_chunk);
  231. /* The TD pointer of UHCI is only 32 bits, make sure this
  232. code works on on 64 bits architectures. */
  233. u->td_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_td) * N_TD);
  234. if (! u->td_chunk)
  235. goto fail;
  236. u->td_virt = grub_dma_get_virt (u->td_chunk);
  237. u->td_phys = grub_dma_get_phys (u->td_chunk);
  238. grub_dprintf ("uhci", "QH=%p, TD=%p\n",
  239. u->qh_virt, u->td_virt);
  240. /* Link all Transfer Descriptors in a list of available Transfer
  241. Descriptors. */
  242. for (i = 0; i < N_TD; i++)
  243. u->td_virt[i].linkptr = u->td_phys + (i + 1) * sizeof(struct grub_uhci_td);
  244. u->td_virt[N_TD - 2].linkptr = 0;
  245. u->tdfree = u->td_virt;
  246. /* Setup the frame list pointers. Since no isochronous transfers
  247. are and will be supported, they all point to the (same!) queue
  248. head. */
  249. fp = u->qh_phys & (~15);
  250. /* Mark this as a queue head. */
  251. fp |= 2;
  252. for (i = 0; i < 1024; i++)
  253. u->framelist_virt[i] = fp;
  254. /* Program the framelist address into the UHCI controller. */
  255. grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD, u->framelist_phys);
  256. /* Make the Queue Heads point to each other. */
  257. for (i = 0; i < N_QH; i++)
  258. {
  259. /* Point to the next QH. */
  260. u->qh_virt[i].linkptr = ((u->qh_phys
  261. + (i + 1) * sizeof(struct grub_uhci_qh))
  262. & (~15));
  263. /* This is a QH. */
  264. u->qh_virt[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
  265. /* For the moment, do not point to a Transfer Descriptor. These
  266. are set at transfer time, so just terminate it. */
  267. u->qh_virt[i].elinkptr = 1;
  268. }
  269. /* The last Queue Head should terminate. */
  270. u->qh_virt[N_QH - 1].linkptr = 1;
  271. /* Enable UHCI again. */
  272. grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
  273. GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP);
  274. /* UHCI is initialized and ready for transfers. */
  275. grub_dprintf ("uhci", "UHCI initialized\n");
  276. #if 0
  277. {
  278. int i;
  279. for (i = 0; i < 10; i++)
  280. {
  281. grub_uint16_t frnum;
  282. frnum = grub_uhci_readreg16 (u, 6);
  283. grub_dprintf ("uhci", "Framenum=%d\n", frnum);
  284. grub_millisleep (100);
  285. }
  286. }
  287. #endif
  288. /* Link to uhci now that initialisation is successful. */
  289. u->next = uhci;
  290. uhci = u;
  291. return 0;
  292. fail:
  293. if (u)
  294. {
  295. grub_dma_free (u->qh_chunk);
  296. grub_dma_free (u->framelist_chunk);
  297. }
  298. grub_free (u);
  299. return 1;
  300. }
  301. static void
  302. grub_uhci_inithw (void)
  303. {
  304. grub_pci_iterate (grub_uhci_pci_iter, NULL);
  305. }
  306. static grub_uhci_td_t
  307. grub_alloc_td (struct grub_uhci *u)
  308. {
  309. grub_uhci_td_t ret;
  310. /* Check if there is a Transfer Descriptor available. */
  311. if (! u->tdfree)
  312. return NULL;
  313. ret = u->tdfree;
  314. u->tdfree = grub_dma_phys2virt (u->tdfree->linkptr, u->td_chunk);
  315. return ret;
  316. }
  317. static void
  318. grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
  319. {
  320. td->linkptr = grub_dma_virt2phys (u->tdfree, u->td_chunk);
  321. u->tdfree = td;
  322. }
  323. static void
  324. grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
  325. grub_usb_transfer_t transfer, grub_size_t *actual)
  326. {
  327. int i; /* Index of TD in transfer */
  328. u->qh_busy[qh - u->qh_virt] = 0;
  329. *actual = 0;
  330. /* Free the TDs in this queue and set last_trans. */
  331. for (i=0; td; i++)
  332. {
  333. grub_uhci_td_t tdprev;
  334. grub_dprintf ("uhci", "Freeing %p\n", td);
  335. /* Check state of TD and possibly set last_trans */
  336. if (transfer && (td->linkptr & 1))
  337. transfer->last_trans = i;
  338. *actual += (td->ctrl_status + 1) & 0x7ff;
  339. /* Unlink the queue. */
  340. tdprev = td;
  341. if (!td->linkptr2)
  342. td = 0;
  343. else
  344. td = grub_dma_phys2virt (td->linkptr2, u->td_chunk);
  345. /* Free the TD. */
  346. grub_free_td (u, tdprev);
  347. }
  348. }
  349. static grub_uhci_qh_t
  350. grub_alloc_qh (struct grub_uhci *u,
  351. grub_transaction_type_t tr __attribute__((unused)))
  352. {
  353. int i;
  354. grub_uhci_qh_t qh;
  355. /* Look for a Queue Head for this transfer. Skip the first QH if
  356. this is a Interrupt Transfer. */
  357. #if 0
  358. if (tr == GRUB_USB_TRANSACTION_TYPE_INTERRUPT)
  359. i = 0;
  360. else
  361. #endif
  362. i = 1;
  363. for (; i < N_QH; i++)
  364. {
  365. if (!u->qh_busy[i])
  366. break;
  367. }
  368. qh = &u->qh_virt[i];
  369. if (i == N_QH)
  370. {
  371. grub_error (GRUB_ERR_OUT_OF_MEMORY,
  372. "no free queue heads available");
  373. return NULL;
  374. }
  375. u->qh_busy[qh - u->qh_virt] = 1;
  376. return qh;
  377. }
  378. static grub_uhci_td_t
  379. grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
  380. grub_transfer_type_t type, unsigned int addr,
  381. unsigned int toggle, grub_size_t size,
  382. grub_uint32_t data, grub_usb_speed_t speed)
  383. {
  384. grub_uhci_td_t td;
  385. static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
  386. /* XXX: Check if data is <4GB. If it isn't, just copy stuff around.
  387. This is only relevant for 64 bits architectures. */
  388. /* Grab a free Transfer Descriptor and initialize it. */
  389. td = grub_alloc_td (u);
  390. if (! td)
  391. {
  392. grub_error (GRUB_ERR_OUT_OF_MEMORY,
  393. "no transfer descriptors available for UHCI transfer");
  394. return 0;
  395. }
  396. grub_dprintf ("uhci",
  397. "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
  398. endp, type, addr, toggle, (unsigned long) size, data, td);
  399. /* Don't point to any TD, just terminate. */
  400. td->linkptr = 1;
  401. /* Active! Only retry a transfer 3 times. */
  402. td->ctrl_status = (1 << 23) | (3 << 27) |
  403. ((speed == GRUB_USB_SPEED_LOW) ? (1 << 26) : 0);
  404. /* If zero bytes are transmitted, size is 0x7FF. Otherwise size is
  405. size-1. */
  406. if (size == 0)
  407. size = 0x7FF;
  408. else
  409. size = size - 1;
  410. /* Setup whatever is required for the token packet. */
  411. td->token = ((size << 21) | (toggle << 19) | (endp << 15)
  412. | (addr << 8) | tf[type]);
  413. td->buffer = data;
  414. return td;
  415. }
  416. struct grub_uhci_transfer_controller_data
  417. {
  418. grub_uhci_qh_t qh;
  419. grub_uhci_td_t td_first;
  420. };
  421. static grub_usb_err_t
  422. grub_uhci_setup_transfer (grub_usb_controller_t dev,
  423. grub_usb_transfer_t transfer)
  424. {
  425. struct grub_uhci *u = (struct grub_uhci *) dev->data;
  426. grub_uhci_td_t td;
  427. grub_uhci_td_t td_prev = NULL;
  428. int i;
  429. struct grub_uhci_transfer_controller_data *cdata;
  430. cdata = grub_malloc (sizeof (*cdata));
  431. if (!cdata)
  432. return GRUB_USB_ERR_INTERNAL;
  433. cdata->td_first = NULL;
  434. /* Allocate a queue head for the transfer queue. */
  435. cdata->qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL);
  436. if (! cdata->qh)
  437. {
  438. grub_free (cdata);
  439. return GRUB_USB_ERR_INTERNAL;
  440. }
  441. grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase);
  442. for (i = 0; i < transfer->transcnt; i++)
  443. {
  444. grub_usb_transaction_t tr = &transfer->transactions[i];
  445. td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid,
  446. transfer->devaddr, tr->toggle,
  447. tr->size, tr->data,
  448. transfer->dev->speed);
  449. if (! td)
  450. {
  451. grub_size_t actual = 0;
  452. /* Terminate and free. */
  453. if (td_prev)
  454. {
  455. td_prev->linkptr2 = 0;
  456. td_prev->linkptr = 1;
  457. }
  458. if (cdata->td_first)
  459. grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);
  460. grub_free (cdata);
  461. return GRUB_USB_ERR_INTERNAL;
  462. }
  463. if (! cdata->td_first)
  464. cdata->td_first = td;
  465. else
  466. {
  467. td_prev->linkptr2 = grub_dma_virt2phys (td, u->td_chunk);
  468. td_prev->linkptr = grub_dma_virt2phys (td, u->td_chunk);
  469. td_prev->linkptr |= 4;
  470. }
  471. td_prev = td;
  472. }
  473. td_prev->linkptr2 = 0;
  474. td_prev->linkptr = 1;
  475. grub_dprintf ("uhci", "setup transaction %d\n", transfer->type);
  476. /* Link it into the queue and terminate. Now the transaction can
  477. take place. */
  478. cdata->qh->elinkptr = grub_dma_virt2phys (cdata->td_first, u->td_chunk);
  479. grub_dprintf ("uhci", "initiate transaction\n");
  480. transfer->controller_data = cdata;
  481. return GRUB_USB_ERR_NONE;
  482. }
  483. static grub_usb_err_t
  484. grub_uhci_check_transfer (grub_usb_controller_t dev,
  485. grub_usb_transfer_t transfer,
  486. grub_size_t *actual)
  487. {
  488. struct grub_uhci *u = (struct grub_uhci *) dev->data;
  489. grub_uhci_td_t errtd;
  490. struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data;
  491. *actual = 0;
  492. if (cdata->qh->elinkptr & ~0x0f)
  493. errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk);
  494. else
  495. errtd = 0;
  496. if (errtd)
  497. {
  498. grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p, %x\n",
  499. errtd->ctrl_status, errtd->buffer & (~15), errtd,
  500. cdata->qh->elinkptr);
  501. }
  502. /* Check if the transaction completed. */
  503. if (cdata->qh->elinkptr & 1)
  504. {
  505. grub_dprintf ("uhci", "transaction complete\n");
  506. /* Place the QH back in the free list and deallocate the associated
  507. TDs. */
  508. cdata->qh->elinkptr = 1;
  509. grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
  510. grub_free (cdata);
  511. return GRUB_USB_ERR_NONE;
  512. }
  513. if (errtd && !(errtd->ctrl_status & (1 << 23)))
  514. {
  515. grub_usb_err_t err = GRUB_USB_ERR_NONE;
  516. /* Check if the endpoint is stalled. */
  517. if (errtd->ctrl_status & (1 << 22))
  518. err = GRUB_USB_ERR_STALL;
  519. /* Check if an error related to the data buffer occurred. */
  520. else if (errtd->ctrl_status & (1 << 21))
  521. err = GRUB_USB_ERR_DATA;
  522. /* Check if a babble error occurred. */
  523. else if (errtd->ctrl_status & (1 << 20))
  524. err = GRUB_USB_ERR_BABBLE;
  525. /* Check if a NAK occurred. */
  526. else if (errtd->ctrl_status & (1 << 19))
  527. err = GRUB_USB_ERR_NAK;
  528. /* Check if a timeout occurred. */
  529. else if (errtd->ctrl_status & (1 << 18))
  530. err = GRUB_USB_ERR_TIMEOUT;
  531. /* Check if a bitstuff error occurred. */
  532. else if (errtd->ctrl_status & (1 << 17))
  533. err = GRUB_USB_ERR_BITSTUFF;
  534. if (err)
  535. {
  536. grub_dprintf ("uhci", "transaction failed\n");
  537. /* Place the QH back in the free list and deallocate the associated
  538. TDs. */
  539. cdata->qh->elinkptr = 1;
  540. grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
  541. grub_free (cdata);
  542. return err;
  543. }
  544. }
  545. /* Fall through, no errors occurred, so the QH might be
  546. updated. */
  547. grub_dprintf ("uhci", "transaction fallthrough\n");
  548. return GRUB_USB_ERR_WAIT;
  549. }
  550. static grub_usb_err_t
  551. grub_uhci_cancel_transfer (grub_usb_controller_t dev,
  552. grub_usb_transfer_t transfer)
  553. {
  554. struct grub_uhci *u = (struct grub_uhci *) dev->data;
  555. grub_size_t actual;
  556. struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data;
  557. grub_dprintf ("uhci", "transaction cancel\n");
  558. /* Place the QH back in the free list and deallocate the associated
  559. TDs. */
  560. cdata->qh->elinkptr = 1;
  561. grub_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual);
  562. grub_free (cdata);
  563. return GRUB_USB_ERR_NONE;
  564. }
  565. static int
  566. grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data)
  567. {
  568. struct grub_uhci *u;
  569. struct grub_usb_controller dev;
  570. for (u = uhci; u; u = u->next)
  571. {
  572. dev.data = u;
  573. if (hook (&dev, hook_data))
  574. return 1;
  575. }
  576. return 0;
  577. }
  578. static grub_usb_err_t
  579. grub_uhci_portstatus (grub_usb_controller_t dev,
  580. unsigned int port, unsigned int enable)
  581. {
  582. struct grub_uhci *u = (struct grub_uhci *) dev->data;
  583. int reg;
  584. unsigned int status;
  585. grub_uint64_t endtime;
  586. grub_dprintf ("uhci", "portstatus, iobase:%08x\n", u->iobase);
  587. grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port);
  588. if (port == 0)
  589. reg = GRUB_UHCI_REG_PORTSC1;
  590. else if (port == 1)
  591. reg = GRUB_UHCI_REG_PORTSC2;
  592. else
  593. return GRUB_USB_ERR_INTERNAL;
  594. status = grub_uhci_readreg16 (u, reg);
  595. grub_dprintf ("uhci", "detect=0x%02x\n", status);
  596. if (!enable) /* We don't need reset port */
  597. {
  598. /* Disable the port. */
  599. grub_uhci_writereg16 (u, reg, 0 << 2);
  600. grub_dprintf ("uhci", "waiting for the port to be disabled\n");
  601. endtime = grub_get_time_ms () + 1000;
  602. while ((grub_uhci_readreg16 (u, reg) & (1 << 2)))
  603. if (grub_get_time_ms () > endtime)
  604. return GRUB_USB_ERR_TIMEOUT;
  605. status = grub_uhci_readreg16 (u, reg);
  606. grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
  607. return GRUB_USB_ERR_NONE;
  608. }
  609. /* Reset the port. */
  610. status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
  611. grub_uhci_writereg16 (u, reg, status | (1 << 9));
  612. grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
  613. /* Wait for the reset to complete. XXX: How long exactly? */
  614. grub_millisleep (50); /* For root hub should be nominaly 50ms */
  615. status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
  616. grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
  617. grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
  618. /* Note: some debug prints were removed because they affected reset/enable timing. */
  619. grub_millisleep (1); /* Probably not needed at all or only few microsecs. */
  620. /* Reset bits Connect & Enable Status Change */
  621. status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
  622. grub_uhci_writereg16 (u, reg, status | (1 << 3) | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED);
  623. grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
  624. /* Enable the port. */
  625. status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
  626. grub_uhci_writereg16 (u, reg, status | (1 << 2));
  627. grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
  628. endtime = grub_get_time_ms () + 1000;
  629. while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2)))
  630. if (grub_get_time_ms () > endtime)
  631. return GRUB_USB_ERR_TIMEOUT;
  632. /* Reset recovery time */
  633. grub_millisleep (10);
  634. /* Read final port status */
  635. status = grub_uhci_readreg16 (u, reg);
  636. grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
  637. return GRUB_USB_ERR_NONE;
  638. }
  639. static grub_usb_speed_t
  640. grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
  641. {
  642. struct grub_uhci *u = (struct grub_uhci *) dev->data;
  643. int reg;
  644. unsigned int status;
  645. grub_dprintf ("uhci", "detect_dev, iobase:%08x\n", u->iobase);
  646. if (port == 0)
  647. reg = GRUB_UHCI_REG_PORTSC1;
  648. else if (port == 1)
  649. reg = GRUB_UHCI_REG_PORTSC2;
  650. else
  651. return GRUB_USB_SPEED_NONE;
  652. status = grub_uhci_readreg16 (u, reg);
  653. grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
  654. /* Connect Status Change bit - it detects change of connection */
  655. if (status & GRUB_UHCI_DETECT_CHANGED)
  656. {
  657. *changed = 1;
  658. /* Reset bit Connect Status Change */
  659. grub_uhci_writereg16 (u, reg, (status & GRUB_UHCI_REG_PORTSC_RW)
  660. | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED);
  661. }
  662. else
  663. *changed = 0;
  664. if (! (status & GRUB_UHCI_DETECT_HAVE_DEVICE))
  665. return GRUB_USB_SPEED_NONE;
  666. else if (status & GRUB_UHCI_DETECT_LOW_SPEED)
  667. return GRUB_USB_SPEED_LOW;
  668. else
  669. return GRUB_USB_SPEED_FULL;
  670. }
  671. static int
  672. grub_uhci_hubports (grub_usb_controller_t dev __attribute__((unused)))
  673. {
  674. /* The root hub has exactly two ports. */
  675. return 2;
  676. }
  677. static struct grub_usb_controller_dev usb_controller =
  678. {
  679. .name = "uhci",
  680. .iterate = grub_uhci_iterate,
  681. .setup_transfer = grub_uhci_setup_transfer,
  682. .check_transfer = grub_uhci_check_transfer,
  683. .cancel_transfer = grub_uhci_cancel_transfer,
  684. .hubports = grub_uhci_hubports,
  685. .portstatus = grub_uhci_portstatus,
  686. .detect_dev = grub_uhci_detect_dev,
  687. /* estimated max. count of TDs for one bulk transfer */
  688. .max_bulk_tds = N_TD * 3 / 4
  689. };
  690. GRUB_MOD_INIT(uhci)
  691. {
  692. grub_stop_disk_firmware ();
  693. grub_uhci_inithw ();
  694. grub_usb_controller_dev_register (&usb_controller);
  695. grub_dprintf ("uhci", "registered\n");
  696. }
  697. GRUB_MOD_FINI(uhci)
  698. {
  699. struct grub_uhci *u;
  700. /* Disable all UHCI controllers. */
  701. for (u = uhci; u; u = u->next)
  702. grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
  703. /* Unregister the controller. */
  704. grub_usb_controller_dev_unregister (&usb_controller);
  705. }