#include <grub/loader.h>
#include <grub/cs5536.h>
#include <grub/disk.h>
+#include <grub/cache.h>
GRUB_MOD_LICENSE ("GPLv3+");
static struct grub_ehci *ehci;
+static void
+sync_all_caches (struct grub_ehci *e)
+{
+ if (!e)
+ return;
+ if (e->td_virt)
+ grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) *
+ GRUB_EHCI_N_TD);
+ if (e->qh_virt)
+ grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) *
+ GRUB_EHCI_N_QH);
+ if (e->framelist_virt)
+ grub_arch_sync_dma_caches (e->framelist_virt, 4096);
+}
+
/* EHCC registers access functions */
static inline grub_uint32_t
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
{
grub_uint64_t maxtime;
+ sync_all_caches (e);
+
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
GRUB_EHCI_CMD_HC_RESET
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
e->next = ehci;
ehci = e;
+ sync_all_caches (e);
+
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
grub_dprintf ("ehci",
/* Found proper existing (and linked) QH, do setup of QH */
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
grub_ehci_setup_qh (qh_iter, transfer);
+ sync_all_caches (e);
return qh_iter;
}
struct grub_ehci_transfer_controller_data *cdata;
grub_uint32_t status;
+ sync_all_caches (e);
+
/* Check if EHCI is running and AL is enabled */
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
* i.e. reset token */
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
+ sync_all_caches (e);
+
/* Finito */
transfer->controller_data = cdata;
grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata);
+ sync_all_caches (e);
+
/* Additionally, do something with EHCI to make it running (what?) */
/* Try enable EHCI and AL */
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata);
+ sync_all_caches (e);
+
/* Evaluation of error code - currently we don't have GRUB USB error
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
* Order of evaluation is critical, specially bubble/stall. */
grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata);
+ sync_all_caches (e);
+
return GRUB_USB_ERR_NONE;
}
transfer->controller_data;
grub_uint32_t token, token_ftd;
+ sync_all_caches (e);
+
grub_dprintf ("ehci",
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
int i;
grub_uint64_t maxtime;
grub_uint32_t qh_phys;
+
+ sync_all_caches (e);
+
grub_uint32_t interrupt =
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata);
+ sync_all_caches (e);
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
return GRUB_USB_ERR_NONE;
}
/* Unlink QH from AL */
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
+ sync_all_caches (e);
+
/* If this is an interrupt transfer, we just wait for the periodic
* schedule to advance a few times and then assume that the EHCI
* controller has read the updated QH. */
grub_dprintf ("ehci", "cancel_transfer: end\n");
+ sync_all_caches (e);
+
return GRUB_USB_ERR_NONE;
}