/* xhci.c - xHCI dummy driver. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2011 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include GRUB_MOD_LICENSE ("GPLv3+"); /* This module solves only xHCI problem: * Machine is cold-booted. - > USB keyboard works in GRUB -> Windows boots -> * Windows does warm reboot -> USB keyboard does not work in GRUB. * This only happens in the ports marked superspeed on the machine. * The problem is that Windows seems to leave the the SS ports in SS mode * when rebooting and a BIOS bug(?) on warm boot leads to not setting * the SS ports in 2.0 mode. */ /* Identification values */ #define GRUB_XHCI_CLASS_CODE 0x0c0330 #define GRUB_XHCI_SBRN_VALUE 0x30 #define GRUB_XHCI_PCI_XUSB2PR 0xD0 #define GRUB_XHCI_PCI_USB3_PSSEN 0xD8 /* PCI iteration function... */ static int grub_xhci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)), void __attribute__ ((unused)) *data) { grub_pci_address_t addr; grub_uint32_t class_code; grub_uint8_t release; addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class_code = grub_pci_read (addr) >> 8; /* If this is not an XHCI controller, just return. */ if (class_code != GRUB_XHCI_CLASS_CODE) return 0; /* Check Serial Bus Release Number */ addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_SBRN_REG); release = grub_pci_read_byte (addr); if (release != GRUB_XHCI_SBRN_VALUE) return 0; /* Since GRUB does not currently handle xHCI we need * to make sure it is disabled and the ports put in 2.0 mode. * To be removed when xHCI is properly introduced. */ addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_USB3_PSSEN); grub_pci_write_word (addr, 0x0); grub_pci_read_word(addr); addr = grub_pci_make_address (dev, GRUB_XHCI_PCI_XUSB2PR); grub_pci_write_word (addr, 0x0); grub_pci_read_word(addr); return 0; } static int grub_xhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { return 0; } static grub_usb_err_t grub_xhci_setup_transfer (grub_usb_controller_t dev, grub_usb_transfer_t transfer) { if (dev && transfer) {} return GRUB_USB_ERR_NONE; } static grub_usb_err_t grub_xhci_check_transfer (grub_usb_controller_t dev, grub_usb_transfer_t transfer, grub_size_t * actual) { if (dev && transfer && actual) {} return GRUB_USB_ERR_NONE; } static grub_usb_err_t grub_xhci_cancel_transfer (grub_usb_controller_t dev, grub_usb_transfer_t transfer) { if (dev && transfer) {} return GRUB_USB_ERR_NONE; } static int grub_xhci_hubports (grub_usb_controller_t dev) { if (dev) {} return 0; } static grub_usb_err_t grub_xhci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { if (dev && port && enable) {} return GRUB_USB_ERR_NONE; } static grub_usb_speed_t grub_xhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) { if (dev &&changed) {} return GRUB_USB_SPEED_NONE; } static grub_err_t grub_xhci_fini_hw (int noreturn __attribute__ ((unused))) { return GRUB_USB_ERR_NONE; } static grub_err_t grub_xhci_restore_hw (void) { return GRUB_USB_ERR_NONE; } static void grub_xhci_inithw (void) { grub_pci_iterate (grub_xhci_pci_iter, NULL); } static struct grub_usb_controller_dev usb_controller = { .name = "xhci", .iterate = grub_xhci_iterate, .setup_transfer = grub_xhci_setup_transfer, .check_transfer = grub_xhci_check_transfer, .cancel_transfer = grub_xhci_cancel_transfer, .hubports = grub_xhci_hubports, .portstatus = grub_xhci_portstatus, .detect_dev = grub_xhci_detect_dev, .max_bulk_tds = 0 }; GRUB_MOD_INIT (xhci) { grub_xhci_inithw (); } GRUB_MOD_FINI (xhci) { grub_xhci_fini_hw (0); }