/*++ Copyright (c) 1999, 2000 Microsoft Corporation Module Name: hydramp.c Abstract: USB 2.0 UHCI driver Environment: kernel mode only Notes: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved. Revision History: 8-12-2000 : created, jsenior --*/ #include "pch.h" //implements the following miniport functions: //UhciStopBIOS //UhciStartBIOS USB_MINIPORT_STATUS UhciStopBIOS( IN PDEVICE_DATA DeviceData, IN PHC_RESOURCES HcResources ) /*++ Routine Description: This routine steals the USB controller from the BIOS, making sure that it saves all the registers for later. Arguments: DeviceData - DeviceData for this USB controller. HcResources - The resources from the pnp start device. Return Value: NT status code. --*/ { USBCMD cmd; USBSTS status; PHC_REGISTER reg; USBSETUP legsup; USB_MINIPORT_STATUS mpStatus = USBMP_STATUS_SUCCESS; LARGE_INTEGER startTime; ULONG sofModifyValue = 0; LARGE_INTEGER finishTime; UhciKdPrint((DeviceData, 2, "'Stop Bios.\n")); UHCI_ASSERT(DeviceData, HcResources->CommonBufferVa != NULL); // validate our resources if ((HcResources->Flags & (HCR_IO_REGS | HCR_IRQ)) != (HCR_IO_REGS | HCR_IRQ)) { mpStatus = USBMP_STATUS_INIT_FAILURE; } // set up or device data structure reg = DeviceData->Registers = (PHC_REGISTER) (HcResources->DeviceRegisters); UhciKdPrint((DeviceData, 2, "'UHCI mapped Operational Regs = %x\n", reg)); // Disable PIRQD, NOTE: the Hal should have disabled it for us // // Disable the PIRQD // USBPORT_READ_CONFIG_SPACE( DeviceData, &legsup, LEGACY_BIOS_REGISTER, // offset of legacy bios reg sizeof(legsup)); #if DBG if (legsup & LEGSUP_USBPIRQD_EN) { UhciKdPrint((DeviceData, 2, "'PIRQD enabled on StartController (%x)\n", legsup)); } #endif UhciDisableInterrupts(DeviceData); // UhciGetRegistryParameters(DeviceData); // // Get the SOF modify value. First, retrieve from // hardware, then see if we have something in the // registry to set it to, then save it away. // /* sofModifyValue = READ_PORT_UCHAR(®->StartOfFrameModify.uc); // Grab any SOF ModifyValue indicated in the registry // bugbug - todo // UHCD_GetSOFRegModifyValue(DeviceObject, // &sofModifyValue); // save the SOF modify for posterity DeviceData->BiosStartOfFrameModify.uc = (CHAR) sofModifyValue; UHCI_ASSERT(DeviceData, sofModifyValue <= 255); */ // IF the host controller is in the global reset state, // clear the bit prior to trying to stop the controller. // stop the controller, // clear RUN bit and config flag so BIOS won't reinit cmd.us = READ_PORT_USHORT(®->UsbCommand.us); cmd.GlobalReset = 0; cmd.RunStop = 0; cmd.ConfigureFlag = 0; WRITE_PORT_USHORT(&DeviceData->Registers->UsbCommand.us, cmd.us); // NOTE: if no BIOS is present // halt bit is initially set with PIIX3 // halt bit is initially clear with VIA // now wait for HC to halt // Spec'ed to take 10 ms, so that's what we'll wait for KeQuerySystemTime(&finishTime); // get current time finishTime.QuadPart += 1000000; KeQuerySystemTime(&startTime); status.us = READ_PORT_USHORT(®->UsbStatus.us); while (!status.HCHalted) { LARGE_INTEGER sysTime; status.us = READ_PORT_USHORT(®->UsbStatus.us); UhciKdPrint((DeviceData, 2, "'STATUS = %x\n", status.us)); KeQuerySystemTime(&sysTime); if (sysTime.QuadPart >= finishTime.QuadPart) { // time out UhciKdPrint((DeviceData, 0, "'TIMEOUT HALTING CONTROLLER! (contact jsenior)\n")); TEST_TRAP(); break; } } WRITE_PORT_USHORT(®->UsbStatus.us, 0xff); // If a legacy bios, disable it. note that PIRQD is disabled if ((legsup & LEGSUP_BIOS_MODE) != 0) { UhciKdPrint((DeviceData, 0, "'*** uhci detected a USB legacy BIOS ***\n")); HcResources->DetectedLegacyBIOS = TRUE; // // if BIOS mode bits set we have to take over // USBPORT_READ_CONFIG_SPACE( DeviceData, &legsup, LEGACY_BIOS_REGISTER, // offset of legacy bios reg sizeof(legsup)); // shut off host controller SMI enable legsup = 0x0000; USBPORT_WRITE_CONFIG_SPACE( DeviceData, &legsup, LEGACY_BIOS_REGISTER, // offset of legacy bios reg sizeof(legsup)); } UhciKdPrint((DeviceData, 2, "'Legacy support reg = 0x%x\n", legsup)); UhciKdPrint((DeviceData, 2, "'exit UhciStopBIOS 0x%x\n", mpStatus)); return mpStatus; }