diff --git a/reactos/drivers/usb/nt4compat/CMakeLists.txt b/reactos/drivers/usb/nt4compat/CMakeLists.txt deleted file mode 100644 index 3075585ebec..00000000000 --- a/reactos/drivers/usb/nt4compat/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ - -add_subdirectory(usbdrv) diff --git a/reactos/drivers/usb/nt4compat/directory.rbuild b/reactos/drivers/usb/nt4compat/directory.rbuild deleted file mode 100644 index 8f2df716086..00000000000 --- a/reactos/drivers/usb/nt4compat/directory.rbuild +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/CMakeLists.txt b/reactos/drivers/usb/nt4compat/usbdrv/CMakeLists.txt deleted file mode 100644 index b44650507c1..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ - -add_definitions( - -DINCLUDE_EHCI - -D_MULTI_UHCI - -D_MULTI_EHCI - -D_X86) - -list(APPEND SOURCE - ehci.c - ohci.c - uhci.c - roothub.c - hub.c - td.c - usb.c - umss.c - bulkonly.c - cbi.c - devmgr.c - dmgrdisp.c - compdrv.c - etd.c - gendrv.c - mouse.c - keyboard.c - usbdriver.rc) - -add_library(usbdrv SHARED ${SOURCE}) - -set_module_type(usbdrv kernelmodedriver) -add_importlibs(usbdrv ntoskrnl hal) - -add_pch(usbdrv usbdriver.h) - -add_cd_file(TARGET usbdrv DESTINATION reactos/system32/drivers NO_CAB FOR all) diff --git a/reactos/drivers/usb/nt4compat/usbdrv/bulkonly.c b/reactos/drivers/usb/nt4compat/usbdrv/bulkonly.c deleted file mode 100644 index 7a0cc124689..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/bulkonly.c +++ /dev/null @@ -1,797 +0,0 @@ -/** - * bulkonly.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" -#include - -#define OLYMPUS_CSW( pdev_EXT, staTUS ) \ -( ( ( pdev_EXT )->flags & UMSS_DEV_FLAG_OLYMPUS_DEV ) ? ( ( staTUS ) == CSW_OLYMPUS_SIGNATURE ) : FALSE ) - -BOOLEAN umss_clear_pass_through_length(PIO_PACKET io_packet); - -NTSTATUS umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext); - -VOID umss_bulkonly_send_cbw_completion(IN PURB purb, IN PVOID context); - -VOID umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext); - -VOID umss_sync_submit_urb_completion(PURB purb, PVOID context); - -NTSTATUS umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext, PURB purb); - -VOID umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext); - -VOID umss_bulkonly_transfer_data_complete(PURB purb, PVOID reference); - -VOID umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference); - -VOID umss_bulkonly_reset_recovery(IN PVOID reference); - -VOID umss_bulkonly_get_status_complete(IN PURB purb, IN PVOID context); - -/*++ -Routine Description: - - Handler for all I/O requests using bulk-only protocol. - - Arguments: - - DeviceExtension - Device extension for our FDO. - -Return Value: - - NONE - ---*/ -NTSTATUS -umss_bulkonly_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext, IN PIO_PACKET io_packet) -{ - PCOMMAND_BLOCK_WRAPPER cbw; - NTSTATUS status; - - if (pdev_ext == NULL || io_packet == NULL || io_packet->pirp == NULL) - return STATUS_INVALID_PARAMETER; - - pdev_ext->retry = TRUE; - RtlCopyMemory(&pdev_ext->io_packet, io_packet, sizeof(pdev_ext->io_packet)); - - // Setup the command block wrapper for this request - cbw = &pdev_ext->cbw; - cbw->dCBWSignature = CBW_SIGNATURE; - cbw->dCBWTag = 0; - cbw->dCBWDataTransferLength = io_packet->data_length; - cbw->bmCBWFlags = (io_packet->flags & USB_DIR_IN) ? 0x80 : 0; - cbw->bCBWLun = io_packet->lun; - cbw->bCBWLength = io_packet->cdb_length; - RtlCopyMemory(cbw->CBWCB, io_packet->cdb, sizeof(cbw->CBWCB)); - - RtlZeroMemory(&pdev_ext->csw, sizeof(pdev_ext->csw)); - // Send the command block wrapper to the device. - // Calls UMSS_BulkOnlySendCBWComplete when transfer completes. - status = umss_bulk_transfer(pdev_ext, - USB_DIR_OUT, - cbw, sizeof(COMMAND_BLOCK_WRAPPER), umss_bulkonly_send_cbw_completion); - - return status; -} - - -NTSTATUS -umss_bulk_transfer(IN PUMSS_DEVICE_EXTENSION pdev_ext, - IN UCHAR trans_dir, IN PVOID buf, IN ULONG buf_length, IN PURBCOMPLETION completion) -{ - PURB purb; - NTSTATUS status; - DEV_HANDLE endp_handle; - - if (pdev_ext == NULL || buf == NULL || completion == NULL) - return STATUS_INVALID_PARAMETER; - - if (buf_length > (ULONG) MAX_BULK_TRANSFER_LENGTH) - return STATUS_INVALID_PARAMETER; - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - - if (purb == NULL) - return STATUS_NO_MEMORY; - - if (trans_dir == USB_DIR_OUT) - { - endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx); - } - else - { - endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx); - } - - UsbBuildInterruptOrBulkTransferRequest(purb, endp_handle, buf, buf_length, completion, pdev_ext, 0); - dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb); - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status == STATUS_PENDING) - { - return status; - } - - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - if (purb) - { - usb_free_mem(purb); - purb = NULL; - } - return status; -} - -VOID -umss_bulkonly_send_cbw_completion(IN PURB purb, IN PVOID context) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - - status = purb->status; - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE) - { - usb_free_mem(purb->data_buffer); - purb->data_buffer = NULL; - purb->data_length = 0; - } - - if (status != STATUS_SUCCESS) - { - if (usb_halted(status)) - { - //Schedule a work-item to do a reset recovery - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - } - else - { - // Device failed CBW without stalling, so complete with error - umss_complete_request(pdev_ext, status); - } - } - else - { - // CBW was accepted by device, so start data phase of I/O operation - umss_bulkonly_transfer_data(pdev_ext); - } - - usb_free_mem(purb); - - purb = NULL; - return; -} - -//can only be called at passive level -NTSTATUS -umss_sync_submit_urb(PUMSS_DEVICE_EXTENSION pdev_ext, PURB purb) -{ - NTSTATUS status; - - if (pdev_ext == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - purb->completion = umss_sync_submit_urb_completion; - purb->context = (PVOID) pdev_ext; - - dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb); - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status == STATUS_PENDING) - { - KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL); - status = purb->status; - } - else - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - return status; -} - -VOID -umss_sync_submit_urb_completion(PURB purb, PVOID context) -{ - PUMSS_DEVICE_EXTENSION pdev_ext; - - if (purb == NULL || context == NULL) - return; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - KeSetEvent(&pdev_ext->sync_event, 0, FALSE); - return; -} - -/*++ -Routine Description: - - Worker function used to execute a reset recovery after a stall. - - Arguments: - - Reference - Our device extension. - -Return Value: - - NONE - ---*/ -VOID -umss_bulkonly_reset_recovery(IN PVOID reference) -{ - PUMSS_DEVICE_EXTENSION pdev_ext; - URB urb; - NTSTATUS status; - DEV_HANDLE endp_handle; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) reference; - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_bulkonly_reset_recovery(): entering...\n")); - // Steps for reset recovery: - // 1. Send device a mass storage reset command on the default endpoint. - // 2. Reset the bulk-in endpoint. - // 3. Reset the bulk-out endpoint. - // 4. Complete the original I/O request with error. - - - // Build the mass storage reset command - UsbBuildVendorRequest(&urb, pdev_ext->dev_handle | 0xffff, //default pipe - NULL, //no extra data - 0, //no size - 0x21, //class, interface - BULK_ONLY_MASS_STORAGE_RESET, - 0, - pdev_ext->pif_desc->bInterfaceNumber, - NULL, //completion - NULL, //context - 0); //reference - - // Send mass storage reset command to device - status = umss_sync_submit_urb(pdev_ext, &urb); - - if (status != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_recovery(): Reset Recovery failed!\n")); - } - else - { - //Reset Bulk-in endpoint - endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx); - status = umss_reset_pipe(pdev_ext, endp_handle); - - if (!NT_SUCCESS(status)) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-in endpoint\n")); - } - - //Reset Bulk-out endpoint - endp_handle = usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx); - status = umss_reset_pipe(pdev_ext, endp_handle); - - if (!NT_SUCCESS(status)) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_reset_recovery(): Unable to clear Bulk-out endpoint\n")); - } - } - umss_complete_request(pdev_ext, status); -} - -/*++ -Routine Description: - - Schedules a bulk data transfer to/from the device. - - Arguments: - - DeviceExtension - Our FDO's device extension. - -Return Value: - - NONE - ---*/ -VOID -umss_bulkonly_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext) -{ - PVOID data_buf; - ULONG data_buf_length; - NTSTATUS status; - UCHAR trans_dir = USB_DIR_IN; // FIXME: Initialize this properly! - - // Steps for data phase - // 1. Get data buffer fragment (either SGD list, flat buffer, or none). - // 2. Schedule data transfer if neccessary. - // 3. Repeat 1-2 until all data transferred, or endpoint stalls. - // 4. Move to status phase. - - // Get next data buffer element, if any - data_buf = umss_get_buffer(pdev_ext, &data_buf_length); - - if (NULL == data_buf) - { - //No data to transfer, so move to status phase - umss_bulkonly_get_status(pdev_ext); - } - else - { - // Schedule the data transfer. - // Calls umss_bulkonly_transfer_data_complete when transfer completes. - - if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL) - trans_dir = (UCHAR) ((pdev_ext->cbw.bmCBWFlags & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT); - else if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE) - trans_dir = USB_DIR_IN; - - if ((status = umss_bulk_transfer(pdev_ext, - trans_dir, - data_buf, - data_buf_length, - umss_bulkonly_transfer_data_complete)) != STATUS_PENDING) - { - umss_complete_request(pdev_ext, status); - } - } - return; -} - -/*++ -Routine Description: - Completion handler for bulk data transfer requests. ---*/ -VOID -umss_bulkonly_transfer_data_complete(PURB purb, PVOID reference) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - pdev_ext = (PUMSS_DEVICE_EXTENSION) reference; - - status = purb->status; - - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - if (status != STATUS_SUCCESS) - { - // - // clear the data length if this is a scsi pass through request - // - umss_clear_pass_through_length(&pdev_ext->io_packet); - - // Device failed data phase - // Check if we need to clear stalled pipe - if (usb_halted(status)) - { - PULONG buf; - buf = usb_alloc_mem(NonPagedPool, 32); - if (!buf) return; - - buf[0] = (ULONG) pdev_ext; - buf[1] = (ULONG) purb->endp_handle; - - usb_dbg_print(DBGLVL_MINIMUM, ("umss_transfer_data_complete(): transfer data error!\n")); - if (!umss_schedule_workitem - ((PVOID) buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr, - pdev_ext->dev_handle)) - { - usb_free_mem(buf), buf = NULL; - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n")); - TRAP(); - umss_complete_request(pdev_ext, status); - } - } - else - { - //finish our request - umss_complete_request(pdev_ext, status); - } - } - else - { - // Start next part of data phase - //umss_bulkonly_transfer_data( pdev_ext ); - umss_bulkonly_get_status(pdev_ext); - //umss_complete_request( pdev_ext, status ); - } - - usb_free_mem(purb); - purb = NULL; - - return; // STATUS_MORE_PROCESSING_REQUIRED; -} - - -VOID -umss_bulkonly_reset_pipe_and_get_status(IN PVOID reference) -{ - PUMSS_DEVICE_EXTENSION pdev_ext; - DEV_HANDLE endp_handle; - NTSTATUS status; - - usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_pipe_and_get_status(): entering...\n")); - - pdev_ext = (PUMSS_DEVICE_EXTENSION) (((PULONG) reference)[0]); - endp_handle = (DEV_HANDLE) ((PULONG) reference)[1]; - usb_free_mem(reference); - reference = NULL; - - // Reset the endpoint - if ((status = umss_reset_pipe(pdev_ext, endp_handle)) != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe failed\n")); - umss_complete_request(pdev_ext, status); - return; - } - // Data phase is finished since the endpoint stalled, so go to status phase - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_reset_pipe_and_get_status(): reset pipe succeeds, continue to get status\n")); - umss_bulkonly_get_status(pdev_ext); -} - -VOID -umss_bulkonly_get_status(PUMSS_DEVICE_EXTENSION pdev_ext) -{ - NTSTATUS status; - // Schedule bulk transfer to get command status wrapper from device - status = umss_bulk_transfer(pdev_ext, - USB_DIR_IN, - &(pdev_ext->csw), - sizeof(COMMAND_STATUS_WRAPPER), umss_bulkonly_get_status_complete); - if (status != STATUS_PENDING) - { - umss_complete_request(pdev_ext, status); - } -} - -/*++ -Routine Description: - - Completion handler for bulk data transfer request. - - Arguments: - - DeviceObject - Previous device object. - Irp - Irp used for sending command. - Reference - Our FDO. - -Return Value: - - Driver-originated IRPs always return STATUS_MORE_PROCESSING_REQUIRED. - ---*/ -VOID -umss_bulkonly_get_status_complete(IN PURB purb, IN PVOID context) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - PCOMMAND_STATUS_WRAPPER csw; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - status = purb->status; - - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - csw = &(pdev_ext->csw); - if (status == STATUS_SUCCESS && - ((csw->dCSWSignature == CSW_SIGNATURE) || OLYMPUS_CSW(pdev_ext, csw->dCSWSignature))) - { - if (csw->bCSWStatus == CSW_STATUS_PASSED) - { - // Received valid CSW with good status - - if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL && - (pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE) && pdev_ext->io_packet.sense_data != NULL) - UMSS_FORGE_GOOD_SENSE(pdev_ext->io_packet.sense_data) - umss_complete_request(pdev_ext, STATUS_SUCCESS); - } - else if (csw->bCSWStatus == CSW_STATUS_FAILED) - { - // start a request sense if necessary - if ((pdev_ext->io_packet.flags & IOP_FLAG_REQ_SENSE) && - (pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL) - { - if (umss_bulkonly_send_sense_req(pdev_ext) != STATUS_PENDING) - { - // don't know how to handle. - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - else - { - // fall through to free the urb - } - } - else - { - // error occurred, reset device - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - } - } - else - { - // error occurred, reset device - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - } - } - else if ((status != STATUS_SUCCESS) && (usb_halted(status)) && (pdev_ext->retry)) - { - // Device stalled CSW transfer, retry once before failing - PULONG buf; - pdev_ext->retry = FALSE; - - buf = usb_alloc_mem(NonPagedPool, 32); - if (!buf) return; - - buf[0] = (ULONG) pdev_ext; - buf[1] = (ULONG) purb->endp_handle; - - if (!umss_schedule_workitem - ((PVOID) buf, umss_bulkonly_reset_pipe_and_get_status, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - usb_free_mem(buf), buf = NULL; - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_get_status_complete(): Failed to allocate work-item to reset pipe!\n")); - TRAP(); - umss_complete_request(pdev_ext, status); - } - } - else if (status != STATUS_CANCELLED) - { - // An error has occured. Reset the device. - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_bulkonly_reset_recovery, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_get_status_complete(): Failed to schedule work-item to reset pipe!\n")); - TRAP(); - umss_complete_request(pdev_ext, status); - } - } - else - { - // the request is canceled - usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_get_status_complete(): the request is canceled\n")); - umss_complete_request(pdev_ext, STATUS_CANCELLED); - } - - usb_free_mem(purb); - purb = NULL; - - return; -} - -/*++ -Routine Description: - - Queries Bulk-Only device for maximum LUN number - - Arguments: - - DeviceExtension - Our device extension. - -Return Value: - - Maximum LUN number for device, or 0 if error occurred. - ---*/ -CHAR -umss_bulkonly_get_maxlun(IN PUMSS_DEVICE_EXTENSION pdev_ext) -{ - PURB purb = NULL; - UCHAR max_lun; - NTSTATUS status; - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - - if (!purb) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_get_maxlun(): Failed to allocate URB, setting max LUN to 0\n")); - max_lun = 0; - } - else - { - // Build the get max lun command - UsbBuildVendorRequest(purb, (pdev_ext->dev_handle | 0xffff), &max_lun, sizeof(max_lun), 0xb1, //class, interface, in - BULK_ONLY_GET_MAX_LUN, 0, pdev_ext->pif_desc->bInterfaceNumber, NULL, NULL, 0); - - // Send get max lun command to device - status = umss_sync_submit_urb(pdev_ext, purb); - - if (status != STATUS_PENDING) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_bulkonly_get_maxlun(): Get Max LUN command failed, setting max LUN to 0!\n")); - max_lun = 0; - } - } - - if (purb) - usb_free_mem(purb); - - usb_dbg_print(DBGLVL_MINIMUM, ("umss_bulkonly_get_maxlun(): Max LUN = %x\n", max_lun)); - - return max_lun; -} - -PVOID -umss_get_buffer(PUMSS_DEVICE_EXTENSION pdev_ext, ULONG * buf_length) -{ - PVOID buffer; - - if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_NORMAL) - { - buffer = (PVOID) pdev_ext->io_packet.data_buffer; - *buf_length = pdev_ext->io_packet.data_length; - } - else if ((pdev_ext->io_packet.flags & IOP_FLAG_STAGE_MASK) == IOP_FLAG_STAGE_SENSE) - { - buffer = (PVOID) pdev_ext->io_packet.sense_data; - *buf_length = pdev_ext->io_packet.sense_data_length; - } - else - { - buffer = NULL; - *buf_length = 0; - } - - return buffer; -} - -BOOLEAN -umss_bulkonly_build_sense_cdb(PUMSS_DEVICE_EXTENSION pdev_ext, PCOMMAND_BLOCK_WRAPPER cbw) -{ - UCHAR sub_class; - PUCHAR cdb; - - if (pdev_ext == NULL || cbw == NULL) - return FALSE; - - cdb = cbw->CBWCB; - RtlZeroMemory(cdb, MAX_CDB_LENGTH); - sub_class = pdev_ext->pif_desc->bInterfaceSubClass; - - cdb[0] = SFF_REQUEST_SENSEE; - cdb[1] = pdev_ext->io_packet.lun << 5; - cdb[4] = 18; - - switch (sub_class) - { - case UMSS_SUBCLASS_SFF8070I: - case UMSS_SUBCLASS_UFI: - { - cbw->bCBWLength = 12; - break; - } - case UMSS_SUBCLASS_RBC: - case UMSS_SUBCLASS_SCSI_TCS: - { - cbw->bCBWLength = 6; - break; - } - default: - return FALSE; - } - return TRUE; -} - -NTSTATUS -umss_bulkonly_send_sense_req(PUMSS_DEVICE_EXTENSION pdev_ext) -{ - PCOMMAND_BLOCK_WRAPPER cbw; - NTSTATUS status; - - if (pdev_ext == NULL || pdev_ext->io_packet.sense_data == NULL - || pdev_ext->io_packet.sense_data_length < 18) - return STATUS_INVALID_PARAMETER; - - pdev_ext->retry = TRUE; - - cbw = usb_alloc_mem(NonPagedPool, sizeof(COMMAND_BLOCK_WRAPPER)); - if (!cbw) return STATUS_NO_MEMORY; - - RtlZeroMemory(cbw, sizeof(COMMAND_BLOCK_WRAPPER)); - pdev_ext->io_packet.flags &= ~IOP_FLAG_STAGE_MASK; - pdev_ext->io_packet.flags |= IOP_FLAG_STAGE_SENSE; - - cbw->dCBWSignature = CBW_SIGNATURE; - cbw->dCBWTag = 0; - cbw->dCBWDataTransferLength = pdev_ext->io_packet.sense_data_length; - cbw->bmCBWFlags = USB_DIR_IN; - cbw->bCBWLun = 0; - - if (umss_bulkonly_build_sense_cdb(pdev_ext, cbw) == FALSE) - { - usb_free_mem(cbw); - cbw = NULL; - return STATUS_UNSUCCESSFUL; - } - - status = umss_bulk_transfer(pdev_ext, - USB_DIR_OUT, - cbw, sizeof(COMMAND_BLOCK_WRAPPER), umss_bulkonly_send_cbw_completion); - - if (status != STATUS_PENDING) - { - usb_free_mem(cbw); - cbw = NULL; - } - return status; -} - -BOOLEAN -umss_clear_pass_through_length(PIO_PACKET io_packet) -{ - // - // clear the respective data length to meet request of scsi pass through requirement. - // - - BOOLEAN sense_stage; - ULONG ctrl_code; - PIO_STACK_LOCATION cur_stack; - PSCSI_PASS_THROUGH pass_through; - PSCSI_PASS_THROUGH_DIRECT pass_through_direct; - - if (io_packet == NULL) - return FALSE; - - if ((io_packet->flags & IOP_FLAG_SCSI_CTRL_TRANSFER) == 0) - return FALSE; - - sense_stage = FALSE; - if (io_packet->flags & IOP_FLAG_STAGE_SENSE) - sense_stage = TRUE; - - cur_stack = IoGetCurrentIrpStackLocation(io_packet->pirp); - ctrl_code = cur_stack->Parameters.DeviceIoControl.IoControlCode; - if (ctrl_code == IOCTL_SCSI_PASS_THROUGH_DIRECT) - { - pass_through_direct = io_packet->pirp->AssociatedIrp.SystemBuffer; - if (sense_stage) - pass_through_direct->SenseInfoLength = 0; - else - pass_through_direct->DataTransferLength = 0; - } - else if (ctrl_code == IOCTL_SCSI_PASS_THROUGH) - { - pass_through = io_packet->pirp->AssociatedIrp.SystemBuffer; - if (sense_stage) - pass_through->SenseInfoLength = 0; - else - pass_through->DataTransferLength = 0; - } - else - return FALSE; - - return TRUE; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/cbi.c b/reactos/drivers/usb/nt4compat/usbdrv/cbi.c deleted file mode 100644 index f90383cd3da..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/cbi.c +++ /dev/null @@ -1,302 +0,0 @@ -/** - * cbi.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -VOID umss_cbi_send_adsc_complete(PURB purb, PVOID context); -VOID umss_cbi_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext); -VOID umss_cbi_get_status(PUMSS_DEVICE_EXTENSION pdev_ext); -VOID umss_cbi_transfer_data_complete(PURB purb, PVOID context); -VOID umss_cbi_get_status_complete(PURB purb, PVOID context); - -NTSTATUS -umss_class_specific_request(IN PUMSS_DEVICE_EXTENSION pdev_ext, - IN UCHAR request, - IN UCHAR dir, - IN PVOID buffer, - IN ULONG buffer_length, - IN PURBCOMPLETION completion) -{ - PURB purb; - NTSTATUS status; - - UNREFERENCED_PARAMETER(dir); - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (!purb) return STATUS_NO_MEMORY; - - // Build URB for the ADSC command - UsbBuildVendorRequest(purb, - pdev_ext->dev_handle | 0xffff, - buffer, - buffer_length, - 0x21, request, 0, pdev_ext->pif_desc->bInterfaceNumber, completion, pdev_ext, 0); - - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - return status; - } - dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb); - return status; -} - -NTSTATUS -umss_cbi_startio(IN PUMSS_DEVICE_EXTENSION pdev_ext, IN PIO_PACKET io_packet) -{ - NTSTATUS status; - - status = STATUS_NOT_SUPPORTED; - return status; - - RtlCopyMemory(&pdev_ext->io_packet, io_packet, sizeof(pdev_ext->io_packet)); - - // Send the ADSC request to the device - // Calls UMSS_CbiSendADSCComplete when transfer completes - status = umss_class_specific_request(pdev_ext, - ACCEPT_DEVICE_SPECIFIC_COMMAND, - USB_DIR_OUT, - io_packet->cdb, io_packet->cdb_length, umss_cbi_send_adsc_complete); - - return status; -} - - - -VOID -umss_cbi_send_adsc_complete(PURB purb, PVOID context) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - PIO_PACKET io_packet; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - io_packet = &pdev_ext->io_packet; - - status = purb->status; - - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - if (!usb_success(status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("umss_cbi_send_adsc_complete(): Command Block Failure!!!\n")); - - // BUGBUG - Should reset device here? - // Device failed Command Block, complete with error - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - - } - else if (io_packet->data_length) - { - - usb_dbg_print(DBGLVL_HIGH, ("umss_cbi_send_adsc_complete(): Queuing Data Transfer DPC\n")); - umss_cbi_transfer_data(pdev_ext); - - } - else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI) - { - // Device supports interrupt pipe, so get status - umss_cbi_get_status(pdev_ext); - } - else - { - // Device does not report status, so complete request - umss_complete_request(pdev_ext, STATUS_SUCCESS); - } - - usb_free_mem(purb); - purb = NULL; -} - - - -VOID -umss_cbi_reset_pipe(IN PVOID reference) -{ - PUMSS_DEVICE_EXTENSION pdev_ext; - pdev_ext = (PUMSS_DEVICE_EXTENSION) reference; - - // Reset the appropriate pipe, based on data direction - umss_reset_pipe(pdev_ext, - (pdev_ext->io_packet.flags & USB_DIR_IN) ? - usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->in_endp_idx) : - usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, pdev_ext->out_endp_idx)); - - // Device stalled endpoint, so complete I/O operation with error. - // BUGBUG is this correct? Check spec... - umss_complete_request(pdev_ext, USB_STATUS_STALL_PID); -} - -VOID -umss_cbi_transfer_data(PUMSS_DEVICE_EXTENSION pdev_ext) -{ - PVOID buffer = NULL; - ULONG buffer_length; - - // Get next data buffer element, if any. - buffer = umss_get_buffer(pdev_ext, &buffer_length); - if (NULL == buffer) - { - //Done with data phase, so move to status phase if (supported) - - if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI) - { - // Device supports interrupt pipe, so get status - umss_cbi_get_status(pdev_ext); - } - else - { - // No interrupt pipe, so just complete the request - umss_complete_request(pdev_ext, STATUS_SUCCESS); - } - } - else - { - // Transfer next element of the data phase - umss_bulk_transfer(pdev_ext, - (UCHAR) ((pdev_ext->io_packet.flags & USB_DIR_IN) ? USB_DIR_IN : USB_DIR_OUT), - buffer, buffer_length, umss_cbi_transfer_data_complete); - } -} - - -VOID -umss_cbi_transfer_data_complete(PURB purb, PVOID context) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - status = purb->status; - - usb_free_mem(purb); - purb = NULL; - - if (!usb_success(status)) - { - // Device failed Data Transfer - // Check if we need to clear stalled pipe - if (usb_halted(status)) - { - // Reset pipe can only be done at passive level, so we need - // to schedule a work item to do it. - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_cbi_transfer_data_complete(): Failed to allocate work-item to reset pipe!\n")); - TRAP(); - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - } - else - { - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - return; - } - // Transfer succeeded - // umss_cbi_transfer_data( pdev_ext ); - umss_complete_request(pdev_ext, STATUS_SUCCESS); - return; -} - - -VOID -umss_cbi_get_status(PUMSS_DEVICE_EXTENSION pdev_ext) -{ - PURB purb; - NTSTATUS status; - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return; - - // Build a URB for our interrupt transfer - UsbBuildInterruptOrBulkTransferRequest(purb, - usb_make_handle((pdev_ext->dev_handle >> 16), pdev_ext->if_idx, - pdev_ext->int_endp_idx), (PUCHAR) & pdev_ext->idb, - sizeof(INTERRUPT_DATA_BLOCK), umss_cbi_get_status_complete, - pdev_ext, 0); - - // Call USB driver stack - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - return; - } - dev_mgr_register_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp, purb); - return; -} - - -VOID -umss_cbi_get_status_complete(PURB purb, PVOID context) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - PINTERRUPT_DATA_BLOCK idb; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - - status = purb->status; - dev_mgr_remove_irp(pdev_ext->dev_mgr, pdev_ext->io_packet.pirp); - - usb_free_mem(purb); - purb = NULL; - - if (!usb_success(status)) - { - // Device failed Data Transfer - // Check if we need to clear stalled pipe - if (usb_halted(status)) - { - if (!umss_schedule_workitem - ((PVOID) pdev_ext, umss_cbi_reset_pipe, pdev_ext->dev_mgr, pdev_ext->dev_handle)) - { - usb_dbg_print(DBGLVL_MINIMUM, - ("umss_cbi_get_status_complete(): Failed to allocate work-item to reset pipe!\n")); - TRAP(); - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - return; - } - } - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - return; - } - - // Interrupt transfer succeeded - idb = &(pdev_ext->idb); - - // Check for an error in the status block - if ((0 != idb->bType) || (0 != (idb->bValue & 0x3))) - { - umss_complete_request(pdev_ext, STATUS_IO_DEVICE_ERROR); - } - else - { - umss_complete_request(pdev_ext, STATUS_SUCCESS); - } -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/compdrv.c b/reactos/drivers/usb/nt4compat/usbdrv/compdrv.c deleted file mode 100644 index 8760a4f6fe3..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/compdrv.c +++ /dev/null @@ -1,511 +0,0 @@ -/** - * compdrv.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//this driver is part of the dev manager responsible to manage if device -#include "usbdriver.h" - -VOID compdev_set_cfg_completion(PURB purb, PVOID context); -VOID compdev_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN compdev_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle); -BOOLEAN compdev_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN compdev_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); - -BOOLEAN -compdev_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = 0; // Interface Class - pdriver->driver_desc.if_sub_class = 0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB composit dev driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - //we have no extra data sturcture currently - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = compdev_connect; - pdriver->disp_tbl.dev_disconnect = compdev_disconnect; - pdriver->disp_tbl.dev_stop = compdev_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - return TRUE; -} - -BOOLEAN -compdev_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - UNREFERENCED_PARAMETER(dev_mgr); - UNREFERENCED_PARAMETER(pdriver); - return TRUE; -} - -BOOLEAN -compdev_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - PURB purb; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - PUCHAR buf; - LONG credit, i, j; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_INTERFACE_DESC pif_desc; - PUSB_DEV_MANAGER dev_mgr; - - if (param == NULL || dev_handle == 0) - return FALSE; - - dev_mgr = param->dev_mgr; - - // let's set the configuration - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - - buf = usb_alloc_mem(NonPagedPool, 512); - if (buf == NULL) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): can not alloc buf\n")); - usb_free_mem(purb); - return FALSE; - } - - // before we set the configuration, let's search to find if there - // exist interfaces we supported - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - purb->endp_handle = dev_handle | 0xffff; - purb->data_buffer = buf; - purb->data_length = 512; - purb->completion = NULL; // this is an immediate request, no completion required - purb->context = NULL; - purb->reference = 0; - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = USB_DT_CONFIG << 8; - psetup->wIndex = 0; - psetup->wLength = 512; - - status = usb_submit_urb(dev_mgr, purb); - if (status == STATUS_PENDING) - { - TRAP(); - usb_free_mem(buf); - usb_free_mem(purb); - return FALSE; - } - - // let's scan the interfacs for those we recognize - pconfig_desc = (PUSB_CONFIGURATION_DESC) buf; - if (pconfig_desc->wTotalLength > 512) - { - usb_free_mem(buf); - usb_free_mem(purb); - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): error, bad configuration desc\n")); - return FALSE; - } - - pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1]; - for(i = 0, credit = 0; i < (LONG) pconfig_desc->bNumInterfaces; i++) - { - for(j = 0; j < DEVMGR_MAX_DRIVERS; j++) - { - credit = dev_mgr_score_driver_for_if(dev_mgr, &dev_mgr->driver_list[j], pif_desc); - if (credit) - break; - } - if (credit) - break; - - if (usb_skip_if_and_altif((PUCHAR *) & pif_desc)) - break; - } - - i = pconfig_desc->bConfigurationValue; - usb_free_mem(buf); - buf = NULL; - if (credit == 0) - { - usb_free_mem(purb); - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): oops..., no supported interface found\n")); - return FALSE; - } - - //set the configuration - urb_init(purb); - purb->endp_handle = dev_handle | 0xffff; - purb->data_buffer = NULL; - purb->data_length = 0; - purb->completion = compdev_set_cfg_completion; - purb->context = dev_mgr; - purb->reference = (ULONG) param->pdriver; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_CONFIGURATION; - psetup->wValue = (USHORT) i; - psetup->wIndex = 0; - psetup->wLength = 0; - - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_connect(): start config the device, cfgval=%d\n", i)); - status = usb_submit_urb(dev_mgr, purb); - - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - - if (status == STATUS_SUCCESS) - return TRUE; - - return FALSE; - } - - return TRUE; -} - -VOID -compdev_event_select_if_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param) -{ - PUSB_DEV_MANAGER dev_mgr; - DEV_HANDLE dev_handle; - - UNREFERENCED_PARAMETER(param); - UNREFERENCED_PARAMETER(context); - UNREFERENCED_PARAMETER(event); - - if (pdev == NULL) - return; - - // - // RtlZeroMemory( &cd, sizeof( cd ) ); - // - dev_mgr = dev_mgr_from_dev(pdev); - dev_handle = usb_make_handle(pdev->dev_id, 0, 0); - compdev_select_driver(dev_mgr, dev_handle); - return; -} - -BOOLEAN -compdev_post_event_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PUSB_EVENT pevent; - BOOLEAN bret; - PUSB_DEV pdev; - USE_BASIC_NON_PENDING_IRQL; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS) - return FALSE; - - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - bret = FALSE; - goto LBL_OUT; - } - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - { - bret = FALSE; - goto LBL_OUT; - } - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->event = USB_EVENT_DEFAULT; - pevent->pdev = pdev; - pevent->context = 0; - pevent->param = 0; - pevent->pnext = 0; //vertical queue for serialized operation - pevent->process_event = compdev_event_select_if_driver; - pevent->process_queue = event_list_default_process_queue; - - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); // wake up the dev_mgr_thread - bret = TRUE; - - LBL_OUT: - - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - usb_unlock_dev(pdev); - return bret; -} - -VOID -compdev_set_cfg_completion(PURB purb, PVOID context) -{ - DEV_HANDLE dev_handle; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdriver; - NTSTATUS status; - PUSB_DEV pdev; - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || context == NULL) - return; - - dev_handle = purb->endp_handle & ~0xffff; - dev_mgr = (PUSB_DEV_MANAGER) context; - pdriver = (PUSB_DRIVER) purb->reference; - - if (purb->status != STATUS_SUCCESS) - { - usb_free_mem(purb); - return; - } - - usb_free_mem(purb); - purb = NULL; - - // set the dev state - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - return; - } - // safe to release the pdev ref since we are in urb completion - usb_unlock_dev(pdev); - - lock_dev(pdev, TRUE); - if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB) - { - unlock_dev(pdev, TRUE); - return; - } - - if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE) - return; - - //transit the state to configured - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - unlock_dev(pdev, TRUE); - - // - // we change to use our thread for driver choosing. it will reduce - // the race condition when different pnp event comes simultaneously - // - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_set_cfg_completion(): start select driver for the dev\n")); - compdev_post_event_select_driver(dev_mgr, dev_handle); - - return; -} - -VOID -compdev_select_driver(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - URB urb; - LONG i, j, k, credit; - ULONG dev_id; - PUCHAR buf; - NTSTATUS status; - PUSB_DRIVER pcand, ptemp_drv; - - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_INTERFACE_DESC pif_desc; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_DEV pdev; - - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): entering...\n")); - - dev_id = dev_handle >> 16; - - buf = usb_alloc_mem(NonPagedPool, 512); - - if (buf == NULL) - return; - - // now let's get the descs, one configuration - urb_init(&urb); - psetup = (PUSB_CTRL_SETUP_PACKET) urb.setup_packet; - urb.endp_handle = dev_handle | 0xffff; - urb.data_buffer = buf; - urb.data_length = 512; - urb.completion = NULL; // this is an immediate request, no completion required - urb.context = NULL; - urb.reference = 0; - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = USB_DT_CONFIG << 8; - psetup->wIndex = 0; - psetup->wLength = 512; - - status = usb_submit_urb(dev_mgr, &urb); - if (status == STATUS_PENDING) - { - TRAP(); - } - - // let's scan the interfaces for those we recognize - pconfig_desc = (PUSB_CONFIGURATION_DESC) buf; - if (pconfig_desc->wTotalLength > 512) - { - usb_free_mem(buf); - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): error, bad configuration desc\n")); - return; - } - pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1]; - - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS) - { - usb_free_mem(buf); - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): error, dev does not exist\n")); - return; - } - - usb_dbg_print(DBGLVL_MAXIMUM, ("compdev_select_driver(): got %d interfaces\n", - (LONG)pconfig_desc->bNumInterfaces)); - - for(i = 0; i < (LONG) pconfig_desc->bNumInterfaces; i++) - { - for(j = 0, credit = 0, pcand = NULL; j < DEVMGR_MAX_DRIVERS; j++) - { - ptemp_drv = &dev_mgr->driver_list[j]; - k = dev_mgr_score_driver_for_if(dev_mgr, ptemp_drv, pif_desc); - if (k > credit) - credit = k, pcand = ptemp_drv; - } - - if (credit) - { - // ok, we find one - DEV_CONNECT_DATA param; - - if (pcand->disp_tbl.dev_connect) - { - param.dev_mgr = dev_mgr; - param.pdriver = pcand; - param.dev_handle = 0; - param.if_desc = pif_desc; - pcand->disp_tbl.dev_connect(¶m, usb_make_handle(dev_id, i, 0)); - } - } - if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE) - { - break; - } - } - usb_unlock_dev(pdev); - - if (buf) - { - usb_free_mem(buf); - buf = NULL; - } - return; -} - -BOOLEAN -compdev_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PUSB_DEV pdev; - LONG i; - ULONG dev_id; - PUSB_DRIVER pdrv; - NTSTATUS status; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - pdev = NULL; - dev_id = dev_handle >> 16; - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (pdev) - { - if (pdev->usb_config) - { - for(i = 0; i < pdev->usb_config->if_count; i++) - { - if ((pdrv = pdev->usb_config->interf[i].pif_drv)) - { - pdrv->disp_tbl.dev_stop(dev_mgr, usb_make_handle(dev_id, i, 0)); - } - } - } - } - if (status == STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - } - return TRUE; -} - -BOOLEAN -compdev_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PUSB_DEV pdev; - LONG i; - ULONG dev_id; - PUSB_DRIVER pdrv; - NTSTATUS status; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - pdev = NULL; - dev_id = dev_handle >> 16; - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (pdev) - { - if (pdev->usb_config) - { - for(i = 0; i < pdev->usb_config->if_count; i++) - { - if ((pdrv = pdev->usb_config->interf[i].pif_drv)) - { - pdrv->disp_tbl.dev_disconnect(dev_mgr, usb_make_handle(dev_id, i, 0)); - } - } - } - } - if (status == STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - } - return TRUE; -} - -// note: -// dev_mgr_set_driver seems to be dangeous since compdev, gendrv and hub and -// umss use it to set the driver while there may exist race condition when the -// dev_mgr_disconnect_dev is called. If the driver is set and the -// disconnect_dev cut in immediately, the stop or disconnect may not function -// well. Now hub and compdev's set dev_mgr_set_driver are ok. -// -// another danger comes from umss's dev irp processing. This may confuse the device -// when the disk is being read or written, and at the same time dmgrdisp's dispatch -// route irp request to the device a control request. diff --git a/reactos/drivers/usb/nt4compat/usbdrv/debug.h b/reactos/drivers/usb/nt4compat/usbdrv/debug.h deleted file mode 100644 index 49d9c16e362..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/debug.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _UHCIDBG_H_ -#define _UHCIDBG_H_ - -#define DBGLVL_OFF 0 // if gDebugLevel set to this, there is NO debug output -#define DBGLVL_MINIMUM 1 // minimum verbosity -#define DBGLVL_DEFAULT 2 // default verbosity level if no registry override -#define DBGLVL_MEDIUM 3 // medium verbosity -#define DBGLVL_HIGH 4 // highest 'safe' level (without severely affecting timing ) -#define DBGLVL_MAXIMUM 5 // maximum level, may be dangerous -#define DBGLVL_ULTRA 6 // ultra, prints hell lots of stuff from ISR/allocs/etc - -#ifndef DBGSTR_PREFIX -#define DBGSTR_PREFIX "wood_uhci: " -#endif - -#define DEBUG_UHCI TRUE -#define DEBUG_HUB TRUE -#define DEBUG_DEV_MGR TRUE - -#define DPRINT DbgPrint - - -#define UHCI_DBGOUTSIZE 512 - -#define hcd_dbg_print_cond( ilev, cond, _x_) \ - if( debug_level && ( ilev <= debug_level ) && ( cond )) { \ - DPRINT( DBGSTR_PREFIX ); \ - DPRINT _x_ ; \ - } - -#define hcd_dbg_print( ilev, _x_) hcd_dbg_print_cond( ilev, TRUE, _x_ ) - -extern ULONG debug_level; - -#if DBG - -#define uhci_dbg_print_cond( ilev, cond, _x_ ) hcd_dbg_print_cond( ilev, cond, _x_ ) -#define uhci_dbg_print( ilev, _x_) hcd_dbg_print_cond( ilev, TRUE, _x_ ) - -#define uhci_trap_cond( ilev, cond ) if ( debug_level && ( ilev <= debug_level ) && (cond) ) TRAP() -#define uhci_trap( ilev ) uhci_trap_cond( ilev, TRUE ) - - -#define uhci_assert( cond ) ASSERT( cond ) -#define dbg_count_list( _x_ ) usb_count_list( _x_ ) - -#define TRAP() DbgBreakPoint() - -#else // if not DBG - -// dummy definitions that go away in the retail build - -#define uhci_dbg_print_cond( ilev, cond, _x_ ) -#define uhci_dbg_print( ilev, _x_) -#define uhci_trap_cont( ilev, cond ) -#define uhci_trap( ilev ) -#define uhci_assert( cond ) -#define TRAP() -#define dbg_count_list( _x_ ) 0 - -#endif //DBG - -#define usb_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ ) -#define ehci_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ ) -#define ohci_dbg_print( ilev, _x_ ) uhci_dbg_print( ilev, _x_ ) -#define ehci_dbg_print_cond( ilev, cond, _x_ ) uhci_dbg_print_cond( ilev, cond, _x_ ) - -#define DO_NOTHING - -LONG usb_count_list( struct _LIST_ENTRY* list_head ); -#endif // included diff --git a/reactos/drivers/usb/nt4compat/usbdrv/devmgr.c b/reactos/drivers/usb/nt4compat/usbdrv/devmgr.c deleted file mode 100644 index 6b0862aebb2..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/devmgr.c +++ /dev/null @@ -1,1564 +0,0 @@ -/** - * devmgr.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -#define realloc_buf( pdEV, puRB ) \ -{\ - PBYTE data_buf;\ - int i;\ - data_buf = usb_alloc_mem( NonPagedPool, ( pdEV )->desc_buf_size += 1024 );\ - if (!data_buf)\ - {\ - goto LBL_OUT;\ - }\ - RtlZeroMemory( data_buf, ( pdEV )->desc_buf_size );\ - for( i = 0; i < ( LONG )( puRB )->context; i++ )\ - {\ - data_buf[ i ] = ( pdEV )->desc_buf[ i ];\ - }\ - usb_free_mem( ( pdEV )->desc_buf );\ - ( pdEV )->desc_buf = data_buf;\ - ( pdEV )->pusb_dev_desc = ( PUSB_DEVICE_DESC )( pdEV )->desc_buf;\ - ( puRB )->data_buffer = &data_buf[ ( LONG ) ( puRB )->context ];\ -} - - -//---------------------------------------------------------- - -USB_DRIVER g_driver_list[DEVMGR_MAX_DRIVERS]; -USB_DEV_MANAGER g_dev_mgr; - - -//---------------------------------------------------------- -BOOLEAN -dev_mgr_set_if_driver(PUSB_DEV_MANAGER dev_mgr, - DEV_HANDLE if_handle, - PUSB_DRIVER pdriver, - PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle, and must have dev_lock acquired. - ) -{ - ULONG i; - USE_BASIC_NON_PENDING_IRQL; - - if (dev_mgr == NULL || if_handle == 0 || pdriver == NULL) - return FALSE; - - i = if_idx_from_handle(if_handle); - if (pdev != NULL) - { - if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB) - { - pdev->usb_config->interf[i].pif_drv = pdriver; - return TRUE; - } - return FALSE; - } - - if (usb_query_and_lock_dev(dev_mgr, if_handle, &pdev) != STATUS_SUCCESS) - return FALSE; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) != USB_DEV_STATE_ZOMB) - { - pdev->usb_config->interf[i].pif_drv = pdriver; - } - unlock_dev(pdev, TRUE); - usb_unlock_dev(pdev); - return TRUE; -} - -BOOLEAN -dev_mgr_set_driver(PUSB_DEV_MANAGER dev_mgr, - DEV_HANDLE dev_handle, - PUSB_DRIVER pdriver, - PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle - ) -{ - USE_BASIC_NON_PENDING_IRQL; - - if (dev_mgr == NULL || dev_handle == 0 || pdriver == NULL) - return FALSE; - - if (pdev != NULL) - { - if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB) - { - pdev->dev_driver = pdriver; - return TRUE; - } - return FALSE; - } - - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS) - return FALSE; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) < USB_DEV_STATE_BEFORE_ZOMB) - { - pdev->dev_driver = pdriver; - } - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - - return TRUE; -} - -BOOLEAN -dev_mgr_post_event(PUSB_DEV_MANAGER dev_mgr, PUSB_EVENT event) -{ - KIRQL old_irql; - - if (dev_mgr == NULL || event == NULL) - return FALSE; - - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - InsertTailList(&dev_mgr->event_list, &event->event_link); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - return TRUE; -} - -VOID -dev_mgr_driver_entry_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr) -{ - // Device Info - - RtlZeroMemory(pdrvr, sizeof(USB_DRIVER) * DEVMGR_MAX_DRIVERS); - - pdrvr[RH_DRIVER_IDX].driver_init = rh_driver_init; // in fact, this routine will init the rh device rather that the driver struct. - pdrvr[RH_DRIVER_IDX].driver_destroy = rh_driver_destroy; // we do not need rh to destroy currently, since that may means fatal hardware failure - - pdrvr[HUB_DRIVER_IDX].driver_init = hub_driver_init; //no need, since dev_mgr is also a hub driver - pdrvr[HUB_DRIVER_IDX].driver_destroy = hub_driver_destroy; - - pdrvr[UMSS_DRIVER_IDX].driver_init = umss_if_driver_init; - pdrvr[UMSS_DRIVER_IDX].driver_destroy = umss_if_driver_destroy; - - pdrvr[COMP_DRIVER_IDX].driver_init = compdev_driver_init; - pdrvr[COMP_DRIVER_IDX].driver_destroy = compdev_driver_destroy; - - pdrvr[GEN_DRIVER_IDX].driver_init = gendrv_driver_init; - pdrvr[GEN_DRIVER_IDX].driver_destroy = gendrv_driver_destroy; - - pdrvr[GEN_IF_DRIVER_IDX].driver_init = gendrv_if_driver_init; - pdrvr[GEN_IF_DRIVER_IDX].driver_destroy = gendrv_if_driver_destroy; - - pdrvr[MOUSE_DRIVER_IDX].driver_init = mouse_driver_init; - pdrvr[MOUSE_DRIVER_IDX].driver_destroy = mouse_driver_destroy; - - pdrvr[KEYBOARD_DRIVER_IDX].driver_init = kbd_driver_init; - pdrvr[KEYBOARD_DRIVER_IDX].driver_destroy = kbd_driver_destroy; -} - -BOOLEAN -dev_mgr_strobe(PUSB_DEV_MANAGER dev_mgr) -{ - PUSB_EVENT pevent; - HANDLE thread_handle; - - if (dev_mgr == NULL) - return FALSE; - if (dev_mgr->hcd_count == 0) - return FALSE; - - dev_mgr->term_flag = FALSE; - - if (dev_mgr->hcd_count == 0) - return FALSE; - - KeInitializeSpinLock(&dev_mgr->event_list_lock); - InitializeListHead(&dev_mgr->event_list); - init_event_pool(&dev_mgr->event_pool); - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - { - destroy_event_pool(&dev_mgr->event_pool); - return FALSE; - } - - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->event = USB_EVENT_INIT_DEV_MGR; - - pevent->process_queue = event_list_default_process_queue; - pevent->process_event = (PROCESS_EVENT)dev_mgr_event_init; - - pevent->context = (ULONG) dev_mgr; - - KeInitializeEvent(&dev_mgr->wake_up_event, SynchronizationEvent, FALSE); - KeInitializeEvent(&dev_mgr->drivers_inited, NotificationEvent, FALSE); - - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - - if (PsCreateSystemThread(&thread_handle, 0, NULL, NULL, NULL, dev_mgr_thread, dev_mgr) != STATUS_SUCCESS) - { - destroy_event_pool(&dev_mgr->event_pool); - return FALSE; - } - - ObReferenceObjectByHandle(thread_handle, - THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID *) & dev_mgr->pthread, NULL); - - ZwClose(thread_handle); - - return TRUE; -} - -BOOLEAN -dev_mgr_event_init(PUSB_DEV pdev, //always null. we do not use this param - ULONG event, ULONG context, ULONG param) -{ - LARGE_INTEGER due_time; - PUSB_DEV_MANAGER dev_mgr; - LONG i; - - usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_init(): dev_mgr=0x%x, event=0x%x\n", context, event)); - dev_mgr = (PUSB_DEV_MANAGER) context; - if (dev_mgr == NULL) - return FALSE; - - if (event != USB_EVENT_INIT_DEV_MGR) - return FALSE; - - //dev_mgr->root_hub = NULL; - KeInitializeTimer(&dev_mgr->dev_mgr_timer); - - KeInitializeDpc(&dev_mgr->dev_mgr_timer_dpc, dev_mgr_timer_dpc_callback, (PVOID) dev_mgr); - - KeInitializeSpinLock(&dev_mgr->timer_svc_list_lock); - InitializeListHead(&dev_mgr->timer_svc_list); - init_timer_svc_pool(&dev_mgr->timer_svc_pool); - dev_mgr->timer_click = 0; - - init_irp_list(&dev_mgr->irp_list); - - KeInitializeSpinLock(&dev_mgr->dev_list_lock); - InitializeListHead(&dev_mgr->dev_list); - - dev_mgr->hub_count = 0; - InitializeListHead(&dev_mgr->hub_list); - - dev_mgr->conn_count = 0; - dev_mgr->driver_list = g_driver_list; - - dev_mgr_driver_entry_init(dev_mgr, dev_mgr->driver_list); - - for(i = 0; i < DEVMGR_MAX_DRIVERS; i++) - { - if (dev_mgr->driver_list[i].driver_init == NULL) - continue; - - if (dev_mgr->driver_list[i].driver_init(dev_mgr, &dev_mgr->driver_list[i]) == FALSE) - break; - } - if (i == DEVMGR_MAX_DRIVERS) - { - due_time.QuadPart = -(DEV_MGR_TIMER_INTERVAL_NS - 10); - - KeSetTimerEx(&dev_mgr->dev_mgr_timer, - due_time, DEV_MGR_TIMER_INTERVAL_MS, &dev_mgr->dev_mgr_timer_dpc); - - /* Signal we're done initing */ - KeSetEvent(&dev_mgr->drivers_inited, 0, FALSE); - - return TRUE; - } - - i--; - - for(; i >= 0; i--) - { - if (dev_mgr->driver_list[i].driver_destroy) - dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]); - } - - KeCancelTimer(&dev_mgr->dev_mgr_timer); - KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc); - KeSetEvent(&dev_mgr->drivers_inited, 0, FALSE); - return FALSE; - -} - -VOID -dev_mgr_destroy(PUSB_DEV_MANAGER dev_mgr) -{ - LONG i; - // oops... - KeCancelTimer(&dev_mgr->dev_mgr_timer); - KeRemoveQueueDpc(&dev_mgr->dev_mgr_timer_dpc); - - for(i = DEVMGR_MAX_DRIVERS - 1; i >= 0; i--) - dev_mgr->driver_list[i].driver_destroy(dev_mgr, &dev_mgr->driver_list[i]); - - destroy_irp_list(&dev_mgr->irp_list); - destroy_timer_svc_pool(&dev_mgr->timer_svc_pool); - destroy_event_pool(&dev_mgr->event_pool); - -} - -VOID -NTAPI -dev_mgr_thread(PVOID context) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_EVENT pevent; - PLIST_ENTRY pthis, pnext; - USB_EVENT usb_event; - LARGE_INTEGER time_out; - NTSTATUS status; - BOOLEAN dev_mgr_inited; - KIRQL old_irql; - LONG i; - - dev_mgr = (PUSB_DEV_MANAGER) context; - dev_mgr_inited = FALSE; - usb_cal_cpu_freq(); - time_out.u.LowPart = (10 * 1000 * 1000) * 100 - 1; //1 minutes - time_out.u.HighPart = 0; - time_out.QuadPart = -time_out.QuadPart; - - //usb_dbg_print( DBGLVL_MAXIMUM + 1, ( "dev_mgr_thread(): current uhci status=0x%x\n", uhci_status( dev_mgr->pdev_ext->uhci ) ) ); - - while (dev_mgr->term_flag == FALSE) - { - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - if (IsListEmpty(&dev_mgr->event_list) == TRUE) - { - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out); - continue; - } - - /* - usb_dbg_print( DBGLVL_MAXIMUM, ( "dev_mgr_thread(): current element in event list is 0x%x\n", \ - dbg_count_list( &dev_mgr->event_list ) ) ); */ - - dev_mgr_inited = TRUE; //since we have post one event, if this statement is executed, dev_mgr_event_init must be called sometime later or earlier - - ListFirst(&dev_mgr->event_list, pthis); - pevent = struct_ptr(pthis, USB_EVENT, event_link); - - while (pevent && ((pevent->flags & USB_EVENT_FLAG_ACTIVE) == 0)) - { - //skip inactive ones - ListNext(&dev_mgr->event_list, &pevent->event_link, pnext); - pevent = struct_ptr(pnext, USB_EVENT, event_link); - } - - if (pevent != NULL) - { - if (pevent->process_queue == NULL) - pevent->process_queue = event_list_default_process_queue; - - pevent->process_queue(&dev_mgr->event_list, &dev_mgr->event_pool, pevent, &usb_event); - } - else - { - //no active event - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - status = KeWaitForSingleObject(&dev_mgr->wake_up_event, Executive, KernelMode, TRUE, &time_out // 10 minutes - ); - - usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_thread(): wake up, reason=0x%x\n", status)); - continue; - } - - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - if (usb_event.process_event) - { - usb_event.process_event(usb_event.pdev, usb_event.event, usb_event.context, usb_event.param); - } - else - { - event_list_default_process_event(usb_event.pdev, - usb_event.event, usb_event.context, usb_event.param); - } - } - - if (dev_mgr_inited) - { - for(i = 0; i < dev_mgr->hcd_count; i++) - dev_mgr_disconnect_dev(dev_mgr->hcd_array[i]->hcd_get_root_hub(dev_mgr->hcd_array[i])); - dev_mgr_destroy(dev_mgr); - } - PsTerminateSystemThread(0); -} - -VOID -NTAPI -dev_mgr_timer_dpc_callback(PKDPC Dpc, PVOID context, PVOID SystemArgument1, PVOID SystemArgument2) -{ - PUSB_DEV_MANAGER dev_mgr; - LIST_HEAD templist; - PLIST_ENTRY pthis, pnext; - static ULONG ticks = 0; - - ticks++; - dev_mgr = (PUSB_DEV_MANAGER) context; - if (dev_mgr == NULL) - return; - - dev_mgr->timer_click++; - InitializeListHead(&templist); - - KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock); - if (IsListEmpty(&dev_mgr->timer_svc_list) == TRUE) - { - KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock); - return; - } - - ListFirst(&dev_mgr->timer_svc_list, pthis); - while (pthis) - { - ((PTIMER_SVC) pthis)->counter++; - ListNext(&dev_mgr->timer_svc_list, pthis, pnext); - if (((PTIMER_SVC) pthis)->counter >= ((PTIMER_SVC) pthis)->threshold) - { - RemoveEntryList(pthis); - InsertTailList(&templist, pthis); - } - pthis = pnext; - } - - KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock); - - - while (IsListEmpty(&templist) == FALSE) - { - pthis = RemoveHeadList(&templist); - ((PTIMER_SVC) pthis)->func(((PTIMER_SVC) pthis)->pdev, (PVOID) ((PTIMER_SVC) pthis)->context); - KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock); - free_timer_svc(&dev_mgr->timer_svc_pool, (PTIMER_SVC) pthis); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock); - } - -} - -BOOLEAN -dev_mgr_request_timer_svc(PUSB_DEV_MANAGER dev_mgr, - PUSB_DEV pdev, ULONG context, ULONG due_time, TIMER_SVC_HANDLER handler) -{ - PTIMER_SVC timer_svc; - KIRQL old_irql; - - if (dev_mgr == NULL || pdev == NULL || due_time == 0 || handler == NULL) - return FALSE; - - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - timer_svc = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (timer_svc == NULL) - { - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return FALSE; - } - timer_svc->pdev = pdev; - timer_svc->threshold = due_time; - timer_svc->func = handler; - timer_svc->counter = 0; - - InsertTailList(&dev_mgr->timer_svc_list, &timer_svc->timer_svc_link); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return TRUE; -} - -BYTE -dev_mgr_alloc_addr(PUSB_DEV_MANAGER dev_mgr, PHCD hcd) -{ - // alloc a usb addr for the device within 1-128 - if (dev_mgr == NULL || hcd == NULL) - return 0xff; - - return hcd->hcd_alloc_addr(hcd); -} - -BOOLEAN -dev_mgr_free_addr(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, BYTE addr) -{ - PHCD hcd; - if (addr & 0x80) - return FALSE; - - if (dev_mgr == NULL || pdev == NULL) - return FALSE; - - hcd = pdev->hcd; - if (hcd == NULL) - return FALSE; - hcd->hcd_free_addr(hcd, addr); - return TRUE; -} - -PUSB_DEV -dev_mgr_alloc_device(PUSB_DEV_MANAGER dev_mgr, PHCD hcd) -{ - BYTE addr; - PUSB_DEV pdev; - - if ((addr = dev_mgr_alloc_addr(dev_mgr, hcd)) == 0xff) - return NULL; - - pdev = usb_alloc_mem(NonPagedPool, sizeof(USB_DEV)); - if (pdev == NULL) - return NULL; - - RtlZeroMemory(pdev, sizeof(USB_DEV)); - - KeInitializeSpinLock(&pdev->dev_lock); - dev_mgr->conn_count++; - - pdev->flags = USB_DEV_STATE_RESET; //class | cur_state | low speed - pdev->ref_count = 0; - pdev->dev_addr = addr; - - pdev->hcd = hcd; - - pdev->dev_id = dev_mgr->conn_count; //will be used to compose dev_handle - - InitializeListHead(&pdev->default_endp.urb_list); - pdev->default_endp.pusb_if = (PUSB_INTERFACE) pdev; - pdev->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP; //toggle | busy-count | stall | default-endp - - return pdev; -} - -VOID -dev_mgr_free_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev) -{ - if (pdev == NULL || dev_mgr == NULL) - return; - - dev_mgr_free_addr(dev_mgr, pdev, pdev->dev_addr); - if (pdev->usb_config && pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd)) - { - //root hub has its config and desc buf allocated together, - //so no usb_config allocated seperately - dev_mgr_destroy_usb_config(pdev->usb_config); - pdev->usb_config = NULL; - } - if (pdev->desc_buf) - { - usb_free_mem(pdev->desc_buf); - pdev->desc_buf = NULL; - } - usb_free_mem(pdev); - pdev = NULL; - return; -} - -//called when a disconnect is detected on the port -VOID -dev_mgr_disconnect_dev(PUSB_DEV pdev) -{ - PLIST_ENTRY pthis, pnext; - PHUB2_EXTENSION phub_ext = NULL; - PUSB_CONFIGURATION pconfig; - PUSB_DEV_MANAGER dev_mgr; - PHCD hcd; - BOOLEAN is_hub, found; - ULONG dev_id; - int i; - - USE_NON_PENDING_IRQL; - - if (pdev == NULL) - return; - - found = FALSE; - - usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_disconnect_dev(): entering, pdev=0x%x\n", pdev)); - lock_dev(pdev, FALSE); - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_BEFORE_ZOMB; - dev_mgr = dev_mgr_from_dev(pdev); - unlock_dev(pdev, FALSE); - - // notify dev_driver that the dev stops function before any operations - if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_stop) - pdev->dev_driver->disp_tbl.dev_stop(dev_mgr, dev_handle_from_dev(pdev)); - - //safe to use the dev pointer in this function. - lock_dev(pdev, FALSE); - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_ZOMB; - hcd = pdev->hcd; - dev_id = pdev->dev_id; - unlock_dev(pdev, FALSE); - - if (dev_mgr == NULL) - return; - - hcd->hcd_remove_device(hcd, pdev); - - //disconnect its children - if ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB || - (pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_ROOT_HUB) - { - phub_ext = hub_ext_from_dev(pdev); - if (phub_ext) - { - for(i = 1; i <= phub_ext->port_count; i++) - { - if (phub_ext->child_dev[i]) - { - dev_mgr_disconnect_dev(phub_ext->child_dev[i]); - phub_ext->child_dev[i] = NULL; - } - } - } - } - - pconfig = pdev->usb_config; - - //remove event belong to the dev - is_hub = ((pdev->flags & USB_DEV_CLASS_MASK) == USB_DEV_CLASS_HUB); - - if (phub_ext && is_hub) - { - for(i = 1; i <= phub_ext->port_count; i++) - { - found = hub_remove_reset_event(pdev, i, FALSE); - if (found) - break; - } - } - - //free event of the dev from the event list - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - ListFirst(&dev_mgr->event_list, pthis); - while (pthis) - { - ListNext(&dev_mgr->event_list, pthis, pnext); - if (((PUSB_EVENT) pthis)->pdev == pdev) - { - PLIST_ENTRY p1; - RemoveEntryList(pthis); - if ((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE) != USB_EVENT_FLAG_NOQUE) - { - //has a queue, re-insert the queue - if ((p1 = (PLIST_ENTRY) ((PUSB_EVENT) pthis)->pnext)) - { - InsertHeadList(&dev_mgr->event_list, p1); - free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link)); - pthis = p1; - //note: this queue will be examined again in the next loop - //to find the matched dev in the queue - continue; - } - } - free_event(&dev_mgr->event_pool, struct_ptr(pthis, USB_EVENT, event_link)); - } - else if (((((PUSB_EVENT) pthis)->flags & USB_EVENT_FLAG_QUE_TYPE) - != USB_EVENT_FLAG_NOQUE) && ((PUSB_EVENT) pthis)->pnext) - { - //has a queue, examine the queue - PUSB_EVENT p1, p2; - p1 = (PUSB_EVENT) pthis; - p2 = p1->pnext; - while (p2) - { - if (p2->pdev == pdev) - { - p1->pnext = p2->pnext; - p2->pnext = NULL; - free_event(&dev_mgr->event_pool, p2); - p2 = p1->pnext; - } - else - { - p1 = p2; - p2 = p2->pnext; - } - } - } - pthis = pnext; - } - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - // found indicates the reset event on one of the dev's port in process - if (found) - hub_start_next_reset_port(dev_mgr_from_dev(pdev), FALSE); - - // remove timer-svc belonging to the dev - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - ListFirst(&dev_mgr->timer_svc_list, pthis); - i = 0; - while (pthis) - { - ListNext(&dev_mgr->timer_svc_list, pthis, pnext); - if (((PUSB_EVENT) pthis)->pdev == pdev) - { - RemoveEntryList(pthis); - free_timer_svc(&dev_mgr->timer_svc_pool, struct_ptr(pthis, TIMER_SVC, timer_svc_link)); - i++; - } - pthis = pnext; - } - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - - // release the refcount - if (i) - { - lock_dev(pdev, FALSE); - pdev->ref_count -= i; - unlock_dev(pdev, FALSE); - } - - // wait for all the reference count be released - for(;;) - { - LARGE_INTEGER interval; - - lock_dev(pdev, FALSE); - if (pdev->ref_count == 0) - { - unlock_dev(pdev, FALSE); - break; - } - unlock_dev(pdev, FALSE); - // Wait two ms. - interval.QuadPart = -20000; - KeDelayExecutionThread(KernelMode, FALSE, &interval); - } - - if (pdev->dev_driver && pdev->dev_driver->disp_tbl.dev_disconnect) - pdev->dev_driver->disp_tbl.dev_disconnect(dev_mgr, dev_handle_from_dev(pdev)); - - // we put it here to let handle valid before disconnect - KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql); - ListFirst(&dev_mgr->dev_list, pthis); - while (pthis) - { - if (((PUSB_DEV) pthis) == pdev) - { - RemoveEntryList(pthis); - break; - } - ListNext(&dev_mgr->dev_list, pthis, pnext); - pthis = pnext; - } - KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql); - - - if (pdev != pdev->hcd->hcd_get_root_hub(pdev->hcd)) - { - dev_mgr_free_device(dev_mgr, pdev); - } - else - { - //rh_destroy( pdev ); - //TRAP(); - //destroy it in dev_mgr_destroy - } - - return; -} - -//called in hub_set_address_completion -BOOLEAN -dev_mgr_start_config_dev(PUSB_DEV pdev) -{ - PBYTE data_buf; - PUSB_CTRL_SETUP_PACKET psetup; - PURB purb; - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - hcd_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_start_config_dev: pdev=%p\n", pdev)); - - if (pdev == NULL) - return FALSE; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - return FALSE; - } - - hcd = pdev->hcd; - - //first, get device descriptor - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - data_buf = usb_alloc_mem(NonPagedPool, 512); - if (purb == NULL || data_buf == NULL) - { - unlock_dev(pdev, TRUE); - return FALSE; - } - - RtlZeroMemory(purb, sizeof(URB)); - RtlZeroMemory(data_buf, 512); - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - purb->data_buffer = data_buf; // user data - purb->data_length = 8; // get partial desc - - pdev->desc_buf = data_buf; - pdev->desc_buf_size = 512; - - purb->pdev = pdev; - purb->pendp = &pdev->default_endp; //pipe for current transfer - - purb->completion = dev_mgr_get_desc_completion; - purb->reference = 0; - - InitializeListHead(&purb->trasac_list); - - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = (USB_DT_DEVICE << 8) | 0; - psetup->wIndex = 0; - psetup->wLength = 8; //sizeof( USB_DEVICE_DESC ); - unlock_dev(pdev, TRUE); - - if (hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb) != STATUS_PENDING) - { - usb_free_mem(purb); - usb_free_mem(data_buf); - return FALSE; - } - return TRUE; -} - -VOID -dev_mgr_get_desc_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_ENDPOINT pendp; - PUSB_DEV_MANAGER dev_mgr; - NTSTATUS status; - PUSB_CTRL_SETUP_PACKET psetup; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL) - return; - - hcd_dbg_print(DBGLVL_MAXIMUM, - ("dev_mgr_get_desc_completion: purb->reference=%d\n", purb->reference)); - - pdev = purb->pdev; - pendp = purb->pendp; - - if (pdev == NULL || pendp == NULL) - { - usb_free_mem(purb); - purb = NULL; - return; - } - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - goto LBL_OUT; - } - - pendp = &pdev->default_endp; - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - if (usb_error(purb->status)) - { - unlock_dev(pdev, TRUE); - hcd_dbg_print(DBGLVL_MAXIMUM, - ("dev_mgr_get_desc_completion: can not get dev desc ref=0x%x, status=0x%x\n", - purb->reference, purb->status)); - goto LBL_OUT; - } - - switch (purb->reference) - { - case 0: - { - //only partial dev_desc - //enable the dev specific default endp maxpacketsize - pdev->pusb_dev_desc = (PUSB_DEVICE_DESC) purb->data_buffer; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - psetup->wLength = sizeof(USB_DEVICE_DESC); - - //get the complete dev_desc - purb->reference = 1; - purb->status = 0; - purb->data_length = sizeof(USB_DEVICE_DESC); - - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - if (status != STATUS_PENDING) - { - goto LBL_OUT; - } - return; - } - case 1: - { - //let's begin to get config descriptors. - if (pdev->pusb_dev_desc->bNumConfigurations == 0) - { - unlock_dev(pdev, TRUE); - goto LBL_OUT; - } - - purb->data_buffer += sizeof(USB_DEVICE_DESC); - purb->data_length = 8; - purb->reference++; - purb->context = (PVOID) sizeof(USB_DEVICE_DESC); - purb->status = 0; - - psetup->wValue = (USB_DT_CONFIG << 8) | 0; - psetup->wLength = 8; - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - - if (status != STATUS_PENDING) - { - goto LBL_OUT; - } - return; - } - default: - { - LONG config_idx; - config_idx = (purb->reference >> 1) - 1; - if ((purb->reference & 1) == 0) - { - //partial config desc is obtained. - pconfig_desc = (PUSB_CONFIGURATION_DESC) purb->data_buffer; - if (pconfig_desc->wTotalLength >= 1024) - { - //treat as an error - unlock_dev(pdev, TRUE); - goto LBL_OUT; - - } - - if (pconfig_desc->wTotalLength > (USHORT) (pdev->desc_buf_size - (LONG) purb->context)) - { - //rewind the 8-byte hdr - *((PULONG) & context) -= 8; - realloc_buf(pdev, purb); - } - purb->data_length = pconfig_desc->wTotalLength; - psetup->wLength = pconfig_desc->wTotalLength; - purb->reference++; - unlock_dev(pdev, TRUE); - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - if (status != STATUS_PENDING) - goto LBL_OUT; - - } - else - { - //complete desc is returned. - if (config_idx + 1 < pdev->pusb_dev_desc->bNumConfigurations) - { - //still have configurations left - *((PULONG) & context) += psetup->wLength; - purb->data_buffer = &pdev->desc_buf[(LONG) context]; - purb->data_length = 8; - psetup->wLength = 8; - psetup->wValue = (((USB_DT_CONFIG) << 8) | (config_idx + 1)); - purb->reference++; - purb->context = context; - - if (((LONG) context) + 8 > pdev->desc_buf_size) - realloc_buf(pdev, purb); - - purb->status = 0; - unlock_dev(pdev, TRUE); - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - if (status != STATUS_PENDING) - goto LBL_OUT; - } - else - { - //config descriptors have all been fetched - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - purb = NULL; - - // load driver for the device - dev_mgr_start_select_driver(pdev); - } - } - return; - } - } - -LBL_OUT: - if (purb) - { - usb_free_mem(purb); - purb = NULL; - } - - lock_dev(pdev, TRUE); - if (dev_state(pdev) != USB_DEV_STATE_ZOMB) - { - if (pdev->desc_buf) - { - usb_free_mem(pdev->desc_buf); - pdev->desc_buf_size = 0; - pdev->desc_buf = NULL; - pdev->pusb_dev_desc = NULL; - pdev->usb_config = NULL; - } - } - unlock_dev(pdev, TRUE); - - return; -} - -BOOLEAN -dev_mgr_start_select_driver(PUSB_DEV pdev) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_EVENT pevent; - BOOLEAN bret; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL) - return FALSE; - - dev_mgr = dev_mgr_from_dev(pdev); - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - bret = FALSE; - goto LBL_OUT; - } - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - { - bret = FALSE; - goto LBL_OUT; - } - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->event = USB_EVENT_DEFAULT; - pevent->pdev = pdev; - pevent->context = 0; - pevent->param = 0; - pevent->pnext = 0; //vertical queue for serialized operation - pevent->process_event = dev_mgr_event_select_driver; - pevent->process_queue = event_list_default_process_queue; - - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - bret = TRUE; - -LBL_OUT: - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return bret; -} - -BOOLEAN -dev_mgr_connect_to_dev(PVOID Parameter) -{ - PUSB_DEV pdev; - DEV_HANDLE dev_handle; - NTSTATUS status; - PUSB_DRIVER pdriver; - PDEV_CONNECT_DATA pcd = (PDEV_CONNECT_DATA) Parameter; - PUSB_DEV_MANAGER dev_mgr; - DEV_CONNECT_DATA param; - - if (pcd == NULL) - return FALSE; - dev_handle = pcd->dev_handle; - pdriver = pcd->pdriver; - dev_mgr = pcd->dev_mgr; - - param.dev_mgr = dev_mgr; - param.pdriver = pdriver; - param.dev_handle = 0; //not used - - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - return FALSE; - - usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_connect_to_dev(): about to call driver's dev_connect\n")); - status = pdriver->disp_tbl.dev_connect(¶m, dev_handle); - usb_unlock_dev(pdev); - return status; -} - -VOID -dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdriver, pcand; - LONG credit, match, i; - DEV_HANDLE handle = 0; - DEV_CONNECT_DATA cd; - - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(param); - UNREFERENCED_PARAMETER(context); - - usb_dbg_print(DBGLVL_MAXIMUM, ("dev_mgr_event_select_driver(): pdev=%p event=0x%x\n", pdev, event)); - - if (pdev == NULL) - return; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return; - } - dev_mgr = dev_mgr_from_dev(pdev); - - pcand = NULL; - match = 0; - for(i = HUB_DRIVER_IDX; i < DEVMGR_MAX_DRIVERS; i++) - { - //bypass root-hub driver with idx zero - pdriver = (PUSB_DRIVER) & dev_mgr->driver_list[i]; - - if (pdriver->driver_desc.flags & USB_DRIVER_FLAG_DEV_CAPABLE) - credit = dev_mgr_score_driver_for_dev(dev_mgr, pdriver, pdev->pusb_dev_desc); - else - { - continue; - } - if (credit > match) - pcand = pdriver, match = credit; - - } - - if (match) - { - // we set class driver here - // pdev->dev_driver = pcand; - handle = usb_make_handle(pdev->dev_id, 0, 0); - } - unlock_dev(pdev, FALSE); - - if (match) - { - - cd.dev_handle = handle; - cd.pdriver = pcand; - cd.dev_mgr = dev_mgr; - - if (dev_mgr_connect_to_dev(&cd)) - return; - - // ExInitializeWorkItem( pwork_item, dev_mgr_connect_to_dev, ( PVOID )pcd ); - // ExQueueWorkItem( pwork_item, DelayedWorkQueue ); - } - cd.dev_handle = handle; - cd.pdriver = &dev_mgr->driver_list[GEN_DRIVER_IDX]; - cd.dev_mgr = dev_mgr; - dev_mgr_connect_to_dev(&cd); - return; -} - -BOOLEAN -dev_mgr_build_usb_endp(PUSB_INTERFACE pif, PUSB_ENDPOINT pendp, PUSB_ENDPOINT_DESC pendp_desc) -{ - if (pendp == NULL || pif == NULL || pendp_desc == NULL) - return FALSE; - - pendp->flags = 0; - InitializeListHead(&pendp->urb_list); //pending urb queue - pendp->pusb_if = pif; - pendp->pusb_endp_desc = pendp_desc; - return TRUE; -} - -BOOLEAN -dev_mgr_build_usb_if(PUSB_CONFIGURATION pcfg, PUSB_INTERFACE pif, PUSB_INTERFACE_DESC pif_desc, BOOLEAN alt_if) -{ - LONG i; - PUSB_ENDPOINT_DESC pendp_desc; - PBYTE pbuf; - - if (pcfg == NULL || pif == NULL || pif_desc == NULL) - return FALSE; - - if (alt_if == FALSE) - { - pif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF - ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints; - - pif->pif_drv = NULL; - pif->pusb_config = pcfg; - pif->pusb_if_desc = pif_desc; - pif->if_ext_size = 0; - pif->if_ext = NULL; - - InitializeListHead(&pif->altif_list); - pif->altif_count = 0; - - pbuf = &((PBYTE) pif_desc)[sizeof(USB_INTERFACE_DESC)]; - - i = 0; - while (i < pif->endp_count) - { - pendp_desc = (PUSB_ENDPOINT_DESC)pbuf; - - // check if it's an endpoint descriptor - if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT) - { - // add it - dev_mgr_build_usb_endp(pif, &pif->endp[i], pendp_desc); - i++; - } - - // skip to the next one - pbuf += pendp_desc->bLength; - } - } - else - { - PUSB_INTERFACE paltif; - PLIST_ENTRY pthis, pnext; - - pif->altif_count++; - paltif = usb_alloc_mem(NonPagedPool, sizeof(USB_INTERFACE)); - if (!paltif) return FALSE; - - RtlZeroMemory(paltif, sizeof(USB_INTERFACE)); - InsertTailList(&pif->altif_list, &paltif->altif_list); - paltif->pif_drv = NULL; - paltif->pusb_config = pcfg; - paltif->pusb_if_desc = pif_desc; - paltif->if_ext_size = 0; - paltif->if_ext = NULL; - paltif->endp_count = pif_desc->bNumEndpoints > MAX_ENDPS_PER_IF - ? MAX_ENDPS_PER_IF : pif_desc->bNumEndpoints; - - ListFirst(&pif->altif_list, pthis); - - while (pthis) - { - //synchronize the altif_count; - PUSB_INTERFACE pthis_if; - pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list)); - pthis_if->altif_count = pif->altif_count; - ListNext(&pif->altif_list, pthis, pnext); - pthis = pnext; - } - - } - return TRUE; -} - -NTSTATUS -dev_mgr_build_usb_config(PUSB_DEV pdev, PBYTE pbuf, ULONG config_val, LONG config_count) -{ - PUSB_CONFIGURATION pcfg; - PUSB_INTERFACE_DESC pif_desc; - PUSB_INTERFACE pif; - int i; - LONG if_count; - - if (pdev == NULL || pbuf == NULL) - return STATUS_INVALID_PARAMETER; - - - pdev->usb_config = usb_alloc_mem(NonPagedPool, sizeof(USB_CONFIGURATION)); - pcfg = pdev->usb_config; - - if (pdev->usb_config == NULL) - return STATUS_NO_MEMORY; - - RtlZeroMemory(pcfg, sizeof(USB_CONFIGURATION)); - pcfg->pusb_config_desc = usb_find_config_desc_by_val(pbuf, config_val, config_count); - - if (pcfg->pusb_config_desc == NULL) - { - usb_free_mem(pcfg); - pdev->usb_config = NULL; - return STATUS_UNSUCCESSFUL; - } - pcfg->if_count = pcfg->pusb_config_desc->bNumInterfaces; - pcfg->pusb_dev = pdev; - pif_desc = (PUSB_INTERFACE_DESC) & ((PBYTE) pcfg->pusb_config_desc)[sizeof(USB_CONFIGURATION_DESC)]; - if_count = pcfg->if_count; - - for(i = 0; i < if_count; i++, pif_desc++) - { - if (pif_desc->bAlternateSetting == 0) - { - dev_mgr_build_usb_if(pcfg, &pcfg->interf[i], pif_desc, FALSE); - } - else - { - pif = &pcfg->interf[i-1]; - dev_mgr_build_usb_if(pcfg, pif, pif_desc, TRUE); - } - } - return STATUS_SUCCESS; -} - -NTSTATUS -dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg) -{ - long i; - PLIST_ENTRY pthis; - PUSB_INTERFACE pif; - - if (pcfg == NULL) - return FALSE; - - for(i = 0; i < pcfg->if_count; i++) - { - pif = &pcfg->interf[i]; - - if (pif->altif_count) - { - ListFirst(&pif->altif_list, pthis); - while (pthis) - { - PUSB_INTERFACE pthis_if; - pthis_if = (PUSB_INTERFACE) (((PBYTE) pthis) - offsetof(USB_INTERFACE, altif_list)); - RemoveEntryList(pthis); - usb_free_mem(pthis_if); - if (IsListEmpty(&pif->altif_list) == TRUE) - break; - - ListFirst(&pif->altif_list, pthis); - } - } - } - usb_free_mem(pcfg); - return TRUE; -} - -#define is_dev_product_match( pdriVER, pdev_DESC ) \ -( ( pdriVER )->driver_desc.vendor_id == ( pdev_DESC )->idVendor \ - && ( pdriVER )->driver_desc.product_id == ( pdev_DESC )->idProduct ) - -LONG -dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc) -{ - LONG credit = 0; - - UNREFERENCED_PARAMETER(dev_mgr); - - //assume supports all the sub_class are supported if sub_class is zero - if (pdriver->driver_desc.dev_class == pdev_desc->bDeviceClass) - { - if (pdriver->driver_desc.dev_sub_class == 0 && pdriver->driver_desc.dev_protocol == 0) - credit = 3; - else if (pdriver->driver_desc.dev_sub_class == pdev_desc->bDeviceSubClass) - { - if (pdriver->driver_desc.dev_protocol == 0) - credit = 6; - else if (pdriver->driver_desc.dev_protocol == pdev_desc->bDeviceProtocol) - credit = 9; - } - } - - if (is_dev_product_match(pdriver, pdev_desc)) - credit += 20; - - return credit; -} - -LONG -dev_mgr_score_driver_for_if(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_INTERFACE_DESC pif_desc) -{ - LONG credit; - - if (pdriver == NULL - || !(pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) || pif_desc == NULL || dev_mgr == NULL) - return 0; - - if (is_header_match((PBYTE) pif_desc, USB_DT_INTERFACE) == FALSE) - { - return 0; - } - - credit = 0; - if ((pdriver->driver_desc.if_class == pif_desc->bInterfaceClass)) - { - if (pdriver->driver_desc.if_sub_class == 0 && pdriver->driver_desc.if_protocol == 0) - credit = 2; - if (pdriver->driver_desc.if_sub_class == pif_desc->bInterfaceSubClass) - { - if (pdriver->driver_desc.if_protocol == 0) - credit = 4; - if (pdriver->driver_desc.if_protocol == pif_desc->bInterfaceProtocol) - credit = 6; - } - } - else - credit = 1; - - return credit; -} - -#define is_equal_driver( pd1, pd2, ret ) \ -{\ - int i;\ - ret = TRUE;\ - PUSB_DRIVER pdr1, pdr2;\ - pdr1 = ( PUSB_DRIVER )( pd1 );\ - pdr2 = ( PUSB_DRIVER ) ( pd2 );\ - for( i = 0; i < 16; i++ )\ - {\ - if( pdr1->driver_name[ i ] != pdr2->driver_name[ i ] )\ - {\ - ret = FALSE;\ - break;\ - }\ - }\ -} - -//return value is the hcd id -UCHAR -dev_mgr_register_hcd(PUSB_DEV_MANAGER dev_mgr, PHCD hcd) -{ - if (dev_mgr == NULL || hcd == NULL) - return 0xff; - - if (dev_mgr->hcd_count >= MAX_HCDS) - return 0xff; - - dev_mgr->hcd_array[dev_mgr->hcd_count++] = hcd; - return dev_mgr->hcd_count - 1; -} - -VOID -dev_mgr_deregister_hcd(PUSB_DEV_MANAGER dev_mgr, UCHAR hcd_id) -{ - UCHAR i; - - if (dev_mgr == NULL || hcd_id >= MAX_HCDS - 1) - return; - - for (i = hcd_id; i < dev_mgr->hcd_count - 1; i++) - dev_mgr->hcd_array[i] = dev_mgr->hcd_array[i + 1]; - - dev_mgr->hcd_count--; -} - -BOOLEAN -dev_mgr_register_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp, PURB purb) -{ - if (dev_mgr == NULL) - return FALSE; - - if (add_irp_to_list(&dev_mgr->irp_list, pirp, purb)) - { - return TRUE; - } - TRAP(); - return FALSE; -} - -//caller must guarantee that when this func is called, -//the urb associated must exist. -PURB -dev_mgr_remove_irp(PUSB_DEV_MANAGER dev_mgr, PIRP pirp) -{ - PURB purb; - if (dev_mgr == NULL) - return NULL; - - purb = remove_irp_from_list(&dev_mgr->irp_list, pirp, NULL); - return purb; -} - -VOID -NTAPI -dev_mgr_cancel_irp(PDEVICE_OBJECT dev_obj, PIRP pirp) -{ - PUSB_DEV_MANAGER dev_mgr; - PDEVEXT_HEADER pdev_ext_hdr; - - pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - dev_mgr = pdev_ext_hdr->dev_mgr; - - if (dev_obj->CurrentIrp == pirp) - { - IoReleaseCancelSpinLock(pirp->CancelIrql); - // we did not IoStartNextPacket, leave it for the urb completion - } - else - { - KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry); - IoReleaseCancelSpinLock(pirp->CancelIrql); - - pirp->IoStatus.Information = 0; - pirp->IoStatus.Status = STATUS_CANCELLED; - IoCompleteRequest(pirp, IO_NO_INCREMENT); - // the device queue is moved on, no need to call IoStartNextPacket - return; - } - - // - // remove the irp and call the dev_mgr_cancel_irp - // the completion will be done in urb completion - // - remove_irp_from_list(&dev_mgr->irp_list, pirp, dev_mgr); - return; - -} - -// release the hcd -VOID -dev_mgr_release_hcd(PUSB_DEV_MANAGER dev_mgr) -{ - LONG i; - PHCD hcd; - for(i = 0; i < dev_mgr->hcd_count; i++) - { - hcd = dev_mgr->hcd_array[i]; - hcd->hcd_release(hcd); - dev_mgr->hcd_array[i] = 0; - } - dev_mgr->hcd_count = 0; - return; -} - -VOID -dev_mgr_start_hcd(PUSB_DEV_MANAGER dev_mgr) -{ - LONG i; - PHCD hcd; - for(i = 0; i < dev_mgr->hcd_count; i++) - { - hcd = dev_mgr->hcd_array[i]; - hcd->hcd_start(hcd); - } - return; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/devmgr.h b/reactos/drivers/usb/nt4compat/usbdrv/devmgr.h deleted file mode 100644 index f90c9f0974c..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/devmgr.h +++ /dev/null @@ -1,281 +0,0 @@ -#ifndef __DEVMGR_H__ -#define __DEVMGR_H__ - -typedef struct _DEV_CONNECT_DATA -{ - DEV_HANDLE dev_handle; - struct _USB_DRIVER *pdriver; - struct _USB_DEV_MANAGER *dev_mgr; - PUSB_INTERFACE_DESC if_desc; - -} DEV_CONNECT_DATA, *PDEV_CONNECT_DATA; - -typedef BOOLEAN ( *PDEV_CONNECT_EX )( PDEV_CONNECT_DATA init_param, DEV_HANDLE dev_handle ); -typedef BOOLEAN ( *PDEV_CONNECT )( struct _USB_DEV_MANAGER *dev_mgr, DEV_HANDLE dev_handle ); -typedef BOOLEAN ( *PDRVR_INIT )( struct _USB_DEV_MANAGER *dev_mgr, struct _USB_DRIVER *pdriver ); - -typedef struct _PNP_DISPATCH -{ - ULONG version; - PDEV_CONNECT_EX dev_connect; - PDEV_CONNECT dev_reserved; //currently we do not use this entry - PDEV_CONNECT dev_stop; - PDEV_CONNECT dev_disconnect; - -}PNP_DISPATCH, *PPNP_DISPATCH; - -#define USB_DRIVER_FLAG_IF_CAPABLE 0x80000000 -#define USB_DRIVER_FLAG_DEV_CAPABLE 0x40000000 - -typedef struct _USB_DRIVER_DESCRIPTION -{ - // Device Info - DWORD flags; - WORD vendor_id; // USB Vendor ID - WORD product_id; // USB Product ID. - WORD release_num; // Release Number of Device - - // Interface Info - BYTE config_val; // Configuration Value - BYTE if_num; // Interface Number - BYTE if_class; // Interface Class - BYTE if_sub_class; // Interface SubClass - BYTE if_protocol; // Interface Protocol - - // Driver Info - const char *driver_name; // Driver name for Name Registry - BYTE dev_class; // Device Class (from SampleStorageDeviceID.h) - BYTE dev_sub_class; // Device Subclass - BYTE dev_protocol; // Protocol Info. - -} USB_DRIVER_DESCRIPTION,*PUSB_DRIVER_DESCRIPTION; - -#define RH_DRIVER_IDX 0 -#define HUB_DRIVER_IDX 1 -#define UMSS_DRIVER_IDX 2 -#define COMP_DRIVER_IDX 3 -#define GEN_DRIVER_IDX 4 -#define GEN_IF_DRIVER_IDX 5 -#define MOUSE_DRIVER_IDX 6 -#define KEYBOARD_DRIVER_IDX 7 -#define DEVMGR_MAX_DRIVERS 8 - -typedef struct _USB_DRIVER -{ - USB_DRIVER_DESCRIPTION driver_desc; - PNP_DISPATCH disp_tbl; - - PBYTE driver_ext; - LONG driver_ext_size; - - PDRVR_INIT driver_init; - PDRVR_INIT driver_destroy; - -} USB_DRIVER, *PUSB_DRIVER; - -extern USB_DRIVER g_driver_list[ DEVMGR_MAX_DRIVERS ]; - -#define MAX_HCDS 8 -#define dev_mgr_from_hcd( hCD ) ( ( hCD )->hcd_get_dev_mgr( hCD ) ) -#define dev_mgr_from_dev( pdEV ) ( dev_mgr_from_hcd( pdEV->hcd ) ) - -typedef struct _USB_DEV_MANAGER -{ - //BYTE dev_addr_map[ MAX_DEVS / 8 ]; //one bit per dev - struct _HCD *hcd_array[ MAX_HCDS ]; - unsigned char hcd_count; - - KSPIN_LOCK dev_list_lock; - LIST_HEAD dev_list; - - //PDEVICE_EXTENSION pdev_ext; - - PVOID pthread; - BOOLEAN term_flag; - KEVENT wake_up_event; - - KSPIN_LOCK event_list_lock; - LIST_HEAD event_list; - USB_EVENT_POOL event_pool; - - KEVENT drivers_inited; - KTIMER dev_mgr_timer; - KDPC dev_mgr_timer_dpc; - KSPIN_LOCK timer_svc_list_lock; - LIST_HEAD timer_svc_list; - TIMER_SVC_POOL timer_svc_pool; - LONG timer_click; - IRP_LIST irp_list; - - PUSB_DRIVER driver_list; - LONG hub_count; - LIST_HEAD hub_list; //for reference only - - //statistics - LONG conn_count; //will also be used to assign device id - PDRIVER_OBJECT usb_driver_obj; //this driver object - LONG open_count; //increment when IRP_MJ_CREATE arrives - //and decrement when IRP_MJ_CLOSE arrives - -} USB_DEV_MANAGER, *PUSB_DEV_MANAGER; - -BOOLEAN -dev_mgr_post_event( -PUSB_DEV_MANAGER dev_mgr, -PUSB_EVENT event -); - -BOOLEAN -dev_mgr_init( -PUSB_DEV dev, //always null. we do not use this param -ULONG event, -ULONG dev_mgr -); - -VOID -dev_mgr_destroy( -PUSB_DEV_MANAGER dev_mgr -); - -VOID NTAPI -dev_mgr_thread( -PVOID dev_mgr -); - -VOID NTAPI -dev_mgr_timer_dpc_callback( -PKDPC Dpc, -PVOID DeferredContext, -PVOID SystemArgument1, -PVOID SystemArgument2 -); - -BOOLEAN -dev_mgr_request_timer_svc( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DEV pdev, -ULONG context, -ULONG due_time, -TIMER_SVC_HANDLER handler -); - -BYTE -dev_mgr_alloc_addr( -PUSB_DEV_MANAGER dev_mgr, -PHCD hcd -); - -BOOLEAN -dev_mgr_free_addr( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DEV pdev, -BYTE addr -); - -PUSB_DEV -dev_mgr_alloc_device( -PUSB_DEV_MANAGER dev_mgr, -PHCD hcd -); - -VOID -dev_mgr_free_device( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DEV pdev -); - -VOID -dev_mgr_disconnect_dev( -PUSB_DEV pdev -); - -BOOLEAN -dev_mgr_strobe( -PUSB_DEV_MANAGER dev_mgr -); - -NTSTATUS -dev_mgr_build_usb_config( -PUSB_DEV pdev, -PBYTE pbuf, -ULONG config_val, -LONG config_count -); - -UCHAR -dev_mgr_register_hcd( -PUSB_DEV_MANAGER dev_mgr, -PHCD hcd -); - -VOID -dev_mgr_deregister_hcd( -PUSB_DEV_MANAGER dev_mgr, -UCHAR hcd_id -); - -NTSTATUS -dev_mgr_dispatch( -IN PUSB_DEV_MANAGER dev_mgr, -IN PIRP irp -); - -BOOLEAN -dev_mgr_register_irp( -PUSB_DEV_MANAGER dev_mgr, -PIRP pirp, -PURB purb -); - -PURB -dev_mgr_remove_irp( -PUSB_DEV_MANAGER dev_mgr, -PIRP pirp -); - -LONG -dev_mgr_score_driver_for_if( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver, -PUSB_INTERFACE_DESC pif_desc -); - -BOOLEAN -dev_mgr_set_driver( -PUSB_DEV_MANAGER dev_mgr, -DEV_HANDLE dev_handle, -PUSB_DRIVER pdriver, -PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle -); - -BOOLEAN -dev_mgr_set_if_driver( -PUSB_DEV_MANAGER dev_mgr, -DEV_HANDLE if_handle, -PUSB_DRIVER pdriver, -PUSB_DEV pdev //if pdev != NULL, we use pdev instead if_handle -); - -VOID -dev_mgr_release_hcd( -PUSB_DEV_MANAGER dev_mgr -); - -VOID -dev_mgr_start_hcd( -PUSB_DEV_MANAGER dev_mgr -); - -BOOLEAN dev_mgr_start_config_dev(PUSB_DEV pdev); -BOOLEAN dev_mgr_event_init(PUSB_DEV dev, //always null. we do not use this param - ULONG event, - ULONG context, - ULONG param); -VOID dev_mgr_get_desc_completion(PURB purb, PVOID context); -VOID dev_mgr_event_select_driver(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param); -LONG dev_mgr_score_driver_for_dev(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver, PUSB_DEVICE_DESC pdev_desc); -NTSTATUS dev_mgr_destroy_usb_config(PUSB_CONFIGURATION pcfg); -BOOLEAN dev_mgr_start_select_driver(PUSB_DEV pdev); -VOID NTAPI dev_mgr_cancel_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp); - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/dmgrdisp.c b/reactos/drivers/usb/nt4compat/usbdrv/dmgrdisp.c deleted file mode 100644 index e24b49821fe..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/dmgrdisp.c +++ /dev/null @@ -1,535 +0,0 @@ -/** - * dmgrdisp.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -VOID -disp_urb_completion(PURB purb, PVOID context) -{ - PUSB_DEV_MANAGER dev_mgr; - ULONG ctrl_code; - NTSTATUS status; - PDEVEXT_HEADER dev_hdr; - - UNREFERENCED_PARAMETER(context); - - if (purb == NULL) - return; - - ctrl_code = (ULONG) purb->reference; - dev_mgr = (PUSB_DEV_MANAGER) purb->context; - - // at this stage, the irp can not be canceled since the urb - // won't be found in any queue and the irp is not in any queue. - // see line 4685 in hub.c - // Sometimes, it may be very fast to enter this routine before - // the dev_mgr_register_irp to be called in dispatch routine in - // usb2.0 environment as - // we did in usb1.1 driver. We can not simply add a loop to wait - // for the dispatch thread to add the irp to the list, because - // here we are at DPC level higher than the dispatch thread - // running level. And the solution is to register the irp - // before the urb is scheduled instead of registering it after - // urb is scheduled. - if (purb->pirp) - { - PIO_STACK_LOCATION irp_stack; - dev_mgr_remove_irp(dev_mgr, purb->pirp); - - status = purb->status; - irp_stack = IoGetCurrentIrpStackLocation(purb->pirp); - - if (purb->status != STATUS_SUCCESS) - { - purb->pirp->IoStatus.Information = 0; - } - else - { - // currently only IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL - // are allowed. And we do not need to set information - // for IRP_MJ_INTERNAL_DEVICE_CONTROL - if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL) - purb->pirp->IoStatus.Information = purb->data_length; - } - purb->pirp->IoStatus.Status = status; - if (irp_stack) - { - dev_hdr = irp_stack->DeviceObject->DeviceExtension; - if (dev_hdr->start_io) - { - IoStartNextPacket(irp_stack->DeviceObject, TRUE); - } - } - IoCompleteRequest(purb->pirp, IO_NO_INCREMENT); - } - return; -} - -VOID -disp_noio_urb_completion(PURB purb, PVOID context) -{ - PUSB_CTRL_SETUP_PACKET psetup; - PURB purb2; - PUSB_DEV_MANAGER dev_mgr; - NTSTATUS status = STATUS_SUCCESS; - PIO_STACK_LOCATION irp_stack; - PDEVEXT_HEADER dev_hdr; - - if (purb == NULL) - return; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - if ((psetup->bmRequestType == 0x2) && - (psetup->bRequest == USB_REQ_CLEAR_FEATURE) && - (psetup->wIndex == 0)) //reset pipe - { - purb2 = (PURB) context; - } - else - { - purb2 = purb; - } - - if (purb2->pirp == NULL) - return; - - dev_mgr = (PUSB_DEV_MANAGER) purb2->context; - - dev_mgr_remove_irp(dev_mgr, purb2->pirp); - - if (purb->status != STATUS_SUCCESS) - status = STATUS_IO_DEVICE_ERROR; - - purb2->pirp->IoStatus.Information = 0; - purb2->pirp->IoStatus.Status = status; - irp_stack = IoGetCurrentIrpStackLocation(purb->pirp); - if (irp_stack) - { - dev_hdr = irp_stack->DeviceObject->DeviceExtension; - if (dev_hdr->start_io) - { - IoStartNextPacket(irp_stack->DeviceObject, TRUE); - } - } - IoCompleteRequest(purb2->pirp, IO_NO_INCREMENT); - return; -} - -//this function is called by the hcd's -//dispatch when they have done their job. -NTSTATUS -dev_mgr_dispatch(IN PUSB_DEV_MANAGER dev_mgr, IN PIRP irp) -{ - PIO_STACK_LOCATION irp_stack; - NTSTATUS status; - ULONG ctrl_code; - USE_NON_PENDING_IRQL; - - ASSERT(irp); - if (dev_mgr == NULL) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - status = STATUS_SUCCESS; - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - - switch (irp_stack->MajorFunction) - { - case IRP_MJ_CREATE: - { - InterlockedIncrement(&dev_mgr->open_count); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IRP_MJ_CLOSE: - { - InterlockedDecrement(&dev_mgr->open_count); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IRP_MJ_INTERNAL_DEVICE_CONTROL: - case IRP_MJ_DEVICE_CONTROL: - { - switch (ctrl_code) - { - case IOCTL_GET_DEV_COUNT: - { - LONG dev_count; - - irp->IoStatus.Information = 0; - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql); - dev_count = usb_count_list(&dev_mgr->dev_list); - KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql); - - *((PLONG) irp->AssociatedIrp.SystemBuffer) = dev_count; - irp->IoStatus.Information = sizeof(LONG); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_ENUM_DEVICES: - { - PLIST_ENTRY pthis, pnext; - LONG dev_count, array_size, i, j = 0; - PUSB_DEV pdev; - PENUM_DEV_ARRAY peda; - - irp->IoStatus.Information = 0; - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LONG)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ENUM_DEV_ARRAY)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - array_size = *((PULONG) irp->AssociatedIrp.SystemBuffer); - - KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql); - dev_count = usb_count_list(&dev_mgr->dev_list); - dev_count = dev_count > array_size ? array_size : dev_count; - peda = (PENUM_DEV_ARRAY) irp->AssociatedIrp.SystemBuffer; - RtlZeroMemory(peda, sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT)); - - if (dev_count) - { - ListFirst(&dev_mgr->dev_list, pthis); - for(i = 0, j = 0; i < dev_count; i++) - { - pdev = struct_ptr(pthis, USB_DEV, dev_link); - ListNext(&dev_mgr->dev_list, pthis, pnext); - pthis = pnext; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - continue; - } - - if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED) - { - unlock_dev(pdev, FALSE); - continue; - } - - peda->dev_arr[i].dev_handle = (pdev->dev_id << 16); - //may not get the desc yet - if (pdev->pusb_dev_desc) - { - peda->dev_arr[i].product_id = pdev->pusb_dev_desc->idProduct; - peda->dev_arr[i].vendor_id = pdev->pusb_dev_desc->idVendor; - } - else - { - peda->dev_arr[i].product_id = 0xffff; - peda->dev_arr[i].vendor_id = 0xffff; - } - peda->dev_arr[i].dev_addr = pdev->dev_addr; - unlock_dev(pdev, FALSE); - j++; - } - } - peda->dev_count = dev_count ? j : 0; - KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql); - - irp->IoStatus.Information = - sizeof(ENUM_DEV_ARRAY) + (dev_count - 1) * sizeof(ENUM_DEV_ELEMENT); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_GET_DEV_DESC: - { - GET_DEV_DESC_REQ gddr; - PUSB_DESC_HEADER pusb_desc_header; - PUSB_DEV pdev; - LONG buf_size; - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < 8) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - status = STATUS_SUCCESS; - buf_size = irp_stack->Parameters.DeviceIoControl.OutputBufferLength; - RtlCopyMemory(&gddr, irp->AssociatedIrp.SystemBuffer, sizeof(GET_DEV_DESC_REQ)); - pusb_desc_header = irp->AssociatedIrp.SystemBuffer; - - if (gddr.desc_type != USB_DT_CONFIG && gddr.desc_type != USB_DT_DEVICE) - { - EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp); - } - - if (usb_query_and_lock_dev(dev_mgr, gddr.dev_handle, &pdev) != STATUS_SUCCESS) - { - EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp); - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = STATUS_INVALID_DEVICE_STATE; - goto ERROR_OUT; - } - if (dev_state(pdev) != USB_DEV_STATE_ADDRESSED && - dev_state(pdev) != USB_DEV_STATE_CONFIGURED) - { - status = STATUS_DEVICE_NOT_READY; - goto ERROR_OUT; - } - - if (pdev->pusb_dev_desc == NULL) - { - status = STATUS_DEVICE_NOT_READY; - goto ERROR_OUT; - } - - if (gddr.desc_type == USB_DT_DEVICE) - { - RtlCopyMemory(pusb_desc_header, - pdev->pusb_dev_desc, - buf_size > sizeof(USB_DEVICE_DESC) - ? sizeof(USB_DEVICE_DESC) : buf_size); - - irp->IoStatus.Information = - buf_size >= sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : buf_size; - } - else if (gddr.desc_type == USB_DT_CONFIG) - { - PUSB_CONFIGURATION_DESC pusb_config_desc; - if (pdev->pusb_dev_desc->bNumConfigurations <= gddr.desc_idx) - { - status = STATUS_INVALID_PARAMETER; - goto ERROR_OUT; - } - - pusb_config_desc = usb_find_config_desc_by_idx((PUCHAR) & pdev->pusb_dev_desc[1], - gddr.desc_idx, - pdev->pusb_dev_desc-> - bNumConfigurations); - - if (pusb_config_desc == NULL) - { - status = STATUS_DEVICE_NOT_READY; - goto ERROR_OUT; - } - - RtlCopyMemory(pusb_desc_header, - pusb_config_desc, - buf_size >= pusb_config_desc->wTotalLength - ? pusb_config_desc->wTotalLength : buf_size); - - irp->IoStatus.Information = - buf_size >= pusb_config_desc->wTotalLength - ? pusb_config_desc->wTotalLength : buf_size; - } - ERROR_OUT: - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - EXIT_DISPATCH(status, irp); - } - case IOCTL_SUBMIT_URB_RD: - case IOCTL_SUBMIT_URB_WR: - case IOCTL_SUBMIT_URB_NOIO: - { - PURB purb; - ULONG endp_idx, if_idx, user_buffer_length = 0; - PUCHAR user_buffer = NULL; - PUSB_DEV pdev; - DEV_HANDLE endp_handle; - PUSB_ENDPOINT pendp; - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - purb = (PURB) irp->AssociatedIrp.SystemBuffer; - endp_handle = purb->endp_handle; - - if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR) - { - if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL) - { - user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength; - if (user_buffer_length == 0) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress); - } - else - { - if (purb->data_buffer == NULL || purb->data_length == 0) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - user_buffer_length = purb->data_length; - user_buffer = purb->data_buffer; - } - } - - if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS) - { - EXIT_DISPATCH(STATUS_IO_DEVICE_ERROR, irp); - } - - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)) - - { - status = STATUS_INVALID_DEVICE_STATE; - goto ERROR_OUT1; - } - - if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle)) - { - status = STATUS_DEVICE_NOT_READY; - goto ERROR_OUT1; - } - - if_idx = if_idx_from_handle(endp_handle); - endp_idx = endp_idx_from_handle(endp_handle); - - //if_idx exceeds the upper limit - if (pdev->usb_config) - { - if (if_idx >= pdev->usb_config->if_count - || endp_idx >= pdev->usb_config->interf[if_idx].endp_count) - { - if (!default_endp_handle(endp_handle)) - { - status = STATUS_INVALID_DEVICE_STATE; - goto ERROR_OUT1; - } - } - } - - endp_from_handle(pdev, endp_handle, pendp); - // FIXME: don't know what evil will let loose - if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL) - { - if (user_buffer_length > 0x100000) - { - status = STATUS_INVALID_PARAMETER; - goto ERROR_OUT1; - } - } - - purb->pirp = irp; - purb->context = dev_mgr; - purb->reference = ctrl_code; - - if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR) - { - if (ctrl_code == IOCTL_SUBMIT_URB_RD) - KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE); - else - KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); - - purb->data_buffer = user_buffer; - purb->data_length = user_buffer_length; - purb->completion = disp_urb_completion; - } - else - { - purb->completion = disp_noio_urb_completion; - } - - unlock_dev(pdev, FALSE); - - // we have to mark irp before the urb is scheduled to - // avoid race condition - IoMarkIrpPending(irp); - ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb)); - status = usb_submit_urb(dev_mgr, purb); - if (status != STATUS_PENDING) - { - IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED; - dev_mgr_remove_irp(dev_mgr, irp); - } - usb_unlock_dev(pdev); - if (status != STATUS_PENDING) - { - irp->IoStatus.Status = status; - IoCompleteRequest(irp, IO_NO_INCREMENT); - } - return status; - ERROR_OUT1: - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - irp->IoStatus.Information = 0; - EXIT_DISPATCH(status, irp); - } - default: - { - irp->IoStatus.Information = 0; - EXIT_DISPATCH(STATUS_NOT_IMPLEMENTED, irp); - } - } - } - default: - { - irp->IoStatus.Information = 0; - break; - } - } - EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp); -} - -/*#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the -//dev count, output_buffer_length must be no less than sizeof( long ). - -#define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer is a dword value to indicate the count of elements in the array -//input_buffer_length is sizeof( long ), output_buffer is to receive a -//structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array. - -#define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is -//no less than sizeof( input_buffer ), output_buffer is a buffer to receive the -//requested dev's desc, and output_buffer_length specifies the length of the -//buffer - -#define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS ) -#define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS ) -// input_buffer is a URB, and input_buffer_length is equal to or greater than -// sizeof( URB ); the output_buffer is a buffer to receive data from or send data -// to device. only the following urb fields can be accessed, others must be zeroed. -// DEV_HANDLE endp_handle; -// UCHAR setup_packet[8]; //for control pipe -// the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined -// by the current URB, for example, a request string from device will use XXX_RD, -// and a write to the bulk endpoint will use XXX_WR - -#define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// input_buffer is a URB, and input_buffer_length is equal to or greater than -// sizeof( URB ); the output_buffer is null and no output_buffer_length, -// only the following fields in urb can be accessed, others must be zeroed. -// DEV_HANDLE endp_handle; -// UCHAR setup_packet[8]; //for control pipe -*/ diff --git a/reactos/drivers/usb/nt4compat/usbdrv/ehci.c b/reactos/drivers/usb/nt4compat/usbdrv/ehci.c deleted file mode 100644 index 0c03e323c07..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/ehci.c +++ /dev/null @@ -1,6328 +0,0 @@ -/** - * ehci.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" -#include "ehci.h" - -//---------------------------------------------------------- -// ehci routines -//#define DEMO - -#define DEFAULT_ENDP( enDP ) \ -( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP ) - -#define dev_from_endp( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( PUSB_DEV )( enDP )->pusb_if )\ - : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) ) - -#define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK ) - -#define endp_num( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0 \ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) ) - -#define endp_dir( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0L\ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ? 1 : 0 ) - -#define dev_set_state( pdEV, staTE ) \ -( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) ) - -#define endp_max_packet_size( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \ - ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\ - : 8 )\ - : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) ) - -#define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 ) - -#define release_adapter( padapTER ) HalPutDmaAdapter(padapTER) - -#define get_int_idx( _urb, _idx ) \ -{\ - UCHAR interVAL;\ - interVAL = ( UCHAR )( ( _urb )->pipe >> 24 );\ - for( _idx = 1; _idx < 9; _idx++ )\ - {\ - interVAL >>= 1;\ - if( !interVAL )\ - break;\ - }\ - _idx --;\ -} - -#define ehci_insert_urb_to_schedule( eHCI, pURB, rET ) \ -{\ - SYNC_PARAM sync_param;\ - sync_param.ehci = eHCI;\ - sync_param.context = ( pURB );\ - sync_param.ret = FALSE;\ -\ - rET = KeSynchronizeExecution( eHCI->pdev_ext->ehci_int, ehci_sync_insert_urb_schedule, &sync_param );\ -} - -#define EHCI_ERROR_INT ( STS_FATAL | STS_ERR ) -#define EHCI_QH_ERROR( qh_contENT ) ( ( qh_contENT )->cur_qtd.status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) ) -#define EHCI_QTD_ERROR( qtd_contENT ) ( ( qtd_contENT )->status & ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_BABBLE | QTD_STS_XACT | QTD_STS_MMF ) ) - -#define EHCI_READ_PORT_ULONG( pul ) ( *pul ) -#define EHCI_WRITE_PORT_ULONG( pul, src ) \ -{\ - ULONG cmd_reg;\ - *pul = ( ULONG )src;\ - cmd_reg = EHCI_READ_PORT_ULONG( ehci->port_base + EHCI_USBCMD );\ - if( cmd_reg == 0 )\ - cmd_reg++;\ -} - -#define EHCI_READ_PORT_UCHAR( pch ) ( *pch ) -#define EHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src ) - -#define EHCI_READ_PORT_USHORT( psh ) ( *psh ) -#define EHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src ) - -#define press_doorbell( eHCI ) \ -{\ - ULONG tmp;\ - tmp = EHCI_READ_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ) );\ - tmp |= CMD_IAAD;\ - EHCI_WRITE_PORT_ULONG( ( PULONG )( ( eHCI )->port_base + EHCI_USBCMD ), tmp );\ -} -#define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) ) - -#define qh_from_list_entry( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define qtd_from_list_entry( pentry ) ( ( PEHCI_QTD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define itd_from_list_entry( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define sitd_from_list_entry( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define fstn_from_list_entry( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, elem_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) - -#define qh_from_schedule( pentry ) ( ( PEHCI_QH )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define itd_from_schedule( pentry ) ( ( PEHCI_ITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define sitd_from_schedule( pentry ) ( ( PEHCI_SITD )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) -#define fstn_from_schedule( pentry ) ( ( PEHCI_FSTN )( ( ( ULONG )struct_ptr( pentry, EHCI_ELEM_LINKS, sched_link )->phys_part ) & PHYS_PART_ADDR_MASK ) ) - -#define elem_type( ptr, from_list ) ( from_list ? ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, elem_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) \ - : ( ( ( ( ULONG )struct_ptr( ptr, EHCI_ELEM_LINKS, sched_link)->phys_part ) & PHYS_PART_TYPE_MASK ) >> 1 ) ) - -// #define elem_type_list_entry( pentry ) ( ( qh_from_schedule( pentry )->hw_next & 0x06 ) >> 1 ) -#define elem_type_list_entry( pentry ) ( elem_type( pentry, TRUE ) ) - -#define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \ -{\ - parent_HUB = pDEV->parent_dev;\ - port_IDX = pdev->port_idx;\ - while( parent_HUB )\ - {\ - if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\ - {\ - parent_HUB = NULL;\ - break;\ - }\ - if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\ - {\ - port_IDX = parent_HUB->port_idx;\ - parent_HUB = parent_HUB->parent_dev;\ - continue;\ - }\ - break;\ - }\ -} - -#define init_elem_phys_part( pelnk ) RtlZeroMemory( ( PVOID )( ( ( ULONG )( pelnk )->phys_part ) & PHYS_PART_ADDR_MASK ), get_elem_phys_part_size( ( ( ( ULONG )( pelnk )->phys_part ) & 0x06 ) >> 1 ) ) -#define REAL_INTERVAL ( 1 << pipe_content->interval ) - -#define elem_safe_free( ptHIS, single ) \ -{\ - UCHAR em_type; \ - em_type = ( UCHAR )elem_type( ptHIS, TRUE ); \ - if( ptHIS )\ - {\ - if( em_type == INIT_LIST_FLAG_QTD )\ - {\ - elem_pool_lock( qtd_pool, TRUE );\ - if( single )\ - elem_pool_free_elem( qtd_from_list_entry( ptHIS )->elem_head_link );\ - else \ - elem_pool_free_elems( qtd_from_list_entry( ptHIS )->elem_head_link );\ - elem_pool_unlock( qtd_pool, TRUE );\ - }\ - else if( em_type == INIT_LIST_FLAG_ITD )\ - {\ - elem_pool_lock( itd_pool, TRUE );\ - if( single )\ - elem_pool_free_elem( itd_from_list_entry( ptHIS )->elem_head_link );\ - else \ - elem_pool_free_elems( itd_from_list_entry( ptHIS )->elem_head_link );\ - elem_pool_unlock( itd_pool, TRUE );\ - }\ - else if( em_type == INIT_LIST_FLAG_SITD )\ - {\ - elem_pool_lock( sitd_pool, TRUE );\ - if( single )\ - elem_pool_free_elem( sitd_from_list_entry( ptHIS )->elem_head_link );\ - else \ - elem_pool_free_elems( sitd_from_list_entry( ptHIS )->elem_head_link );\ - elem_pool_unlock( sitd_pool, TRUE );\ - }\ - else if( em_type == INIT_LIST_FLAG_FSTN )\ - {\ - elem_pool_lock( fstn_pool, TRUE );\ - if( single )\ - elem_pool_free_elem( fstn_from_list_entry( ptHIS )->elem_head_link );\ - else \ - elem_pool_free_elems( fstn_from_list_entry( ptHIS )->elem_head_link );\ - elem_pool_unlock( fstn_pool, TRUE );\ - }\ - else if( em_type == INIT_LIST_FLAG_QH )\ - {\ - elem_pool_lock( qh_pool, TRUE );\ - if( single )\ - elem_pool_free_elem( qh_from_list_entry( ptHIS )->elem_head_link );\ - else \ - elem_pool_free_elems( qh_from_list_entry( ptHIS )->elem_head_link );\ - elem_pool_unlock( qh_pool, TRUE );\ - }\ - }\ -} - -#ifndef min -#define min( a, b ) ( ( a ) > ( b ) ? ( b ) : ( a ) ) -#endif -#ifndef max -#define max( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) ) -#endif - -#define CLR_RH2_PORTSTAT( port_idx, x ) \ -{\ - PULONG addr; \ - addr = ( PULONG )( ehci->port_base + port_idx ); \ - status = EHCI_READ_PORT_ULONG( addr ); \ - status = ( status & 0xfffffd5 ) & ~( x ); \ - EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \ -} - -#define SET_RH2_PORTSTAT( port_idx, x ) \ -{\ - PULONG addr; \ - addr = ( PULONG )( ehci->port_base + port_idx ); \ - status = EHCI_READ_PORT_ULONG( addr ); \ - if( x & PORT_PR ) \ - status = ( status & 0xffffffd1 ) | ( x ); \ - else \ - status = ( status & 0xffffffd5 ) | ( x ); \ - EHCI_WRITE_PORT_ULONG( addr, ( ULONG )status ); \ -} - -#define ehci_from_hcd( hCD ) ( struct_ptr( ( hCD ), EHCI_DEV, hcd_interf ) ) -#define ehci_from_dev( dEV ) ( ehci_from_hcd( dEV->hcd ) ) - -#define ehci_copy_overlay( pQHC, pTDC ) \ -{\ - LONG td_size;\ - PEHCI_QH pqh1;\ - PEHCI_QTD ptd1;\ - pqh1 = ( PEHCI_QH )( pQHC );\ - ptd1 = ( PEHCI_QTD )( pTDC );\ - td_size = get_elem_phys_part_size( INIT_LIST_FLAG_QTD );\ - ( pQHC )->cur_qtd_ptr = ptd1->phys_addr;\ - RtlZeroMemory( &( pQHC )->cur_qtd, td_size );\ - ( pQHC )->cur_qtd.data_toggle = ( pTDC )->data_toggle;\ - pqh1->hw_qtd_next = ptd1->phys_addr;\ - pqh1->hw_alt_next = EHCI_PTR_TERM;\ -} - -//declarations -typedef struct -{ - union - { - PUHCI_DEV uhci; - PEHCI_DEV ehci; - }; - PVOID context; - ULONG ret; - -} SYNC_PARAM, *PSYNC_PARAM; - -PDEVICE_OBJECT -ehci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr); - -BOOLEAN ehci_init_schedule(PEHCI_DEV ehci, PADAPTER_OBJECT padapter); - -BOOLEAN ehci_release(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr); - -static VOID ehci_stop(PEHCI_DEV ehci); - -BOOLEAN ehci_destroy_schedule(PEHCI_DEV ehci); - -BOOLEAN NTAPI ehci_sync_insert_urb_schedule(PVOID context); - -VOID ehci_init_hcd_interface(PEHCI_DEV ehci); - -NTSTATUS ehci_rh_submit_urb(PUSB_DEV rh, PURB purb); - -NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp); - -VOID ehci_generic_urb_completion(PURB purb, PVOID context); - -static NTSTATUS ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb); - -static NTSTATUS ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb); - -static NTSTATUS ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb); - -static NTSTATUS ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb); - -static ULONG ehci_scan_iso_error(PEHCI_DEV ehci, PURB purb); - -BOOLEAN ehci_claim_bandwidth(PEHCI_DEV ehci, PURB purb, BOOLEAN claim_bw); //true to claim band-width, false to free band-width - -static VOID ehci_insert_bulk_schedule(PEHCI_DEV ehci, PURB purb); - -#define ehci_insert_control_schedule ehci_insert_bulk_schedule - -static VOID ehci_insert_int_schedule(PEHCI_DEV ehci, PURB purb); - -static VOID ehci_insert_iso_schedule(PEHCI_DEV ehci, PURB purb); - -#define ehci_remove_control_from_schedule ehci_remove_bulk_from_schedule - -PDEVICE_OBJECT ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr); - -PDEVICE_OBJECT ehci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr); - -BOOLEAN ehci_delete_device(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr); - -VOID ehci_get_capabilities(PEHCI_DEV ehci, PBYTE base); - -BOOLEAN NTAPI ehci_isr(PKINTERRUPT interrupt, PVOID context); - -BOOLEAN ehci_start(PHCD hcd); - -extern VOID rh_timer_svc_reset_port_completion(PUSB_DEV dev, PVOID context); - -extern VOID rh_timer_svc_int_completion(PUSB_DEV dev, PVOID context); - -extern USB_DEV_MANAGER g_dev_mgr; - -#ifndef INCLUDE_EHCI -ULONG debug_level = DBGLVL_MAXIMUM; -PDRIVER_OBJECT usb_driver_obj = NULL; - -//pending endpoint pool funcs -VOID -ehci_wait_ms(PEHCI_DEV ehci, LONG ms) -{ - LARGE_INTEGER lms; - if (ms <= 0) - return; - - lms.QuadPart = -10 * ms; - KeSetTimer(&ehci->reset_timer, lms, NULL); - - KeWaitForSingleObject(&ehci->reset_timer, Executive, KernelMode, FALSE, NULL); - - return; -} - -BOOLEAN -init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool) -{ - int i; - if (pool == NULL) - return FALSE; - - pool->pending_endp_array = - usb_alloc_mem(NonPagedPool, sizeof(UHCI_PENDING_ENDP) * UHCI_MAX_PENDING_ENDPS); - InitializeListHead(&pool->free_que); - pool->free_count = 0; - pool->total_count = UHCI_MAX_PENDING_ENDPS; - KeInitializeSpinLock(&pool->pool_lock); - - for(i = 0; i < MAX_TIMER_SVCS; i++) - { - free_pending_endp(pool, &pool->pending_endp_array[i]); - } - - return TRUE; - -} - -BOOLEAN -free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp) -{ - if (pool == NULL || pending_endp == NULL) - { - return FALSE; - } - - RtlZeroMemory(pending_endp, sizeof(UHCI_PENDING_ENDP)); - InsertTailList(&pool->free_que, (PLIST_ENTRY) & pending_endp->endp_link); - pool->free_count++; - - return TRUE; -} - -PUHCI_PENDING_ENDP -alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count) -{ - PUHCI_PENDING_ENDP new; - if (pool == NULL || count != 1) - return NULL; - - if (pool->free_count <= 0) - return NULL; - - new = (PUHCI_PENDING_ENDP) RemoveHeadList(&pool->free_que); - pool->free_count--; - return new; -} - -BOOLEAN -destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool) -{ - if (pool == NULL) - return FALSE; - - InitializeListHead(&pool->free_que); - pool->free_count = pool->total_count = 0; - usb_free_mem(pool->pending_endp_array); - pool->pending_endp_array = NULL; - - return TRUE; - -} -#else -#define ehci_wait_ms uhci_wait_ms -extern VOID uhci_wait_ms(PEHCI_DEV ehci, LONG ms); - -extern BOOLEAN init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool); - -extern BOOLEAN free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp); - -extern PUHCI_PENDING_ENDP alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count); - -extern BOOLEAN destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool); - -#endif - -//end of pending endpoint pool funcs - -static VOID NTAPI -ehci_cancel_pending_endp_urb(IN PVOID Parameter) -{ - PLIST_ENTRY abort_list; - PUSB_DEV pdev; - PURB purb; - USE_BASIC_NON_PENDING_IRQL; - - abort_list = (PLIST_ENTRY) Parameter; - - if (abort_list == NULL) - return; - - while (IsListEmpty(abort_list) == FALSE) - { - //these devs are protected by purb's ref-count - purb = (PURB) RemoveHeadList(abort_list); - pdev = purb->pdev; - // purb->status is set when they are added to abort_list - - ehci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, FALSE); - pdev->ref_count--; - unlock_dev(pdev, FALSE); - } - usb_free_mem(abort_list); - return; -} - -static BOOLEAN -ehci_process_pending_endp(PEHCI_DEV ehci) -{ - PUSB_DEV pdev; - LIST_ENTRY temp_list, abort_list; - PLIST_ENTRY pthis; - PURB purb; - PUSB_ENDPOINT pendp; - NTSTATUS can_submit = STATUS_SUCCESS; - PWORK_QUEUE_ITEM pwork_item; - PLIST_ENTRY cancel_list; - PUSB_DEV pparent = NULL; - UCHAR port_idx = 0; - BOOLEAN tt_needed; - UCHAR hub_addr = 0; - USE_BASIC_IRQL; - - if (ehci == NULL) - return FALSE; - - InitializeListHead(&temp_list); - InitializeListHead(&abort_list); - - purb = NULL; - ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_process_pending_endp(): entering..., ehci=0x%x\n", ehci)); - - lock_pending_endp_list(&ehci->pending_endp_list_lock); - while (IsListEmpty(&ehci->pending_endp_list) == FALSE) - { - - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_process_pending_endp(): pending_endp_list=0x%x\n", - &ehci->pending_endp_list)); - - tt_needed = FALSE; - pthis = RemoveHeadList(&ehci->pending_endp_list); - pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp; - pdev = dev_from_endp(pendp); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - //delegate to ehci_remove_device for remiving the purb queue on the endpoint - continue; - } - if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0) - { - // prepare split transaction - unlock_dev(pdev, TRUE); - - // pparent won't be removed when pending_endp_list_lock is acquired. - get_parent_hs_hub(pdev, pparent, port_idx); - - if (pparent == NULL) - { - TRAP(); - ehci_dbg_print(DBGLVL_MEDIUM, - ("ehci_process_pending_endp(): full/low speed device with no parent!!!\n")); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - continue; - } - - if (hub_lock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)) == FALSE) - { - lock_dev(pdev, TRUE); - if (dev_state(pdev) != USB_DEV_STATE_ZOMB) - { - // reinsert the pending-endp to the list - InsertTailList(&temp_list, pthis); - unlock_dev(pdev, TRUE); - } - else - { - // delegate to ehci_remove_device for purb removal - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, - struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - } - continue; - } - - // backup the hub address for future use - hub_addr = pparent->dev_addr; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - tt_needed = TRUE; - // go on processing - } - - if (endp_state(pendp) == USB_ENDP_FLAG_STALL) - { - while (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - purb->status = USB_STATUS_ENDPOINT_HALTED; - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - } - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - if (tt_needed) - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - - if (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - ASSERT(purb); - } - else - { - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - if (tt_needed) - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - - if (tt_needed) - { - ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr = hub_addr; - ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx = port_idx; - } - - // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule - switch (endp_type(pendp)) - { - case USB_ENDPOINT_XFER_BULK: - { - can_submit = ehci_internal_submit_bulk(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_CONTROL: - { - can_submit = ehci_internal_submit_ctrl(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_INT: - { - can_submit = ehci_internal_submit_int(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_ISOC: - { - can_submit = ehci_internal_submit_iso(ehci, purb); - break; - } - } - - if (can_submit == STATUS_NO_MORE_ENTRIES) - { - //no enough bandwidth or tds - InsertHeadList(&pendp->urb_list, &purb->urb_link); - InsertTailList(&temp_list, pthis); - } - else - { - // otherwise error or success - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - - if (can_submit != STATUS_SUCCESS) - { - //abort these URBs - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - purb->status = can_submit; - } - } - unlock_dev(pdev, TRUE); - if (can_submit != STATUS_SUCCESS && tt_needed) - { - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - } - } - - if (IsListEmpty(&temp_list) == FALSE) - { - //re-append them to the pending_endp_list - ListFirst(&temp_list, pthis); - RemoveEntryList(&temp_list); - MergeList(&ehci->pending_endp_list, pthis); - } - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - - if (IsListEmpty(&abort_list) == FALSE) - { - PLIST_ENTRY pthis; - cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY)); - ASSERT(cancel_list); - - ListFirst(&abort_list, pthis); - RemoveEntryList(&abort_list); - InsertTailList(pthis, cancel_list); - - pwork_item = (PWORK_QUEUE_ITEM) & cancel_list[1]; - - // we do not need to worry the ehci_cancel_pending_endp_urb running when the - // driver is unloading since purb-reference count will prevent the dev_mgr to - // quit till all the reference count to the dev drop to zero. - ExInitializeWorkItem(pwork_item, ehci_cancel_pending_endp_urb, (PVOID) cancel_list); - ExQueueWorkItem(pwork_item, DelayedWorkQueue); - } - return TRUE; -} - -NTSTATUS -ehci_submit_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - int i; - PUHCI_PENDING_ENDP pending_endp; - NTSTATUS status; - USE_BASIC_IRQL; - - if (ehci == NULL) - return STATUS_INVALID_PARAMETER; - - if (pdev == NULL || pendp == NULL || purb == NULL) - { - // give a chance to those pending urb, especially for clearing hub tt - ehci_process_pending_endp(ehci); - return STATUS_INVALID_PARAMETER; - } - - lock_pending_endp_list(&ehci->pending_endp_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - - if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB) - { - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - status = ehci_rh_submit_urb(pdev, purb); - return status; - } - - if (pendp) - purb->pendp = pendp; - else - purb->pendp = &pdev->default_endp; - - if (dev_from_endp(purb->pendp) != pdev) - { - status = purb->status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - - if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL) - { - status = purb->status = USB_STATUS_ENDPOINT_HALTED; - goto LBL_OUT; - } - - if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0) - { - // wait one ms - usb_wait_ms_dpc(1); - } - - purb->pdev = pdev; - purb->rest_bytes = purb->data_length; - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK) - purb->bytes_to_transfer = (purb->data_length > EHCI_MAX_SIZE_TRANSFER ? EHCI_MAX_SIZE_TRANSFER : purb->data_length); //multiple transfer for large data block - else - purb->bytes_to_transfer = purb->data_length; - - ehci_dbg_print(DBGLVL_MEDIUM, ("ehci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer)); - - purb->bytes_transfered = 0; - InitializeListHead(&purb->trasac_list); - purb->last_finished_td = &purb->trasac_list; - purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL); - purb->flags |= URB_FLAG_STATE_PENDING; - - - i = IsListEmpty(&pendp->urb_list); - InsertTailList(&pendp->urb_list, &purb->urb_link); - - pdev->ref_count++; //for purb reference - - if (i == FALSE) - { - //there is purb pending, simply queue it and return - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC) - { - // - //No purb waiting but purb overlap not allowed, - //so leave it in queue and return, will be scheduled - //later - // - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - - pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1); - if (pending_endp == NULL) - { - //panic - status = purb->status = STATUS_UNSUCCESSFUL; - goto LBL_OUT2; - } - - pending_endp->pendp = purb->pendp; - InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link); - - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - - ehci_process_pending_endp(ehci); - return STATUS_PENDING; - - LBL_OUT2: - pdev->ref_count--; - RemoveEntryList(&purb->urb_link); - - LBL_OUT: - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - ehci_process_pending_endp(ehci); - return status; -} - -static NTSTATUS -ehci_set_error_code(PURB purb, ULONG raw_status) -{ - PURB_HS_PIPE_CONTENT pipe_content; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - - //test if the purb is canceled - if (purb->flags & URB_FLAG_FORCE_CANCEL) - { - purb->status = STATUS_CANCELLED; - } - else if (raw_status == 0) - purb->status = STATUS_SUCCESS; - - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT || - pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL) - { - - if (raw_status & QTD_STS_BABBLE) - purb->status = USB_STATUS_DATA_OVERRUN; - - else if (raw_status & QTD_STS_HALT) - purb->status = USB_STATUS_ENDPOINT_HALTED; - - else if (raw_status & QTD_STS_DBE) - purb->status = USB_STATUS_BUFFER_OVERRUN; - - else if (raw_status & QTD_STS_XACT) - purb->status = USB_STATUS_CRC; // crc is included in xact err. - - else if (raw_status & QTD_STS_MMF) - purb->status = USB_STATUS_BTSTUFF; - - else - purb->status = STATUS_UNSUCCESSFUL; - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC) - { - if (pipe_content->speed_high) - { - if (raw_status & ITD_STS_BUFERR) - purb->status = USB_STATUS_BUFFER_OVERRUN; - - else if (raw_status & ITD_STS_BABBLE) - purb->status = USB_STATUS_BABBLE_DETECTED; - - else if (raw_status & ITD_STS_XACTERR) // Xact Err - purb->status = USB_STATUS_CRC; - - else - purb->status = STATUS_UNSUCCESSFUL; - - } - else - { - if (raw_status & SITD_STS_ERR) // ERR is received from hub's tt - purb->status = USB_STATUS_ERROR; - - else if (raw_status & SITD_STS_DBE) - purb->status = USB_STATUS_BUFFER_OVERRUN; - - else if (raw_status & SITD_STS_BABBLE) - purb->status = USB_STATUS_BABBLE_DETECTED; - - else if (raw_status & SITD_STS_XACTERR) // Xact Error - purb->status = USB_STATUS_CRC; - - else if (raw_status & SITD_STS_MISSFRM) // missing microframe - purb->status = USB_STATUS_DATA_TOGGLE_MISMATCH; - - else - purb->status = STATUS_UNSUCCESSFUL; - } - } - if (purb->status != STATUS_SUCCESS) - { - hcd_dbg_print(DBGLVL_MEDIUM, ("ehci_set_error_code(): error status 0x%x\n", raw_status)); - } - return purb->status; -} - -static BOOLEAN NTAPI -ehci_sync_remove_urb_finished(PVOID context) -{ - PEHCI_DEV ehci; - PLIST_ENTRY pthis, pnext, ptemp; - PURB purb; - PSYNC_PARAM pparam; - - pparam = (PSYNC_PARAM) context; - ehci = pparam->ehci; - ptemp = (PLIST_ENTRY) pparam->context; - - if (ehci == NULL) - { - return (UCHAR) (pparam->ret = FALSE); - } - - ListFirst(&ehci->urb_list, pthis); - while (pthis) - { - //remove urbs not in the schedule - ListNext(&ehci->urb_list, pthis, pnext); - purb = (PURB) pthis; - - if ((purb->flags & URB_FLAG_IN_SCHEDULE) == 0) - { - //finished or canceled( not applied for split bulk ). - RemoveEntryList(pthis); - InsertTailList(ptemp, pthis); - } - pthis = pnext; - } - pparam->ret = TRUE; - return (UCHAR) TRUE; -} - -VOID NTAPI -ehci_dpc_callback(PKDPC dpc, PVOID context, PVOID sysarg1, PVOID sysarg2) -{ - PEHCI_DEV ehci; - - LIST_HEAD temp_list; - PLIST_ENTRY pthis, pnext; - PURB purb; - PEHCI_QH pqh; - PEHCI_QTD ptd; - PUHCI_PENDING_ENDP pending_endp; - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - - BOOLEAN finished; - LONG i; - ULONG ehci_status, urb_status; - - SYNC_PARAM sync_param; - UCHAR ep_type; - USE_BASIC_NON_PENDING_IRQL; - - ehci = (PEHCI_DEV) context; - if (ehci == NULL) - return; - - ehci_status = (ULONG) sysarg1; - - InitializeListHead(&temp_list); - - sync_param.ehci = ehci; - sync_param.context = (PVOID) & temp_list; - - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_dpc_callback(): entering..., ehci=0x%x\n", ehci)); - //remove finished purb from ehci's purb-list - KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_remove_urb_finished, &sync_param); - - //release resources( itds, sitds, fstns, tds, and qhs ) allocated for the purb - while (IsListEmpty(&temp_list) == FALSE) - { - //not in any public queue, if do not access into dev, no race - //condition will occur - purb = (PURB) RemoveHeadList(&temp_list); - urb_status = purb->status; - ep_type = endp_type(purb->pendp); - - if (ep_type == USB_ENDPOINT_XFER_ISOC) - { - // collect error for iso transfer - urb_status = ehci_scan_iso_error(ehci, purb); - } - - //the only place we do not use this lock on non-pending-endp-list data - KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock); - while (IsListEmpty(&purb->trasac_list) == FALSE) - { - UCHAR em_type; - pthis = RemoveHeadList(&purb->trasac_list); - em_type = (UCHAR) elem_type(pthis, TRUE); - - if (em_type == INIT_LIST_FLAG_QH) - { - pqh = qh_from_list_entry(pthis); - elem_safe_free(pthis, TRUE); - } - else - { - //must be an itd, sitd chain - InsertHeadList(&purb->trasac_list, pthis); - for(i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++) - { - PEHCI_QTD_CONTENT ptdc = NULL; - PEHCI_ITD_CONTENT pitdc; - PEHCI_SITD_CONTENT psitdc; - - em_type = (UCHAR) elem_type(pthis, TRUE); - - // accumulate data transfered in tds - if (em_type == INIT_LIST_FLAG_QTD) - { - ptd = qtd_from_list_entry(pthis); - ptdc = (PEHCI_QTD_CONTENT) ptd; - if ((ptdc->status & QTD_STS_ACTIVE) == 0 && ((ptdc->status & QTD_ANY_ERROR) == 0)) - purb->bytes_transfered += ptd->bytes_to_transfer; - } - else if (em_type == INIT_LIST_FLAG_ITD) - { - int j; - pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis); - for(j = 0; j < 8; j++) - { - if ((pitdc->status_slot[j].status & ITD_STS_ACTIVE) == 0 - && (pitdc->status_slot[j].status & ITD_ANY_ERROR) == 0) - purb->bytes_transfered += ptdc->bytes_to_transfer; - } - } - else if (em_type == INIT_LIST_FLAG_SITD) - { - psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis); - if ((psitdc->status & SITD_STS_ACTIVE) == 0 && (psitdc->status & SITD_ANY_ERROR) == 0) - purb->bytes_transfered += ptdc->bytes_to_transfer; - } - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - - // check to see if an fstn is there - ListFirstPrev(&purb->trasac_list, pthis); - if (elem_type(pthis, TRUE) == INIT_LIST_FLAG_FSTN) - { - RemoveEntryList(pthis); - elem_safe_free(pthis, TRUE); - } - - ListFirst(&purb->trasac_list, pthis); - RemoveEntryList(&purb->trasac_list); - - // free the tds - elem_safe_free(pthis, FALSE); - - //termination condition - InitializeListHead(&purb->trasac_list); - purb->last_finished_td = NULL; - } - } - - if (ep_type == USB_ENDPOINT_XFER_ISOC || ep_type == USB_ENDPOINT_XFER_INT) - ehci_claim_bandwidth(ehci, purb, FALSE); //release band-width - - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - - ehci_set_error_code(purb, urb_status); - - pdev = dev_from_endp(purb->pendp); - pendp = purb->pendp; - - // perform clear tt buffer if error on full/low bulk/control pipe - if (ep_type == USB_ENDPOINT_XFER_BULK || ep_type == USB_ENDPOINT_XFER_CONTROL) - { - PURB_HS_PIPE_CONTENT pipe_content; - PUSB_DEV phub; - UCHAR port_idx; - - get_parent_hs_hub(pdev, phub, port_idx); - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - - if (pipe_content->speed_high == 0 && purb->status != STATUS_SUCCESS) - { - // lets schedule an event to clear the tt buffer - hub_post_clear_tt_event(phub, port_idx, purb->pipe); - } - else if (pipe_content->speed_high == 0) - { - if (phub == NULL) - TRAP(); - else - { - // release tt if no error - hub_unlock_tt(phub, (UCHAR) port_idx, (UCHAR) pipe_content->trans_type); - } - } - } - - finished = TRUE; - - //since the ref_count for the purb is not released, we can safely have one - //pointer to dev - - if (purb->status == USB_STATUS_BABBLE_DETECTED) - { - usb_dbg_print(DBGLVL_MEDIUM, - ("ehci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n")); - // ehci_start( ehci ); - } - - if (ehci_status & STS_HALT) //&& !ehci->is_suspended - { - ehci_start(&ehci->hcd_interf); - } - - //this will let the new request in ehci_generic_urb_completion to this endp - //be processed rather than queued in the pending_endp_list - lock_dev(pdev, TRUE); - usb_endp_busy_count_dec(pendp); - unlock_dev(pdev, TRUE); - - if (usb_success(purb->status) == FALSE) - { - // set error code and complete the purb and purb is invalid from this point - ehci_generic_urb_completion(purb, purb->context); - } - else - { - if (ep_type == USB_ENDPOINT_XFER_BULK) - { - purb->rest_bytes -= purb->bytes_transfered; - if (purb->rest_bytes) - { - finished = FALSE; - } - else - { - ehci_generic_urb_completion(purb, purb->context); - } - } - else - { - ehci_generic_urb_completion(purb, purb->context); - // DbgBreakPoint(); - //purb is now invalid - } - } - - KeAcquireSpinLockAtDpcLevel(&ehci->pending_endp_list_lock); - lock_dev(pdev, TRUE); - - if (finished) - pdev->ref_count--; - - if (urb_status && ((ep_type == USB_ENDPOINT_XFER_BULK) || (ep_type == USB_ENDPOINT_XFER_INT))) - { - // error on int or bulk pipe, cleared in usb_reset_pipe_completion - pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK; - pendp->flags |= USB_ENDP_FLAG_STALL; - } - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - if (finished == FALSE) - { - - purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - ehci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, TRUE); - pdev->ref_count--; - unlock_dev(pdev, TRUE); - } - continue; - } - - if (finished && IsListEmpty(&pendp->urb_list) == TRUE) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - continue; - } - else if (finished == TRUE) - { - //has purb in the endp's purb-list - if (usb_endp_busy_count(pendp) > 0) - { - //the urbs still have chance to be sheduled but not this time - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - continue; - } - } - - if (finished == FALSE) - { - //a split bulk transfer, ( not the high speed split transfer ) - purb->bytes_transfered = 0; - purb->bytes_to_transfer = - EHCI_MAX_SIZE_TRANSFER > purb->rest_bytes ? purb->rest_bytes : EHCI_MAX_SIZE_TRANSFER; - - //the purb is not finished - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_PENDING; - - InsertHeadList(&pendp->urb_list, &purb->urb_link); - } - - pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1); - if (!pending_endp) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - return; - } - pending_endp->pendp = pendp; - InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link); - - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&ehci->pending_endp_list_lock); - } - - //ah...exhausted, let's find some in the pending_endp_list to rock - ehci_process_pending_endp(ehci); - return; -} - -static BOOLEAN NTAPI -ehci_sync_cancel_urbs_dev(PVOID context) -{ - //cancel all the urbs on one dev - PEHCI_DEV ehci; - PUSB_DEV pdev, dest_dev; - PSYNC_PARAM sync_param; - PLIST_ENTRY pthis, pnext; - LONG count; - - sync_param = (PSYNC_PARAM) context; - dest_dev = (PUSB_DEV) sync_param->context; - ehci = sync_param->ehci; - - if (ehci == NULL || dest_dev == NULL) - { - return (UCHAR) (sync_param->ret = FALSE); - } - count = 0; - ListFirst(&ehci->urb_list, pthis); - while (pthis) - { - pdev = dev_from_endp(((PURB) pthis)->pendp); - if (pdev == dest_dev) - { - ((PURB) pthis)->flags |= URB_FLAG_FORCE_CANCEL; - } - ListNext(&ehci->urb_list, pthis, pnext); - pthis = pnext; - count++; - } - - if (count) - { - // signal an int for further process - press_doorbell(ehci); - } - return (UCHAR) (sync_param->ret = TRUE); -} - -BOOLEAN -ehci_remove_device(PEHCI_DEV ehci, PUSB_DEV dev) -{ - PUHCI_PENDING_ENDP ppending_endp; - PLIST_ENTRY pthis, pnext; - PURB purb; - LIST_HEAD temp_list; - int i, j, k; - SYNC_PARAM sync_param; - - USE_BASIC_IRQL; - - if (ehci == NULL || dev == NULL) - return FALSE; - - InitializeListHead(&temp_list); - - //free pending endp that has purb queued from pending endp list - lock_pending_endp_list(&ehci->pending_endp_list_lock); - - ListFirst(&ehci->pending_endp_list, pthis); - - while (pthis) - { - ppending_endp = (PUHCI_PENDING_ENDP) pthis; - ListNext(&ehci->pending_endp_list, pthis, pnext); - if (dev_from_endp(ppending_endp->pendp) == dev) - { - RemoveEntryList(pthis); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - } - pthis = pnext; - } - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - - //cancel all the urbs in the purb-list - sync_param.ehci = ehci; - sync_param.context = (PVOID) dev; - - KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urbs_dev, &sync_param); - - //cancel all the purb in the endp's purb-list - k = 0; - lock_dev(dev, FALSE); - if (dev->usb_config) - { - //only for configed dev - for(i = 0; i < dev->usb_config->if_count; i++) - { - for(j = 0; j < dev->usb_config->interf[i].endp_count; j++) - { - ListFirst(&dev->usb_config->interf[i].endp[j].urb_list, pthis); - while (pthis) - { - ListNext(&dev->usb_config->interf[i].endp[j].urb_list, pthis, pnext); - - RemoveEntryList(pthis); - InsertHeadList(&temp_list, pthis); - pthis = pnext; - k++; - } - - } - } - } - ListFirst(&dev->default_endp.urb_list, pthis); - - while (pthis) - { - ListNext(&dev->default_endp.urb_list, pthis, pnext); - - RemoveEntryList(pthis); - InsertHeadList(&temp_list, pthis); - pthis = pnext; - k++; - } - unlock_dev(dev, FALSE); - - if (IsListEmpty(&temp_list) == FALSE) - { - for(i = 0; i < k; i++) - { - //complete those urbs with error - pthis = RemoveHeadList(&temp_list); - purb = (PURB) pthis; - purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - { - ehci_generic_urb_completion(purb, purb->context); - } - } - } - - lock_dev(dev, FALSE) dev->ref_count -= k; - unlock_dev(dev, FALSE); - - return TRUE; -} - -static BOOLEAN -ehci_insert_urb_schedule(PEHCI_DEV ehci, PURB purb) -// must have dev_lock( ehci_process_pending_endp ) and frame_list_lock acquired -{ - PURB_HS_PIPE_CONTENT pipe_content; - - if (ehci == NULL || purb == NULL) - return FALSE; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - switch (pipe_content->trans_type) - { - case USB_ENDPOINT_XFER_CONTROL: - ehci_insert_control_schedule(ehci, purb); - break; - case USB_ENDPOINT_XFER_BULK: - ehci_insert_bulk_schedule(ehci, purb); - break; - case USB_ENDPOINT_XFER_INT: - ehci_insert_int_schedule(ehci, purb); - break; - case USB_ENDPOINT_XFER_ISOC: - ehci_insert_iso_schedule(ehci, purb); - break; - default: - return FALSE; - } - - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE; - InsertTailList(&ehci->urb_list, &purb->urb_link); - - return TRUE; -} - -static BOOLEAN -ehci_insert_tds_qh(PEHCI_DEV ehci, PEHCI_QH pqh, PEHCI_QTD td_chain) -{ - if (pqh == NULL || td_chain == NULL) - return FALSE; - - UNREFERENCED_PARAMETER(ehci); - - ehci_copy_overlay((PEHCI_QH_CONTENT) pqh, (PEHCI_QTD_CONTENT) td_chain); - InsertTailList(&td_chain->elem_head_link->elem_link, &pqh->elem_head_link->elem_link); - return TRUE; -} - -static BOOLEAN -ehci_insert_qh_urb(PURB purb, PEHCI_QH pqh) -{ - PLIST_ENTRY pthis, pnext; - if (pqh == NULL || purb == NULL) - return FALSE; - - InsertTailList(&pqh->elem_head_link->elem_link, &purb->trasac_list); - ListFirst(&purb->trasac_list, pthis) while (pthis) - { - // note: fstn may in this chain - struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb; - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - return TRUE; -} - -#define calc_td_count( pURB, start_aDDR, td_coUNT ) \ -{\ - LONG i, j, k;\ - td_coUNT = 0;\ - k = ( ( pURB )->bytes_to_transfer + max_packet_size - 1 ) / max_packet_size;\ - if( k != 0 )\ - {\ - LONG packets_per_td, packets_per_page;\ - packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size;\ - packets_per_page = PAGE_SIZE / max_packet_size;\ - i = ( ( LONG )&( pURB )->data_buffer[ ( start_aDDR ) ] ) & ( PAGE_SIZE - 1 );\ - if( i )\ - {\ - i = PAGE_SIZE - i;\ - j = i & ( max_packet_size - 1 );\ - k -= ( EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j ) / max_packet_size;\ - if( k < 0 )\ - td_coUNT = 1;\ - else\ - {\ - if( j )\ - i = packets_per_td - packets_per_page;\ - else\ - i = packets_per_td;\ - td_coUNT = 1 + ( k + i - 1 ) / i; \ - }\ - }\ - else\ - {\ - td_coUNT = ( k + packets_per_td - 1 ) / packets_per_td;\ - }\ - }\ -} - -static BOOLEAN -ehci_fill_td_buf_ptr(PURB purb, LONG start_addr, // start idx into purb->data_buffer - PLIST_ENTRY td_list, LONG td_count, ULONG toggle) -// fill the tds' bytes_to_transfer and hw_buf, return next toggle value: true 1, false 0 -{ - LONG i, j, k, data_load; - LONG packets_per_td, packets_per_page, bytes_to_transfer, max_packet_size; - PLIST_ENTRY pthis, pnext; - PEHCI_QTD_CONTENT ptdc; - PEHCI_QTD ptd; - PVOID ptr; - - if (purb == NULL || td_list == NULL || td_count == 0) - return toggle; - - max_packet_size = 1 << ((PURB_HS_PIPE_CONTENT) & purb->pipe)->max_packet_size; - packets_per_td = EHCI_QTD_MAX_TRANS_SIZE / max_packet_size; - packets_per_page = PAGE_SIZE / max_packet_size; - - pthis = td_list; - bytes_to_transfer = purb->bytes_to_transfer; - - i = ((LONG) & (purb)->data_buffer[(start_addr)]) & (PAGE_SIZE - 1); - if (i) - { - i = PAGE_SIZE - i; - j = i & (max_packet_size - 1); - } - else - { - i = j = 0; - } - - while (bytes_to_transfer) - { - ptd = qtd_from_list_entry(pthis); - ptd->hw_buf[0] = MmGetPhysicalAddress(&purb->data_buffer[start_addr]).LowPart; - ptdc = (PEHCI_QTD_CONTENT) ptd; - - if (i != 0) - { - data_load = (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) < bytes_to_transfer - ? (LONG) (EHCI_QTD_MAX_TRANS_SIZE - PAGE_SIZE + i - j) : bytes_to_transfer; - - ptdc->bytes_to_transfer = (USHORT) data_load; - ptd->bytes_to_transfer = (USHORT) data_load; - - // subtract the header part - data_load -= (i < data_load ? i : data_load); - - for(k = 1; data_load > 0; k++) - { - ptr = &purb->data_buffer[start_addr + i + (k - 1) * PAGE_SIZE]; - ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1)); - ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart; - data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load; - } - } - else - { - // aligned on page boundary - data_load = EHCI_QTD_MAX_TRANS_SIZE < bytes_to_transfer - ? EHCI_QTD_MAX_TRANS_SIZE : bytes_to_transfer; - - ptdc->bytes_to_transfer = (USHORT) data_load; - ptd->bytes_to_transfer = (USHORT) data_load; - - data_load -= (PAGE_SIZE < data_load ? PAGE_SIZE : data_load); - - for(k = 1; data_load > 0; k++) - { - ptr = &purb->data_buffer[start_addr + k * PAGE_SIZE]; - ptr = (PVOID) (((ULONG) ptr) & ~(PAGE_SIZE - 1)); - ptd->hw_buf[k] = MmGetPhysicalAddress(ptr).LowPart; - data_load -= PAGE_SIZE < data_load ? PAGE_SIZE : data_load; - } - } - ptdc->data_toggle = toggle; - if (((ptdc->bytes_to_transfer + max_packet_size - 1) / max_packet_size) & 1) - { - //only odd num of transactions has effect - toggle ^= 1; - } - start_addr += ptdc->bytes_to_transfer; - bytes_to_transfer -= ptdc->bytes_to_transfer; - ListNext(td_list, pthis, pnext); - pthis = pnext; - i = j; - } - return toggle; -} - -static NTSTATUS -ehci_internal_submit_bulk(PEHCI_DEV ehci, PURB purb) -// -// assume that the purb has its rest_bytes and bytes_to_transfer set -// and bytes_transfered is zeroed. -// dev_lock must be acquired outside -// purb comes from dev's endpoint purb-list. it is already removed from -// the endpoint purb-list. -// -{ - - LONG max_packet_size, td_count, offset, bytes_to_transfer; - PBYTE start_addr; - PEHCI_QTD ptd; - PEHCI_QH pqh; - LIST_ENTRY td_list, *pthis, *pnext; - BOOLEAN old_toggle, toggle, ret; - UCHAR pid; - LONG i, j; - PURB_HS_PIPE_CONTENT pipe_content; - PEHCI_QTD_CONTENT ptdc; - PEHCI_QH_CONTENT pqhc; - PEHCI_ELEM_LINKS pelnk; - PEHCI_ELEM_LINKS plnk; - - if (ehci == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - max_packet_size = endp_max_packet_size(purb->pendp); - if (purb->bytes_to_transfer == 0) - { - return STATUS_INVALID_PARAMETER; - } - - start_addr = &purb->data_buffer[purb->data_length - purb->rest_bytes]; - calc_td_count(purb, purb->data_length - purb->rest_bytes, td_count); - - elem_pool_lock(qtd_pool, TRUE); - pelnk = elem_pool_alloc_elems(qtd_pool, td_count); - elem_pool_unlock(qtd_pool, TRUE); - - if (pelnk == NULL) - { - return STATUS_UNSUCCESSFUL; - } - ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - - InitializeListHead(&td_list); - InsertTailList(&ptd->elem_head_link->elem_link, &td_list); - - ListFirst(&td_list, pthis); - ListNext(&td_list, pthis, pnext); - - offset = 0; - - old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE; - bytes_to_transfer = purb->bytes_to_transfer; - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_bulk():dev toggle=%d\n", toggle)); - - for(i = 1; i < 16; i++) - { - if ((max_packet_size >> i) == 0) - break; - } - i--; - i &= 0xf; - - purb->pipe = 0; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - pipe_content->max_packet_size = i; - pipe_content->endp_addr = endp_num(purb->pendp); - pipe_content->dev_addr = dev_from_endp(purb->pendp)->dev_addr; - pipe_content->trans_dir = endp_dir(purb->pendp); - pipe_content->trans_type = USB_ENDPOINT_XFER_BULK; - pipe_content->data_toggle = toggle; - pipe_content->speed_high = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; - pipe_content->speed_low = (dev_from_endp(purb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0; - - pid = (((ULONG) purb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT); - - i = ((ULONG) start_addr) & (PAGE_SIZE - 1); // header part within first page - if (i) - { - i = PAGE_SIZE - i; - if (i < purb->bytes_to_transfer) - j = i & (max_packet_size - 1); - else - j = 0; - } - else - j = 0; - - // fill the page pointer and toggle - - toggle = ehci_fill_td_buf_ptr(purb, purb->data_length - purb->rest_bytes, pthis, td_count, toggle); - while (pthis) - { - ptd = qtd_from_list_entry(pthis); - ptdc = (PEHCI_QTD_CONTENT) ptd; - - // ptdc->alt_terminal = 1; - // ptdc->alt_qtd = 0; - ptd->hw_alt_next = EHCI_PTR_TERM; - ptdc->pid = pid; - - // ptd->elem_head_link->purb = purb; will be filled later - ptdc->err_count = 3; - ptdc->status = 0x80; // active, and do_start_split for split transfer - ptdc->cur_page = 0; - // ptdc->data_toggle = toggle; - - if (pnext) - { - ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr; - } - else - { - //Last one, enable ioc and short packet detect if necessary - ptd->hw_next = EHCI_PTR_TERM; - ptdc->ioc = TRUE; - if (bytes_to_transfer < max_packet_size && (pid == QTD_PID_IN)) - { - //ptd->status |= TD_CTRL_SPD; - } - } - - pthis = pnext; - - if (pthis) - ListNext(&td_list, pthis, pnext); - } - - ListFirst(&td_list, pthis); - RemoveEntryList(&td_list); - - elem_pool_lock(qh_pool, TRUE); - - plnk = elem_pool_alloc_elem(qh_pool); - if (plnk == NULL) - { - // free the qtds - elem_safe_free(pthis, TRUE); - if (qh_pool) elem_pool_unlock(qh_pool, TRUE); - return STATUS_UNSUCCESSFUL; - } - - pqh = (PEHCI_QH) ((ULONG) plnk->phys_part & PHYS_PART_ADDR_MASK); - elem_pool_unlock(qh_pool, TRUE); - - if (pqh == NULL) - { - // free the qtds - elem_safe_free(pthis, TRUE); - return STATUS_NO_MORE_ENTRIES; - - } - - purb->td_count = td_count; - pqhc = (PEHCI_QH_CONTENT) pqh; - pqh->hw_next = EHCI_PTR_TERM; // filled later - pqhc->dev_addr = pipe_content->dev_addr; - pqhc->inactive = 0; - pqhc->endp_addr = pipe_content->endp_addr; - pqhc->data_toggle = 0; //pipe_content->data_toggle; - pqhc->is_async_head = 0; - pqhc->max_packet_size = (1 << pipe_content->max_packet_size); - pqhc->is_ctrl_endp = 0; - pqhc->reload_counter = EHCI_NAK_RL_COUNT; - - if (pipe_content->speed_high) - pqhc->endp_spd = USB_SPEED_HIGH; - else if (pipe_content->speed_low) - pqhc->endp_spd = USB_SPEED_LOW; - else - pqhc->endp_spd = USB_SPEED_FULL; - - pqh->hw_info2 = 0; - pqhc->mult = 1; - pqh->hw_current = 0; - pqh->hw_qtd_next = 0; // filled later - pqh->hw_alt_next = EHCI_PTR_TERM; - pqh->hw_token = 0; //indicate to advance queue before execution - - if (!pipe_content->speed_high) - { - pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr; - pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx; - } - - ptd = qtd_from_list_entry(pthis); - ehci_insert_tds_qh(ehci, pqh, ptd); - ehci_insert_qh_urb(purb, pqh); - purb->pendp->flags = - (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle ? USB_ENDP_FLAG_DATATOGGLE : 0); - usb_endp_busy_count_inc(purb->pendp); - ehci_insert_urb_to_schedule(ehci, purb, ret); - - if (ret == FALSE) - { - // undo all we have done - ListFirst(&pqh->elem_head_link->elem_link, pthis); - - RemoveEntryList(&purb->trasac_list); - RemoveEntryList(&pqh->elem_head_link->elem_link); //remove qh from td_chain - - elem_safe_free(pthis, FALSE); - elem_safe_free(&pqh->elem_head_link->elem_link, TRUE); - - InitializeListHead(&purb->trasac_list); - // usb_endp_busy_count_dec( purb->pendp ); // the decrement is done in the dpc callback - purb->pendp->flags = - (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0); - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} - -static NTSTATUS -ehci_internal_submit_ctrl(PEHCI_DEV ehci, PURB purb) -{ - - LIST_ENTRY td_list, *pthis, *pnext; - LONG i, td_count; - LONG toggle; - LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx; - - PEHCI_QTD ptd; - PEHCI_QH pqh; - PEHCI_QH_CONTENT pqhc; - UCHAR dev_addr; - BOOLEAN ret; - PURB_HS_PIPE_CONTENT pipe_content; - PEHCI_QTD_CONTENT ptdc; - PEHCI_ELEM_LINKS pelnk; - PUSB_DEV pdev; - - if (ehci == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - bytes_rest = purb->rest_bytes; - bytes_to_transfer = purb->bytes_to_transfer; - max_packet_size = endp_max_packet_size(purb->pendp); - start_idx = purb->data_length - purb->rest_bytes; - - calc_td_count(purb, start_idx, td_count); - td_count += 2; // add setup td and handshake td - - elem_pool_lock(qtd_pool, TRUE); - pelnk = elem_pool_alloc_elems(qtd_pool, td_count); - elem_pool_unlock(qtd_pool, TRUE); - - if (pelnk == NULL) - { - return STATUS_NO_MORE_ENTRIES; - } - - InsertTailList(&pelnk->elem_link, &td_list); - ListFirst(&td_list, pthis); - ListNext(&td_list, pthis, pnext); - - ptd = qtd_from_list_entry(pthis); - - pdev = dev_from_endp(purb->pendp); - dev_addr = pdev->dev_addr; - - if (dev_state(pdev) <= USB_DEV_STATE_RESET) //only valid for control transfer - dev_addr = 0; - - usb_dbg_print(DBGLVL_MAXIMUM, ("ehci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr)); - - // fill the setup packet - ptdc = (PEHCI_QTD_CONTENT) ptd; - ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr; - ptd->hw_alt_next = EHCI_PTR_TERM; - ptdc->status = 0x80; // active - ptdc->pid = QTD_PID_SETUP; - ptdc->err_count = 3; - ptdc->cur_page = 0; - ptdc->ioc = 0; - ptdc->bytes_to_transfer = sizeof(USB_CTRL_SETUP_PACKET); - ptdc->data_toggle = 0; - ptd->hw_buf[0] = MmGetPhysicalAddress(purb->setup_packet).LowPart; - - for(i = 1; i < 16; i++) - { - if ((max_packet_size >> i) == 0) - break; - } - i--; - i &= 0xf; - - purb->pipe = 0; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - pipe_content->max_packet_size = i; - pipe_content->endp_addr = endp_num(purb->pendp); - pipe_content->dev_addr = dev_addr; - pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0; - pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; - pipe_content->trans_type = USB_ENDPOINT_XFER_CONTROL; - - pthis = pnext; - ListNext(&td_list, pthis, pnext); - - // all the tds's toggle and data_buffer pointer is filled here - toggle = 1; - ehci_fill_td_buf_ptr(purb, start_idx, pthis, td_count - 2, toggle); - - for(i = 0; ((i < td_count - 2) && pthis); i++) - { - //construct tds for DATA packets of data stage. - ptd = qtd_from_list_entry(pthis); - ptdc = (PEHCI_QTD_CONTENT) ptd; - ptd->hw_alt_next = EHCI_PTR_TERM; - ptdc->status = 0x80; // active and startXSplit - ptdc->pid = ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_IN : QTD_PID_OUT); - ptdc->err_count = 3; - ptdc->cur_page = 0; - ptdc->ioc = 0; - - if (pnext) - ptd->hw_next = qtd_from_list_entry(pnext)->phys_addr; - else - ptd->hw_next = EHCI_PTR_TERM; - - pthis = pnext; - if (pthis) - ListNext(&td_list, pthis, pnext); - } - - if (pthis) - ptd->hw_next = qtd_from_list_entry(pthis)->phys_addr; - else - TRAP(); - - // ListFirstPrev( &td_list, pthis ); - ptd = qtd_from_list_entry(pthis); - - //the last is an IN transaction - ptdc = (PEHCI_QTD_CONTENT) ptd; - ptd->hw_alt_next = EHCI_PTR_TERM; - ptdc->status = 0x80; - ptdc->pid = ((td_count > 2) - ? ((purb->setup_packet[0] & USB_DIR_IN) ? QTD_PID_OUT : QTD_PID_IN) : QTD_PID_IN); - - ptdc->err_count = 3; - ptdc->cur_page = 0; - ptdc->ioc = 1; - ptdc->bytes_to_transfer = 0; - ptdc->data_toggle = 1; - ptd->hw_next = EHCI_PTR_TERM; - - ListFirst(&td_list, pthis); - RemoveEntryList(&td_list); - - ptd = qtd_from_list_entry(pthis); - elem_pool_lock(qh_pool, TRUE); - pelnk = elem_pool_alloc_elem(qh_pool); - elem_pool_unlock(qh_pool, TRUE); - - if (pelnk == NULL) - { - elem_safe_free(pthis, FALSE); - return STATUS_NO_MORE_ENTRIES; - - } - pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - pqhc = (PEHCI_QH_CONTENT) pqh; - - pqh->hw_alt_next = pqh->hw_next = EHCI_PTR_TERM; - - pqhc->dev_addr = dev_addr; - pqhc->inactive = 0; - pqhc->endp_addr = endp_num(purb->pendp); - - if (pipe_content->speed_high) - pqhc->endp_spd = USB_SPEED_HIGH; - else if (pipe_content->speed_low) - pqhc->endp_spd = USB_SPEED_LOW; - else - pqhc->endp_spd = USB_SPEED_FULL; - - pqhc->data_toggle = 1; // use dt from qtd - pqhc->is_async_head = 0; - pqhc->max_packet_size = endp_max_packet_size(purb->pendp); - - if (pipe_content->speed_high == 0) - pqhc->is_ctrl_endp = 1; - else - pqhc->is_ctrl_endp = 0; - - pqhc->reload_counter = EHCI_NAK_RL_COUNT; - - // DWORD 2 - pqh->hw_info2 = 0; - pqhc->mult = 1; - - if (!pipe_content->speed_high) - { - pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr; - pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx; - } - - purb->td_count = td_count; - - ehci_insert_tds_qh(ehci, pqh, ptd); - ehci_insert_qh_urb(purb, pqh); - - usb_endp_busy_count_inc(purb->pendp); - ehci_insert_urb_to_schedule(ehci, purb, ret); - - if (ret == FALSE) - { - RemoveEntryList(&purb->trasac_list); - RemoveEntryList(&pqh->elem_head_link->elem_link); - - elem_safe_free(&pqh->elem_head_link->elem_link, TRUE); - elem_safe_free(pthis, FALSE); - - InitializeListHead(&purb->trasac_list); - // usb_endp_busy_count_dec( purb->pendp ); - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} - -static NTSTATUS -ehci_internal_submit_int(PEHCI_DEV ehci, PURB purb) -{ - LONG i, max_packet_size; - PEHCI_QTD ptd; - BOOLEAN ret; - PUSB_DEV pdev; - PURB_HS_PIPE_CONTENT pipe_content; - UCHAR mult_trans, toggle, old_toggle; - PEHCI_ELEM_LINKS pelnk; - PEHCI_QTD_CONTENT ptdc; - PEHCI_QH pqh; - PEHCI_QH_CONTENT pqhc; - PEHCI_FSTN pfstn; - - if (ehci == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - old_toggle = toggle = (purb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE; - max_packet_size = endp_max_packet_size(purb->pendp); - pdev = dev_from_endp(purb->pendp); - - if (max_packet_size == 0 || max_packet_size > 64) - return STATUS_INVALID_PARAMETER; - - if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0) - { - if (max_packet_size < purb->data_length) - return STATUS_INVALID_PARAMETER; - - for(i = 1; i < 16; i++) - { - if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0) - break; - } - i--; - mult_trans = 1; - } - else - { - mult_trans = endp_mult_count(purb->pendp); - if (max_packet_size * endp_mult_count(purb->pendp) < purb->data_length) - return STATUS_INVALID_PARAMETER; - i = purb->pendp->pusb_endp_desc->bInterval - 1; - } - - purb->pipe = 0; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - pipe_content->interval = i; - pipe_content->trans_type = USB_ENDPOINT_XFER_INT; // bit 0-1 - pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5 - pipe_content->speed_low = (pdev->flags & USB_DEV_FLAG_LOW_SPEED) ? 1 : 0; // bit 6 - pipe_content->trans_dir = endp_dir(purb->pendp); // bit 7 - pipe_content->dev_addr = pdev->dev_addr; // bit 8-14 - pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18 - pipe_content->data_toggle = 1; // bit 19 - pipe_content->mult_count = mult_trans; - - // pipe_content->start_uframe : 3; // bit 28-30 will be filled later - - for(i = 1; i <= 16; i++) - { - if (((ULONG) max_packet_size) >> i) - continue; - else - break; - } - i--; - i &= 0xf; - - pipe_content->max_packet_size = i; // bit 20-23 log2( max_packet_size ) - - if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE) - { - // can not allocate bandwidth for it - return STATUS_UNSUCCESSFUL; - } - - // one qtd is enough - elem_pool_lock(qtd_pool, TRUE); - pelnk = elem_pool_alloc_elem(qtd_pool); - elem_pool_unlock(qtd_pool, TRUE); - - if (pelnk == NULL) - { - ehci_claim_bandwidth(ehci, purb, FALSE); - return STATUS_NO_MORE_ENTRIES; - } - - ptd = (PEHCI_QTD) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - ptdc = (PEHCI_QTD_CONTENT) ptd; - ptd->hw_next = EHCI_PTR_TERM; - // DWORD 1 - ptd->hw_alt_next = EHCI_PTR_TERM; - // DWORD 2 - ptdc->status = 0x80; - ptdc->pid = pipe_content->trans_dir ? QTD_PID_IN : QTD_PID_OUT; - ptdc->err_count = 3; - ptdc->cur_page = 0; - ptdc->ioc = 1; - ptdc->bytes_to_transfer = purb->data_length; - toggle = (UCHAR) ehci_fill_td_buf_ptr(purb, 0, &pelnk->elem_link, 1, toggle); - - elem_pool_lock(qh_pool, TRUE); - pelnk = elem_pool_alloc_elem(qh_pool); - elem_pool_unlock(qh_pool, TRUE); - if (pelnk == NULL) - { - elem_safe_free(&ptd->elem_head_link->elem_link, TRUE); - InitializeListHead(&purb->trasac_list); - ehci_claim_bandwidth(ehci, purb, FALSE); - return STATUS_NO_MORE_ENTRIES; - } - pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - pqhc = (PEHCI_QH_CONTENT) pqh; - - pqh->hw_next = EHCI_PTR_TERM; - pqhc->dev_addr = pdev->dev_addr; - pqhc->inactive = 0; - pqhc->endp_addr = endp_num(purb->pendp); - - if (pipe_content->speed_high) - pqhc->endp_spd = USB_SPEED_HIGH; - else if (pipe_content->speed_low) - pqhc->endp_spd = USB_SPEED_LOW; - else - pqhc->endp_spd = USB_SPEED_FULL; - - pqhc->data_toggle = 0; - pqhc->is_async_head = 0; - pqhc->max_packet_size = endp_max_packet_size(purb->pendp); - pqhc->is_ctrl_endp = 0; - pqhc->reload_counter = 0; - - // DWORD 2 - pqh->hw_info2 = 0; - pqhc->mult = mult_trans; - - if (pipe_content->speed_high) - { - if (pipe_content->interval == 0) // one poll per uframe - pqhc->s_mask = 0xff; - else if (pipe_content->interval == 1) // one poll every 2 uframe - pqhc->s_mask = pipe_content->start_uframe == 0 ? 0x55 : 0xbb; - else if (pipe_content->interval == 2) - { - pqhc->s_mask = 0x11; - pqhc->s_mask <<= pipe_content->start_uframe; - } - else - { - pqhc->s_mask = 1 << (pipe_content->start_uframe); - } - pqhc->c_mask = 0; - } - else // full/low speed - { - pqhc->s_mask = 1 << pipe_content->start_uframe; - if (pipe_content->start_uframe < 4) - { - pqhc->c_mask = 0x07 << (pipe_content->start_uframe + 2); - } - else if (pipe_content->start_uframe == 4) - { - pqhc->c_mask = 0xc1; - } - else if (pipe_content->start_uframe >= 5) - { - // we need fstn - pqhc->c_mask = 0x03; - if (pipe_content->start_uframe == 5) - { - pqhc->c_mask |= 0x80; - } - } - if (pipe_content->start_uframe >= 4) - { - // chain an fstn - elem_pool_lock(fstn_pool, TRUE); - pelnk = elem_pool_alloc_elem(fstn_pool); - elem_pool_unlock(fstn_pool, TRUE); - if (pelnk == NULL) - { - elem_safe_free(&pqh->elem_head_link->elem_link, TRUE); - elem_safe_free(&ptd->elem_head_link->elem_link, TRUE); - InitializeListHead(&purb->trasac_list); - ehci_claim_bandwidth(ehci, purb, FALSE); - return STATUS_NO_MORE_ENTRIES; - } - pfstn = (PEHCI_FSTN) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - pfstn->hw_prev = ptd->phys_addr; - pfstn->elem_head_link->purb = purb; - InsertTailList(&ptd->elem_head_link->elem_link, &pfstn->elem_head_link->elem_link); - } - pqhc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr; - pqhc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx; - } - - // DWORD 3 - purb->td_count = 1; - - InitializeListHead(&purb->trasac_list); - ehci_insert_tds_qh(ehci, pqh, ptd); - ehci_insert_qh_urb(purb, pqh); - - purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle << 31); - usb_endp_busy_count_inc(purb->pendp); - - ehci_insert_urb_to_schedule(ehci, purb, ret); - - if (ret == FALSE) - { - RemoveEntryList(&purb->trasac_list); - RemoveEntryList(&pqh->elem_head_link->elem_link); - - elem_safe_free(&pqh->elem_head_link->elem_link, TRUE); - // an fstn may follow the td - elem_safe_free(&ptd->elem_head_link->elem_link, FALSE); - - InitializeListHead(&purb->trasac_list); - ehci_claim_bandwidth(ehci, purb, FALSE); - - purb->pendp->flags = (purb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | ((toggle ^ 1) << 31); - // usb_endp_busy_count_dec( purb->pendp ); - - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - - -static NTSTATUS -ehci_internal_submit_iso(PEHCI_DEV ehci, PURB purb) -{ - LONG i, j, td_count, temp; - PEHCI_ITD pitd; - PEHCI_SITD psitd; - PEHCI_SITD_CONTENT psitdc; - PEHCI_ITD_CONTENT pitdc; - LIST_ENTRY td_list, *pthis, *pnext, *pprev; - BOOLEAN ret; - PURB_HS_PIPE_CONTENT pipe_content; - PUSB_DEV pdev; - PEHCI_ELEM_LINKS pelnk; - - if (ehci == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - if (purb->iso_frame_count == 0) - return STATUS_INVALID_PARAMETER; - - pdev = dev_from_endp(purb->pendp); - purb->pipe = 0; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - pipe_content->trans_type = USB_ENDPOINT_XFER_ISOC; // bit 0-1 - pipe_content->speed_high = (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) ? 1 : 0; // bit 5 - pipe_content->speed_low = 0; // bit 6 - pipe_content->trans_dir = endp_dir(purb->pendp); // bit 7 - pipe_content->dev_addr = pdev->dev_addr; // bit 8-14 - pipe_content->endp_addr = endp_num(purb->pendp); // bit 15-18 - pipe_content->data_toggle = 0; // bit 19 - - ret = FALSE; - purb->params[0] = j = endp_max_packet_size(purb->pendp); - - if (pipe_content->speed_high == 0) - { - // check to see if the frame data is too long to transfer - if (purb->iso_frame_count >= (LONG) ehci->frame_count) - return STATUS_INVALID_PARAMETER; - - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - if (purb->iso_packet_desc[i].length > j) - return STATUS_INVALID_PARAMETER; - } - } - else - { - // excess the frame count limit - if (purb->iso_frame_count >= (LONG) (ehci->frame_count << 3)) - return STATUS_INVALID_PARAMETER; - - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - if (purb->iso_packet_desc[i].length > j * endp_mult_count(purb->pendp)) // 3 is max mult-transaction count - return STATUS_INVALID_PARAMETER; - } - - pipe_content->mult_count = endp_mult_count(purb->pendp); - } - - pipe_content->max_packet_size = 0; // bit 20-23 log( max_packet_size ), not correct, should not be used - - if (pipe_content->speed_high == 0) - { - for(i = 1; i < 16; i++) - { - if ((((ULONG) purb->pendp->pusb_endp_desc->bInterval) >> i) == 0) - break; - } - i--; - } - else - { - i = purb->pendp->pusb_endp_desc->bInterval - 1; - } - - pipe_content->interval = i; // bit 24-27 the same definition as in USB2.0 spec, for high or full/low speed - - if (ehci_claim_bandwidth(ehci, purb, TRUE) == FALSE) - return STATUS_UNSUCCESSFUL; - - if (pipe_content->speed_high == 0) - { - td_count = purb->iso_frame_count; - - // test to see if the last td needs one more sitd for pure complete-split - if (pipe_content->trans_dir == 0) - { - j = (purb->iso_packet_desc[purb->iso_frame_count - 1].length + 187) / 188; - if (purb->iso_packet_desc[purb->iso_frame_count - 1].params.start_uframe + 1 + j >= 8) - { - td_count++; - ret = TRUE; - } - } - elem_pool_lock(itd_pool, TRUE); - pelnk = elem_pool_alloc_elems(itd_pool, td_count); - elem_pool_unlock(itd_pool, TRUE); - - } - else - { - i = REAL_INTERVAL; - if (pipe_content->interval >= 3) - { - td_count = purb->iso_frame_count; - j = 0; - } - else - { - j = purb->iso_start_frame & 0x07; - if (j == 0) - { - td_count = (purb->iso_frame_count + 8 / i - 1) * i / 8; - } - else - { - j = 1 + (7 - j) / i; // the leading packets from the 8-trans boundary - td_count = (j >= (LONG) purb->iso_frame_count ? - 1 : 1 + (purb->iso_frame_count - j + 8 / i - 1) * i / 8); - } - } - - elem_pool_lock(sitd_pool, TRUE); - pelnk = elem_pool_alloc_elems(sitd_pool, td_count); - elem_pool_unlock(sitd_pool, TRUE); - } - - if (pelnk == NULL) - { - ehci_claim_bandwidth(ehci, purb, FALSE); - return STATUS_NO_MORE_ENTRIES; - } - - InsertTailList(&pelnk->elem_link, &td_list); - ListFirst(&td_list, pthis); - pprev = pthis; - purb->td_count = td_count; - - //set up offset for high speed and interval == 1 - if (pipe_content->speed_high && pipe_content->interval == 0) - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - if (i == 0) - purb->iso_packet_desc[i].offset = 0; - else - purb->iso_packet_desc[i].offset = purb->iso_packet_desc[i - 1].offset + - purb->iso_packet_desc[i].length; - } - } - - i = 0, temp = 0; - - while (pthis) - { - init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)); - if (pipe_content->speed_high) - { - LONG start_uframe, k; - LONG l, pk_idx, offset, start_uf, td_length; - PULONG pbuf; - ULONG phys_addr[8]; - - pitd = itd_from_list_entry(pthis); - pitdc = (PEHCI_ITD_CONTENT) pitd; - start_uframe = purb->iso_start_frame & 0x07; - - // will be filled later - pitd->hw_next = EHCI_PTR_TERM; - - // DWORD 9; - pitdc->dev_addr = pdev->dev_addr; - pitdc->endp_num = endp_num(purb->pendp); - - pitdc->max_packet_size = endp_max_packet_size(purb->pendp); - pitdc->io_dir = pipe_content->trans_dir; - pitdc->mult = endp_mult_count(purb->pendp); - - pbuf = pitd->hw_bufp; - RtlZeroMemory(phys_addr, sizeof(phys_addr)); - - if (pipe_content->interval < 3) - { - // this indicates one itd schedules more than one uframes - // for multiple transactions described by iso_packet_desc - if (i == 0) - k = td_count == 1 ? purb->iso_frame_count : j; // the first itd - else - k = (LONG) (purb->iso_frame_count - i) <= 8 / REAL_INTERVAL - ? (purb->iso_frame_count - i) : 8 / REAL_INTERVAL; - - // j is the header transactions out of the interval - // aligned transactions per td - if (j > 0 && i == 0) // handle the first itd - start_uf = start_uframe; - else - start_uf = start_uframe % REAL_INTERVAL; - } - else - { - k = 1, start_uf = start_uframe & 0x07; - } - - - // calculate the data to transfer with this td - td_length = 0; - for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL) - { - td_length += purb->iso_packet_desc[pk_idx].length; - phys_addr[l] = - MmGetPhysicalAddress(&purb->data_buffer[purb->iso_packet_desc[pk_idx].offset]).LowPart; - } - - // fill the page pointer, and offset - if (pipe_content->interval != 0) - { - for(l = start_uf, pk_idx = i; pk_idx < i + k; pk_idx++, l += REAL_INTERVAL) - { - pitdc->status_slot[l].offset = phys_addr[l] & (PAGE_SIZE - 1); - pbuf[l >> pipe_content->interval] |= phys_addr[l] & (~(PAGE_SIZE - 1)); - pitdc->status_slot[l].page_sel = l >> pipe_content->interval; - pitdc->status_slot[l].status = 0x08; - pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length; - if (PAGE_SIZE - pitdc->status_slot[l].offset < - (ULONG) purb->iso_packet_desc[pk_idx].length) - { - // fill the next page buf, we can not simply add - // PAGE_SIZE to the phys_addr[ l ]. - pbuf[(l >> pipe_content->interval) + 1] |= - MmGetPhysicalAddress((PBYTE) - (((ULONG) & purb-> - data_buffer[purb->iso_packet_desc[pk_idx]. - offset]) & (~(PAGE_SIZE - 1))) + - PAGE_SIZE).LowPart; - } - } - } - else // interval == 0 - { - LONG m, n = 0, n2 = 0; - // fill the page buffer first - // calculate the page buffer needed - offset = phys_addr[0] & (PAGE_SIZE - 1); - if (offset != 0) - { - offset = PAGE_SIZE - offset; - l = 1 + (td_length - offset + PAGE_SIZE - 1) / PAGE_SIZE; - } - else - { - l = (td_length + PAGE_SIZE - 1) / PAGE_SIZE; - } - - if (l > 7) - TRAP(); - - // fill the hw_bufp array and PG field, pk_idx is index into hw_bufp - for(pk_idx = 0; pk_idx < l; pk_idx++) - { - if (pk_idx == 0) - { - offset = phys_addr[start_uf] & (~(PAGE_SIZE - 1)); - pbuf[pk_idx] |= offset; - n = pk_idx; - pitdc->status_slot[0].page_sel = n; - n2 = start_uf; - } - else - { - // scan to find if the buf pointer already filled in the td - // since interval = 1, we do not need k * REAL_INTERVAL - // k is transaction count for current td, - // n is hw_bufp( pbuf ) index - // n2 is the last phys_addr index we stopped - for(m = n2; m < start_uf + k; m++) - { - // we can not determine the phys_addr[ x ] is piror - // to offset if it is less than offset. - // because phys_addr is discrete. - // if( ( phys_addr[ m ] & ( ~( PAGE_SIZE - 1 ) ) ) < offset ) - // continue; - - if ((phys_addr[m] & (~(PAGE_SIZE - 1))) == (ULONG) offset) - { - pitdc->status_slot[m].page_sel = n; - continue; - } - break; - } - - if (m == start_uf + k) - TRAP(); - - offset = phys_addr[m] & (~(PAGE_SIZE - 1)); - pbuf[pk_idx] |= offset; - n = pk_idx; - n2 = m; - pitdc->status_slot[m].page_sel = n; - } - } - // fill offset and others - for(l = start_uf, pk_idx = i; l < start_uf + k; l++, pk_idx++) - { - pitdc->status_slot[l].offset = (phys_addr[l] & (PAGE_SIZE - 1)); - pitdc->status_slot[l].status = 0x08; - pitdc->status_slot[l].trans_length = purb->iso_packet_desc[pk_idx].length; - } - // exhausted - } - i += k; - } - else // full/low speed - { - psitd = sitd_from_list_entry(pthis); - psitdc = (PEHCI_SITD_CONTENT) psitd; - psitd->hw_next = EHCI_PTR_TERM; - - // DWORD 1; - psitdc->dev_addr = pdev->dev_addr; - psitdc->endp_num = endp_num(purb->pendp); - psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr; - psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx; - psitdc->io_dir = endp_dir(purb->pendp); - - psitdc->status &= 0x80; // in DWORD 3 - - // DWORD 2; - j = (purb->iso_packet_desc[i].length + 187) / 188; - - if (psitdc->io_dir == 0) - { - for(; j > 0; j--) - { - psitdc->s_mask |= (1 << (j - 1)); - } - psitdc->s_mask <<= purb->iso_packet_desc[i].params.start_uframe & 0x07; - psitdc->c_mask = 0; - } - else - { - LONG k; - - psitdc->s_mask = 1 << purb->iso_packet_desc[i].params.start_uframe & 0x07; - // iso split case 2b: ehci spec 1.0 - if (j == 6) - j = 5; - - j = j - 1 + 2; // actual complete-split count - - psitdc->c_mask |= temp >> 8; // the previous sitd's complete split - if (temp >> 8) // link back for sitd split completion - { - psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr; - psitdc->status &= 0x82; - } - else - { - psitd->hw_backpointer = EHCI_PTR_TERM; - } - - for(k = temp = 0; k < j; k++) - { - temp |= 1 << k; - } - - temp <<= ((purb->iso_packet_desc[i].params.start_uframe & 0x07) + 2); - - // only uframe zero and one have complete split for prev sitd - if ((temp >> 8) > 3) - TRAP(); - - psitdc->c_mask |= temp & 0xff; - } - - // DWORD 3: - psitdc->c_prog_mask = 0; - psitdc->bytes_to_transfer = purb->iso_packet_desc[i].length; - psitdc->page_sel = 0; - psitdc->ioc = 0; - - // DWORD 4; - j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[i].offset); - psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart; - - // DWORD 5; - if (PAGE_SIZE - (j & (PAGE_SIZE - 1)) < (ULONG) purb->iso_packet_desc[i].length) - { - // need to fill another slot - psitdc->page1 = - MmGetPhysicalAddress((PVOID) ((j & ~(PAGE_SIZE - 1)) + PAGE_SIZE)).LowPart >> 12; - } - - if (purb->iso_packet_desc[i].length > 188) - psitdc->trans_pos = 0x00; - else if (purb->iso_packet_desc[i].length <= 188) - psitdc->trans_pos = 0x01; - - if (psitdc->io_dir == 0) - psitdc->trans_count = (purb->iso_packet_desc[i].length + 187) / 188; - - } - ListNext(&td_list, pthis, pnext); - pprev = pthis; - pthis = pnext; - - } - - if (pipe_content->speed_high == 0) - { - // has an extra sitd to fill at the tail - if (ret) - { - ListFirstPrev(&td_list, pthis); - init_elem_phys_part(struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)); - - psitd = sitd_from_list_entry(pthis); - psitdc = (PEHCI_SITD_CONTENT) psitd; - psitd->hw_next = EHCI_PTR_TERM; - - // DWORD 1; - psitdc->dev_addr = pdev->dev_addr; - psitdc->endp_num = endp_num(purb->pendp); - psitdc->hub_addr = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr; - psitdc->port_idx = ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx; - psitdc->io_dir = endp_dir(purb->pendp); - - psitdc->status &= 0x80; // in DWORD 3 - - // DWORD 2; - psitdc->s_mask = 0x04; // uframe 2, random selection - - psitdc->c_mask = 0x70; // complete split at uframe 4, 5, 6 - ListFirstPrev(pthis, pprev); - psitd->hw_backpointer = sitd_from_list_entry(pprev)->phys_addr; - psitdc->status &= 0x82; - - // DWORD 3: - psitdc->c_prog_mask = 0; - psitdc->bytes_to_transfer = 1; // purb->iso_packet_desc[ purb->iso_frame_count - 1 ].length; - psitdc->page_sel = 0; - - j = (ULONG) ((PBYTE) purb->data_buffer + purb->iso_packet_desc[purb->iso_frame_count - 1].offset); - // the last byte is overridden. - j += purb->iso_packet_desc[purb->iso_frame_count - 1].length - 1; - psitd->hw_tx_results2 = MmGetPhysicalAddress((PVOID) j).LowPart; - } - - // set the interrupt - ListFirstPrev(&td_list, pthis); - psitdc = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis); - psitdc->ioc = 1; - } - else - { - // set the ioc - ListFirstPrev(&td_list, pthis); - pitdc = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis); - for(i = 7; i >= 0; i--) - { - if (pitdc->status_slot[i].status == 0x08) - { - pitdc->status_slot[i].ioc = 1; - break; - } - } - if (i < 0) - TRAP(); - } - - ListFirst(&td_list, pthis); - // ListFirst( &purb->trasac_list, pthis ) - RemoveEntryList(&td_list); - InsertTailList(pthis, &purb->trasac_list); - - while (pthis) - { - // fill the purb ptr - struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)->purb = purb; - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - - //indirectly guarded by pending_endp_list_lock - usb_endp_busy_count_inc(purb->pendp); - ehci_insert_urb_to_schedule(ehci, purb, ret); - - if (ret == FALSE) - { - // usb_endp_busy_count_dec( purb->pendp ); - - ListFirst(&purb->trasac_list, pthis); - RemoveEntryList(&purb->trasac_list); - - elem_safe_free(pthis, FALSE); - ehci_claim_bandwidth(ehci, purb, FALSE); - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} - -BOOLEAN NTAPI -//this function used as the KeSynchronizeExecution param to delegate control to ehci_insert_urb_schedule -ehci_sync_insert_urb_schedule(PVOID context) -{ - PSYNC_PARAM sync_param; - PEHCI_DEV ehci; - PURB purb; - - sync_param = (PSYNC_PARAM) context; - if (sync_param == NULL) - return FALSE; - - ehci = sync_param->ehci; - purb = (PURB) sync_param->context; - - if (ehci == NULL || purb == NULL) - return (UCHAR) (sync_param->ret = FALSE); - - return (UCHAR) (sync_param->ret = ehci_insert_urb_schedule(ehci, purb)); -} - -static BOOLEAN NTAPI -ehci_sync_cancel_urb(PVOID context) -{ - //cancel a single purb - PEHCI_DEV ehci; - PSYNC_PARAM sync_param; - PURB purb2, dest_urb; - PLIST_ENTRY pthis, pnext; - BOOLEAN found = FALSE; - - if (context == NULL) - return FALSE; - - sync_param = (PSYNC_PARAM) context; - ehci = sync_param->ehci; - dest_urb = (PURB) sync_param->context; - - if (ehci == NULL || dest_urb == NULL) - return (UCHAR) (sync_param->ret = FALSE); - - ListFirst(&ehci->urb_list, pthis); - while (pthis) - { - purb2 = (PURB) pthis; - if (purb2 == dest_urb) - { - found = TRUE; - purb2->flags |= URB_FLAG_FORCE_CANCEL; - break; - } - ListNext(&ehci->urb_list, pthis, pnext); - pthis = pnext; - } - - if (found) - { - press_doorbell(ehci); - } - return (UCHAR) (sync_param->ret = found); -} - -NTSTATUS -ehci_cancel_urb(PEHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -//note any fields of the purb can not be referenced unless it is found in some queue -{ - PLIST_ENTRY pthis, pnext; - BOOLEAN found; - PURB purb2; - - SYNC_PARAM sync_param; - - USE_BASIC_NON_PENDING_IRQL; - - if (ehci == NULL || purb == NULL || pdev == NULL || pendp == NULL) - return STATUS_INVALID_PARAMETER; - - lock_dev(pdev, FALSE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - //delegate to remove device for this job - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - if (dev_from_endp(pendp) != pdev) - { - unlock_dev(pdev, FALSE); - return STATUS_INVALID_PARAMETER; - } - - if (endp_state(pendp) == USB_ENDP_FLAG_STALL) - { - //it will be canceled in ehci_process_pending_endp - unlock_dev(pdev, FALSE); - return USB_STATUS_ENDPOINT_HALTED; - } - - found = FALSE; - ListFirst(&pendp->urb_list, pthis); - while (pthis) - { - purb2 = (PURB) pthis; - if (purb2 == purb) - { - found = TRUE; - RemoveEntryList(pthis); - InitializeListHead(pthis); - break; - } - ListNext(&pendp->urb_list, pthis, pnext); - pthis = pnext; - } - unlock_dev(pdev, FALSE); - - if (found) - { - purb->status = STATUS_CANCELLED; - - ehci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, FALSE); - pdev->ref_count--; - unlock_dev(pdev, FALSE); - return STATUS_SUCCESS; - } - - // search the purb in the purb-list and try to cancel - sync_param.ehci = ehci; - sync_param.context = purb; - - KeSynchronizeExecution(ehci->pdev_ext->ehci_int, ehci_sync_cancel_urb, &sync_param); - - found = sync_param.ret; - - if (found) - return USB_STATUS_CANCELING; - - return STATUS_INVALID_PARAMETER; -} - -VOID -ehci_generic_urb_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - BOOLEAN is_ctrl = FALSE; - USE_NON_PENDING_IRQL; - - old_irql = KeGetCurrentIrql(); - if (old_irql > DISPATCH_LEVEL) - TRAP(); - - if (old_irql < DISPATCH_LEVEL) - KeRaiseIrql(DISPATCH_LEVEL, &old_irql); - - pdev = purb->pdev; - if (purb == NULL) - goto LBL_LOWER_IRQL; - - if (pdev == NULL) - goto LBL_LOWER_IRQL; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - // no need to do following statistics - unlock_dev(pdev, TRUE); - goto LBL_CLIENT_PROCESS; - } - if (usb_error(purb->status)) - { - pdev->error_count++; - } - - if (purb->pendp == &pdev->default_endp) - { - if (usb_halted(purb->status)) - { - pdev->time_out_count++; - if (pdev->time_out_count > 3) - { - dev_set_state(pdev, USB_DEV_STATE_ZOMB); - ehci_dbg_print(DBGLVL_MAXIMUM, - ("ehci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n", - pdev)); - } - } - else - pdev->time_out_count = 0; - - } - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_CONTROL) - is_ctrl = TRUE; - - unlock_dev(pdev, TRUE); - - LBL_CLIENT_PROCESS: - if (!is_ctrl) - { - if (purb->completion) - purb->completion(purb, context); - } - else - { - if (purb->ctrl_req_context.ctrl_stack_count == 0) - { - if (purb->completion) - purb->completion(purb, context); - } - else - { - // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ]; - // if( pstack->urb_completion ) - // pstack->urb_completion( purb, pstack->context ); - usb_call_ctrl_completion(purb); - } - } - - LBL_LOWER_IRQL: - if (old_irql < DISPATCH_LEVEL) - KeLowerIrql(old_irql); - - return; -} - -NTSTATUS -ehci_rh_submit_urb(PUSB_DEV pdev, PURB purb) -{ - PUSB_DEV_MANAGER dev_mgr; - PTIMER_SVC ptimer; - PUSB_CTRL_SETUP_PACKET psetup; - PEHCI_DEV ehci; - NTSTATUS status; - PHUB2_EXTENSION hub_ext; - PUSB_PORT_STATUS ps, psret; - LONG i; - UCHAR port_count; - - USE_NON_PENDING_IRQL; - if (pdev == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - dev_mgr = dev_mgr_from_dev(pdev); - - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - ehci = ehci_from_hcd(pdev->hcd); - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext); - port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count; - - switch (endp_type(purb->pendp)) - { - case USB_ENDPOINT_XFER_CONTROL: - { - if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS) - { - //get-port-status - if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength < 4) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1; - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - ps = &hub_ext->rh_port_status[psetup->wIndex]; - - psret = (PUSB_PORT_STATUS) purb->data_buffer; - ps->wPortStatus = 0; - - if (status & PORT_CCS) - { - ps->wPortStatus |= USB_PORT_STAT_CONNECTION; - } - if (status & PORT_PE) - { - ps->wPortStatus |= USB_PORT_STAT_ENABLE; - ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec - } - if (status & PORT_PR) - { - ps->wPortStatus |= USB_PORT_STAT_RESET; - } - if (status & PORT_SUSP) - { - ps->wPortStatus |= USB_PORT_STAT_SUSPEND; - } - if (PORT_USB11(status)) - { - ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED; - } - - //always power on - ps->wPortStatus |= USB_PORT_STAT_POWER; - - //now set change field - if ((status & PORT_CSC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED)) - { - ps->wPortChange |= USB_PORT_STAT_C_CONNECTION; - } - if ((status & PORT_PEC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED)) - { - ps->wPortChange |= USB_PORT_STAT_C_ENABLE; - } - - //don't touch other fields, might be filled by - //other function - - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n", - ps->wPortStatus, ps->wPortChange, ps)); - - psret->wPortChange = ps->wPortChange; - psret->wPortStatus = ps->wPortStatus; - - purb->status = STATUS_SUCCESS; - - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE) - { - //clear-port-feature - if (psetup->wIndex == 0 || psetup->wIndex > port_count) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1; - ps = &hub_ext->rh_port_status[psetup->wIndex]; - - purb->status = STATUS_SUCCESS; - switch (psetup->wValue) - { - case USB_PORT_FEAT_C_CONNECTION: - { - SET_RH2_PORTSTAT(i, USBPORTSC_CSC); - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex)); - ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION; - break; - } - case USB_PORT_FEAT_C_ENABLE: - { - SET_RH2_PORTSTAT(i, USBPORTSC_PEC); - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex)); - ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE; - break; - } - case USB_PORT_FEAT_C_RESET: - { - ps->wPortChange &= ~USB_PORT_STAT_C_RESET; - //the reset signal is down in rh_timer_svc_reset_port_completion - // enable or not is set by host controller - // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) ); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n", - psetup->wIndex)); - break; - } - case USB_PORT_FEAT_ENABLE: - { - ps->wPortStatus &= ~USB_PORT_STAT_ENABLE; - CLR_RH2_PORTSTAT(i, USBPORTSC_PE); - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex)); - break; - } - default: - purb->status = STATUS_UNSUCCESSFUL; - } - break; - } - else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE) - { - // get bus state - if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength == 0) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1; - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - purb->data_buffer[0] = (status & USBPORTSC_LS); - - // reverse the order - purb->data_buffer[0] ^= 0x3; - purb->status = STATUS_SUCCESS; - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_SET_FEATURE) - { - //reset port - if (psetup->wValue != USB_PORT_FEAT_RESET) - { - purb->status = STATUS_INVALID_PARAMETER; - ehci_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue)); - break; - } - - i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1; - - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - - ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_reset_port_completion; - - //start the timer - pdev->ref_count += 2; //one for timer and one for purb - - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status)); - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - purb->status = STATUS_PENDING; - } - else - { - purb->status = STATUS_INVALID_PARAMETER; - } - break; - } - case USB_ENDPOINT_XFER_INT: - { - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - ptimer->threshold = RH_INTERVAL; - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_int_completion; - - //start the timer - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - - usb_dbg_print(DBGLVL_MAXIMUM, - ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count)); - pdev->ref_count += 2; //one for timer and one for purb - - purb->status = STATUS_PENDING; - break; - } - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_ISOC: - default: - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - } - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return purb->status; -} - -//must have rh dev_lock acquired -BOOLEAN -ehci_rh_reset_port(PHCD hcd, UCHAR port_idx) -{ - ULONG i; - PEHCI_DEV ehci; - ULONG status; - UCHAR port_count; - - if (hcd == NULL) - return FALSE; - - ehci = ehci_from_hcd(hcd); - port_count = (UCHAR) ((PEHCI_HCS_CONTENT) & ehci->ehci_caps.hcs_params)->port_count; - - if (port_idx < 1 || port_idx > port_count) - return FALSE; - - i = (ULONG) (EHCI_PORTSC + 4 * (port_idx - 1)); - - // assert the reset signal,(implicitly disable the port) - SET_RH2_PORTSTAT(i, PORT_PR); - - usb_wait_ms_dpc(50); - // clear the reset signal, delay port enable till clearing port feature - CLR_RH2_PORTSTAT(i, PORT_PR); - - // wait the port stable - usb_wait_ms_dpc(2); - - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - if (!(status & PORT_PE)) - { - // release the ownership from ehci to companion hc - status |= PORT_OWNER; - EHCI_WRITE_PORT_ULONG((PULONG) (ehci->port_base + i), status); - // the host controller will set PORTSC automatically - return FALSE; - } - usb_wait_us_dpc(10); - // SET_RH_PORTSTAT( i, PORT_PE ); - - //recovery time 10ms - usb_wait_ms_dpc(10); - - // clear PORT_PEC and PORT_PCC - SET_RH2_PORTSTAT(i, 0x0a); - - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, ("ehci_rh_reset_port(): status after written=0x%x\n", status)); - return TRUE; -} - -NTSTATUS -ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp) -{ - PEHCI_DEVICE_EXTENSION pdev_ext; - PUSB_DEV_MANAGER dev_mgr; - PEHCI_DEV ehci; - - pdev_ext = DeviceObject->DeviceExtension; - ehci = pdev_ext->ehci; - - dev_mgr = ehci->hcd_interf.hcd_get_dev_mgr(&ehci->hcd_interf); - return dev_mgr_dispatch(dev_mgr, irp); -} - -//the following are for hcd interface methods -VOID -ehci_set_dev_mgr(PHCD hcd, PUSB_DEV_MANAGER dev_mgr) -{ - hcd->dev_mgr = dev_mgr; -} - -PUSB_DEV_MANAGER -ehci_get_dev_mgr(PHCD hcd) -{ - return hcd->dev_mgr; -} - -ULONG -ehci_get_type(PHCD hcd) -{ - return HCD_TYPE_EHCI; // ( hcd->flags & HCD_TYPE_MASK ); -} - -VOID -ehci_set_id(PHCD hcd, UCHAR id) -{ - hcd->flags &= ~HCD_ID_MASK; - hcd->flags |= (HCD_ID_MASK & id); -} - -UCHAR -ehci_get_id(PHCD hcd) -{ - return (UCHAR) (hcd->flags & HCD_ID_MASK); -} - - -UCHAR -ehci_alloc_addr(PHCD hcd) -{ - LONG i; - if (hcd == NULL) - return 0; - - for(i = 1; i < MAX_DEVS; i++) - { - if (hcd->dev_addr_map[i >> 3] & (1 << (i & 7))) - { - continue; - } - else - { - break; - } - } - - if (i >= MAX_DEVS) - return 0xff; - - hcd->dev_addr_map[i >> 3] |= (1 << (i & 7)); - hcd->conn_count++; - return (BYTE) i; -} - -VOID -ehci_free_addr(PHCD hcd, UCHAR addr) -{ - if (addr & 0x80) - return; - - if (hcd == NULL) - return; - - hcd->dev_addr_map[addr >> 3] &= ~(1 << (addr & 7)); - return; - -} - -NTSTATUS -ehci_submit_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - return ehci_submit_urb(ehci_from_hcd(hcd), pdev, pendp, purb); -} - -PUSB_DEV -ehci_get_root_hub(PHCD hcd) -{ - return ehci_from_hcd(hcd)->root_hub; -} - -VOID -ehci_set_root_hub(PHCD hcd, PUSB_DEV root_hub) -{ - if (hcd == NULL || root_hub == NULL) - return; - ehci_from_hcd(hcd)->root_hub = root_hub; - return; -} - -BOOLEAN -ehci_remove_device2(PHCD hcd, PUSB_DEV pdev) -{ - if (hcd == NULL || pdev == NULL) - return FALSE; - - return ehci_remove_device(ehci_from_hcd(hcd), pdev); -} - -BOOLEAN -ehci_hcd_release(PHCD hcd) -{ - PEHCI_DEV ehci; - PEHCI_DEVICE_EXTENSION pdev_ext; - - if (hcd == NULL) - return FALSE; - - ehci = ehci_from_hcd(hcd); - pdev_ext = ehci->pdev_ext; - return ehci_release(pdev_ext->pdev_obj, hcd->dev_mgr); -} - -NTSTATUS -ehci_cancel_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - PEHCI_DEV ehci; - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - - ehci = ehci_from_hcd(hcd); - return ehci_cancel_urb(ehci, pdev, pendp, purb); -} - -BOOLEAN -ehci_rh_get_dev_change(PHCD hcd, PBYTE buf) //must have the rh dev_lock acquired -{ - PEHCI_DEV ehci; - LONG port_count, i; - ULONG status; - - if (hcd == NULL) - return FALSE; - - ehci = ehci_from_hcd(hcd); - port_count = HCS_N_PORTS(ehci->ehci_caps.hcs_params); - for(i = 0; i < port_count; i++) - { - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_PORTSC + (i << 2))); - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_rh_get_dev_change(): erh port%d status=0x%x\n", i, status)); - - if (status & (PORT_PEC | PORT_CSC | PORT_OCC)) - { - buf[(i + 1) >> 3] |= (1 << ((i + 1) & 7)); - } - } - return TRUE; -} - -NTSTATUS -ehci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param) -{ - PEHCI_DEV ehci; - - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - ehci = ehci_from_hcd(hcd); - switch (disp_code) - { - case HCD_DISP_READ_PORT_COUNT: - { - if (param == NULL) - return STATUS_INVALID_PARAMETER; - *((PUCHAR) param) = (UCHAR) HCS_N_PORTS(ehci->ehci_caps.hcs_params); - return STATUS_SUCCESS; - } - case HCD_DISP_READ_RH_DEV_CHANGE: - { - if (ehci_rh_get_dev_change(hcd, param) == FALSE) - return STATUS_INVALID_PARAMETER; - return STATUS_SUCCESS; - } - } - return STATUS_NOT_IMPLEMENTED; -} - -//------------------------------------------------------------------------------ -// EHCI routines follows -// -VOID ehci_init_int8_qh(PEHCI_QH_CONTENT qh); - -BOOLEAN NTAPI -ehci_cal_cpu_freq(PVOID context) -{ - usb_cal_cpu_freq(); - return TRUE; -} - -PDEVICE_OBJECT -ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr) -{ - LONG bus, i, j, ret = 0; - PCI_SLOT_NUMBER slot_num; - PPCI_COMMON_CONFIG pci_config; - PDEVICE_OBJECT pdev; - BYTE buffer[sizeof(PCI_COMMON_CONFIG)]; - PEHCI_DEVICE_EXTENSION pdev_ext; - LONG count = 0; - - slot_num.u.AsULONG = 0; - pci_config = (PPCI_COMMON_CONFIG) buffer; - pdev = NULL; - - //scan the PCI buses to find ehci controller - for (bus = 0; bus <= PCI_MAX_BRIDGE_NUMBER; bus++) //Yes, it should be <= - { - for(i = 0; i <= PCI_MAX_DEVICES; i++) - { - slot_num.u.bits.DeviceNumber = i; - for(j = 0; j <= PCI_MAX_FUNCTION; j++) - { - slot_num.u.bits.FunctionNumber = j; - - ret = HalGetBusData(PCIConfiguration, - bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH); - - if (ret == 0) /*no this bus */ - break; - - if (ret == 2) /*no device on the slot */ - break; - - if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03 - && pci_config->ProgIf == 0x20) - { - //well, we find our usb host controller( EHCI ), create device - pdev = ehci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr); - if (pdev) -#ifdef _MULTI_EHCI - count++; -#else - goto LBL_LOOPOUT; -#endif - } - } - - if (ret == 0) - break; - } - } - -#ifndef _MULTI_EHCI -LBL_LOOPOUT: -#endif - DbgPrint("Found %d EHCI controllers\n", count); - - if (pdev) - { - pdev_ext = pdev->DeviceExtension; - if (pdev_ext) - { - // acquire higher irql to eliminate pre-empty - KeSynchronizeExecution(pdev_ext->ehci_int, ehci_cal_cpu_freq, NULL); - } - } - return pdev; -} - -PDEVICE_OBJECT -ehci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr) -{ - - LONG frd_num, prd_num; - PDEVICE_OBJECT pdev; - PEHCI_DEVICE_EXTENSION pdev_ext; - ULONG vector, addr_space; - LONG bus, i; - KIRQL irql; - KAFFINITY affinity; - - DEVICE_DESCRIPTION dev_desc; - CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd; - PCI_SLOT_NUMBER slot_num; - NTSTATUS status; - - - pdev = ehci_create_device(drvr_obj, dev_mgr); - - if (pdev == NULL) - return NULL; - - pdev_ext = pdev->DeviceExtension; - - pdev_ext->pci_addr = bus_addr; - bus = (bus_addr >> 8); - - slot_num.u.AsULONG = 0; - slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3); - slot_num.u.bits.FunctionNumber = (bus_addr & 0x07); - - //now create adapter object - RtlZeroMemory(&dev_desc, sizeof(dev_desc)); - - dev_desc.Version = DEVICE_DESCRIPTION_VERSION; - dev_desc.Master = TRUE; - dev_desc.ScatterGather = TRUE; - dev_desc.Dma32BitAddresses = TRUE; - dev_desc.BusNumber = bus; - dev_desc.InterfaceType = PCIBus; - dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER; - - pdev_ext->map_regs = 2; // we do not use it seriously - - pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs); - - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_alloc(): padapter=0x%x\n", pdev_ext->padapter)); - if (pdev_ext->padapter == NULL) - { - //fatal error - ehci_delete_device(pdev, dev_mgr); - return NULL; - } - - DbgPrint("ehci_alloc(): reg_path=0x%x, \n \ - ehci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \ - ehci_alloc(): slot_num=0x%x, &res_list=0x%x \n \ - ehci_alloc(): adapter=0x%x \n", (DWORD) reg_path, (DWORD) PCIBus, (DWORD) bus, (DWORD) bus_addr, (DWORD) slot_num.u.AsULONG, (DWORD) & pdev_ext->res_list, pdev_ext->padapter); - - //let's allocate resources for this device - DbgPrint("ehci_alloc(): about to assign slot res\n"); - if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet - drvr_obj, NULL, //no support of another ehci controller - PCIBus, - bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS) - { - DbgPrint("ehci_alloc(): error assign slot res, 0x%x\n", status); - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev, dev_mgr); - return NULL; - } - - //parse the resource list - for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++) - { - for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count; - prd_num++) - { - pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num]; - if (pprd->Type == CmResourceTypePort) - { - RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port)); - - } - else if (pprd->Type == CmResourceTypeInterrupt) - { - RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt)); - } - else if (pprd->Type == CmResourceTypeMemory) - { - RtlCopyMemory(&pdev_ext->res_memory, &pprd->u.Memory, sizeof(pprd->u.Memory)); - } - } - } - - //for port, translate them to system address - addr_space = 0; - if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space - &pdev_ext->ehci->ehci_reg_base) != (BOOLEAN) TRUE) - { - DbgPrint("ehci_alloc(): error, can not translate bus address\n"); - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev, dev_mgr); - return NULL; - } - - DbgPrint("ehci_alloc(): address space=0x%x\n, reg_base=0x%x\n", - addr_space, pdev_ext->ehci->ehci_reg_base.u.LowPart); - - if (addr_space == 0) - { - //port has been mapped to memory space - pdev_ext->ehci->port_mapped = TRUE; - pdev_ext->ehci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->ehci->ehci_reg_base, - pdev_ext->res_port.Length, FALSE); - - //fatal error can not map the registers - if (pdev_ext->ehci->port_base == NULL) - { - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev, dev_mgr); - return NULL; - } - } - else - { - //io space - pdev_ext->ehci->port_mapped = FALSE; - pdev_ext->ehci->port_base = (PBYTE) pdev_ext->ehci->ehci_reg_base.LowPart; - } - - //before we connect the interrupt, we have to init ehci - pdev_ext->ehci->pdev_ext = pdev_ext; - - //init ehci_caps - // i = ( ( PEHCI_HCS_CONTENT )( &pdev_ext->ehci->ehci_caps.hcs_params ) )->length; - - ehci_get_capabilities(pdev_ext->ehci, pdev_ext->ehci->port_base); - i = pdev_ext->ehci->ehci_caps.length; - pdev_ext->ehci->port_base += i; - - if (ehci_init_schedule(pdev_ext->ehci, pdev_ext->padapter) == FALSE) - { - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev, dev_mgr); - return NULL; - } - - InitializeListHead(&pdev_ext->ehci->urb_list); - KeInitializeSpinLock(&pdev_ext->ehci->pending_endp_list_lock); - InitializeListHead(&pdev_ext->ehci->pending_endp_list); - - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_alloc(): pending_endp_list=0x%x\n", - &pdev_ext->ehci->pending_endp_list)); - - init_pending_endp_pool(&pdev_ext->ehci->pending_endp_pool); - - KeInitializeTimer(&pdev_ext->ehci->reset_timer); - - vector = HalGetInterruptVector(PCIBus, - bus, - pdev_ext->res_interrupt.level, - pdev_ext->res_interrupt.vector, &irql, &affinity); - - KeInitializeDpc(&pdev_ext->ehci_dpc, ehci_dpc_callback, (PVOID) pdev_ext->ehci); - - //connect the interrupt - DbgPrint("ehci_alloc(): the int=0x%x\n", vector); - if (IoConnectInterrupt(&pdev_ext->ehci_int, ehci_isr, pdev_ext->ehci, NULL, //&pdev_ext->ehci->frame_list_lock, - vector, irql, irql, LevelSensitive, TRUE, //share the vector - affinity, FALSE) //No float save - != STATUS_SUCCESS) - { - ehci_release(pdev, dev_mgr); - return NULL; - } - - return pdev; -} - -PDEVICE_OBJECT -ehci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr) -{ - NTSTATUS status; - PDEVICE_OBJECT pdev; - PEHCI_DEVICE_EXTENSION pdev_ext; - - UNICODE_STRING dev_name; - UNICODE_STRING symb_name; - - STRING string, another_string; - CHAR str_dev_name[64], str_symb_name[64]; - UCHAR hcd_id; - - if (drvr_obj == NULL) - return NULL; - - //note: hcd count wont increment till the hcd is registered in dev_mgr - sprintf(str_dev_name, "%s%d", EHCI_DEVICE_NAME, dev_mgr->hcd_count); - sprintf(str_symb_name, "%s%d", EHCI_DOS_DEVICE_NAME, dev_mgr->hcd_count); - - RtlInitString(&string, str_dev_name); - RtlAnsiStringToUnicodeString(&dev_name, &string, TRUE); - - pdev = NULL; - status = IoCreateDevice(drvr_obj, - sizeof(EHCI_DEVICE_EXTENSION) + sizeof(EHCI_DEV), - &dev_name, FILE_EHCI_DEV_TYPE, 0, FALSE, &pdev); - - if (status != STATUS_SUCCESS || pdev == NULL) - { - RtlFreeUnicodeString(&dev_name); - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_create_device(): error create device 0x%x\n", status)); - return NULL; - } - - pdev_ext = pdev->DeviceExtension; - RtlZeroMemory(pdev_ext, sizeof(EHCI_DEVICE_EXTENSION) + sizeof(EHCI_DEV)); - - pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD; - pdev_ext->dev_ext_hdr.dispatch = ehci_dispatch_irp; - pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio - pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr; - - pdev_ext->pdev_obj = pdev; - pdev_ext->pdrvr_obj = drvr_obj; - - pdev_ext->ehci = (PEHCI_DEV) & (pdev_ext[1]); - - RtlInitString(&another_string, str_symb_name); - RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE); - //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME ); - - IoCreateSymbolicLink(&symb_name, &dev_name); - - ehci_dbg_print(DBGLVL_MAXIMUM, - ("ehci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev, - pdev_ext, pdev_ext->ehci, dev_mgr)); - - RtlFreeUnicodeString(&dev_name); - RtlFreeUnicodeString(&symb_name); - - //register with dev_mgr though it is not initilized - ehci_init_hcd_interface(pdev_ext->ehci); - hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->ehci->hcd_interf); - - pdev_ext->ehci->hcd_interf.hcd_set_id(&pdev_ext->ehci->hcd_interf, hcd_id); - pdev_ext->ehci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->ehci->hcd_interf, dev_mgr); - - return pdev; - -} - -VOID -ehci_init_hcd_interface(PEHCI_DEV ehci) -{ - ehci->hcd_interf.hcd_set_dev_mgr = ehci_set_dev_mgr; - ehci->hcd_interf.hcd_get_dev_mgr = ehci_get_dev_mgr; - ehci->hcd_interf.hcd_get_type = ehci_get_type; - ehci->hcd_interf.hcd_set_id = ehci_set_id; - ehci->hcd_interf.hcd_get_id = ehci_get_id; - ehci->hcd_interf.hcd_alloc_addr = ehci_alloc_addr; - ehci->hcd_interf.hcd_free_addr = ehci_free_addr; - ehci->hcd_interf.hcd_submit_urb = ehci_submit_urb2; - ehci->hcd_interf.hcd_generic_urb_completion = ehci_generic_urb_completion; - ehci->hcd_interf.hcd_get_root_hub = ehci_get_root_hub; - ehci->hcd_interf.hcd_set_root_hub = ehci_set_root_hub; - ehci->hcd_interf.hcd_remove_device = ehci_remove_device2; - ehci->hcd_interf.hcd_rh_reset_port = ehci_rh_reset_port; - ehci->hcd_interf.hcd_release = ehci_hcd_release; - ehci->hcd_interf.hcd_cancel_urb = ehci_cancel_urb2; - ehci->hcd_interf.hcd_start = ehci_start; - ehci->hcd_interf.hcd_dispatch = ehci_hcd_dispatch; - - ehci->hcd_interf.flags = HCD_TYPE_EHCI; //hcd types | hcd id -} - -BOOLEAN -ehci_init_schedule(PEHCI_DEV ehci, PADAPTER_OBJECT padapter) -{ - PEHCI_DEVICE_EXTENSION pdev_ext; - BOOLEAN ret = TRUE; - LONG i; - PEHCI_QH_CONTENT pqh_content; - PEHCI_QH pqh; - PEHCI_ELEM_LINKS pelnk; - - if (ehci == NULL) - return FALSE; - - pdev_ext = ehci->pdev_ext; - if (pdev_ext == NULL) - return FALSE; - - // padapter = pdev_ext->padapter; - if (ehci->frame_count == 0) - ehci->frame_count = EHCI_DEFAULT_FRAMES; - - // allocate pools - for(i = 0; i < 5; i++) - { - ret = elem_pool_init_pool(&ehci->elem_pools[i], i, padapter); - if (ret == FALSE) - break; - } - - if (ret == FALSE) - { - i--; - for(; i >= 0; i--) - elem_pool_destroy_pool(&ehci->elem_pools[i]); - return FALSE; - } - - // allocate periodic frame list - ehci->frame_list = - HalAllocateCommonBuffer(padapter, - sizeof(ULONG) * ehci->frame_count, &ehci->frame_list_phys_addr, FALSE); - if (ehci->frame_list == NULL) - goto ERROR_OUT; - - RtlZeroMemory(ehci->frame_list, sizeof(ULONG) * ehci->frame_count); - ehci->frame_list_cpu = usb_alloc_mem(NonPagedPool, sizeof(LIST_HEAD) * ehci->frame_count); - - if (ehci->frame_list_cpu == NULL) - goto ERROR_OUT; - - for(i = 0; i < (LONG) ehci->frame_count; i++) - { - InitializeListHead(&ehci->frame_list_cpu[i].td_link); - } - - for(i = 0; i < 8; i++) - { - InitializeListHead(&ehci->periodic_list_cpu[i]); - } - - InitializeListHead(&ehci->async_list_cpu); - - // init frame band budget array - ehci->frame_bw = usb_alloc_mem(NonPagedPool, sizeof(USHORT) * ehci->frame_count * 8); - if (ehci->frame_bw == NULL) - goto ERROR_OUT; - - for(i = 0; i < (LONG) ehci->frame_count * 8; i++) - { - ehci->frame_bw[i] = EHCI_MAX_SYNC_BUS_TIME; - } - ehci->min_bw = EHCI_MAX_SYNC_BUS_TIME; - - // chain the 1ms interrupt qh to the schedule - if ((pelnk = elem_pool_alloc_elem(&ehci->elem_pools[EHCI_QH_POOL_IDX])) == NULL) - goto ERROR_OUT; - - pqh_content = (PEHCI_QH_CONTENT) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - ehci_init_int8_qh(pqh_content); - - // chain qh to the shadow list - InsertTailList(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], &pelnk->sched_link); - - // chain it to the periodic schedule, we use it as a docking point - // for req of 8- uframes request - pqh = (PEHCI_QH) pqh_content; - - for(i = 0; i < (LONG) ehci->frame_count; i++) - { - ehci->frame_list[i] = pqh->phys_addr; - } - - // allocate fstn - /*if( ( pelnk = elem_pool_alloc_elem( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) ) == NULL ) - goto ERROR_OUT; - - pfstn = ( PEHCI_FSTN )( ( ULONG )pelnk->phys_part & PHYS_PART_ADDR_MASK ); - pfstn->hw_next = EHCI_PTR_TERM; - pfstn->hw_prev = EHCI_PTR_TERM | ( INIT_LIST_FLAG_QH << 1 ); - InsertTailList( &ehci->periodic_list_cpu[ EHCI_SCHED_FSTN_INDEX ], &pelnk->sched_link ); - pqh->hw_next = pfstn->phys_addr; */ - - // allocate for async list head - if ((pelnk = elem_pool_alloc_elem(&ehci->elem_pools[EHCI_QH_POOL_IDX])) == NULL) - goto ERROR_OUT; - - // init the async list head - pqh = (PEHCI_QH) ((ULONG) pelnk->phys_part & PHYS_PART_ADDR_MASK); - pqh_content = (PEHCI_QH_CONTENT) pqh; - ehci_init_int8_qh(pqh_content); - pqh->hw_next = pqh->phys_addr; - pqh_content->s_mask = 0; - pqh_content->is_async_head = 1; - pqh_content->endp_addr = 0; - ehci->skel_async_qh = pqh; - InsertTailList(&ehci->async_list_cpu, &pqh->elem_head_link->sched_link); - return TRUE; - - ERROR_OUT: - ehci_destroy_schedule(ehci); - return FALSE; -} - -BOOLEAN -ehci_destroy_schedule(PEHCI_DEV ehci) -{ - LONG i; - if (ehci == NULL) - return FALSE; - - if (ehci->frame_bw) - usb_free_mem(ehci->frame_bw); - ehci->frame_bw = NULL; - - if (ehci->frame_list_cpu) - usb_free_mem(ehci->frame_list_cpu); - ehci->frame_list_cpu = NULL; - - if (ehci->frame_list) - HalFreeCommonBuffer(ehci->pdev_ext->padapter, - sizeof(ULONG) * ehci->frame_count, - ehci->frame_list_phys_addr, ehci->frame_list, FALSE); - - ehci->frame_list = NULL; - ehci->frame_list_phys_addr.LowPart = 0; - ehci->frame_list_phys_addr.HighPart = 0; - - for(i = 0; i < 5; i++) - elem_pool_destroy_pool(&ehci->elem_pools[i]); - - return TRUE; -} - -VOID -ehci_init_int8_qh(PEHCI_QH_CONTENT qh) -{ - if (qh == NULL) - return; - // DWORD 0 - qh->terminal = EHCI_PTR_TERM; - qh->ptr_type = 0; - qh->reserved = 0; - qh->next_link = 0; - - // DWORD 1 - qh->dev_addr = 126; // a fake addr - qh->inactive = 0; - qh->endp_addr = 1; // a fake endp - qh->endp_spd = USB_SPEED_HIGH; - qh->data_toggle = 0; - qh->is_async_head = 0; - qh->max_packet_size = 64; - qh->is_ctrl_endp = 0; - qh->reload_counter = 0; - - // DWORD 2 - qh->s_mask = 0x80; // we are interrupt qh - qh->c_mask = 0; - qh->hub_addr = 0; - qh->port_idx = 0; - qh->mult = 1; - - // DWORD 3 - qh->cur_qtd_ptr = 0; // a terminal - - // overlay - // !active and !halted - RtlZeroMemory(&qh->cur_qtd, get_elem_phys_part_size(INIT_LIST_FLAG_QTD)); - qh->cur_qtd.alt_terminal = 1; // don't use this - qh->cur_qtd.terminal = 1; - qh->cur_qtd.status = QTD_STS_HALT; -} - -VOID -ehci_get_capabilities(PEHCI_DEV ehci, PBYTE base) -// fetch capabilities register from ehci -{ - PEHCI_CAPS pcap; - PEHCI_HCS_CONTENT phcs; - LONG i; - - if (ehci == NULL) - return; - - pcap = &ehci->ehci_caps; - pcap->length = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 0)); - pcap->reserved = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 1)); - pcap->hci_version = EHCI_READ_PORT_USHORT((PUSHORT) (base + 2)); - pcap->hcs_params = EHCI_READ_PORT_ULONG((PULONG) (base + 4)); - pcap->hcc_params = EHCI_READ_PORT_ULONG((PULONG) (base + 8)); - - phcs = (PEHCI_HCS_CONTENT) & pcap->hcs_params; - if (phcs->port_rout_rules) - { - for(i = 0; i < 8; i++) - pcap->portroute[i] = EHCI_READ_PORT_UCHAR((PUCHAR) (base + 12 + i)); - } - return; -} - -BOOLEAN -ehci_delete_device(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr) -{ - STRING string; - UNICODE_STRING symb_name; - CHAR str_symb_name[64]; - PEHCI_DEVICE_EXTENSION pdev_ext; - - if (pdev == NULL) - return FALSE; - - pdev_ext = pdev->DeviceExtension; - - sprintf(str_symb_name, - "%s%d", EHCI_DOS_DEVICE_NAME, pdev_ext->ehci->hcd_interf.hcd_get_id(&pdev_ext->ehci->hcd_interf)); - - RtlInitString(&string, str_symb_name); - RtlAnsiStringToUnicodeString(&symb_name, &string, TRUE); - IoDeleteSymbolicLink(&symb_name); - RtlFreeUnicodeString(&symb_name); - - dev_mgr_deregister_hcd(dev_mgr, pdev_ext->ehci->hcd_interf.hcd_get_id(&pdev_ext->ehci->hcd_interf)); - - if (pdev_ext->res_list) - ExFreePool(pdev_ext->res_list); // not allocated by usb_alloc_mem - - IoDeleteDevice(pdev); - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_delete_device(): device deleted\n")); - return TRUE; -} - -VOID -ehci_stop(PEHCI_DEV ehci) -{ - PBYTE base; - PEHCI_USBCMD_CONTENT usbcmd; - LONG tmp; - - base = ehci->port_base; - // turn off all the interrupt - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR), 0); - tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); - usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; - usbcmd->run_stop = 0; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); -} - -BOOLEAN -ehci_release(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr) -{ - PEHCI_DEVICE_EXTENSION pdev_ext; - PEHCI_DEV ehci; - - if (pdev == NULL) - return FALSE; - - pdev_ext = pdev->DeviceExtension; - - if (pdev_ext == NULL) - return FALSE; - - ehci = pdev_ext->ehci; - if (ehci == NULL) - return FALSE; - - ehci_stop(ehci); - - if (pdev_ext->ehci_int) - { - IoDisconnectInterrupt(pdev_ext->ehci_int); - pdev_ext->ehci_int = NULL; - } - else - TRAP(); - destroy_pending_endp_pool(&pdev_ext->ehci->pending_endp_pool); - - ehci_destroy_schedule(ehci); - - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - - ehci_delete_device(pdev, dev_mgr); - - return FALSE; - -} - -BOOLEAN -ehci_start(PHCD hcd) -{ - ULONG tmp; - PBYTE base; - PEHCI_USBCMD_CONTENT usbcmd; - PEHCI_DEV ehci; - - if (hcd == NULL) - return FALSE; - - ehci = struct_ptr(hcd, EHCI_DEV, hcd_interf); - base = ehci->port_base; - - // stop the controller - tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); - usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; - usbcmd->run_stop = 0; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - - // wait the controller stop( ehci spec, 16 microframe ) - usb_wait_ms_dpc(2); - - // reset the controller - usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; - usbcmd->hcreset = TRUE; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - - for(;;) - { - // interval.QuadPart = -100 * 10000; // 10 ms - // KeDelayExecutionThread( KernelMode, FALSE, &interval ); - KeStallExecutionProcessor(10); - tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); - if (!usbcmd->hcreset) - break; - } - - // prepare the registers - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CTRLDSSEGMENT), 0); - - // turn on all the int - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBINTR), - EHCI_USBINTR_INTE | EHCI_USBINTR_ERR | EHCI_USBINTR_ASYNC | EHCI_USBINTR_HSERR - // EHCI_USBINTR_FLROVR | \ // it is noisy - // EHCI_USBINTR_PC | // we detect it by polling - ); - // write the list base reg - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_PERIODICLISTBASE), ehci->frame_list_phys_addr.LowPart); - - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_ASYNCLISTBASE), ehci->skel_async_qh->phys_addr & ~(0x1f)); - - usbcmd->int_threshold = 1; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - - // let's rock - usbcmd->run_stop = 1; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - - // set the configuration flag - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_CONFIGFLAG), 1); - - // enable the list traversaling - usbcmd->async_enable = 1; - usbcmd->periodic_enable = 1; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - - return TRUE; -} - -VOID -ehci_run_stop(PEHCI_DEV ehci, BOOLEAN start) -{ - PEHCI_USBCMD_CONTENT usbcmd; - PEHCI_USBSTS_CONTENT usbsts; - ULONG tmp; - PBYTE base; - - if (ehci == NULL) - return; - - base = ehci->port_base; - usbcmd = (PEHCI_USBCMD_CONTENT) & tmp; - usbsts = (PEHCI_USBSTS_CONTENT) & tmp; - - tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBSTS)); - if (start && usbsts->hc_halted == 0) - { - TRAP(); - usb_dbg_print(DBGLVL_MEDIUM, ("ehci_run_stop(): WARNING: hc running, can not start again\n")); - return; - } - tmp = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_USBCMD)); - usbcmd->run_stop = start ? 1 : 0; - EHCI_WRITE_PORT_ULONG((PULONG) (base + EHCI_USBCMD), tmp); - if (start) - usb_wait_ms_dpc(2); //ehci spec 16 microframes -} - -VOID -ehci_find_min_bandwidth(PEHCI_DEV ehci) -{ - LONG i; - if (ehci == NULL) - return; - - for(i = 0; i < (LONG) (ehci->frame_count << 3); i++) - { - ehci->min_bw = ehci->min_bw < ehci->frame_bw[i] ? ehci->min_bw : ehci->frame_bw[i]; - } - return; -} - -BOOLEAN -ehci_claim_bw_for_int(PEHCI_DEV ehci, PURB purb, BOOLEAN release) -// should have pending_endp_list_lock acquired, and purb->pipe prepared -{ - PURB_HS_PIPE_CONTENT pipe_content; - LONG i, j; - ULONG interval, bus_time, ss_time, cs_time; - BOOLEAN bw_avail; - ULONG max_packet_size; - - if (ehci == NULL || purb == NULL) - return FALSE; - - if (purb->pipe == 0) - return FALSE; - - bw_avail = FALSE; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = REAL_INTERVAL; - if (pipe_content->speed_high == 0) - { - // translate to high speed uframe count - interval <<= 3; - } - - if (interval > (ehci->frame_count << 3)) - interval = (ehci->frame_count << 3); - - max_packet_size = (1 << pipe_content->max_packet_size); - if (pipe_content->speed_high) - { - // this is a high speed endp - - bus_time = usb_calc_bus_time(USB_SPEED_HIGH, - (pipe_content->trans_dir) << 7, - FALSE, min(purb->data_length, (LONG) max_packet_size)); - - // multiple transactions per uframe - if (purb->data_length > (LONG) max_packet_size) - { - bus_time *= (purb->data_length) / max_packet_size; - bus_time += usb_calc_bus_time(USB_SPEED_HIGH, - (pipe_content->trans_dir) << 7, - FALSE, purb->data_length % max_packet_size); - } - bus_time = (bus_time + 1) >> 1; - - if (release) - { - for(i = pipe_content->start_uframe + (purb->int_start_frame << 3); - i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] += (USHORT) bus_time; - } - goto LBL_OUT; - } - if (bus_time < ehci->min_bw) - { - // start the poll from uframe zero of each frame - bw_avail = TRUE; - pipe_content->start_uframe = 0; - for(i = 0; i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] -= (USHORT) bus_time; - if (ehci->frame_bw[i] < ehci->min_bw) - ehci->min_bw = ehci->frame_bw[i]; - } - } - else // bother to find a pattern - { - for(j = 0; j < (LONG) interval; j++) - { - for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval) - { - if (ehci->frame_bw[i] < bus_time) - break; - } - if (i > (LONG) (ehci->frame_count << 3)) - { - bw_avail = TRUE; - break; - } - } - if (bw_avail) - { - for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] -= (USHORT) bus_time; - if (ehci->frame_bw[i] < ehci->min_bw) - ehci->min_bw = ehci->frame_bw[i]; - } - pipe_content->start_uframe = j & 7; - purb->int_start_frame = j >> 3; - } - } - } - else // full/low speed pipe - { - // split condition is considered - if (pipe_content->trans_dir) - { - // an input interrupt, with handshake - // 55 is 144 - 90 + 1, turnaround time is one byte not the worst case 90 bytes, - // refer to ehci-1.0 table 4-5 p64 - ss_time = 231 * 25 / 12; - // cs_time = ( 55 * 8 + ( LONG )( ( ( 19 + 7 * 8 * purb->data_length ) / 6 ) ) ) * 25 / 12; - cs_time = (55 * 8 + (LONG) (((7 * 8 * purb->data_length) / 6))) * 25 / 12; - } - else - { - // according to ehci-1.0 table 4-5 p64 - ss_time = (49 * 8 + (LONG) (((7 * 8 * purb->data_length) / 6))) * 25 / 12; - // 287 = 237 + 48( handshake ) + 8( turn around time ) - cs_time = 287 * 25 / 12; - } - ss_time >>= 1, cs_time >>= 1; - if (release) - { - for(i = pipe_content->start_uframe + (purb->int_start_frame << 3); - i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] += (USHORT) ss_time; - ehci->frame_bw[i + 2] += (USHORT) cs_time; - ehci->frame_bw[i + 3] += (USHORT) cs_time; - if ((i & 0x07) != 0x06) - ehci->frame_bw[i + 4] += (USHORT) cs_time; - } - goto LBL_OUT; - } - if (ss_time < ehci->min_bw && cs_time < ehci->min_bw) - { - pipe_content->start_uframe = 0; - bw_avail = TRUE; - for(i = 0; i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] -= (USHORT) ss_time; - ehci->min_bw = min(ehci->frame_bw[i], ehci->min_bw); - ehci->frame_bw[i + 2] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 2], ehci->min_bw); - ehci->frame_bw[i + 3] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 3], ehci->min_bw); - if ((i & 0x07) != 0x06) - { - ehci->frame_bw[i + 4] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 4], ehci->min_bw); - } - } - } - else - { - for(j = 0; j < (LONG) interval; j++) - { - if ((j & 0x7) == 7) // start-split not allowed at this uframe - continue; - - for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval) - { - if (ehci->frame_bw[i] < ss_time) - break; - if (ehci->frame_bw[i + 2] < cs_time) - break; - if (ehci->frame_bw[i + 3] < cs_time) - break; - if ((i & 0x7) != 6) - if (ehci->frame_bw[i + 4] < cs_time) - break; - } - if (i > (LONG) (ehci->frame_count << 3)) - { - bw_avail = TRUE; - break; - } - } - - pipe_content->start_uframe = j & 7; - purb->int_start_frame = j >> 3; - - for(i = j; i < (LONG) (ehci->frame_count << 3); i += interval) - { - ehci->frame_bw[i] -= (USHORT) ss_time; - ehci->min_bw = min(ehci->frame_bw[i], ehci->min_bw); - ehci->frame_bw[i + 2] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 2], ehci->min_bw); - ehci->frame_bw[i + 3] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 3], ehci->min_bw); - if ((i & 0x7) != 6) - { - ehci->frame_bw[i + 4] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[i + 4], ehci->min_bw); - } - } - } - } - - LBL_OUT: - if (!release) - return bw_avail; - else - { - ehci_find_min_bandwidth(ehci); - return TRUE; - } -} - -LONG -ehci_get_cache_policy(PEHCI_DEV ehci) -{ - PEHCI_HCC_CONTENT hcc_content; - - hcc_content = (PEHCI_HCC_CONTENT) & ehci->ehci_caps; - if (hcc_content->iso_sched_threshold >= 8) - return 16; - if (hcc_content->iso_sched_threshold == 0) - return 2; - return hcc_content->iso_sched_threshold + 2; -} - -// 25/12 is bus-time per bit ( 1000 / 480 ) -#define BEST_BUDGET_TIME_UFRAME ( ( 188 * 7 / 6 ) * 25 / 12 ) - -// in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet -// out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet -#define iso_max_data_load( dir ) ( dir == USB_DIR_IN ? \ - ( ( 188 * 8 - 231 - 8 - 67 + ( 8 - 1 ) ) / 8 ) : ( 188 - 49 ) ) - -#define iso_uframes_data_load( dir, data_load, uf_cnt ) - -BOOLEAN -ehci_claim_bw_for_iso(PEHCI_DEV ehci, PURB purb, BOOLEAN release) -{ - PURB_HS_PIPE_CONTENT pipe_content; - LONG i, j, k; - ULONG interval, bus_time, ss_time, cs_time, remainder; - BOOLEAN bw_avail; - ULONG cur_uframe, start_uframe = 0, max_time, max_packet_size; - PBYTE base; - if (ehci == NULL || purb == NULL) - return FALSE; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - base = ehci->port_base; - cur_uframe = EHCI_READ_PORT_ULONG((PULONG) (base + EHCI_FRINDEX)) + 1; - bw_avail = FALSE; - - max_packet_size = purb->params[0]; //( 1 << pipe_content->max_packet_size ); - - if (pipe_content->speed_high) - { - interval = REAL_INTERVAL; - if (purb->iso_frame_count == 0 || purb->iso_frame_count + 2 * 8 > (LONG) (ehci->frame_count << 3)) - return FALSE; - - for(i = 0, max_time = 0; i < (LONG) purb->iso_frame_count; i++) - { - bus_time = usb_calc_bus_time(USB_SPEED_HIGH, - (pipe_content->trans_dir) << 7, - TRUE, min(purb->iso_packet_desc[i].length, (LONG) max_packet_size)); - // NOTE: we did not use endp_mult_count here, because the comparison is enough - // to calculate the bandwidth - if (purb->iso_packet_desc[i].length > (LONG) max_packet_size) - { - // multiple transactions per uframe - bus_time *= purb->iso_packet_desc[i].length / max_packet_size; - bus_time += usb_calc_bus_time(USB_SPEED_HIGH, - (pipe_content->trans_dir) << 7, - TRUE, purb->iso_packet_desc[i].length % max_packet_size); - } - bus_time = (bus_time + 1) >> 1; - max_time = max(bus_time, max_time); - purb->iso_packet_desc[i].bus_time = bus_time; - } - - if (release) - { - // it is a release operation - for(i = purb->iso_start_frame, k = 0; k < (LONG) purb->iso_frame_count; - k++, i = (i + interval) % (ehci->frame_count << 3)) - { - ehci->frame_bw[i] += (USHORT) purb->iso_packet_desc[k].bus_time; - } - ehci_find_min_bandwidth(ehci); - return TRUE; - } - - if (max_time < ehci->min_bw) - { - start_uframe = cur_uframe + ehci_get_cache_policy(ehci); // avoid cache - for(i = start_uframe, j = 0; j < (LONG) purb->iso_frame_count; - i = (i + interval) % (ehci->frame_count << 3), j++) - { - ehci->frame_bw[i] -= (USHORT) purb->iso_packet_desc[j].bus_time; - ehci->min_bw = min(ehci->frame_bw[j], ehci->min_bw); - } - purb->iso_start_frame = start_uframe; - return TRUE; - } - else // max_time >= ehci->min_bw - { - for(j = 0; j < (LONG) interval; j++) - { - start_uframe = cur_uframe + ehci_get_cache_policy(ehci) + j; - for(i = start_uframe, k = 0; k < (LONG) purb->iso_frame_count; - k++, i = (i + interval) % (ehci->frame_count << 3)) - { - if (ehci->frame_bw[i] < (USHORT) purb->iso_packet_desc[k].bus_time) - { - break; - } - } - - if (k < (LONG) purb->iso_frame_count) - continue; - bw_avail = TRUE; - break; - } - if (bw_avail) - { - // allocate the bandwidth - for(i = start_uframe, k = 0; k < (LONG) purb->iso_frame_count; - k++, i = (i + interval) % (ehci->frame_count << 3)) - { - ehci->frame_bw[i] -= (USHORT) purb->iso_packet_desc[k].bus_time; - ehci->min_bw = min(ehci->min_bw, ehci->frame_bw[i]); - } - purb->iso_start_frame = start_uframe; - } - } - } - else // not high speed endpoint - { - // split transfer - if (purb->iso_frame_count == 0 || purb->iso_frame_count + 2 > (LONG) ehci->frame_count) - return FALSE; - - if (max_packet_size > 1023) - return FALSE; - - remainder = 0; - - // - // calculate for each frame - // in: 231 is sum of split token + host ipg + token, 8 is bus turn-around time, 67 is full speed data token in DATA packet - // out: 49 byte is sum of split token+ host ipg + token + host ipg + data packet - // bit-stuffing is for high speed bus transfer - // - - if (pipe_content->trans_dir) - { - // an input transfer, no handshake - ss_time = 231 * 25 / 12; - // cs_time = ( 231 + 8 + 67 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12; - cs_time = (231 + 8 + 67 + (LONG) (((7 * 8 * 188) / 6))) * 25 / 12; - } - else - { - // an output transfer according to ehci-1.0 table 4-5 p64 - // ss_time = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * 188 ) / 6 ) ) ) * 25 / 12; - ss_time = (49 * 8 + (LONG) (((7 * 8 * 188) / 6))) * 25 / 12; - cs_time = 0; - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - // remainder = ( 49 * 8 + ( LONG )( ( ( 19 + 7 * 8 * ( purb->iso_packet_desc[ i ].length % 188 ) ) / 6 ) ) ) * 25 / 12; - remainder = - (49 * 8 + (LONG) (((7 * 8 * (purb->iso_packet_desc[i].length % 188)) / 6))) * 25 / 12; - remainder >>= 1; - purb->iso_packet_desc[i].params.bus_time = (USHORT) remainder; - } - } - - ss_time >>= 1; - cs_time >>= 1; - cur_uframe = (cur_uframe + 7) & (~0x07); - - j = ehci->frame_count << 3; - if (release) - { - if (pipe_content->trans_dir) - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - ehci->frame_bw[purb->iso_packet_desc[i].params.start_uframe] += (USHORT) ss_time; - for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++) - { - ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] += (USHORT) cs_time; - } - - // two extra complete-split - ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] += (USHORT) cs_time; - ehci->frame_bw[(cur_uframe + 0x13 + (i << 3) + k) % j] += (USHORT) cs_time; - } - } - else - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++) - { - ehci->frame_bw[(cur_uframe + 0x10 + (i << 3) + k) % j] += (USHORT) ss_time; - } - } - } - ehci_find_min_bandwidth(ehci); - } - - // search for available bw - if (ss_time < ehci->min_bw && cs_time < ehci->min_bw) - { - if (pipe_content->trans_dir) - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - ehci->frame_bw[(cur_uframe + 0x10 + (i << 3)) % j] -= (USHORT) ss_time; - ehci->min_bw = min(ehci->frame_bw[(cur_uframe + 0x10 + (i << 3)) % j], ehci->min_bw); - - for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++) - { - ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] -= (USHORT) cs_time; - ehci->min_bw = - min(ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j], ehci->min_bw); - } - - // two extra complete-split - ehci->frame_bw[(cur_uframe + 0x12 + (i << 3) + k) % j] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[cur_uframe + 0x12 + (i << 3) + k], ehci->min_bw); - ehci->frame_bw[(cur_uframe + 0x13 + (i << 3) + k) % j] -= (USHORT) cs_time; - ehci->min_bw = min(ehci->frame_bw[cur_uframe + 0x13 + (i << 3) + k], ehci->min_bw); - } - } - else // iso output - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - for(k = 0; k < (purb->iso_packet_desc[i].length + 187) / 188; k++) - { - ehci->frame_bw[(cur_uframe + 0x10 + (i << 3) + k) % j] -= (USHORT) ss_time; - ehci->min_bw = - min(ehci->frame_bw[(cur_uframe + 0x11 + (i << 3) + k) % j], ehci->min_bw); - } - } - } - purb->iso_start_frame = 0; - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - if (i == 0) - purb->iso_packet_desc[i].params.start_uframe = (USHORT) (cur_uframe + 0x10); - else - purb->iso_packet_desc[i].params.start_uframe = - purb->iso_packet_desc[i - 1].params.start_uframe + 0x8; - } - bw_avail = TRUE; - } - else // take the pain to find one - { - BOOLEAN large; - long temp, base; - - for(j = (cur_uframe >> 3) + 2; j != (LONG) (cur_uframe >> 3); j = (j + 1) % ehci->frame_count) - { - temp = 0; - - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - large = purb->iso_packet_desc[i].length > 579; - base = (purb->iso_packet_desc[i].length + 187) / 188; - - if (base > 6) - return FALSE; - - if (pipe_content->trans_dir) - { - // input split iso, for those large than 579, schedule it at the uframe boundary - for(temp = 0; temp < (large == FALSE) ? (8 - base - 1) : 1; temp++) - { - k = (((j + i) << 3) + temp) % (ehci->frame_count << 3); - if (ehci->frame_bw[k] > ss_time) - continue; - - k = base; - while (k != 0) - { - if (ehci-> - frame_bw[(((j + i) << 3) + 1 + temp + k) % (ehci->frame_count << 3)] < - cs_time) - break; - k--; - } - if (k > 0) // not available - continue; - - // the first following extra cs - k = (((j + i) << 3) + 2 + temp + base) % (ehci->frame_count << 3); - if (ehci->frame_bw[k] < cs_time) - continue; - - if (base < 6) - { - // very large one does not have this second extra cs - if (ehci->frame_bw[(k + 1) % (ehci->frame_count << 3)] < cs_time) - continue; - } - } - - if (temp == 8 - 1 - base) // no bandwidth for ss - break; - } - else // output - { - // note: 8 - 1 - base has different meaning from the above - // it is to avoid the ss on H-Frame 7, but the above one is - // the latency of the classic bus. - for(temp = 0; temp < 8 - 1 - base; temp++) - { - if (ehci->frame_bw[((j + i) << 3) % (ehci->frame_count << 3) + temp] > ss_time) - continue; - - for(k = temp; k < temp + base; k++) - { - if (ehci->frame_bw[((j + i) << 3) % (ehci->frame_count << 3) + k] < ss_time) - break; - } - } - - if (temp == 8 - 1 - base) - break; - } - - purb->iso_packet_desc[i].params.start_uframe = - (USHORT) ((((j + i) << 3) + temp) % (ehci->frame_count << 3)); - // next frame - } - if (i < (LONG) purb->iso_frame_count) - { - // skip to the next section - j = (j + i) % (ehci->frame_count << 3); - continue; - } - bw_avail = TRUE; - break; - } - // FIXME: Should we claim bw for the last complete split sitd? this is not done - // yet. - if (bw_avail) - { - if (pipe_content->trans_dir) - { - // input iso - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - j = purb->iso_packet_desc[i].length; - temp = (purb->iso_packet_desc[i].params.start_uframe) % (ehci->frame_count << 3); - ehci->frame_bw[temp] -= (USHORT) ss_time; - for(k = 0; k < (j + 187) / 188; j++) - { - ehci->frame_bw[temp + 2 + k] -= (USHORT) cs_time; - } - ehci->frame_bw[temp + 2 + k] -= (USHORT) cs_time; - if ((j + 187) / 188 < 6) //ehci restriction - { - ehci->frame_bw[temp + 3 + k] -= (USHORT) cs_time; - } - } - } - else //output iso - { - for(i = 0; i < (LONG) purb->iso_frame_count; i++) - { - j = purb->iso_packet_desc[i].length; - temp = (purb->iso_packet_desc[i].params.start_uframe) % (ehci->frame_count << 3); - for(k = 0; k < j / 188; j++) - { - ehci->frame_bw[temp + k] -= (USHORT) ss_time; - } - if (j % 188) - ehci->frame_bw[temp + k] -= purb->iso_packet_desc[i].params.bus_time; - } - } - } - } - } - return bw_avail; -} - -BOOLEAN -ehci_claim_bandwidth(PEHCI_DEV ehci, PURB purb, BOOLEAN claim_bw) //true to claim band-width, false to free band-width -// should have pending_endp_list_lock acquired, and purb->pipe prepared -{ - PURB_HS_PIPE_CONTENT pipe_content; - BOOLEAN ret; - - if (ehci == NULL || purb == NULL) - return FALSE; - - ret = FALSE; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC) - { - ret = ehci_claim_bw_for_iso(ehci, purb, claim_bw ? FALSE : TRUE); - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT) - { - ret = ehci_claim_bw_for_int(ehci, purb, claim_bw ? FALSE : TRUE); - } - else - TRAP(); - return ret; -} - -BOOLEAN -ehci_can_remove(PURB purb, BOOLEAN door_bell_rings, ULONG cur_frame) -// test if the purb can be removed from the schedule, by current frame index and -// purb states -{ - PURB_HS_PIPE_CONTENT pipe_content; - ULONG interval; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = REAL_INTERVAL; - - switch (purb->flags & URB_FLAG_STATE_MASK) - { - case URB_FLAG_STATE_PENDING: - { - // not impossible - TRAP(); - break; - } - case URB_FLAG_STATE_IN_PROCESS: - { - break; - } - case URB_FLAG_STATE_DOORBELL: - { - if ((pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL) && door_bell_rings == TRUE) - { - return TRUE; - } - else if ((pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL)) - { - break; - } - else - { - TRAP(); - break; - } - } - case URB_FLAG_STATE_WAIT_FRAME: - { - // need more processing - if ((purb->flags & URB_FLAG_FORCE_CANCEL) == 0) - { - TRAP(); - break; - } - if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT) - { - return door_bell_rings; - } - else // isochronous can not be canceled - { - TRAP(); - break; - } - } - } - return FALSE; -} - -NTSTATUS ehci_remove_urb_from_schedule(PEHCI_DEV ehci, PURB purb); - -static VOID -ehci_deactivate_urb(PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content; - PLIST_ENTRY pthis, pnext; - PEHCI_QH_CONTENT pqh_content; - PEHCI_QTD_CONTENT pqtd_content; - - if (purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - switch (pipe_content->trans_type) - { - case USB_ENDPOINT_XFER_CONTROL: - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_INT: - { - ListFirst(&purb->trasac_list, pthis); - pqh_content = (PEHCI_QH_CONTENT) qh_from_list_entry(pthis); - ListNext(&purb->trasac_list, pthis, pnext); - do - { - pqtd_content = (PEHCI_QTD_CONTENT) qtd_from_list_entry(pthis); - if (pqtd_content->status & QTD_STS_ACTIVE) - { - pqtd_content->status &= ~QTD_STS_ACTIVE; - } - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - - } - while (pthis); - break; - } - case USB_ENDPOINT_XFER_ISOC: - { - // fall through - } - default: - TRAP(); - } - return; -} - -static VOID -ehci_insert_bulk_schedule(PEHCI_DEV ehci, PURB purb) -// list head is only a handle, the qh and qtd are following it. -{ - PLIST_ENTRY list_head; - PEHCI_QH pqh, pqhprev, pqhnext; - PLIST_ENTRY pthis, pprev, pnext; - - if (ehci == NULL || purb == NULL) - return; - - list_head = &purb->trasac_list; - ListFirst(list_head, pthis); - if (pthis == NULL) - return; - - if (elem_type_list_entry(pthis) != INIT_LIST_FLAG_QH) - return; - - pqh = qh_from_list_entry(pthis); - // the last qh - ListFirstPrev(&ehci->async_list_cpu, pprev); - pqhprev = qh_from_schedule(pprev); - - // the first qh - ListFirst(&ehci->async_list_cpu, pnext); - pqhnext = qh_from_schedule(pnext); - - if (pprev == &ehci->async_list_cpu) - { - // always a qh in async list - TRAP(); - return; - } - pqh->hw_next = pqhnext->phys_addr; - InsertTailList(&ehci->async_list_cpu, &pqh->elem_head_link->sched_link); - pqhprev->hw_next = pqh->phys_addr; - return; -} - -static VOID -ehci_remove_bulk_from_schedule(PEHCI_DEV ehci, PURB purb) -// executed in isr, and have frame_list_lock acquired, so -// never try to acquire any spin-lock -// remove the bulk purb from schedule, and mark it not in -// the schedule -{ - PLIST_ENTRY list_head; - PEHCI_QH pqh, pqhprev, pqhnext; - PEHCI_QH_CONTENT pqhc; - PLIST_ENTRY pthis, pprev, pnext; - - if (ehci == NULL || purb == NULL) - return; - - list_head = &purb->trasac_list; - ListFirst(list_head, pthis); - if (pthis == NULL) - { - TRAP(); - return; - } - pqh = qh_from_list_entry(pthis); - pqhc = (PEHCI_QH_CONTENT) pqh; - - if (pqhc->is_async_head) - TRAP(); - - ListFirst(&pqh->elem_head_link->sched_link, pnext); - ListFirstPrev(&pqh->elem_head_link->sched_link, pprev); - - if (pprev == &ehci->async_list_cpu) - { - // we will at least have a qh with H-bit 1 in the async-list - TRAP(); - } - else if (pnext == &ehci->async_list_cpu) - { - // remove the last one - pqhprev = qh_from_schedule(pprev); - ListFirst(&ehci->async_list_cpu, pnext); - pqhnext = qh_from_schedule(pnext); - pqhprev->hw_next = pqhnext->phys_addr; - } - else - { - pqhprev = qh_from_schedule(pprev); - pqhnext = qh_from_schedule(pnext); - pqhprev->hw_next = pqhnext->phys_addr; - } - RemoveEntryList(&pqh->elem_head_link->sched_link); - return; -} - - -static VOID -ehci_insert_fstn_schedule(PEHCI_DEV ehci, PURB purb) -{ - - PURB_HS_PIPE_CONTENT pipe_content, pc; - PLIST_ENTRY pthis, list_head, pnext = NULL, pprev; - PEHCI_QH pqhnext; - PEHCI_FSTN pfstn; - PURB purb1; - - ULONG interval, start_frame, start_uframe; - LONG i; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = (1 << (pipe_content->interval + 3)); - list_head = &purb->trasac_list; - start_frame = purb->int_start_frame; - start_uframe = (start_frame << 3) + 1; //( start_frame << 3 ) + pipe_content->start_uframe; - - if ((start_frame << 3) >= interval) - TRAP(); - - ListFirstPrev(list_head, pprev); - - if (elem_type_list_entry(pprev) != INIT_LIST_FLAG_FSTN) - { - TRAP(); - return; - } - - pfstn = fstn_from_list_entry(pprev); - - if (interval == 8) - { - ListFirst(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis); - - // skip the first one - ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext); - pprev = pthis; - pthis = pnext; - - while (pthis) - { - purb1 = qh_from_schedule(pthis)->elem_head_link->purb; - pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe; - if (pc->speed_high) - { - TRAP(); - return; - } - if ((1 << (pc->interval + 3)) > (LONG) interval) - { - TRAP(); - continue; - } - else if ((1 << (pc->interval + 3) < (LONG) interval)) - { - break; - } - else if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN) - { - ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext); - pprev = pthis; - pthis = pnext; - } - else if (pc->start_uframe <= 1) - { - ListNext(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], pthis, pnext); - pprev = pthis; - pthis = pnext; - } - break; - } - if (pprev == NULL) - { - TRAP(); - return; - } - if (pthis == NULL) - { - //the last one - InsertTailList(&ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX], - &pfstn->elem_head_link->sched_link); - } - else - { - if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN) - { - InsertHeadList(&fstn_from_schedule(pprev)->elem_head_link->sched_link, - &pfstn->elem_head_link->sched_link); - } - else - { - InsertHeadList(&qh_from_schedule(pprev)->elem_head_link->sched_link, - &pfstn->elem_head_link->sched_link); - } - } - pfstn->hw_next = qh_from_schedule(pprev)->hw_next; - qh_from_schedule(pprev)->hw_next = pfstn->phys_addr; - } - else - { - start_frame++; - for(i = start_frame; i < (LONG) start_frame + 1; i += (interval >> 3)) - { - list_head = &ehci->frame_list_cpu[i].td_link; - ListFirst(list_head, pthis); - - pprev = list_head; - while (pthis) - { - // skip itds and sitds - if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_ITD || - elem_type(pthis, FALSE) == INIT_LIST_FLAG_SITD) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - break; - } - - while (pthis) - { - // find the insertion point - ULONG u; - - pqhnext = qh_from_schedule(pthis); - if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN) - purb1 = fstn_from_schedule(pthis)->elem_head_link->purb; - else - purb1 = pqhnext->elem_head_link->purb; - - if (purb1 == NULL) - TRAP(); - - pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe; - u = 1 << (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3))); - - if (u > interval) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - else if (u == interval) - { - if (start_uframe >= - (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ? - 1 : pc->start_uframe) + (purb1->int_start_frame << 3)) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - else - break; - } - else if (u < interval) - { - break; - } - } - - if (pprev == list_head) - { - // insert to the list head - pnext = pfstn->elem_head_link->sched_link.Flink = list_head->Flink; - list_head->Flink = &pfstn->elem_head_link->sched_link; - pfstn->hw_next = ehci->frame_list[i]; // point to following node - ehci->frame_list[i] = pfstn->phys_addr; - } - else - { - pnext = pfstn->elem_head_link->sched_link.Flink = pprev->Flink; - pprev->Flink = &pfstn->elem_head_link->sched_link; - - // fstn can be handled correctly - pfstn->hw_next = qh_from_schedule(pprev)->hw_next; - qh_from_schedule(pprev)->hw_next = pfstn->phys_addr; - } - } - // the pointer to next node of this fstn is alway same across the frame list. - for(i = start_frame + (interval >> 3); i < (LONG) ehci->frame_count; i += (interval >> 3)) - { - pprev = list_head = &ehci->frame_list_cpu[i].td_link; - ListFirst(list_head, pthis); - - while (pthis) - { - if (pthis == pnext) - { - break; - } - pprev = pthis; - ListNext(list_head, pthis, pthis); - } - - pprev->Flink = &pfstn->elem_head_link->sched_link; - if (pprev == list_head) - ehci->frame_list[i] = pfstn->phys_addr; - else - qh_from_schedule(pprev)->hw_next = pfstn->phys_addr; - } - } -} - -static VOID -ehci_remove_fstn_from_schedule(PEHCI_DEV ehci, PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content; - PLIST_ENTRY pthis, list_head, pnext, pprev; - PEHCI_FSTN pfstn; - - ULONG interval, start_frame, start_uframe; - LONG i; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = (1 << (pipe_content->interval + 3)); - list_head = &purb->trasac_list; - start_frame = purb->int_start_frame; - start_uframe = 1; - - if ((start_frame << 3) >= interval) - TRAP(); - start_frame++; - - ListFirstPrev(list_head, pprev); - if (elem_type_list_entry(pprev) != INIT_LIST_FLAG_FSTN) - { - TRAP(); - return; - } - - pfstn = fstn_from_list_entry(pprev); - if (interval < 8) - { - TRAP(); - return; - } - if (interval == 8) - { - ListFirstPrev(&pfstn->elem_head_link->sched_link, pprev); - qh_from_schedule(pprev)->hw_next = pfstn->hw_next; - RemoveEntryList(&pfstn->elem_head_link->sched_link); - } - else - { - for(i = start_frame; i < (LONG) ehci->frame_count; i++) - { - ListFirst(&ehci->frame_list_cpu[i].td_link, pthis); - if (pthis == NULL) - { - TRAP(); - return; - } - pprev = &ehci->frame_list_cpu[i].td_link; - while (pthis && pthis != &pfstn->elem_head_link->sched_link) - { - pprev = pthis; - ListNext(&ehci->frame_list_cpu[i].td_link, pthis, pnext); - pthis = pnext; - } - if (pthis == NULL) - { - TRAP(); - return; - } - qh_from_schedule(pprev)->hw_next = pfstn->hw_next; - pprev->Flink = pfstn->elem_head_link->sched_link.Flink; - } - } - return; -} - -static VOID -ehci_insert_int_schedule(PEHCI_DEV ehci, PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content, pc; - PLIST_ENTRY pthis, list_head, pnext = NULL, pprev; - PEHCI_ELEM_LINKS elem_link; - PEHCI_QH pqh, pqhprev, pqhnext; - PURB purb1; - - ULONG interval, u, start_frame, start_uframe; - LONG i; - UCHAR need_fstn; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = REAL_INTERVAL; - start_uframe = (purb->int_start_frame << 3) + pipe_content->start_uframe; - start_frame = purb->int_start_frame; - need_fstn = FALSE; - list_head = &purb->trasac_list; - - ListFirst(list_head, pthis); - if (pthis == NULL) - return; - - pqh = qh_from_list_entry(pthis); - - if (!pipe_content->speed_high) - { - interval = (interval << 3); - ListFirstPrev(list_head, pprev); - if (elem_type_list_entry(pprev) == INIT_LIST_FLAG_FSTN) - need_fstn = TRUE; - } - - if (interval < 16) - { - pqhprev = pqhnext = NULL; - if (interval == 1) - { - list_head = &ehci->periodic_list_cpu[EHCI_SCHED_FSTN_INDEX]; - ListFirst(list_head, pthis); - InsertTailList(list_head, &pqh->elem_head_link->sched_link); - ListFirstPrev(&pqh->elem_head_link->sched_link, pprev); - pqh->hw_next = EHCI_PTR_TERM; - if (pprev == pthis) - { - fstn_from_schedule(pthis)->hw_next = pqh->phys_addr; - } - else - { - qh_from_schedule(pthis)->hw_next = pqh->phys_addr; - } - } - else // interval == 2 or 4 or 8 - { - list_head = &ehci->periodic_list_cpu[EHCI_SCHED_INT8_INDEX]; - ListFirst(list_head, pthis); - pprev = NULL; - while (pthis) - { - elem_link = struct_ptr(pthis, EHCI_ELEM_LINKS, sched_link); - purb1 = elem_link->purb; - pc = (PURB_HS_PIPE_CONTENT) purb1->pipe; - u = (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3))); - - if (interval < u) - { - ListFirstPrev(pthis, pprev); - break; - } - else if (interval > u) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - // FIXME: is this right to fix fstn's start_uf 1??? - else if (start_uframe <= - (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ? - 1 : pc->start_uframe) + (purb1->int_start_frame << 3)) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - else // interval is equal, and start_uframe is greater - { - ListFirstPrev(pthis, pprev); - break; - } - } - if (pprev == NULL) - { - // at least one dummy qh is there - TRAP(); - } - else if (pnext == NULL) - { - // the last one in this chain, fstn can be handled correctly - InsertTailList(list_head, &pqh->elem_head_link->sched_link); - pqhprev = qh_from_schedule(pprev); - pqh->hw_next = pqhprev->hw_next; - pqhprev->hw_next = pqh->phys_addr; - } - else - { - pqhprev = qh_from_schedule(pprev); - if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_QH) - { - InsertHeadList(&pqhprev->elem_head_link->sched_link, &pqh->elem_head_link->sched_link); - } - else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN) - { - InsertHeadList(&fstn_from_schedule(pprev)->elem_head_link->sched_link, - &pqh->elem_head_link->sched_link); - } - pqh->hw_next = pqhprev->hw_next; - pqhprev->hw_next = pqh->phys_addr; - } - } - } - else // interval >= 16 - { - if ((start_frame << 3) >= interval) - TRAP(); - - for(i = start_frame; i < (LONG) start_frame + 1; i += (interval >> 3)) - { - list_head = &ehci->frame_list_cpu[i].td_link; - ListFirst(list_head, pthis); - - pprev = list_head; - while (pthis) - { - // skip itds and sitds - if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_ITD || - elem_type(pthis, FALSE) == INIT_LIST_FLAG_SITD) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - break; - } - - while (pthis) - { - // find the insertion point - - pqhnext = qh_from_schedule(pthis); - if (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN) - purb1 = fstn_from_schedule(pthis)->elem_head_link->purb; - else - purb1 = pqhnext->elem_head_link->purb; - - if (purb1 == NULL) - TRAP(); - - pc = (PURB_HS_PIPE_CONTENT) & purb1->pipe; - u = 1 << (pc->speed_high ? (1 << pc->interval) : (1 << (pc->interval + 3))); - - if (u > interval) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - else if (u == interval) - { - if (start_uframe >= - (elem_type(pthis, FALSE) == INIT_LIST_FLAG_FSTN ? - 1 : pc->start_uframe) + (purb1->int_start_frame << 3)) - { - ListNext(list_head, pthis, pnext); - pprev = pthis; - pthis = pnext; - continue; - } - else - break; - } - else if (u < interval) - { - break; - } - } - if (pprev == list_head) - { - // insert to the list head - pnext = pqh->elem_head_link->sched_link.Flink = list_head->Flink; - list_head->Flink = &pqh->elem_head_link->sched_link; - pqh->hw_next = ehci->frame_list[i]; // point to following node - ehci->frame_list[i] = pqh->phys_addr; - } - else - { - pnext = pqh->elem_head_link->sched_link.Flink = pprev->Flink; - pprev->Flink = &pqh->elem_head_link->sched_link; - - // fstn can be handled correctly - pqh->hw_next = qh_from_schedule(pprev)->hw_next; - qh_from_schedule(pprev)->hw_next = pqh->phys_addr; - } - } - for(i = start_frame + (interval >> 3); i < (LONG) ehci->frame_count; i += (interval >> 3)) - { - pprev = list_head = &ehci->frame_list_cpu[i].td_link; - ListFirst(list_head, pthis); - - while (pthis) - { - if (pthis == pnext) - { - break; - } - pprev = pthis; - ListNext(list_head, pthis, pthis); - } - - pprev->Flink = &pqh->elem_head_link->sched_link; - if (pprev == list_head) - ehci->frame_list[i] = pqh->phys_addr; - else - qh_from_schedule(pprev)->hw_next = pqh->phys_addr; - } - } - - if (need_fstn) - ehci_insert_fstn_schedule(ehci, purb); - - return; -} - -static VOID -ehci_remove_int_from_schedule(PEHCI_DEV ehci, PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content; - PLIST_ENTRY pthis, list_head, pnext, pprev, pcur; - PEHCI_QH pqh, pqhprev; - - ULONG interval, start_frame, start_uframe; - LONG i; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - interval = REAL_INTERVAL; - start_uframe = (purb->int_start_frame << 3) + pipe_content->start_uframe; - start_frame = purb->int_start_frame; - - ListFirst(&purb->trasac_list, pthis); - if (pthis == NULL) - return; - - pqh = qh_from_list_entry(pthis); - list_head = &purb->trasac_list; - - if (IsListEmpty(list_head)) - { - TRAP(); - return; - } - - if (!pipe_content->speed_high) - { - interval = (interval << 3); - } - - if (interval >= 256 * 8) - return; - - if (interval < 16) - { - ListFirstPrev(&pqh->elem_head_link->sched_link, pprev); - RemoveEntryList(&pqh->elem_head_link->sched_link); - if (interval > 1) - { - pqhprev = qh_from_schedule(pprev); - pqhprev->hw_next = pqh->hw_next; - } - else - { - ListFirst(&ehci->frame_list_cpu[EHCI_SCHED_FSTN_INDEX].td_link, list_head); - if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN) - { - fstn_from_schedule(list_head)->hw_next = pqh->hw_next; - } - else - { - qh_from_schedule(pprev)->hw_next = pqh->hw_next; - } - } - } - else if (interval >= 16) - { - ListFirst(list_head, pthis); - pthis = &pqh->elem_head_link->sched_link; - - for(i = start_uframe; i < (LONG) (ehci->frame_count << 3); i += interval) - { - ListFirst(&ehci->frame_list_cpu[i].td_link, pcur); - pprev = NULL; - while (pthis != pcur && pcur) - { - ListNext(&ehci->frame_list_cpu[i].td_link, pcur, pnext); - pprev = pcur; - pcur = pnext; - } - - if (pcur == NULL) - { - TRAP(); - continue; - } - else if (pprev == NULL) - { - // the first one in the frame list - ehci->frame_list_cpu[i].td_link.Flink = pthis->Flink; - ehci->frame_list[i] = qh_from_schedule(pthis)->hw_next; - } - else - { - if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_QH) - { - qh_from_schedule(pprev)->elem_head_link->sched_link.Flink = - pqh->elem_head_link->sched_link.Flink; - qh_from_schedule(pprev)->hw_next = pqh->hw_next; - } - else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_ITD) - { - itd_from_schedule(pprev)->elem_head_link->sched_link.Flink = - pqh->elem_head_link->sched_link.Flink; - itd_from_schedule(pprev)->hw_next = pqh->hw_next; - } - else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_SITD) - { - sitd_from_schedule(pprev)->elem_head_link->sched_link.Flink = - pqh->elem_head_link->sched_link.Flink; - sitd_from_schedule(pprev)->hw_next = pqh->hw_next; - } - else if (elem_type(pprev, FALSE) == INIT_LIST_FLAG_FSTN) - { - fstn_from_schedule(pprev)->elem_head_link->sched_link.Flink = - pqh->elem_head_link->sched_link.Flink; - fstn_from_schedule(pprev)->hw_next = pqh->hw_next; - } - else - TRAP(); - } - } - } - - ListFirstPrev(&purb->trasac_list, pprev); - if (elem_type_list_entry(pprev) == INIT_LIST_FLAG_FSTN) - ehci_remove_fstn_from_schedule(ehci, purb); - return; -} - -static VOID -ehci_insert_iso_schedule(PEHCI_DEV ehci, PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content; - PLIST_ENTRY pthis, list_head, pnext; - - ULONG interval, start_frame; - LONG i; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - - interval = 8; - if (pipe_content->speed_high) - interval = REAL_INTERVAL; - - start_frame = purb->iso_start_frame; - - ListFirst(&purb->trasac_list, pthis); - if (pthis == NULL) - { - TRAP(); - return; - } - - list_head = &purb->trasac_list; - if (IsListEmpty(list_head)) - { - TRAP(); - return; - } - - i = start_frame; - while (pthis) - { - if (pipe_content->speed_high) - { - itd_from_list_entry(pthis)->elem_head_link->sched_link.Flink = - ehci->frame_list_cpu[i].td_link.Flink; - itd_from_list_entry(pthis)->hw_next = ehci->frame_list[i]; - - ehci->frame_list[i] = itd_from_list_entry(pthis)->phys_addr; - ehci->frame_list_cpu[i].td_link.Flink = pthis; - } - else - { - sitd_from_list_entry(pthis)->elem_head_link->sched_link.Flink = - ehci->frame_list_cpu[i].td_link.Flink; - sitd_from_list_entry(pthis)->hw_next = ehci->frame_list[i]; - - ehci->frame_list[i] = sitd_from_list_entry(pthis)->phys_addr; - ehci->frame_list_cpu[i].td_link.Flink = pthis; - } - - ListNext(list_head, pthis, pnext); - pthis = pnext; - - if (interval <= 8) - i++; - else - i += (interval >> 3); - } - return; -} - -static VOID -ehci_remove_iso_from_schedule(PEHCI_DEV ehci, PURB purb) -{ - PURB_HS_PIPE_CONTENT pipe_content; - PLIST_ENTRY pthis, list_head, pnext, pprev, pcur; - - ULONG interval, start_frame; - LONG i; - - if (ehci == NULL || purb == NULL) - return; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - - interval = 8; - if (pipe_content->speed_high) - interval = REAL_INTERVAL; - - start_frame = purb->iso_start_frame; - - ListFirst(&purb->trasac_list, pthis); - if (pthis == NULL) - { - TRAP(); - return; - } - - list_head = &purb->trasac_list; - if (IsListEmpty(list_head)) - { - TRAP(); - return; - } - - i = start_frame; - while (pthis) - { - // for the possible existance of sitd back pointer, we can not use for(...) - ListFirst(&ehci->frame_list_cpu[i].td_link, pcur); - pprev = &ehci->frame_list_cpu[i].td_link; - while (pcur) - { - if (pcur != pthis) - { - ListNext(&ehci->frame_list_cpu[i].td_link, pcur, pnext); - pprev = pcur; - pcur = pnext; - continue; - } - break; - } - - if (pcur == NULL) - { - TRAP(); - } - pprev->Flink = pcur->Flink; - if (pprev != &ehci->frame_list_cpu[i].td_link) - qh_from_schedule(pprev)->hw_next = qh_from_schedule(pcur)->hw_next; - else - ehci->frame_list[i] = qh_from_schedule(pcur)->hw_next; - - ListNext(list_head, pthis, pnext); - pthis = pnext; - - if (interval <= 8) - i++; - else - i += (interval >> 3); - } - return; -} - -NTSTATUS -ehci_isr_removing_urb(PEHCI_DEV ehci, PURB purb, BOOLEAN doorbell_rings, ULONG cur_frame) -{ - UCHAR type; - PLIST_ENTRY pthis; - PURB_HS_PIPE_CONTENT pipe_content; - PEHCI_ITD_CONTENT pitd_content; - PEHCI_SITD_CONTENT psitd_content; - PEHCI_QH_CONTENT pqh_content; - PEHCI_QTD_CONTENT pqtd_content; - LONG i; - - if (purb == NULL || ehci == NULL) - return STATUS_INVALID_PARAMETER; - - if ((purb->flags & URB_FLAG_STATE_MASK) == URB_FLAG_STATE_FINISHED) - return STATUS_SUCCESS; - - type = 0; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - - switch (purb->flags & URB_FLAG_STATE_MASK) - { - case URB_FLAG_STATE_IN_PROCESS: - { - // determine the removal type: complete, error or cancel - ListFirst(&purb->trasac_list, pthis); - if (purb->flags & URB_FLAG_FORCE_CANCEL) - { - type = 3; - } - else - { - if (pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_INT || - pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL) - { - pqh_content = - (PEHCI_QH_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)-> - phys_part & PHYS_PART_ADDR_MASK); - if (EHCI_QH_ERROR(pqh_content)) - { - purb->status = pqh_content->cur_qtd.status; - type = 2; - } - else - { - pqtd_content = &pqh_content->cur_qtd; - if (pqtd_content->terminal && ((pqtd_content->status & QTD_STS_ACTIVE) == 0)) - { - type = 1; - } - // else, not finished - } - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC) - { - // FIXME: do we need to check if current frame falls out of the - // frame range of iso transfer - // inspect the last td to determine if finished - ListFirstPrev(&purb->trasac_list, pthis); - if (pthis) - { - if (pipe_content->speed_high) - { - pitd_content = - (PEHCI_ITD_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)-> - phys_part & PHYS_PART_ADDR_MASK); - for(i = 0; i < 8; i++) - { - if (pitd_content->status_slot[i].trans_length && - pitd_content->status_slot[i].status & 0x08) - { - break; - } - } - if (i == 8) - { - // the itds are all inactive - type = 1; - } - } - else - { - psitd_content = - (PEHCI_SITD_CONTENT) ((ULONG) struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link)-> - phys_part & PHYS_PART_ADDR_MASK); - if ((psitd_content->status & 0x80) == 0) - { - type = 1; - } - } - } - else // empty transaction list in purb - TRAP(); - } - else // unknown transfer type - TRAP(); - - } // end of not force cancel - - if (type == 0) - return STATUS_SUCCESS; - - switch (type) - { - case 1: - { - if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || - pipe_content->trans_type == USB_ENDPOINT_XFER_BULK) - { - ehci_remove_bulk_from_schedule(ehci, purb); - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_DOORBELL; - purb->status = 0; - press_doorbell(ehci); - return STATUS_SUCCESS; - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_ISOC) - { - ehci_remove_iso_from_schedule(ehci, purb); - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT) - { - ehci_remove_int_from_schedule(ehci, purb); - } - else // unknown transfer type - TRAP(); - - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_FINISHED; - - // notify dpc the purb can be completed; - purb->flags &= ~URB_FLAG_IN_SCHEDULE; - purb->status = 0; - - return STATUS_SUCCESS; - } - case 2: - { - if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || - pipe_content->trans_type == USB_ENDPOINT_XFER_BULK) - { - ehci_deactivate_urb(purb); - ehci_remove_bulk_from_schedule(ehci, purb); - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_DOORBELL; - press_doorbell(ehci); - } - else if (pipe_content->trans_type == USB_ENDPOINT_XFER_INT) - { - ehci_remove_int_from_schedule(ehci, purb); - - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_FINISHED; - purb->flags &= ~URB_FLAG_IN_SCHEDULE; - } - else // unknown transfer or iso transfer - TRAP(); - return STATUS_SUCCESS; - } - case 3: - { - if (pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL || - pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_INT) - { - ehci_deactivate_urb(purb); - if (pipe_content->trans_type == USB_ENDPOINT_XFER_BULK || - pipe_content->trans_type == USB_ENDPOINT_XFER_CONTROL) - ehci_remove_bulk_from_schedule(ehci, purb); - else - ehci_remove_int_from_schedule(ehci, purb); - - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_DOORBELL; - - press_doorbell(ehci); - - } - else // unknown transfer or iso transfer - DO_NOTHING; - purb->status = 0; - return STATUS_SUCCESS; - } - default: - TRAP(); - } - break; - } - case URB_FLAG_STATE_DOORBELL: - { - if (doorbell_rings == FALSE) - return STATUS_SUCCESS; - - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_FINISHED; - purb->flags &= ~URB_FLAG_IN_SCHEDULE; - return STATUS_SUCCESS; - } - } - return STATUS_SUCCESS; -} - -static ULONG -ehci_scan_iso_error(PEHCI_DEV ehci, PURB purb) -// we only report the first error of the ITDs, purb->status is the status code -// return the raw status for ehci_set_error_code -{ - PURB_HS_PIPE_CONTENT pipe_content; - PEHCI_SITD_CONTENT psitd_content; - PEHCI_ITD_CONTENT pitd_content; - PLIST_ENTRY pthis, pnext; - LONG i; - - if (ehci == NULL || purb == NULL) - return 0; - - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->pipe; - if (pipe_content->trans_type != USB_ENDPOINT_XFER_ISOC) - { - return 0; - } - - ListFirst(&purb->trasac_list, pthis); - if (pipe_content->speed_high) - { - while (pthis) - { - pitd_content = (PEHCI_ITD_CONTENT) itd_from_list_entry(pthis); - for(i = 0; i < 8; i++) - { - if (pitd_content->status_slot[i].status & ITD_ANY_ERROR) - break; - } - if (i < 8) - { - // error occured - return purb->status = pitd_content->status_slot[i].status; - } - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - } - else - { - while (pthis) - { - psitd_content = (PEHCI_SITD_CONTENT) sitd_from_list_entry(pthis); - if (psitd_content->status & SITD_ANY_ERROR) - { - // error occured - if (psitd_content->s_mask == 0x04 && - psitd_content->c_mask == 0x70 && psitd_content->bytes_to_transfer == 1) - return purb->status = 0; - - return purb->status = psitd_content->status; - } - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - } - return 0; -} - -BOOLEAN NTAPI -ehci_isr(PKINTERRUPT interrupt, PVOID context) - // we can not use endp here for it is within the dev scope, and - // we can not acquire the dev-lock, fortunately we saved some - // info in purb->pipe in ehci_internal_submit_XXX. -{ - - PEHCI_DEV ehci; - ULONG status; -#if DBG - ULONG urb_count; -#endif - PLIST_ENTRY pthis, pnext; - PURB purb; - BOOLEAN door_bell_rings; - ULONG cur_frame; - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - ehci = (PEHCI_DEV) context; - if (ehci == NULL) - return FALSE; - - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_USBSTS)); - cur_frame = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + EHCI_FRINDEX)); - - status &= (EHCI_ERROR_INT | STS_INT | STS_IAA); - if (!status) /* shared interrupt, not mine */ - { - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): not our int\n")); - return FALSE; - } - - /* clear it */ - EHCI_WRITE_PORT_ULONG((PULONG) (ehci->port_base + EHCI_USBSTS), status); - - if (status & EHCI_ERROR_INT) - { - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): current ehci status=0x%x\n", status)); - } - else - { - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): congratulations, no error occurs\n")); - } - - - if (status & STS_FATAL) - { - DbgPrint("ehci_isr(): host system error, PCI problems?\n"); - for(;;); - - } - - if (status & STS_HALT) //&& !ehci->is_suspended - { - DbgPrint("ehci_isr(): host controller halted. very bad\n"); - /* FIXME: Reset the controller, fix the offending TD */ - // reset is performed in dpc - } - - - door_bell_rings = ((status & STS_IAA) != 0); - - // scan to remove those due -#if DBG - urb_count = dbg_count_list(&ehci->urb_list); - ehci_dbg_print(DBGLVL_MAXIMUM, ("ehci_isr(): urb# in process is %d\n", urb_count)); -#endif - - ListFirst(&ehci->urb_list, pthis); - while (pthis) - { - purb = (PURB) pthis; - ehci_isr_removing_urb(ehci, purb, door_bell_rings, cur_frame); - ListNext(&ehci->urb_list, pthis, pnext); - pthis = pnext; - } - - KeInsertQueueDpc(&ehci->pdev_ext->ehci_dpc, (PVOID) status, 0); - return TRUE; -} - -#ifndef INCLUDE_EHCI -VOID -ehci_unload(IN PDRIVER_OBJECT DriverObject) -{ - PDEVICE_OBJECT pdev; - PEHCI_DEVICE_EXTENSION pdev_ext; - PUSB_DEV_MANAGER dev_mgr; - LONG i; - - pdev = DriverObject->DeviceObject; - - if (pdev == NULL) - return; - - pdev_ext = pdev->DeviceExtension; - if (pdev_ext == NULL) - return; - - dev_mgr = &g_dev_mgr; - if (dev_mgr == NULL) - return; - // - // set the termination flag - // - dev_mgr->term_flag = TRUE; - // - // wake up the thread if it is - // - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - KeWaitForSingleObject(dev_mgr->pthread, Executive, KernelMode, TRUE, NULL); - ObDereferenceObject(dev_mgr->pthread); - dev_mgr->pthread = NULL; - - dev_mgr_release_hcd(dev_mgr); - return; -} - -NTSTATUS -generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - PDEVEXT_HEADER dev_ext; - - dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - - if (dev_ext && dev_ext->dispatch) - return dev_ext->dispatch(dev_obj, irp); - - irp->IoStatus.Information = 0; - - EXIT_DISPATCH(STATUS_UNSUCCESSFUL, irp); -} - -VOID -generic_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - PDEVEXT_HEADER dev_ext; - - KIRQL old_irql; - - IoAcquireCancelSpinLock(&old_irql); - if (irp != dev_obj->CurrentIrp || irp->Cancel) - { - IoReleaseCancelSpinLock(old_irql); - return; - } - else - { - IoSetCancelRoutine(irp, NULL); - IoReleaseCancelSpinLock(old_irql); - } - - dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - - if (dev_ext && dev_ext->start_io) - { - dev_ext->start_io(dev_obj, irp); - return; - } - - irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - - IoStartNextPacket(dev_obj, FALSE); - IoCompleteRequest(irp, IO_NO_INCREMENT); -} - -NTSTATUS -NTAPI -DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) -{ - NTSTATUS ntStatus = STATUS_SUCCESS; - BOOLEAN fRes; - -#if DBG - // should be done before any debug output is done. - // read our debug verbosity level from the registry - //NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path - // L"DebugLevel", // REG_DWORD ValueName - // &gDebugLevel ); // Value receiver - - // debug_level = DBGLVL_MAXIMUM; -#endif - - ehci_dbg_print_cond(DBGLVL_MINIMUM, DEBUG_UHCI, - ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer)); - - // Remember our driver object, for when we create our child PDO - usb_driver_obj = DriverObject; - - // - // Create dispatch points for create, close, unload - DriverObject->MajorFunction[IRP_MJ_CREATE] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = generic_dispatch_irp; - DriverObject->DriverUnload = ehci_unload; - - // User mode DeviceIoControl() calls will be routed here - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = generic_dispatch_irp; - - // User mode ReadFile()/WriteFile() calls will be routed here - DriverObject->MajorFunction[IRP_MJ_WRITE] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_READ] = generic_dispatch_irp; - - DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_SCSI] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = generic_dispatch_irp; - - DriverObject->DriverStartIo = generic_start_io; - // routines for handling system PNP and power management requests - //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp; - - // The Functional Device Object (FDO) will not be created for PNP devices until - // this routine is called upon device plug-in. - RtlZeroMemory(&g_dev_mgr, sizeof(USB_DEV_MANAGER)); - g_dev_mgr.usb_driver_obj = DriverObject; - - ehci_probe(DriverObject, RegistryPath, &g_dev_mgr); - - if (dev_mgr_strobe(&g_dev_mgr) == FALSE) - { - dev_mgr_release_hcd(&g_dev_mgr); - return STATUS_UNSUCCESSFUL; - } - - dev_mgr_start_hcd(&g_dev_mgr); - ehci_dbg_print_cond(DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus)); - return STATUS_SUCCESS; -} -#endif - -//note: the initialization will be in the following order -// dev_mgr_strobe -// ehci_start - -// to kill dev_mgr_thread: -// dev_mgr->term_flag = TRUE; -// KeSetEvent( &dev_mgr->wake_up_event ); -// this piece of code must run at passive-level -// -// diff --git a/reactos/drivers/usb/nt4compat/usbdrv/ehci.h b/reactos/drivers/usb/nt4compat/usbdrv/ehci.h deleted file mode 100644 index 4ea31e55eea..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/ehci.h +++ /dev/null @@ -1,808 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __EHCI_H__ -#define __EHCI_H__ - -#define EHCI_QH_SIZE sizeof( EHCI_QH ) -#define EHCI_ITD_SIZE sizeof( EHCI_ITD ) -#define EHCI_SITD_SIZE sizeof( EHCI_SITD ) -#define EHCI_FSTN_SIZE sizeof( EHCI_FSTN ) -#define EHCI_QTD_SIZE sizeof( EHCI_QTD ) - -#define INIT_LIST_FLAG_TYPE 0x0f -#define INIT_LIST_FLAG_ITD 0x00 -#define INIT_LIST_FLAG_QH 0x01 -#define INIT_LIST_FLAG_SITD 0x02 -#define INIT_LIST_FLAG_FSTN 0x03 -#define INIT_LIST_FLAG_QTD 0x04 - -#define EHCI_MAX_SIZE_TRANSFER 0x100000 // 1 MB per transfer -#define EHCI_MAX_ELEMS_POOL 1024 -#define EHCI_MAX_LISTS_POOL 0x08 -#define EHCI_MAX_QHS_LIST 256 // 4 pages -#define EHCI_MAX_ITDS_LIST ( PAGE_SIZE / EHCI_ITD_SIZE * 2 ) // 2 pages -#define EHCI_MAX_SITDS_LIST ( PAGE_SIZE / EHCI_SITD_SIZE )// 1 page -#define EHCI_MAX_FSTNS_LIST ( PAGE_SIZE / EHCI_FSTN_SIZE )// 1 page -#define EHCI_MAX_QTDS_LIST 256 // 4 pages - -#define EHCI_PTR_TERM 0x01 -#define EHCI_NAK_RL_COUNT 0x04 - -#define EHCI_QTD_MAX_TRANS_SIZE 20480 -#define PHYS_PART_TYPE_MASK 0x01f -#define PHYS_PART_ADDR_MASK ( ~PHYS_PART_TYPE_MASK ) - -typedef struct _EHCI_ELEM_LINKS -{ - LIST_ENTRY elem_link; // link for one urb request - LIST_ENTRY sched_link; // to shadow link of schedule - struct _EHCI_ELEM_POOL* pool_link; - struct _EHCI_ELEM_LIST* list_link; // opaque to client, which list this td belongs to - PVOID phys_part; // point to EHCI_XXX, the lower 5 bits is used to indicate the type of the element - PURB purb; - -} EHCI_ELEM_LINKS, *PEHCI_ELEM_LINKS; - -typedef struct _INIT_ELEM_LIST_CONTEXT -{ - PADAPTER_OBJECT padapter; - struct _EHCI_ELEM_POOL *pool; - -} INIT_ELEM_LIST_CONTEXT, *PINIT_ELEM_LIST_CONTEXT; - -typedef VOID ( *PDESTROY_ELEM_LIST )( struct _EHCI_ELEM_LIST* plist ); -typedef PLIST_ENTRY ( *PGET_LIST_HEAD )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PGET_TOTAL_COUNT )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PGET_ELEM_SIZE )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PGET_LINK_OFFSET )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PADD_REF )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PRELEASE_REF )( struct _EHCI_ELEM_LIST* plist ); -typedef LONG ( *PGET_REF )( struct _EHCI_ELEM_LIST* plist ); - -typedef struct _EHCI_ELEM_LIST -{ - PDESTROY_ELEM_LIST destroy_list; - PGET_LIST_HEAD get_list_head; - PGET_TOTAL_COUNT get_total_count; - PGET_ELEM_SIZE get_elem_size; - PGET_LINK_OFFSET get_link_offset; - PADD_REF add_ref; - PRELEASE_REF release_ref; - PGET_REF get_ref; - - // private area - LONG flags; // contails element's type info - LONG total_count; - LONG elem_size; - LIST_HEAD free_list; // chains of all the elements - struct _EHCI_ELEM_POOL *parent_pool; - LONG reference; - - // used to represent the physical memory - PPHYSICAL_ADDRESS phys_addrs; // array of non-contigous memory - PBYTE *phys_bufs; - PEHCI_ELEM_LINKS elem_head_buf; - PADAPTER_OBJECT padapter; - -} EHCI_ELEM_LIST, *PEHCI_ELEM_LIST; - -BOOLEAN elem_pool_init_pool( struct _EHCI_ELEM_POOL* pool, LONG flags, PVOID context); -VOID elem_pool_destroy_pool ( struct _EHCI_ELEM_POOL* pool ); -PEHCI_ELEM_LINKS elem_pool_alloc_elem ( struct _EHCI_ELEM_POOL* pool ); -VOID elem_pool_free_elem ( PEHCI_ELEM_LINKS elem_link ); -LONG elem_pool_get_total_count ( struct _EHCI_ELEM_POOL* pool ); -BOOLEAN elem_pool_is_empty ( struct _EHCI_ELEM_POOL* pool ); -LONG elem_pool_get_free_count ( struct _EHCI_ELEM_POOL* pool ); -LONG elem_pool_get_link_offset ( struct _EHCI_ELEM_POOL* pool ); -PEHCI_ELEM_LINKS elem_pool_alloc_elems ( struct _EHCI_ELEM_POOL* pool, LONG count ); -BOOLEAN elem_pool_free_elems( PEHCI_ELEM_LINKS elem_chains ); -LONG elem_pool_get_type( struct _EHCI_ELEM_POOL* pool ); - -// the following are private functions -BOOLEAN elem_pool_expand_pool( struct _EHCI_ELEM_POOL* pool, LONG elem_count ); -BOOLEAN elem_pool_collect_garbage( struct _EHCI_ELEM_POOL* pool ); - -// lock operations -BOOLEAN elem_pool_lock( struct _EHCI_ELEM_POOL* pool, BOOLEAN at_dpc ); -BOOLEAN elem_pool_unlock( struct _EHCI_ELEM_POOL* pool, BOOLEAN at_dpc ); - -// helper -LONG get_elem_phys_part_size( ULONG type ); - -typedef struct _EHCI_ELEM_POOL -{ - LONG flags; - LONG free_count; // free count of all the lists currently allocated - LONG link_offset; // a cache for elem_list->get_link_offset - LONG list_count; // lists currently allocated - PEHCI_ELEM_LIST elem_lists[ EHCI_MAX_LISTS_POOL ]; - -} EHCI_ELEM_POOL, *PEHCI_ELEM_POOL; - -/*-------------------------------------------------------------------------*/ - -#define QTD_NEXT(dma) cpu_to_le32((u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ -#define QTD_ANY_ERROR ( QTD_STS_HALT | QTD_STS_DBE | QTD_STS_XACT | QTD_STS_MMF | QTD_STS_BABBLE ) - -#define QTD_PID_SETUP 0x02 -#define QTD_PID_IN 0x01 -#define QTD_PID_OUT 0x00 - -#pragma pack( push, usb_align, 1 ) - -typedef struct _EHCI_QTD_CONTENT -{ - // DWORD 0 - ULONG terminal : 1; - ULONG reserved : 4; - ULONG next_qtd : 27; - - // DWORD 1 - ULONG alt_terminal : 1; - ULONG reserved1 : 4; - ULONG alt_qtd : 27; - - // DWORD 2 - ULONG status : 8; - ULONG pid : 2; - ULONG err_count : 2; - ULONG cur_page : 3; - ULONG ioc : 1; - ULONG bytes_to_transfer : 15; - ULONG data_toggle : 1; - - // DWORD 3 - ULONG cur_offset : 12; - ULONG page0 : 20; - - // DWORD 4- - ULONG pages[ 4 ]; - -} EHCI_QTD_CONTENT, *PEHCI_QTD_CONTENT; - -typedef struct _EHCI_QTD -{ - /* first part defined by EHCI spec */ - ULONG hw_next; /* see EHCI 3.5.1 */ - ULONG hw_alt_next; /* see EHCI 3.5.2 */ - ULONG hw_token; /* see EHCI 3.5.3 */ - ULONG hw_buf [5]; /* see EHCI 3.5.4 */ - - /* the rest is HCD-private */ - PEHCI_ELEM_LINKS elem_head_link; - ULONG phys_addr; /* qtd address */ - USHORT bytes_to_transfer; /* the bytes_to_transfer in hw_token will drop to zero when completed*/ - USHORT reserved2; - ULONG reserved[ 5 ]; - -} EHCI_QTD, *PEHCI_QTD; //__attribute__ ((aligned (32))); - -#define QTD_MASK cpu_to_le32 (~0x1f) /* mask NakCnt+T in qh->hw_alt_next */ - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) - -/* values for that type tag */ -#define Q_TYPE_ITD (0 << 1) -#define Q_TYPE_QH (1 << 1) -#define Q_TYPE_SITD (2 << 1) -#define Q_TYPE_FSTN (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -#define QH_HEAD 0x00008000 -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ -#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ -#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ -#define NO_FRAME ((unsigned short)~0) /* pick new start */ - -typedef struct _EHCI_QH_CONTENT -{ - // DWORD 0 - ULONG terminal : 1; - ULONG ptr_type : 2; - ULONG reserved : 2; - ULONG next_link : 27; - - // DWORD 1 - ULONG dev_addr : 7; - ULONG inactive : 1; - ULONG endp_addr : 4; - ULONG endp_spd : 2; - ULONG data_toggle : 1; - ULONG is_async_head : 1; - ULONG max_packet_size : 11; - ULONG is_ctrl_endp : 1; - ULONG reload_counter : 4; - - // DWORD 2 - ULONG s_mask : 8; - ULONG c_mask : 8; - ULONG hub_addr : 7; - ULONG port_idx : 7; - ULONG mult : 2; - - // DWORD 3 - ULONG cur_qtd_ptr; - - // overlay - EHCI_QTD_CONTENT cur_qtd; - -} EHCI_QH_CONTENT, *PEHCI_QH_CONTENT; - -typedef struct _EHCI_QH -{ - /* first part defined by EHCI spec */ - ULONG hw_next; /* see EHCI 3.6.1 */ - ULONG hw_info1; /* see EHCI 3.6.2 */ - ULONG hw_info2; /* see EHCI 3.6.2 */ - ULONG hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - ULONG hw_qtd_next; - ULONG hw_alt_next; - ULONG hw_token; - ULONG hw_buf [5]; - - /* the rest is HCD-private */ - PEHCI_ELEM_LINKS elem_head_link; - ULONG phys_addr; /* address of qh */ - ULONG reserved[ 2 ]; - -} EHCI_QH, *PEHCI_QH; // __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.3 - * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" - * - * Schedule records for high speed iso xfers - */ - -#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ -#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ -#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ -#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ -#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ - -#define ITD_STS_ACTIVE 8 -#define ITD_STS_BUFERR 4 -#define ITD_STS_BABBLE 2 -#define ITD_STS_XACTERR 1 - -#define ITD_ANY_ERROR ( ITD_STS_BUFERR | ITD_STS_BABBLE | ITD_STS_XACTERR ) - -typedef struct _EHCI_ITD_STATUS_SLOT -{ - ULONG offset : 12; - ULONG page_sel : 3; - ULONG ioc : 1; - ULONG trans_length : 12; - ULONG status : 4; - -} EHCI_ITD_STATUS_SLOT, *PEHCI_ITD_STATUS_SLOT; - -typedef struct _EHCI_ITD_CONTENT -{ - // DWORD 0; - ULONG terminal : 1; - ULONG ptr_type : 2; - ULONG reserved : 2; - ULONG next_link : 27; - // DWORD 1-8; - EHCI_ITD_STATUS_SLOT status_slot[ 8 ]; - // DWORD 9; - ULONG dev_addr : 7; - ULONG reserved1 : 1; - ULONG endp_num : 4; - ULONG page0 : 20; - // DWORD 10; - ULONG max_packet_size : 11; - ULONG io_dir : 1; - ULONG page1 : 20; - // DWORD 11; - ULONG mult : 2; - ULONG reserved2 : 10; - ULONG page2 : 20; - // DWORD 12-; - ULONG pages[ 4 ]; - -} EHCI_ITD_CONTENT, *PEHCI_ITD_CONTENT; - -typedef struct _EHCI_ITD { - - /* first part defined by EHCI spec */ - ULONG hw_next; /* see EHCI 3.3.1 */ - ULONG hw_transaction [8]; /* see EHCI 3.3.2 */ - ULONG hw_bufp [7]; /* see EHCI 3.3.3 */ - - /* the rest is EHCI-private */ - PEHCI_ELEM_LINKS elem_head_link; - ULONG phys_addr; /* for this itd */ - ULONG buf_phys_addr; /* buffer address */ - ULONG reserved[ 5 ]; - -} EHCI_ITD, *PEHCI_ITD; // __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.4 - * siTD, aka split-transaction isochronous Transfer Descriptor - * ... describe low/full speed iso xfers through TT in hubs - * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) - */ -#define SITD_STS_ACTIVE 0x80 -#define SITD_STS_ERR 0x40 // error from device -#define SITD_STS_DBE 0x20 // data buffer error -#define SITD_STS_BABBLE 0x10 // data more than expected -#define SITD_STS_XACTERR 0x08 // general error on hc -#define SITD_STS_MISSFRM 0x04 // missd micro frames -#define SITD_STS_SC 0x02 // state is whether start-split( 0 ) or complete-split( 1 ) -#define SITD_STS_RESERVED 0x01 -#define SITD_ANY_ERROR ( SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE | SITD_STS_XACTERR | SITD_STS_MISSFRM ) - -typedef struct _EHCI_SITD_CONTENT -{ - // DWORD 0; - ULONG terminal : 1; - ULONG ptr_type : 2; - ULONG reserved : 2; - ULONG next_link : 27; - // DWORD 1; - ULONG dev_addr : 7; - ULONG reserved1 : 1; - ULONG endp_num : 4; - ULONG reserved2 : 4; - ULONG hub_addr : 7; - ULONG reserved3 : 1; - ULONG port_idx : 7; - ULONG io_dir : 1; - // DWORD 2; - ULONG s_mask : 8; - ULONG c_mask : 8; - ULONG reserved4 : 16; - // DWORD 3: - ULONG status : 8; - ULONG c_prog_mask : 8; - ULONG bytes_to_transfer : 10; - ULONG reserved5 : 4; - ULONG page_sel : 1; - ULONG ioc : 1; - // DWORD 4; - ULONG cur_offset : 12; - ULONG page0 : 20; - // DWORD 5; - ULONG trans_count : 3; - ULONG trans_pos : 2; - ULONG reserved6 : 7; - ULONG page1 : 20; - // DWORD 6; - ULONG back_terminal : 1; - ULONG reserved7 : 4; - ULONG back_ptr : 27; - -} EHCI_SITD_CONTENT, *PEHCI_SITD_CONTENT; - -typedef struct _EHCI_SITD -{ - /* first part defined by EHCI spec */ - ULONG hw_next; - /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - - ULONG hw_fullspeed_ep; /* see EHCI table 3-9 */ - ULONG hw_uframe; /* see EHCI table 3-10 */ - ULONG hw_tx_results1; /* see EHCI table 3-11 */ - ULONG hw_tx_results2; /* see EHCI table 3-12 */ - ULONG hw_tx_results3; /* see EHCI table 3-12 */ - ULONG hw_backpointer; /* see EHCI table 3-13 */ - - /* the rest is HCD-private */ - PEHCI_ELEM_LINKS elem_head_link; - ULONG phys_addr; - ULONG buf_phys_addr; /* buffer address */ - - USHORT usecs; /* start bandwidth */ - USHORT c_usecs; /* completion bandwidth */ - ULONG reserved[ 5 ]; - -} EHCI_SITD, *PEHCI_SITD; // __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.96 Section 3.7 - * Periodic Frame Span Traversal Node (FSTN) - * - * Manages split interrupt transactions (using TT) that span frame boundaries - * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN - * makes the HC jump (back) to a QH to scan for fs/ls QH completions until - * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. - */ -typedef struct _EHCI_FSTN -{ - ULONG hw_next; /* any periodic q entry */ - ULONG hw_prev; /* qh or EHCI_LIST_END */ - - /* the rest is HCD-private */ - PEHCI_ELEM_LINKS elem_head_link; - ULONG phys_addr; - ULONG reserved[ 4 ]; - -} EHCI_FSTN, *PEHCI_FSTN; // __attribute__ ((aligned (32))); - - -/* NOTE: urb->transfer_flags expected to not use this bit !!! */ -#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */ - -/*-------------------------------------------------------------------------*/ - -/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ - -/* Section 2.2 Host Controller Capability Registers */ -#define HCS_DEBUG_PORT(p) (((p)>>20)&0xf) /* bits 23:20, debug port? */ -#define HCS_INDICATOR(p) ((p)&(1 << 16)) /* true: has port indicators */ -#define HCS_N_CC(p) (((p)>>12)&0xf) /* bits 15:12, #companion HCs */ -#define HCS_N_PCC(p) (((p)>>8)&0xf) /* bits 11:8, ports per CC */ -#define HCS_PORTROUTED(p) ((p)&(1 << 7)) /* true: port routing */ -#define HCS_PPC(p) ((p)&(1 << 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ - -#define HCC_EXT_CAPS(p) (((p)>>8)&0xff) /* for pci extended caps */ -#define HCC_ISOC_CACHE(p) ((p)&(1 << 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)>>4)&0x7) /* bits 6:4, uframes cached */ -#define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ -#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ -#define HCC_64BIT_ADDR(p) ((p)&(1)) /* true: can use 64-bit addr */ - -/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ -#define CMD_PARK (1<<11) /* enable "park" on async qh */ -#define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ -#define CMD_LRESET (1<<7) /* partial reset (no ports, etc) */ -#define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ -#define CMD_ASE (1<<5) /* async schedule enable */ -#define CMD_PSE (1<<4) /* periodic schedule enable */ -/* 3:2 is periodic frame list size */ -#define CMD_RESET (1<<1) /* reset HC not bus */ -#define CMD_RUN (1<<0) /* start/stop HC */ - -/* these STS_* flags are also intr_enable bits (USBINTR) */ -#define STS_IAA (1<<5) /* Interrupted on async advance */ -#define STS_FATAL (1<<4) /* such as some PCI access errors */ -#define STS_FLR (1<<3) /* frame list rolled over */ -#define STS_PCD (1<<2) /* port change detect */ -#define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ -#define STS_INT (1<<0) /* "normal" completion (short, ...) */ - -#define STS_ASS (1<<15) /* Async Schedule Status */ -#define STS_PSS (1<<14) /* Periodic Schedule Status */ -#define STS_RECL (1<<13) /* Reclamation */ -#define STS_HALT (1<<12) /* Not running (any reason) */ - -/* 31:23 reserved */ -#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ -#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ -#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ -/* 19:16 for port testing */ -/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */ -#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ -#define PORT_POWER (1<<12) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ -/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ -/* 9 reserved */ -#define PORT_PR (1<<8) /* reset port */ -#define PORT_SUSP (1<<7) /* suspend port */ -#define PORT_RESUME (1<<6) /* resume it */ -#define PORT_OCC (1<<5) /* over current change */ -#define PORT_OC (1<<4) /* over current active */ -#define PORT_PEC (1<<3) /* port enable change */ -#define PORT_PE (1<<2) /* port enable */ -#define PORT_CSC (1<<1) /* connect status change */ -#define PORT_CCS (1<<0) /* device connected */ - -#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ - -typedef struct _EHCI_HCS_CONTENT -{ - ULONG port_count : 4; - ULONG port_power_control : 1; - ULONG reserved : 2; - ULONG port_rout_rules : 1; - ULONG port_per_chc : 4; - ULONG chc_count : 4; - ULONG port_indicator : 1; - ULONG reserved2 : 3; - ULONG dbg_port_num : 4; - ULONG reserved3 : 8; - -} EHCI_HCS_CONTENT, *PEHCI_HCS_CONTENT; - -typedef struct _EHCI_HCC_CONTENT -{ - ULONG cur_addr_bits : 1; /* 0: 32 bit addressing 1: 64 bit addressing */ - ULONG var_frame_list : 1; /* 0: 1024 frames, 1: support other number of frames */ - ULONG park_mode : 1; - ULONG reserved : 1; - ULONG iso_sched_threshold : 4; - ULONG eecp_capable : 8; - ULONG reserved2 : 16; - -} EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT; - -typedef struct _EHCI_CAPS { - UCHAR length; /* CAPLENGTH - size of this struct */ - UCHAR reserved; /* offset 0x1 */ - USHORT hci_version; /* HCIVERSION - offset 0x2 */ - ULONG hcs_params; /* HCSPARAMS - offset 0x4 */ - - ULONG hcc_params; /* HCCPARAMS - offset 0x8 */ - UCHAR portroute [8]; /* nibbles for routing - offset 0xC */ - -} EHCI_CAPS, *PEHCI_CAPS; - -/* Section 2.3 Host Controller Operational Registers */ - -#define EHCI_USBCMD 0x00 -#define EHCI_USBSTS 0x04 -#define EHCI_USBINTR 0x08 -#define EHCI_FRINDEX 0x0c -#define EHCI_CTRLDSSEGMENT 0x10 -#define EHCI_PERIODICLISTBASE 0x14 -#define EHCI_ASYNCLISTBASE 0x18 -#define EHCI_CONFIGFLAG 0x40 -#define EHCI_PORTSC 0x44 - -#define EHCI_USBINTR_INTE 0x01 -#define EHCI_USBINTR_ERR 0x02 -#define EHCI_USBINTR_PC 0x04 -#define EHCI_USBINTR_FLROVR 0x08 -#define EHCI_USBINTR_HSERR 0x10 -#define EHCI_USBINTR_ASYNC 0x20 - -typedef struct _EHCI_USBCMD_CONTENT -{ - ULONG run_stop : 1; - ULONG hcreset : 1; - ULONG frame_list_size : 2; - ULONG periodic_enable : 1; - ULONG async_enable : 1; - ULONG door_bell : 1; - ULONG light_reset : 1; - ULONG async_park_count : 2; - ULONG reserved : 1; - ULONG async_park_enable : 1; - ULONG reserved1 : 4; - ULONG int_threshold : 8; - ULONG reserved2 : 8; - -} EHCI_USBCMD_CONTENT, *PEHCI_USBCMD_CONTENT; - -typedef struct _EHCI_USBSTS_CONTENT -{ - ULONG ioc : 1; - ULONG trasac_error : 1; - ULONG port_change : 1; - ULONG fl_rollover : 1; - ULONG host_system_error : 1; - ULONG async_advance : 1; - ULONG reserved : 6; - ULONG hc_halted : 1; - ULONG reclaimation : 1; - ULONG periodic_status : 1; - ULONG async_status : 1; - ULONG reserved1 : 16; - -} EHCI_USBSTS_CONTENT, *PEHCI_USBSTS_CONTENT; - -typedef struct _EHCI_RHPORTSC_CONTENT -{ - ULONG cur_connect : 1; - ULONG cur_connect_change : 1; - ULONG port_enable : 1; - ULONG port_enable_change : 1; - ULONG over_current : 1; - ULONG over_current_change : 1; - ULONG force_port_resume : 1; - ULONG suspend : 1; - ULONG port_reset : 1; - ULONG reserved : 1; - ULONG line_status : 2; - ULONG port_power : 1; - ULONG port_owner : 1; - ULONG port_indicator : 2; - ULONG port_test : 4; - ULONG we_connect : 1; - ULONG we_disconnect : 1; - ULONG we_over_current : 1; - ULONG reserved1 : 9; - -} EHCI_RHPORTSC_CONTENT, *PEHCI_RHPORTSC_CONTENT; - -typedef struct _EHCI_REGS { - - ULONG command; - ULONG status; - ULONG intr_enable; - ULONG frame_index; /* current microframe number */ - ULONG segment; /* address bits 63:32 if needed */ - ULONG frame_list; /* points to periodic list */ - ULONG async_next; /* address of next async queue head */ - ULONG reserved [9]; - ULONG configured_flag; - ULONG port_status [0]; /* up to N_PORTS */ - -} EHCI_REGS, *PEHCI_REGS; - -#pragma pack( pop, usb_align ) - -/* ehci_hcd->lock guards shared data against other CPUs: - * ehci_hcd: async, reclaim, periodic (and shadow), ... - * hcd_dev: ep[] - * ehci_qh: qh_next, qtd_list - * ehci_qtd: qtd_list - * - * Also, hold this lock when talking to HC registers or - * when updating hw_* fields in shared qh/qtd/... structures. - */ - -#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ - -#define EHCI_DEVICE_NAME "\\Device\\EHCI" - -#define EHCI_DOS_DEVICE_NAME "\\DosDevices\\EHCI" - -#define EHCI_ITD_POOL_IDX INIT_LIST_FLAG_ITD -#define EHCI_QH_POOL_IDX INIT_LIST_FLAG_QH -#define EHCI_SITD_POOL_IDX INIT_LIST_FLAG_SITD -#define EHCI_FSTN_POOL_IDX INIT_LIST_FLAG_FSTN -#define EHCI_QTD_POOL_IDX INIT_LIST_FLAG_QTD - -#define EHCI_DEFAULT_FRAMES UHCI_MAX_FRAMES -#define EHCI_MAX_SYNC_BUS_TIME 50000 // stands for 100000 ns, only to get wrapped within one word - -#define EHCI_SCHED_INT8_INDEX 0 -#define EHCI_SCHED_INT4_INDEX 1 -#define EHCI_SCHED_INT2_INDEX 2 -#define EHCI_SCHED_FSTN_INDEX 3 -#define EHCI_SCHED_INT1_INDEX 4 - -#define qtd_pool ( &ehci->elem_pools[ EHCI_QTD_POOL_IDX ] ) -#define qh_pool ( &ehci->elem_pools[ EHCI_QH_POOL_IDX ] ) -#define fstn_pool ( &ehci->elem_pools[ EHCI_FSTN_POOL_IDX ] ) -#define itd_pool ( &ehci->elem_pools[ EHCI_ITD_POOL_IDX ] ) -#define sitd_pool ( &ehci->elem_pools[ EHCI_SITD_POOL_IDX ] ) - - -typedef struct _EHCI_DEV -{ - HCD hcd_interf; - - EHCI_CAPS ehci_caps; - - PHYSICAL_ADDRESS ehci_reg_base; // io space - BOOLEAN port_mapped; - PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base - - ULONG frame_count; - PHYSICAL_ADDRESS frame_list_phys_addr; - - KSPIN_LOCK frame_list_lock; // run at DIRQL - PULONG frame_list; // periodic schedule - - PFRAME_LIST_CPU_ENTRY frame_list_cpu; // periodic schedule shadow - - LIST_HEAD urb_list; // active urb-list - - LIST_HEAD async_list_cpu; - LIST_HEAD periodic_list_cpu[ 8 ]; // each slot for one periodic - PEHCI_QH skel_async_qh; - - - // - // pools for device specific data - // - EHCI_ELEM_POOL elem_pools[ 5 ]; - - // - //for iso and int bandwidth claim, bandwidth schedule - // - KSPIN_LOCK pending_endp_list_lock; //lock to access the following two - LIST_HEAD pending_endp_list; - UHCI_PENDING_ENDP_POOL pending_endp_pool; - PUSHORT frame_bw; //unit uFrame - USHORT min_bw; //the bottle-neck of the bandwidths across frame-list - - KTIMER reset_timer; //used to reset the host controller - struct _EHCI_DEVICE_EXTENSION *pdev_ext; - PUSB_DEV root_hub; //root hub - -} EHCI_DEV, *PEHCI_DEV; - -typedef UHCI_PORT EHCI_MEMORY; - -typedef struct _EHCI_DEVICE_EXTENSION -{ - //struct _USB_DEV_MANAGER *pdev_mgr; - DEVEXT_HEADER dev_ext_hdr; - PDEVICE_OBJECT pdev_obj; - PDRIVER_OBJECT pdrvr_obj; - PEHCI_DEV ehci; - - //device resources - PADAPTER_OBJECT padapter; - ULONG map_regs; - PCM_RESOURCE_LIST res_list; - ULONG pci_addr; // bus number | slot number | funciton number - UHCI_INTERRUPT res_interrupt; - union - { - UHCI_PORT res_port; - EHCI_MEMORY res_memory; - }; - - PKINTERRUPT ehci_int; - KDPC ehci_dpc; - -} EHCI_DEVICE_EXTENSION, *PEHCI_DEVICE_EXTENSION; - -/*-------------------------------------------------------------------------*/ - -#endif /* __EHCI_H__ */ diff --git a/reactos/drivers/usb/nt4compat/usbdrv/etd.c b/reactos/drivers/usb/nt4compat/usbdrv/etd.c deleted file mode 100644 index e3a4d32089f..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/etd.c +++ /dev/null @@ -1,643 +0,0 @@ -/** - * etd.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include "ehci.h" - -#define init_elem( ptr, type, ehci_elem_type ) \ -{\ - PEHCI_ELEM_LINKS tmp;\ - ptr = ( type* )( plist->phys_bufs[ i ] + sizeof( type ) * j );\ - ptr->hw_next = ehci_elem_type << 1;\ - if( ehci_elem_type == INIT_LIST_FLAG_QTD )\ - ptr->hw_next = 0;\ - tmp = ptr->elem_head_link = &plist->elem_head_buf[ i * elms_per_page + j ];\ - InitializeListHead( &tmp->elem_link );\ - InitializeListHead( &tmp->sched_link );\ - InsertTailList( &plist->free_list, &tmp->elem_link );\ - tmp->list_link = plist;\ - tmp->pool_link = pinit_ctx->pool;\ - tmp->phys_part = ( PVOID )( ( ULONG )ptr | ( ehci_elem_type << 1 ) );\ - if( ehci_elem_type != INIT_LIST_FLAG_QTD )\ - ptr->phys_addr = ( plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ) | ( ehci_elem_type << 1 );\ - else \ - ptr->phys_addr = plist->phys_addrs[ i ].LowPart + sizeof( type ) * j ;\ -} - -// get the actual max list count of the pool, two limit, max_elem_pool and max_lists_pool -#define get_max_lists_count( pOOL, max_liSTS ) \ -{\ - LONG ii1=0;\ - switch( elem_pool_get_type( pOOL ) )\ - {\ - case INIT_LIST_FLAG_QTD:\ - ii1 = EHCI_MAX_QTDS_LIST;\ - break;\ - case INIT_LIST_FLAG_FSTN:\ - ii1 = EHCI_MAX_QHS_LIST;\ - break;\ - case INIT_LIST_FLAG_SITD:\ - ii1 = EHCI_MAX_ITDS_LIST;\ - break;\ - case INIT_LIST_FLAG_QH: \ - ii1 = EHCI_MAX_SITDS_LIST;\ - break;\ - case INIT_LIST_FLAG_ITD: \ - ii1 = EHCI_MAX_FSTNS_LIST;\ - break;\ - }\ - max_liSTS = ( EHCI_MAX_ELEMS_POOL / ii1 ) > EHCI_MAX_LISTS_POOL ? EHCI_MAX_LISTS_POOL : ( EHCI_MAX_ELEMS_POOL / ii1 );\ -} - -VOID elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist); - -PLIST_ENTRY elem_list_get_list_head(PEHCI_ELEM_LIST plist); - -LONG elem_list_get_total_count(PEHCI_ELEM_LIST plist); - -LONG elem_list_get_elem_size(PEHCI_ELEM_LIST plist); - -LONG elem_list_get_link_offset(PEHCI_ELEM_LIST plist); - -LONG elem_list_add_ref(PEHCI_ELEM_LIST plist); - -LONG elem_list_release_ref(PEHCI_ELEM_LIST plist); - -LONG elem_list_get_ref(PEHCI_ELEM_LIST plist); - -BOOLEAN -elem_pool_lock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc) -{ - UNREFERENCED_PARAMETER(pool); - UNREFERENCED_PARAMETER(at_dpc); - - return TRUE; -} - -BOOLEAN -elem_pool_unlock(PEHCI_ELEM_POOL pool, BOOLEAN at_dpc) -{ - UNREFERENCED_PARAMETER(pool); - UNREFERENCED_PARAMETER(at_dpc); - - return TRUE; -} - -LONG -get_elem_phys_part_size(ULONG type) -{ - // type is INIT_LIST_FLAG_XXX - LONG size; - - size = 0; - switch (type) - { - case INIT_LIST_FLAG_ITD: - size = 64; - break; - case INIT_LIST_FLAG_SITD: - size = 28; - break; - case INIT_LIST_FLAG_QTD: - size = 32; - break; - case INIT_LIST_FLAG_QH: - size = 48; - break; - case INIT_LIST_FLAG_FSTN: - size = 8; - break; - } - return size; -} - -BOOLEAN -elem_list_init_elem_list(PEHCI_ELEM_LIST plist, LONG init_flags, PVOID context, LONG count) -{ - LONG pages, i, j, elms_per_page; - PEHCI_QH pqh; - PEHCI_ITD pitd; - PEHCI_SITD psitd; - PEHCI_QTD pqtd; - PEHCI_FSTN pfstn; - PINIT_ELEM_LIST_CONTEXT pinit_ctx; - - UNREFERENCED_PARAMETER(count); - - if (plist == NULL || context == NULL) - return FALSE; - - RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST)); - - pinit_ctx = context; - - plist->destroy_list = elem_list_destroy_elem_list; - plist->get_list_head = elem_list_get_list_head; - plist->get_total_count = elem_list_get_total_count; - plist->get_elem_size = elem_list_get_elem_size; - plist->get_link_offset = elem_list_get_link_offset; - plist->add_ref = elem_list_add_ref; - plist->release_ref = elem_list_release_ref; - plist->get_ref = elem_list_get_ref; - - InitializeListHead(&plist->free_list); - - switch (init_flags & 0x0f) - { - case INIT_LIST_FLAG_ITD: - plist->total_count = EHCI_MAX_ITDS_LIST; - plist->elem_size = sizeof(EHCI_ITD); - break; - case INIT_LIST_FLAG_QH: - plist->total_count = EHCI_MAX_QHS_LIST; - plist->elem_size = sizeof(EHCI_QH); - break; - case INIT_LIST_FLAG_SITD: - plist->total_count = EHCI_MAX_SITDS_LIST; - plist->elem_size = sizeof(EHCI_SITD); - break; - case INIT_LIST_FLAG_FSTN: - plist->total_count = EHCI_MAX_FSTNS_LIST; - plist->elem_size = sizeof(EHCI_FSTN); - break; - case INIT_LIST_FLAG_QTD: - plist->total_count = EHCI_MAX_QTDS_LIST; - plist->elem_size = sizeof(EHCI_QTD); - break; - default: - goto ERROR_OUT; - } - if (plist->elem_size & 0x1f) - { - plist->total_count = 0; - goto ERROR_OUT; - } - - plist->flags = init_flags; - plist->parent_pool = pinit_ctx->pool; - plist->padapter = pinit_ctx->padapter; - pages = ((plist->elem_size * plist->total_count) + (PAGE_SIZE - 1)) / PAGE_SIZE; - elms_per_page = PAGE_SIZE / plist->elem_size; - - plist->phys_addrs = usb_alloc_mem(NonPagedPool, - (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages + - sizeof(EHCI_ELEM_LINKS) * plist->total_count); - - if (plist->phys_addrs == NULL) - { - plist->total_count = 0; - goto ERROR_OUT; - } - - plist->phys_bufs = (PBYTE *) & plist->phys_addrs[pages]; - plist->elem_head_buf = (PEHCI_ELEM_LINKS) & plist->phys_bufs[pages]; - RtlZeroMemory(plist->phys_addrs, - (sizeof(PHYSICAL_ADDRESS) + sizeof(PBYTE)) * pages + - sizeof(EHCI_ELEM_LINKS) * plist->total_count); - - for(i = 0; i < pages; i++) - { - plist->phys_bufs[i] = HalAllocateCommonBuffer(plist->padapter, - PAGE_SIZE, &plist->phys_addrs[i], FALSE); - - if (plist->phys_bufs[i] == NULL) - { - // failed, roll back - for(j = i - 1; j >= 0; j--) - HalFreeCommonBuffer(plist->padapter, - PAGE_SIZE, plist->phys_addrs[j], plist->phys_bufs[j], FALSE); - goto ERROR_OUT; - } - RtlZeroMemory(plist->phys_bufs[i], PAGE_SIZE); - for(j = 0; j < elms_per_page; j++) - { - switch (init_flags & 0xf) - { - case INIT_LIST_FLAG_QH: - { - init_elem(pqh, EHCI_QH, INIT_LIST_FLAG_QH); - break; - } - case INIT_LIST_FLAG_ITD: - { - init_elem(pitd, EHCI_ITD, INIT_LIST_FLAG_ITD); - break; - } - case INIT_LIST_FLAG_QTD: - { - init_elem(pqtd, EHCI_QTD, INIT_LIST_FLAG_QTD); - break; - } - case INIT_LIST_FLAG_SITD: - { - init_elem(psitd, EHCI_SITD, INIT_LIST_FLAG_SITD); - break; - } - case INIT_LIST_FLAG_FSTN: - { - init_elem(pfstn, EHCI_FSTN, INIT_LIST_FLAG_FSTN); - break; - } - default: - TRAP(); - } - } - } - return TRUE; - -ERROR_OUT: - if (plist->phys_addrs != NULL) - usb_free_mem(plist->phys_addrs); - - RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST)); - return FALSE; -} - -VOID -elem_list_destroy_elem_list(PEHCI_ELEM_LIST plist) -{ - LONG i, pages; - - if (plist == NULL) - return; - - pages = (plist->total_count * plist->elem_size + PAGE_SIZE - 1) / PAGE_SIZE; - for(i = 0; i < pages; i++) - HalFreeCommonBuffer(plist->padapter, PAGE_SIZE, plist->phys_addrs[i], plist->phys_bufs[i], FALSE); - - usb_free_mem(plist->phys_addrs); - RtlZeroMemory(plist, sizeof(EHCI_ELEM_LIST)); -} - -PLIST_ENTRY -elem_list_get_list_head(PEHCI_ELEM_LIST plist) -{ - if (plist == NULL) - return NULL; - return &plist->free_list; -} - -LONG -elem_list_get_total_count(PEHCI_ELEM_LIST plist) -{ - if (plist == NULL) - return 0; - return plist->total_count; -} - -LONG -elem_list_get_elem_size(PEHCI_ELEM_LIST plist) -{ - if (plist == NULL) - return 0; - return plist->elem_size; -} - -LONG -elem_list_get_link_offset(PEHCI_ELEM_LIST plist) -{ - if (plist == NULL) - return 0; - - return get_elem_phys_part_size(plist->flags & 0xf); -} - -LONG -elem_list_add_ref(PEHCI_ELEM_LIST plist) -{ - plist->reference++; - return plist->reference; -} - -LONG -elem_list_release_ref(PEHCI_ELEM_LIST plist) -{ - plist->reference--; - return plist->reference; -} - -LONG -elem_list_get_ref(PEHCI_ELEM_LIST plist) -{ - return plist->reference; -} - -// -// pool methods -// - -BOOLEAN -elem_pool_init_pool(PEHCI_ELEM_POOL pool, LONG flags, PVOID context) -{ - INIT_ELEM_LIST_CONTEXT init_ctx; - - if (pool == NULL || context == NULL) - return FALSE; - - RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL)); - - init_ctx.pool = pool; - init_ctx.padapter = context; - - pool->elem_lists[0] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST)); - - if (pool->elem_lists[0] == NULL) - return FALSE; - - if (elem_list_init_elem_list(pool->elem_lists[0], flags, &init_ctx, 0) == FALSE) - { - usb_free_mem(pool->elem_lists[0]); - return FALSE; - } - pool->link_offset = pool->elem_lists[0]->get_link_offset(pool->elem_lists[0]); - pool->free_count = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]); - pool->list_count = 1; - pool->flags = flags; - - return TRUE; -} - -LONG -elem_pool_get_link_offset(PEHCI_ELEM_POOL elem_pool) -{ - return elem_pool->link_offset; -} - -LONG -elem_pool_get_total_count(PEHCI_ELEM_POOL elem_pool) -{ - return elem_pool->elem_lists[0]->get_total_count(elem_pool->elem_lists[0]) * elem_pool->list_count; -} - -VOID -elem_pool_destroy_pool(PEHCI_ELEM_POOL pool) -{ - LONG i; - if (pool == NULL) - return; - for(i = pool->list_count - 1; i >= 0; i--) - { - pool->elem_lists[i]->destroy_list(pool->elem_lists[i]); - usb_free_mem(pool->elem_lists[i]); - pool->elem_lists[i] = NULL; - } - RtlZeroMemory(pool, sizeof(EHCI_ELEM_POOL)); - return; -} - -PEHCI_ELEM_LINKS -elem_pool_alloc_elem(PEHCI_ELEM_POOL pool) -{ - LONG i; - PEHCI_ELEM_LIST pel = NULL; - PLIST_HEAD lh; - PEHCI_ELEM_LINKS elnk; - - if (pool == NULL) - return NULL; - - for(i = 0; i < pool->list_count; i++) - { - pel = pool->elem_lists[i]; - if (pel->get_ref(pel) == pel->get_total_count(pel)) - continue; - break; - } - if (i == pool->list_count) - { - if (elem_pool_expand_pool(pool, pel->get_total_count(pel)) == FALSE) - return NULL; - pel = pool->elem_lists[i]; - } - - lh = pel->get_list_head(pel); - elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(lh); - InitializeListHead(&elnk->elem_link); - InitializeListHead(&elnk->sched_link); - - pel->add_ref(pel); - pool->free_count--; - - return elnk; -} - -VOID -elem_pool_free_elem(PEHCI_ELEM_LINKS elem_link) -{ - PLIST_HEAD lh; - LONG ref; - PEHCI_ELEM_POOL pool; - if (elem_link == NULL) - return; - pool = elem_link->pool_link; - lh = elem_link->list_link->get_list_head(elem_link->list_link); - if (lh == NULL) - return; - InsertHeadList(lh, &elem_link->elem_link); - ref = elem_link->list_link->release_ref(elem_link->list_link); - pool->free_count++; - if (ref == 0) - elem_pool_collect_garbage(pool); - return; -} - -BOOLEAN -elem_pool_is_empty(PEHCI_ELEM_POOL pool) -{ - PEHCI_ELEM_LIST pel; - - if (pool == NULL) - return TRUE; - pel = pool->elem_lists[0]; - return (BOOLEAN) (pool->list_count == 1 && pool->free_count == pel->get_total_count(pel)); -} - -LONG -elem_pool_get_free_count(PEHCI_ELEM_POOL pool) -{ - if (pool == NULL) - return 0; - return pool->free_count; -} - -PEHCI_ELEM_LINKS -elem_pool_alloc_elems(PEHCI_ELEM_POOL pool, LONG count) -{ - LIST_HEAD lh; - PLIST_ENTRY pthis; - LONG i, alloc_count, max_pool_lists; - PEHCI_ELEM_LIST pel; - PEHCI_ELEM_LINKS elnk; - // calculate to see if the count is affordable - - if (pool == NULL || count <= 0) - return NULL; - - get_max_lists_count(pool, max_pool_lists); - InitializeListHead(&lh); - pel = pool->elem_lists[0]; - if (count <= pool->free_count) - alloc_count = 0; - else - alloc_count = count - pool->free_count; - - if (alloc_count > pel->get_total_count(pel) * (max_pool_lists - pool->list_count)) - return NULL; - - for(i = 0; i < count; i++) - { - if ((elnk = elem_pool_alloc_elem(pool)) == NULL) - { - // undo what we have done - while (IsListEmpty(&lh) == FALSE) - { - pthis = RemoveHeadList(&lh); - elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link); - elem_pool_free_elem(elnk); - } - return NULL; - } - InsertTailList(&lh, &elnk->elem_link); - } - ListFirst(&lh, pthis); - elnk = struct_ptr(pthis, EHCI_ELEM_LINKS, elem_link); - RemoveEntryList(&lh); - return elnk; -} - -BOOLEAN -elem_pool_free_elems(PEHCI_ELEM_LINKS elem_chains) -{ - // note: no list head exists. - LIST_HEAD lh; - PEHCI_ELEM_LINKS elnk; - - InsertTailList(&elem_chains->elem_link, &lh); - while (IsListEmpty(&lh) == FALSE) - { - elnk = (PEHCI_ELEM_LINKS) RemoveHeadList(&lh); - elem_pool_free_elem(elnk); - } - return TRUE; -} - -LONG -elem_pool_get_type(PEHCI_ELEM_POOL pool) -{ - if (pool == NULL) - return -1; - return (pool->flags & 0xf); -} - -BOOLEAN -elem_pool_expand_pool(PEHCI_ELEM_POOL pool, LONG elem_count) -{ - LONG elem_cnt_list, list_count, i, j; - INIT_ELEM_LIST_CONTEXT init_ctx; - - if (pool == NULL || elem_count <= 0 || elem_count > EHCI_MAX_ELEMS_POOL) - return FALSE; - - init_ctx.pool = pool; - init_ctx.padapter = pool->elem_lists[0]->padapter; - - elem_cnt_list = pool->elem_lists[0]->get_total_count(pool->elem_lists[0]); - list_count = (elem_count + elem_cnt_list - 1) / elem_cnt_list; - get_max_lists_count(pool, i); - - if (list_count + pool->list_count > i) - return FALSE; - - for(i = pool->list_count; i < list_count + pool->list_count; i++) - { - pool->elem_lists[i] = usb_alloc_mem(NonPagedPool, sizeof(EHCI_ELEM_LIST)); - if (elem_list_init_elem_list(pool->elem_lists[i], pool->flags, &init_ctx, 0) == FALSE) - break; - } - - if (i < list_count + pool->list_count) - { - // undo all we have done - for(j = pool->list_count; j < pool->list_count + i; j++) - { - pool->elem_lists[j]->destroy_list(pool->elem_lists[j]); - usb_free_mem(pool->elem_lists[j]); - pool->elem_lists[j] = NULL; - } - return FALSE; - } - - // update pool - pool->free_count += elem_cnt_list * list_count; - pool->list_count += list_count; - return TRUE; -} - -BOOLEAN -elem_pool_collect_garbage(PEHCI_ELEM_POOL pool) -{ - LONG i, j, k, fl; - LONG free_elem_lists[EHCI_MAX_LISTS_POOL - 1]; - PEHCI_ELEM_LIST pel; - - if (pool == NULL) - return FALSE; - - for(i = 1, fl = 0; i < pool->list_count; i++) - { - if (pool->elem_lists[i]->get_ref(pool->elem_lists[i]) == 0) - { - free_elem_lists[fl++] = i; - } - } - for(j = fl - 1; j >= 0; j--) - { - pel = pool->elem_lists[free_elem_lists[j]]; - pel->destroy_list(pel); - usb_free_mem(pel); - - for(k = free_elem_lists[j] + 1; k < pool->list_count; k++) - { - // shrink the elem_lists - pool->elem_lists[k - 1] = pool->elem_lists[k]; - } - pool->elem_lists[k] = NULL; - pel = pool->elem_lists[0]; - pool->free_count -= pel->get_total_count(pel); - pool->list_count--; - } - return TRUE; -} - -BOOLEAN -elem_pool_can_transfer(PEHCI_ELEM_POOL pool, LONG td_count) -{ - LONG i; - if (pool == NULL || td_count <= 0) - return FALSE; - get_max_lists_count(pool, i); - if ((i - pool->list_count) - * pool->elem_lists[0]->get_total_count(pool->elem_lists[0]) + pool->free_count < td_count) - return FALSE; - return TRUE; -} - -//---------------------------------------------------------- diff --git a/reactos/drivers/usb/nt4compat/usbdrv/events.h b/reactos/drivers/usb/nt4compat/usbdrv/events.h deleted file mode 100644 index bbbe4f3144b..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/events.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __EVENTS_H -#define __EVENTS_H - -//event definitions - -#define MAX_EVENTS 128 -#define MAX_TIMER_SVCS 24 - -#define USB_EVENT_FLAG_ACTIVE 0x80000000 - -#define USB_EVENT_FLAG_QUE_TYPE 0x000000FF -#define USB_EVENT_FLAG_QUE_RESET 0x01 -#define USB_EVENT_FLAG_NOQUE 0x00 - -#define USB_EVENT_DEFAULT 0x00 //as a placeholder -#define USB_EVENT_INIT_DEV_MGR 0x01 -#define USB_EVENT_HUB_POLL 0x02 -#define USB_EVENT_WAIT_RESET_PORT 0x03 -#define USB_EVENT_CLEAR_TT_BUFFER 0x04 - -typedef VOID ( *PROCESS_QUEUE )( -PLIST_HEAD event_list, -struct _USB_EVENT_POOL *event_pool, -struct _USB_EVENT *usb_event, -struct _USB_EVENT *out_event -); - -typedef VOID ( *PROCESS_EVENT )( -PUSB_DEV dev, -ULONG event, -ULONG context, -ULONG param -); - -typedef struct _USB_EVENT -{ - LIST_ENTRY event_link; - ULONG flags; - ULONG event; - PUSB_DEV pdev; - ULONG context; - ULONG param; - struct _USB_EVENT *pnext; //vertical queue for serialized operation - PROCESS_EVENT process_event; - PROCESS_QUEUE process_queue; - -} USB_EVENT, *PUSB_EVENT; - -typedef struct _USB_EVENT_POOL -{ - PUSB_EVENT event_array; - LIST_HEAD free_que; - LONG free_count; - LONG total_count; - KSPIN_LOCK pool_lock; - -} USB_EVENT_POOL, *PUSB_EVENT_POOL; - -BOOLEAN -init_event_pool( -PUSB_EVENT_POOL pool -); - -BOOLEAN -free_event( -PUSB_EVENT_POOL pool, -PUSB_EVENT pevent -); //add qhs till pnext == NULL - -PUSB_EVENT -alloc_event( -PUSB_EVENT_POOL pool, -LONG count -); //null if failed - -BOOLEAN -destroy_event_pool( -PUSB_EVENT_POOL pool -); - -VOID -lock_event_pool( -PUSB_EVENT_POOL pool -); - -VOID -unlock_event_pool( -PUSB_EVENT_POOL pool -); - -#define DEV_MGR_TIMER_INTERVAL_NS ( 10 * 1000 * 10 ) //unit 100 ns -#define DEV_MGR_TIMER_INTERVAL_MS 10 - -typedef VOID ( *TIMER_SVC_HANDLER )(PUSB_DEV dev, PVOID context); - -typedef struct _TIMER_SVC -{ - LIST_ENTRY timer_svc_link; - ULONG counter; - ULONG threshold; - ULONG context; - PUSB_DEV pdev; - TIMER_SVC_HANDLER func; - -} TIMER_SVC, *PTIMER_SVC; - -typedef struct _TIMER_SVC_POOL -{ - PTIMER_SVC timer_svc_array; - LIST_HEAD free_que; - LONG free_count; - LONG total_count; - KSPIN_LOCK pool_lock; - -} TIMER_SVC_POOL, *PTIMER_SVC_POOL; - -BOOLEAN -init_timer_svc_pool( -PTIMER_SVC_POOL pool -); -BOOLEAN -free_timer_svc( -PTIMER_SVC_POOL pool, -PTIMER_SVC ptimer -); - -PTIMER_SVC -alloc_timer_svc( -PTIMER_SVC_POOL pool, -LONG count -); //null if failed - -BOOLEAN -destroy_timer_svc_pool( -PTIMER_SVC_POOL pool -); - -VOID -lock_timer_svc_pool( -PTIMER_SVC_POOL pool -); - -VOID -unlock_timer_svc_pool( -PTIMER_SVC_POOL pool -); - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/gendrv.c b/reactos/drivers/usb/nt4compat/usbdrv/gendrv.c deleted file mode 100644 index b9b4231ddb2..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/gendrv.c +++ /dev/null @@ -1,1847 +0,0 @@ -/** - * gendrv.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -//this driver is part of the dev manager responsible to manage non-driver device -#include "usbdriver.h" -#include "gendrv.h" - -#define if_dev( dev_obj ) \ -( ( ( ( PGENDRV_DEVICE_EXTENSION)dev_obj->DeviceExtension )->pdriver->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE ) != 0 ) - -#define GENDRV_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \ -{\ - iRp->IoStatus.Status = staTUS;\ - if( staTUS != STATUS_PENDING)\ - {\ - IoCompleteRequest( iRp, IO_NO_INCREMENT);\ - return staTUS;\ - }\ - IoMarkIrpPending( iRp );\ - IoStartPacket( dev_OBJ, iRp, NULL, gendrv_cancel_queued_irp ); \ - return STATUS_PENDING;\ -} - -#define GENDRV_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \ -{\ - iRP->IoStatus.Status = staTUS;\ - if( staTUS != STATUS_PENDING )\ - {\ - IoStartNextPacket( dev_OBJ, TRUE );\ - IoCompleteRequest( iRP, IO_NO_INCREMENT );\ - }\ - return;\ -} - -extern POBJECT_TYPE NTSYSAPI IoDriverObjectType; - -extern VOID disp_urb_completion(PURB purb, PVOID context); - - -VOID disp_noio_urb_completion(PURB purb, PVOID context); - -NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName); - -NTSYSAPI NTSTATUS NTAPI ZwClose(IN HANDLE Handle); - -NTSYSAPI -NTSTATUS -NTAPI -ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, - IN POBJECT_TYPE ObjectType OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN OUT PACCESS_STATE AccessState OPTIONAL, - IN ACCESS_MASK DesiredAccess OPTIONAL, - IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle); - -BOOLEAN gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); - -VOID gendrv_set_cfg_completion(PURB purb, PVOID context); - -BOOLEAN gendrv_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle); - -BOOLEAN gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); - -BOOLEAN gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); - -VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp); - -VOID NTAPI gendrv_cancel_queued_irp(PDEVICE_OBJECT pdev_obj, PIRP pirp); - -VOID gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry); - -VOID gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj); - -PGENDRV_EXT_DRVR_ENTRY gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext); - -PDRIVER_OBJECT gendrv_open_ext_driver(PUNICODE_STRING unicode_string); - -NTSTATUS -gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information); - -NTSTATUS -gendrv_open_reg_key(OUT PHANDLE handle, - IN HANDLE base_handle OPTIONAL, - IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create); - -BOOLEAN gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOLEAN is_if); - -BOOLEAN gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOLEAN is_if); - -NTSTATUS gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx); - -BOOLEAN gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj); - -PDEVICE_OBJECT gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle); - -PDRIVER_OBJECT gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc); - -PDRIVER_OBJECT gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key); - -ULONG gendrv_make_key(PUSB_DESC_HEADER pdesc); - -BOOLEAN -gendrv_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PGENDRV_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = 0xff; // Interface Class - pdriver->driver_desc.if_sub_class = 0xff; // Interface SubClass - pdriver->driver_desc.if_protocol = 0xff; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB generic dev driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_VENDOR_SPEC; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION)); - if (!pdriver->driver_ext) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_driver_init(): memory allocation failed!\n")); - return FALSE; - } - - pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size); - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext; - - // InitializeListHead( &pdrvr_ext->dev_list ); - InitializeListHead(&pdrvr_ext->ext_drvr_list); - pdrvr_ext->ext_drvr_count = 0; - ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex); - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = gendrv_connect; - pdriver->disp_tbl.dev_disconnect = gendrv_disconnect; - pdriver->disp_tbl.dev_stop = gendrv_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - return TRUE; -} - -BOOLEAN -gendrv_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - return gendrv_if_driver_destroy(dev_mgr, pdriver); -} - -BOOLEAN -gendrv_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - PURB purb; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - PUCHAR buf; - LONG i; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_DEV_MANAGER dev_mgr; - - if (param == NULL || dev_handle == 0) - return FALSE; - - dev_mgr = param->dev_mgr; - - // let's set the configuration - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - - buf = usb_alloc_mem(NonPagedPool, 512); - if (buf == NULL) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): can not alloc buf\n")); - usb_free_mem(purb); - return FALSE; - } - - // before we set the configuration, let's search to find if there - // exist interfaces we supported - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - purb->endp_handle = dev_handle | 0xffff; - purb->data_buffer = buf; - purb->data_length = 512; - purb->completion = NULL; // this is an immediate request, no completion required - purb->context = NULL; - purb->reference = 0; - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = USB_DT_CONFIG << 8; - psetup->wIndex = 0; - psetup->wLength = 512; - - status = usb_submit_urb(dev_mgr, purb); - if (status == STATUS_PENDING) - { - TRAP(); - usb_free_mem(buf); - usb_free_mem(purb); - return FALSE; - } - - // check the config desc valid - pconfig_desc = (PUSB_CONFIGURATION_DESC) buf; - if (pconfig_desc->wTotalLength > 512) - { - usb_free_mem(buf); - usb_free_mem(purb); - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): error, bad configuration desc\n")); - return FALSE; - } - - i = pconfig_desc->bConfigurationValue; - usb_free_mem(buf); - buf = NULL; - - //set the configuration - urb_init(purb); - purb->endp_handle = dev_handle | 0xffff; - purb->data_buffer = NULL; - purb->data_length = 0; - purb->completion = gendrv_set_cfg_completion; - purb->context = dev_mgr; - purb->reference = (ULONG) param->pdriver; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_CONFIGURATION; - psetup->wValue = (USHORT) i; - psetup->wIndex = 0; - psetup->wLength = 0; - - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_connect(): start config the device, cfgval=%d\n", i)); - status = usb_submit_urb(dev_mgr, purb); - - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - - if (status == STATUS_SUCCESS) - return TRUE; - - return FALSE; - } - - return TRUE; -} - -BOOLEAN -gendrv_event_select_driver(PUSB_DEV pdev, //always null. we do not use this param - ULONG event, ULONG context, ULONG param) -{ - // - // try to search the registry to find one driver. - // if found, create the PDO, load the driver. - // and call its AddDevice. - // - LONG i; - PUSB_DRIVER pdrvr; - PGENDRV_DRVR_EXTENSION pdrvr_ext; - PGENDRV_EXT_DRVR_ENTRY pentry; - PGENDRV_DEVICE_EXTENSION pdev_ext; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_DEV_MANAGER dev_mgr; - - PDEVICE_OBJECT pdev_obj; - PDRIVER_OBJECT pdrvr_obj; - PLIST_ENTRY pthis, pnext; - - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(context); - UNREFERENCED_PARAMETER(event); - - if (pdev == NULL) - return FALSE; - - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_event_select_driver(): entering...\n")); - - pdrvr = (PUSB_DRIVER) param; - //original code: pconfig_desc = (PUSB_CONFIGURATION_DESC) pdev->desc_buf[sizeof(USB_DEVICE_DESC)]; - pconfig_desc = (PUSB_CONFIGURATION_DESC) &pdev->desc_buf[sizeof(USB_DEVICE_DESC)]; - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext; - - // - // well, let's do the hard work to see if there is a class driver - // for this device. - // in the event routine, we have no need to check if the device is zomb or - // not, it must be alive there. - // - i = gendrv_make_key((PUSB_DESC_HEADER) pdev->pusb_dev_desc); - if (i == -1) - { - return FALSE; - } - - pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i); - if (!pdrvr_obj) - { - if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pdev->pusb_dev_desc)) == NULL) - return FALSE; - } - - dev_mgr = dev_mgr_from_dev(pdev); - pdev_obj = gendrv_create_device(dev_mgr, pdrvr, usb_make_handle(pdev->dev_id, 0, 0)); - if (pdev_obj == NULL) - { - goto ERROR_OUT; - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || - dev_mgr_set_driver(dev_mgr, usb_make_handle(pdev->dev_id, 0, 0), pdrvr, pdev) == FALSE) - { - unlock_dev(pdev, FALSE); - gendrv_delete_device(dev_mgr, pdev_obj); - goto ERROR_OUT; - } - - if (pdev->usb_config) - { - pdev->dev_obj = pdev_obj; - } - - unlock_dev(pdev, FALSE); - - pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension; - pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512); - if (!pdev_ext->desc_buf) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_event_select_driver(): memory allocation failed!\n")); - goto ERROR_OUT; - } - - RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512); - - // insert the device to the dev_list - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - ListFirst(&pdrvr_ext->ext_drvr_list, pthis); - pentry = NULL; - while (pthis) - { - pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis; - if (pentry->pext_drvr == pdrvr_obj) - break; - ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext); - pthis = pnext; - pentry = NULL; - } - ASSERT(pentry); - InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link); - pdev_ext->ext_drvr_entry = pentry; - pentry->ref_count++; - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - // notify the class driver, some device comes - gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj); - usb_unlock_dev(pdev); - return TRUE; - - ERROR_OUT: - - usb_unlock_dev(pdev); - return FALSE; -} - -VOID -gendrv_set_cfg_completion(PURB purb, PVOID context) -{ - DEV_HANDLE dev_handle; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdriver; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_EVENT pevent; - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || context == NULL) - return; - - dev_handle = purb->endp_handle & ~0xffff; - dev_mgr = (PUSB_DEV_MANAGER) context; - pdriver = (PUSB_DRIVER) purb->reference; - - if (purb->status != STATUS_SUCCESS) - { - usb_free_mem(purb); - return; - } - - usb_free_mem(purb); - purb = NULL; - - // set the dev state - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - return; - } - usb_unlock_dev(pdev); // safe to release the pdev ref since we are in urb completion - - - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return; - } - - if (dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return; - } - - //transit the state to configured - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return; - } - - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->event = USB_EVENT_DEFAULT; - pevent->pdev = pdev; - pevent->context = 0; - pevent->param = (ULONG) pdriver; - pevent->pnext = 0; //vertical queue for serialized operation - pevent->process_event = (PROCESS_EVENT) gendrv_event_select_driver; - pevent->process_queue = event_list_default_process_queue; - - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - - return; -} - - -BOOLEAN -gendrv_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - if (dev_mgr == NULL) - return FALSE; - return gendrv_do_stop(dev_mgr, dev_handle, FALSE); -} - -BOOLEAN -gendrv_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - if (dev_mgr == NULL) - return FALSE; - return gendrv_do_disconnect(dev_mgr, dev_handle, FALSE); -} - -BOOLEAN -gendrv_build_reg_string(PUSB_DESC_HEADER pdesc, PUNICODE_STRING pus) -{ - - CHAR desc_str[128]; - STRING atemp; - - if (pdesc == NULL || pus == NULL) - return FALSE; - - if (pdesc->bDescriptorType == USB_DT_DEVICE) - { - PUSB_DEVICE_DESC pdev_desc; - pdev_desc = (PUSB_DEVICE_DESC) pdesc; - sprintf(desc_str, "%sv_%04x&p_%04x", - "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\device\\", - pdev_desc->idVendor, pdev_desc->idProduct); - } - else if (pdesc->bDescriptorType == USB_DT_INTERFACE) - { - PUSB_INTERFACE_DESC pif_desc; - pif_desc = (PUSB_INTERFACE_DESC) pdesc; - sprintf(desc_str, "%sc_%04x&s_%04x&p_%04x", - "\\Registry\\Machine\\System\\CurrentControlSet\\Services\\ehci\\interface\\", - pif_desc->bInterfaceClass, pif_desc->bInterfaceSubClass, pif_desc->bInterfaceProtocol); - } - else - return FALSE; - - RtlInitString(&atemp, desc_str); - RtlAnsiStringToUnicodeString(pus, &atemp, TRUE); - return TRUE; -} - -ULONG -gendrv_make_key(PUSB_DESC_HEADER pdesc) -{ - PUSB_DEVICE_DESC pdev_desc; - PUSB_INTERFACE_DESC pif_desc; - - if (pdesc == NULL) - return (ULONG) - 1; - if (pdesc->bDescriptorType == USB_DT_DEVICE) - { - pdev_desc = (PUSB_DEVICE_DESC) pdesc; - return ((((ULONG) pdev_desc->idVendor) << 16) | pdev_desc->idProduct); - } - else if (pdesc->bDescriptorType == USB_DT_INTERFACE) - { - pif_desc = (PUSB_INTERFACE_DESC) pdesc; - return ((((ULONG) pif_desc->bInterfaceClass) << 16) | - (((ULONG) pif_desc->bInterfaceSubClass) << 8) | ((ULONG) pif_desc->bInterfaceProtocol)); - } - return (ULONG) - 1; -} - -PDRIVER_OBJECT -gendrv_find_drvr_by_key(PGENDRV_DRVR_EXTENSION pdrvr_ext, ULONG key) -{ - PGENDRV_EXT_DRVR_ENTRY pentry; - PLIST_ENTRY pthis, pnext; - if (pdrvr_ext == NULL || key == (ULONG) - 1) - return NULL; - - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - ListFirst(&pdrvr_ext->ext_drvr_list, pthis); - while (pthis) - { - pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis; - if (pentry->drvr_key == key) - { - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - return pentry->pext_drvr; - } - ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext); - pthis = pnext; - } - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - return NULL; -} - -PDRIVER_OBJECT -gendrv_load_ext_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PUSB_DESC_HEADER pdesc) -{ - PDRIVER_OBJECT pdrvr_obj; - PGENDRV_EXT_DRVR_ENTRY pentry; - UNICODE_STRING usz, svc_name, svc_key, utemp; - PKEY_VALUE_FULL_INFORMATION val_info; - PWCHAR val_buf; - HANDLE handle; - NTSTATUS status; - - if (pdrvr_ext == NULL || pdesc == NULL) - return NULL; - - // try to search and load driver from outside - handle = NULL; - RtlZeroMemory(&svc_key, sizeof(svc_key)); - val_info = NULL; - RtlInitUnicodeString(&usz, L""); - gendrv_build_reg_string(pdesc, &usz); -DbgPrint("UHCI: Trying to load driver %wZ\n", &usz); - if (gendrv_open_reg_key(&handle, NULL, &usz, KEY_READ, FALSE) != STATUS_SUCCESS) - { - goto ERROR_OUT; - } - if (gendrv_get_key_value(handle, L"service", &val_info) != STATUS_SUCCESS) - { - goto ERROR_OUT; - } - - if (val_info->DataLength > 32) - goto ERROR_OUT; - - val_buf = (PWCHAR) (((PBYTE) val_info) + val_info->DataOffset); - svc_key.Length = 0, svc_key.MaximumLength = 255; - svc_key.Buffer = usb_alloc_mem(NonPagedPool, 256); - - RtlInitUnicodeString(&utemp, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - RtlAppendUnicodeStringToString(&svc_key, &utemp); - RtlInitUnicodeString(&svc_name, val_buf); - RtlAppendUnicodeStringToString(&svc_key, &svc_name); - - status = ZwLoadDriver(&svc_key); - if (status != STATUS_SUCCESS) - goto ERROR_OUT; - - svc_key.Length = 0; - RtlZeroMemory(svc_key.Buffer, 128); - RtlInitUnicodeString(&svc_key, L"\\Driver\\"); - RtlAppendUnicodeStringToString(&svc_key, &svc_name); - pdrvr_obj = gendrv_open_ext_driver(&svc_key); - if (pdrvr_obj == NULL) - goto ERROR_OUT; - - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - - // insert the driver to the drvr list - pentry = gendrv_alloc_ext_drvr_entry(pdrvr_ext); - if (pentry == NULL) - { - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - ObDereferenceObject(pdrvr_obj); - goto ERROR_OUT; - } - pentry->pext_drvr = pdrvr_obj; - InsertTailList(&pdrvr_ext->ext_drvr_list, &pentry->drvr_link); - pdrvr_ext->ext_drvr_count++; - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - ZwClose(handle); - return pdrvr_obj; - -ERROR_OUT: - RtlFreeUnicodeString(&usz); - if (val_info != NULL) - { - usb_free_mem(val_info); - val_info = NULL; - } - if (svc_key.Buffer) - usb_free_mem(svc_key.Buffer); - - if (handle) - ZwClose(handle); - - return NULL; -} - -VOID -gendrv_release_drvr(PGENDRV_DRVR_EXTENSION pdrvr_ext, PDRIVER_OBJECT pdrvr_obj) -{ - PLIST_ENTRY pthis, pnext; - PGENDRV_EXT_DRVR_ENTRY pentry; - - if (pdrvr_ext == NULL || pdrvr_obj == NULL) - return; - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - ListFirst(&pdrvr_ext->ext_drvr_list, pthis); - while (pthis) - { - pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis; - if (pentry->pext_drvr == pdrvr_obj) - { - ASSERT(pentry->ref_count); - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - return; - } - ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext); - pthis = pnext; - } - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); -} - -NTSTATUS -gendrv_send_pnp_msg(ULONG msg, PDEVICE_OBJECT pdev_obj, PVOID pctx) -{ - if (pdev_obj == NULL) - return STATUS_INVALID_PARAMETER; - - switch (msg) - { - case GENDRV_MSG_ADDDEVICE: - { - PDRIVER_OBJECT pdrvr_obj; - if (pctx == NULL) - return STATUS_INVALID_PARAMETER; - pdrvr_obj = (PDRIVER_OBJECT) pctx; - if (pdrvr_obj->DriverExtension) - { - return pdrvr_obj->DriverExtension->AddDevice(pdrvr_obj, pdev_obj); - } - return STATUS_IO_DEVICE_ERROR; - } - case GENDRV_MSG_STOPDEVICE: - case GENDRV_MSG_DISCDEVICE: - { - NTSTATUS status; - IO_STACK_LOCATION *irpstack; - IRP *irp; - // IRP_MJ_PNP_POWER - irp = IoAllocateIrp(2, FALSE); - if (irp == NULL) - return STATUS_NO_MEMORY; - - irpstack = IoGetNextIrpStackLocation(irp); - irpstack->MajorFunction = IRP_MJ_PNP_POWER; - irpstack->MinorFunction = - (msg == GENDRV_MSG_STOPDEVICE) ? IRP_MN_STOP_DEVICE : IRP_MN_REMOVE_DEVICE; - status = IoCallDriver(pdev_obj, irp); - ASSERT(status != STATUS_PENDING); - status = irp->IoStatus.Status; - IoFreeIrp(irp); - return STATUS_MORE_PROCESSING_REQUIRED; - } - } - return STATUS_INVALID_PARAMETER; -} - - -BOOLEAN -gendrv_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle) -{ - // - // try to search the registry to find one driver. - // if found, create the PDO, load the driver. - // and call its AddDevice. - // - LONG if_idx, i; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr; - PUSB_INTERFACE_DESC pif_desc; - PGENDRV_DEVICE_EXTENSION pdev_ext; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_DEV_MANAGER dev_mgr; - PGENDRV_DRVR_EXTENSION pdrvr_ext; - PGENDRV_EXT_DRVR_ENTRY pentry; - - PDEVICE_OBJECT pdev_obj; - PDRIVER_OBJECT pdrvr_obj; - PLIST_ENTRY pthis, pnext; - USE_BASIC_NON_PENDING_IRQL; - - pdev = NULL; - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): entering...\n")); - - if (params == NULL) - return FALSE; - - dev_mgr = params->dev_mgr; - pdrvr = params->pdriver; - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext; - - status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev); - if (status != STATUS_SUCCESS) - { - goto ERROR_OUT; - } - // obtain the pointer to the config desc, the dev won't go away in this routine - pconfig_desc = pdev->usb_config->pusb_config_desc; // - usb_unlock_dev(pdev); - pdev = NULL; - - if_idx = if_idx_from_handle(if_handle); - pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]); - - for(i = 0; i < if_idx; i++) - { - //search for our if - if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE) - break; - } - if (pif_desc == NULL) - return FALSE; - - // - // well, let's do the hard work to see if there is a class driver - // for this device. - // - i = gendrv_make_key((PUSB_DESC_HEADER) pif_desc); - if (i == -1) - { - return FALSE; - } - - pdrvr_obj = gendrv_find_drvr_by_key(pdrvr_ext, (ULONG) i); - if (!pdrvr_obj) - { - if ((pdrvr_obj = gendrv_load_ext_drvr(pdrvr_ext, (PUSB_DESC_HEADER) pif_desc)) == NULL) - return FALSE; - } - - - pdev_obj = gendrv_create_device(dev_mgr, pdrvr, if_handle); - if (pdev_obj == NULL) - { - goto ERROR_OUT; - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || - dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE) - { - unlock_dev(pdev, FALSE); - gendrv_delete_device(dev_mgr, pdev_obj); - goto ERROR_OUT; - } - - if (pdev->usb_config) - { - pdev->usb_config->interf[if_idx].if_ext = pdev_obj; - pdev->usb_config->interf[if_idx].if_ext_size = 0; - } - - unlock_dev(pdev, FALSE); - - pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev_obj->DeviceExtension; - pdev_ext->desc_buf = usb_alloc_mem(NonPagedPool, 512); - if (!pdev_ext->desc_buf) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_if_connect(): memory allocation failed!\n")); - goto ERROR_OUT; - } - - RtlCopyMemory(pdev_ext->desc_buf, pconfig_desc, 512); - pdev_ext->if_ctx.pif_desc = - (PUSB_INTERFACE_DESC) & pdev_ext->desc_buf[(PBYTE) pif_desc - (PBYTE) pconfig_desc]; - - // insert the device to the dev_list - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - ListFirst(&pdrvr_ext->ext_drvr_list, pthis); - pentry = NULL; - while (pthis) - { - pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis; - if (pentry->pext_drvr == pdrvr_obj) - break; - ListNext(&pdrvr_ext->ext_drvr_list, pthis, pnext); - pthis = pnext; - pentry = NULL; - } - ASSERT(pentry); - InsertTailList(&pentry->dev_list, &pdev_ext->dev_obj_link); - pdev_ext->ext_drvr_entry = pentry; - pentry->ref_count++; - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - // notify the class driver, some device comes - gendrv_send_pnp_msg(GENDRV_MSG_ADDDEVICE, pdev_obj, pdrvr_obj); - usb_unlock_dev(pdev); - return TRUE; - - ERROR_OUT: - - usb_unlock_dev(pdev); - return FALSE; -} - -BOOLEAN -gendrv_do_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, BOOLEAN is_if) -{ - PUSB_DEV pdev; - PDEVICE_OBJECT pdev_obj; - ULONG if_idx; - - if (dev_mgr == NULL) - return FALSE; - - // clean up the irps - if_idx = if_idx_from_handle(dev_handle); - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS) - { - return FALSE; - } - if (is_if && pdev->usb_config) - pdev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext; - else - pdev_obj = pdev->dev_obj; - - gendrv_clean_up_queued_irps(pdev_obj); - usb_unlock_dev(pdev); - - // send message to class drivers. - gendrv_send_pnp_msg(GENDRV_MSG_STOPDEVICE, pdev_obj, NULL); - - return TRUE; -} - -BOOLEAN -gendrv_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - if (dev_mgr == NULL) - return FALSE; - - return gendrv_do_stop(dev_mgr, dev_handle, TRUE); -} - -BOOLEAN -gendrv_do_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle, BOOLEAN is_if) -{ - PUSB_DEV pdev; - PDEVICE_OBJECT dev_obj = NULL; - NTSTATUS status; - PUSB_DRIVER pdrvr; - PGENDRV_DRVR_EXTENSION pdrvr_ext = NULL; - PGENDRV_DEVICE_EXTENSION pdev_ext = NULL; - ULONG if_idx; - - status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev); - if (pdev == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - // must be a bug - TRAP(); - } - if_idx = if_idx_from_handle(if_handle); - if (pdev->usb_config) - { - if (is_if) - { - pdrvr = pdev->usb_config->interf[if_idx].pif_drv; - dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext; - } - else - { - pdrvr = pdev->dev_driver; - dev_obj = pdev->dev_obj; - } - - if (dev_obj == NULL) - { - // it means no driver was found for the device and thus no device object created - // we just do nothing here - return TRUE; - } - - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext; - pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension; - } - else - TRAP(); - pdev = NULL; - - // remove the device from the list - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - RemoveEntryList(&pdev_ext->dev_obj_link); - pdev_ext->ext_drvr_entry->ref_count--; - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - // send message to class driver - gendrv_send_pnp_msg(GENDRV_MSG_DISCDEVICE, dev_obj, NULL); - // delete the device object - gendrv_delete_device(dev_mgr, dev_obj); - return TRUE; -} - -BOOLEAN -gendrv_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle) -{ - return gendrv_do_disconnect(dev_mgr, if_handle, TRUE); -} - -BOOLEAN -gendrv_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PGENDRV_DRVR_EXTENSION pdrvr_ext; - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE; - pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID - pdriver->driver_desc.product_id = 0x0000; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = 0x0; // Interface Class - pdriver->driver_desc.if_sub_class = 0x0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0x0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB generic interface driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = 0; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - //we have no extra data sturcture currently - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = gendrv_if_connect; - pdriver->disp_tbl.dev_disconnect = gendrv_if_disconnect; - pdriver->disp_tbl.dev_stop = gendrv_if_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(GENDRV_DRVR_EXTENSION)); - if (!pdriver->driver_ext) return FALSE; - - pdriver->driver_ext_size = sizeof(GENDRV_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, pdriver->driver_ext_size); - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext; - - // InitializeListHead( &pdrvr_ext->dev_list ); - InitializeListHead(&pdrvr_ext->ext_drvr_list); - pdrvr_ext->ext_drvr_count = 0; - ExInitializeFastMutex(&pdrvr_ext->drvr_ext_mutex); - - return TRUE; -} - -BOOLEAN -gendrv_if_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PGENDRV_DRVR_EXTENSION pdrvr_ext; - PLIST_ENTRY pthis; - PGENDRV_EXT_DRVR_ENTRY pentry; - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - if (pdriver->driver_ext) - { - // should we lock it? - // ExAcquireFastMutex( &pdrvr_ext->drvr_ext_mutex ); - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdriver->driver_ext; - if (pdrvr_ext->ext_drvr_count) - { - while (IsListEmpty(&pdrvr_ext->ext_drvr_list)) - { - pthis = RemoveHeadList(&pdrvr_ext->ext_drvr_list); - pentry = (PGENDRV_EXT_DRVR_ENTRY) pthis; - if (pentry->pext_drvr) - { - if (pentry->ref_count) - { - // FIXME: really fail? - continue; - } - ObDereferenceObject(pentry->pext_drvr); - gendrv_release_ext_drvr_entry(pdrvr_ext, pentry); - } - } - pdrvr_ext->ext_drvr_count = 0; - } - - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - } - return TRUE; -} - -PDRIVER_OBJECT -gendrv_open_ext_driver(PUNICODE_STRING unicode_string) -{ - NTSTATUS status; - OBJECT_ATTRIBUTES oa; - HANDLE drvr_handle; - UNICODE_STRING oname; - PDRIVER_OBJECT pdrvr = NULL; - - RtlZeroMemory(&oa, sizeof(oa)); - oa.Length = sizeof(oa); - oa.ObjectName = &oname; - oa.Attributes = OBJ_CASE_INSENSITIVE; - RtlInitUnicodeString(&oname, L""); - RtlAppendUnicodeStringToString(&oname, unicode_string); - - status = ObOpenObjectByName(&oa, IoDriverObjectType, // object type - KernelMode, // access mode - NULL, // access state - FILE_READ_DATA, // STANDARD_RIGHTS_READ, access right - NULL, - &drvr_handle); - - if (status != STATUS_SUCCESS) - { - return NULL; - } - ObReferenceObjectByHandle(drvr_handle, - FILE_READ_DATA, - IoDriverObjectType, - KernelMode, - (PVOID)&pdrvr, - NULL); // OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL - - ZwClose(drvr_handle); - return pdrvr; -} - -BOOLEAN -gendrv_close_ext_driver(PDRIVER_OBJECT pdrvr) -{ - if (pdrvr == NULL) - return FALSE; - ObDereferenceObject(pdrvr); - return TRUE; -} - -NTSTATUS -gendrv_dispatch(PDEVICE_OBJECT dev_obj, PIRP irp) -{ - IO_STACK_LOCATION *irpstack; - PUSB_DEV_MANAGER dev_mgr; - PDEVEXT_HEADER ext_hdr; - NTSTATUS status; - - if (dev_obj == NULL || irp == NULL) - return STATUS_INVALID_PARAMETER; - - ext_hdr = dev_obj->DeviceExtension; - dev_mgr = ext_hdr->dev_mgr; - - irpstack = IoGetNextIrpStackLocation(irp); - switch (irpstack->MajorFunction) - { - case IRP_MJ_PNP_POWER: - { - irp->IoStatus.Information = 0; - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp); - } - case IRP_MJ_INTERNAL_DEVICE_CONTROL: - { - status = STATUS_NOT_SUPPORTED; - if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD || - irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR || - irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO) - { - PURB purb; - DEV_HANDLE endp_handle; - PGENDRV_DEVICE_EXTENSION pdev_ext; - - pdev_ext = dev_obj->DeviceExtension; - if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB)) - { - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - purb = (PURB) irp->AssociatedIrp.SystemBuffer; - endp_handle = purb->endp_handle; - if (purb->data_buffer == NULL || purb->data_length == 0) - { - if (irpstack->Parameters.DeviceIoControl.IoControlCode != IOCTL_SUBMIT_URB_NOIO) - { - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - } - if (!default_endp_handle(endp_handle)) - { - //no permit to other interface if interface dev - if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx) - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp); - } - else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC) - { - // this is a synchronous call, route to dev_mgr_dispatch - return dev_mgr_dispatch(dev_mgr, irp); - } - else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE) - { - PGENDRV_DEVICE_EXTENSION pdev_ext; - pdev_ext = dev_obj->DeviceExtension; - if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG)) - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - - *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle; - irp->IoStatus.Information = sizeof(LONG); - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp); - } - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp); - } - case IRP_MJ_DEVICE_CONTROL: - { - status = STATUS_NOT_SUPPORTED; - if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_RD || - irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_WR || - irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SUBMIT_URB_NOIO) - { - PURB purb; - DEV_HANDLE endp_handle; - PGENDRV_DEVICE_EXTENSION pdev_ext; - - pdev_ext = dev_obj->DeviceExtension; - if (irpstack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB)) - { - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - purb = (PURB) irp->AssociatedIrp.SystemBuffer; - endp_handle = purb->endp_handle; - if (!default_endp_handle(endp_handle)) - { - //no permit to other interface if interface dev - if (if_dev(dev_obj) && if_idx_from_handle(endp_handle) != pdev_ext->if_ctx.if_idx) - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_PENDING, irp); - } - else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_DESC) - { - // this is a synchronous call, route to dev_mgr_dispatch - return dev_mgr_dispatch(dev_mgr, irp); - } - else if (irpstack->Parameters.DeviceIoControl.IoControlCode == IOCTL_GET_DEV_HANDLE) - { - PGENDRV_DEVICE_EXTENSION pdev_ext; - pdev_ext = dev_obj->DeviceExtension; - if (irpstack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG)) - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_INVALID_PARAMETER, irp); - - *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle; - irp->IoStatus.Information = sizeof(LONG); - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_SUCCESS, irp); - } - GENDRV_EXIT_DISPATCH(dev_obj, STATUS_NOT_SUPPORTED, irp); - } - } - irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - irp->IoStatus.Information = 0; - IoCompleteRequest(irp, IO_NO_INCREMENT); - - return STATUS_NOT_SUPPORTED; -} - -BOOLEAN -gendrv_init_dev_ext_hdr(PDEVICE_OBJECT dev_obj, PUSB_DEV_MANAGER dev_mgr) -{ - PDEVEXT_HEADER dev_hdr = NULL; - if (dev_obj == NULL || dev_mgr == NULL) - return FALSE; - - dev_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - dev_hdr->type = NTDEV_TYPE_CLIENT_DEV; - dev_hdr->dispatch = gendrv_dispatch; - dev_hdr->start_io = (PDRIVER_STARTIO) gendrv_startio; - return TRUE; -} - -PDEVICE_OBJECT -gendrv_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER gen_drvr, DEV_HANDLE dev_handle) -{ - BOOLEAN is_if; - PDEVICE_OBJECT pdev; - PGENDRV_DEVICE_EXTENSION pdev_ext; - ULONG dev_id; - PGENDRV_DRVR_EXTENSION pdrvr_ext; - CHAR dev_name[64]; - STRING string; - UNICODE_STRING name_string, symb_link; - NTSTATUS status; - - if (dev_mgr == NULL || gen_drvr == NULL || dev_handle == 0) - return NULL; - - is_if = (gen_drvr->driver_desc.flags & USB_DRIVER_FLAG_IF_CAPABLE) ? 1 : 0; - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_create_device(): entering...\n")); - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) gen_drvr->driver_ext; - dev_id = (UCHAR) dev_id_from_handle(dev_handle); - - if (is_if == FALSE) - sprintf(dev_name, "\\Device\\gendev_%d", (int)dev_id); - else - sprintf(dev_name, "\\Device\\genifdev_%d", (int)dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&name_string, &string, TRUE); - pdev = NULL; - - status = IoCreateDevice(dev_mgr->usb_driver_obj, - sizeof(GENDRV_DEVICE_EXTENSION), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev); - - if (status == STATUS_SUCCESS) - { - // - // We do direct io - // - pdev->Flags |= DO_DIRECT_IO; - - pdev->Flags &= ~DO_DEVICE_INITIALIZING; - pdev->StackSize = 2; //one for fdo, one for file device obj - - pdev_ext = (PGENDRV_DEVICE_EXTENSION) pdev->DeviceExtension; - - //may be accessed by other thread - - gendrv_init_dev_ext_hdr(pdev, dev_mgr); - - pdev_ext->dev_id = (UCHAR) dev_id; - pdev_ext->pdo = pdev; - pdev_ext->dev_handle = dev_handle; - pdev_ext->dev_mgr = dev_mgr; - pdev_ext->pdriver = gen_drvr; - - if (is_if == FALSE) - sprintf(dev_name, "\\DosDevices\\gendev%d", (int)dev_id); - else - sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoCreateSymbolicLink(&symb_link, &name_string); - RtlFreeUnicodeString(&symb_link); - KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE); - KeInitializeSpinLock(&pdev_ext->dev_lock); - - } - RtlFreeUnicodeString(&name_string); - return pdev; -} - - - -VOID -gendrv_deferred_delete_device(PVOID context) -{ - PDEVICE_OBJECT dev_obj; - PGENDRV_DEVICE_EXTENSION pdev_ext; - PGENDRV_DRVR_EXTENSION pdrvr_ext; - LARGE_INTEGER interval; - - if (context == NULL) - return; - - dev_obj = (PDEVICE_OBJECT) context; - pdev_ext = dev_obj->DeviceExtension; - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext; - - interval.QuadPart = -20000; //two ms - - for(;;) - { - if (dev_obj->ReferenceCount) - KeDelayExecutionThread(KernelMode, TRUE, &interval); - else - { - KeDelayExecutionThread(KernelMode, TRUE, &interval); - if (dev_obj->ReferenceCount == 0) - break; - } - } - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_deferred_delete_device(): delete device, 0x%x\n", dev_obj)); - - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - RemoveEntryList(&pdev_ext->dev_obj_link); - pdev_ext->ext_drvr_entry->ref_count--; - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - IoDeleteDevice(dev_obj); - return; -} - -BOOLEAN -gendrv_delete_device(PUSB_DEV_MANAGER dev_mgr, PDEVICE_OBJECT dev_obj) -{ - BOOLEAN is_if; - PUSB_DRIVER pdrvr; - PGENDRV_DEVICE_EXTENSION pdev_ext; - CHAR dev_name[64]; - STRING string; - UNICODE_STRING symb_link; - PGENDRV_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || dev_obj == 0) - return FALSE; - - pdev_ext = (PGENDRV_DEVICE_EXTENSION) dev_obj->DeviceExtension; - pdrvr = pdev_ext->pdriver; - pdrvr_ext = (PGENDRV_DRVR_EXTENSION) pdrvr->driver_ext; - is_if = (BOOLEAN) if_dev(dev_obj); - if (is_if == FALSE) - sprintf(dev_name, "\\DosDevices\\gendev%d", (int)pdev_ext->dev_id); - else - sprintf(dev_name, "\\DosDevices\\genifdev%d", (int)pdev_ext->dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoDeleteSymbolicLink(&symb_link); - RtlFreeUnicodeString(&symb_link); - - if (pdev_ext->desc_buf) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("gendrv_delete_device(): delete desc_buf\n")); - usb_free_mem(pdev_ext->desc_buf); - pdev_ext->desc_buf = NULL; - - } - - if (dev_obj->ReferenceCount == 0) - { - ExAcquireFastMutex(&pdrvr_ext->drvr_ext_mutex); - RemoveEntryList(&pdev_ext->dev_obj_link); - pdev_ext->ext_drvr_entry->ref_count--; //the ext_drvr_entry is actually in pdrvr_ext, so lock it. - ExReleaseFastMutex(&pdrvr_ext->drvr_ext_mutex); - - IoDeleteDevice(dev_obj); - return TRUE; - } - - // borrow from umss's work routine - return umss_schedule_workitem(dev_obj, gendrv_deferred_delete_device, NULL, 0); -} - -// must have the drvr_ext_mutex acquired. -PGENDRV_EXT_DRVR_ENTRY -gendrv_alloc_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext) -{ - LONG i; - if (pdrvr_ext == NULL) - return NULL; - if (pdrvr_ext->ext_drvr_count == GENDRV_MAX_EXT_DRVR) - return NULL; - for(i = 0; i < GENDRV_MAX_EXT_DRVR; i++) - { - if (pdrvr_ext->ext_drvr_array[i].drvr_link.Flink == NULL && - pdrvr_ext->ext_drvr_array[i].drvr_link.Blink == NULL) - { - return &pdrvr_ext->ext_drvr_array[i]; - } - } - return NULL; -} - -// must have the drvr_ext_mutex acquired. -VOID -gendrv_release_ext_drvr_entry(PGENDRV_DRVR_EXTENSION pdrvr_ext, PGENDRV_EXT_DRVR_ENTRY pentry) -{ - if (pdrvr_ext == NULL || pentry == NULL) - return; - RtlZeroMemory(pentry, sizeof(GENDRV_EXT_DRVR_ENTRY)); - InitializeListHead(&pentry->dev_list); - return; -} - -NTSTATUS -gendrv_open_reg_key(OUT PHANDLE handle, - IN HANDLE base_handle OPTIONAL, - IN PUNICODE_STRING keyname, IN ACCESS_MASK desired_access, IN BOOLEAN create) -/*++ - -Routine Description: - - Opens or creates a VOLATILE registry key using the name passed in based - at the BaseHandle node. - -Arguments: - - Handle - Pointer to the handle which will contain the registry key that - was opened. - - BaseHandle - Handle to the base path from which the key must be opened. - - KeyName - Name of the Key that must be opened/created. - - DesiredAccess - Specifies the desired access that the caller needs to - the key. - - Create - Determines if the key is to be created if it does not exist. - -Return Value: - - The function value is the final status of the operation. - ---*/ -{ - OBJECT_ATTRIBUTES object_attr; - ULONG disposition; - - // - // Initialize the object for the key. - // - - InitializeObjectAttributes(&object_attr, - keyname, OBJ_CASE_INSENSITIVE, base_handle, (PSECURITY_DESCRIPTOR) NULL); - - // - // Create the key or open it, as appropriate based on the caller's - // wishes. - // - - if (create) - { - return ZwCreateKey(handle, - desired_access, - &object_attr, 0, (PUNICODE_STRING) NULL, REG_OPTION_VOLATILE, &disposition); - } - else - { - return ZwOpenKey(handle, desired_access, &object_attr); - } - return STATUS_INVALID_PARAMETER; -} - -NTSTATUS -gendrv_get_key_value(IN HANDLE KeyHandle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION * Information) -/*++ - -Routine Description: - - This routine is invoked to retrieve the data for a registry key's value. - This is done by querying the value of the key with a zero-length buffer - to determine the size of the value, and then allocating a buffer and - actually querying the value into the buffer. - - It is the responsibility of the caller to free the buffer. - -Arguments: - - KeyHandle - Supplies the key handle whose value is to be queried - - ValueName - Supplies the null-terminated Unicode name of the value. - - Information - Returns a pointer to the allocated data buffer. - -Return Value: - - The function value is the final status of the query operation. - ---*/ -{ - UNICODE_STRING unicodeString; - NTSTATUS status; - PKEY_VALUE_FULL_INFORMATION infoBuffer; - ULONG keyValueLength; - - PAGED_CODE(); - - RtlInitUnicodeString(&unicodeString, ValueName); - - // - // Figure out how big the data value is so that a buffer of the - // appropriate size can be allocated. - // - - status = ZwQueryValueKey(KeyHandle, - &unicodeString, KeyValueFullInformation, (PVOID) NULL, 0, &keyValueLength); - if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) - { - return status; - } - - // - // Allocate a buffer large enough to contain the entire key data value. - // - - infoBuffer = usb_alloc_mem(NonPagedPool, keyValueLength); - if (!infoBuffer) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - // - // Query the data for the key value. - // - - status = ZwQueryValueKey(KeyHandle, - &unicodeString, - KeyValueFullInformation, infoBuffer, keyValueLength, &keyValueLength); - if (!NT_SUCCESS(status)) - { - usb_free_mem(infoBuffer); - return status; - } - - // - // Everything worked, so simply return the address of the allocated - // buffer to the caller, who is now responsible for freeing it. - // - - *Information = infoBuffer; - return STATUS_SUCCESS; -} - -VOID -gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - PIO_STACK_LOCATION irp_stack; - ULONG ctrl_code; - PUSB_DEV_MANAGER dev_mgr; - USE_NON_PENDING_IRQL; - - if (dev_obj == NULL || irp == NULL) - return; - - // standard process from walter oney - IoAcquireCancelSpinLock(&old_irql); - if (irp != dev_obj->CurrentIrp || irp->Cancel) - { - // already move on to other irp - IoReleaseCancelSpinLock(old_irql); - return; - } - else - { - (void)IoSetCancelRoutine(irp, NULL); - } - IoReleaseCancelSpinLock(old_irql); - - irp->IoStatus.Information = 0; - - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - dev_mgr = ((PDEVEXT_HEADER) dev_obj->DeviceExtension)->dev_mgr; - - if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL && - irp_stack->MajorFunction != IRP_MJ_INTERNAL_DEVICE_CONTROL) - { - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp); - } - - switch (ctrl_code) - { - case IOCTL_SUBMIT_URB_RD: - case IOCTL_SUBMIT_URB_NOIO: - case IOCTL_SUBMIT_URB_WR: - { - PURB purb; - ULONG endp_idx, if_idx, user_buffer_length = 0; - PUCHAR user_buffer = NULL; - PUSB_DEV pdev; - DEV_HANDLE endp_handle; - PUSB_ENDPOINT pendp; - - NTSTATUS status; - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB)) - { - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - purb = (PURB) irp->AssociatedIrp.SystemBuffer; - if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR) - { - if (irp_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL) - { - user_buffer = MmGetSystemAddressForMdl(irp->MdlAddress); - user_buffer_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength; - if (user_buffer_length == 0) - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - else - { - if (purb->data_buffer == NULL || purb->data_length == 0) - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - user_buffer = purb->data_buffer; - user_buffer_length = purb->data_length; - } - } - - purb->reference = 0; - endp_handle = purb->endp_handle; - - if (usb_query_and_lock_dev(dev_mgr, endp_handle & ~0xffff, &pdev) != STATUS_SUCCESS) - { - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_IO_DEVICE_ERROR, irp); - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || (dev_state(pdev) < USB_DEV_STATE_ADDRESSED)) - - { - status = STATUS_INVALID_DEVICE_STATE; - goto ERROR_OUT1; - } - - if (dev_state(pdev) == USB_DEV_STATE_ADDRESSED && !default_endp_handle(endp_handle)) - { - status = STATUS_DEVICE_NOT_READY; - goto ERROR_OUT1; - } - - if_idx = if_idx_from_handle(endp_handle); - endp_idx = endp_idx_from_handle(endp_handle); - - //if_idx exceeds the upper limit - if (pdev->usb_config) - { - if (if_idx >= pdev->usb_config->if_count - || endp_idx >= pdev->usb_config->interf[if_idx].endp_count) - { - if (!default_endp_handle(endp_handle)) - { - status = STATUS_INVALID_DEVICE_STATE; - goto ERROR_OUT1; - } - } - } - - endp_from_handle(pdev, endp_handle, pendp); - - // FIXME: don't know what evil will let loose - if (endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL) - { - if (user_buffer_length > 16) - { - status = STATUS_INVALID_PARAMETER; - goto ERROR_OUT1; - } - } - - purb->pirp = irp; - purb->context = dev_mgr; - purb->reference = ctrl_code; - - if (ctrl_code == IOCTL_SUBMIT_URB_RD || ctrl_code == IOCTL_SUBMIT_URB_WR) - { - purb->data_buffer = user_buffer; - purb->data_length = user_buffer_length; - purb->completion = disp_urb_completion; - } - else - { - purb->completion = disp_noio_urb_completion; - } - - unlock_dev(pdev, FALSE); - - // - // we have to register irp before the urb is scheduled to - // avoid race condition. - // - ASSERT(dev_mgr_register_irp(dev_mgr, irp, purb)); - // - // the irp can not be canceled at this point, since it is - // now the current irp and not in any urb queue. dev_mgr_cancel_irp - // can not find it and simply return. - // - // FIXME: there is a time window that the irp is registered and - // the urb is not queued. In the meantime, the cancel - // request may come and cause the irp removed from the irp - // queue while fail to cancel due to urb not in any urb queue . - // Thus from that point on, the irp can not be canceled till it - // is completed or hanging there forever. - // - status = usb_submit_urb(dev_mgr, purb); - if (status != STATUS_PENDING) - { - // unmark the pending bit - IoGetCurrentIrpStackLocation((irp))->Control &= ~SL_PENDING_RETURNED; - dev_mgr_remove_irp(dev_mgr, irp); - } - usb_unlock_dev(pdev); - if (status != STATUS_PENDING) - { - irp->IoStatus.Status = status; - GENDRV_COMPLETE_START_IO(dev_obj, status, irp); - } - return; - - ERROR_OUT1: - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - irp->IoStatus.Information = 0; - GENDRV_COMPLETE_START_IO(dev_obj, status, irp); - } - } - GENDRV_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp); -} - -VOID -gendrv_clean_up_queued_irps(PDEVICE_OBJECT dev_obj) -{ - // called when device may not function or about to be removed, need cleanup - KIRQL cancelIrql; - PIRP irp, cur_irp; - PKDEVICE_QUEUE_ENTRY packet; - LIST_ENTRY cancel_irps, *pthis; - - // - // cancel all the irps in the queue - // - if (dev_obj == NULL) - return; - - InitializeListHead(&cancel_irps); - - // remove the irps from device queue - IoAcquireCancelSpinLock(&cancelIrql); - cur_irp = dev_obj->CurrentIrp; - while ((packet = KeRemoveDeviceQueue(&dev_obj->DeviceQueue))) - { - irp = struct_ptr(packet, IRP, Tail.Overlay.DeviceQueueEntry); - InsertTailList(&cancel_irps, &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry); - } - IoReleaseCancelSpinLock(cancelIrql); - - // cancel the irps in process - // we did not cancel the current irp, it will be done by hcd when - // disconnect is detected. - // remove_irp_from_list( &dev_mgr->irp_list, cur_irp, dev_mgr ); - - while (IsListEmpty(&cancel_irps) == FALSE) - { - pthis = RemoveHeadList(&cancel_irps); - irp = struct_ptr(pthis, IRP, Tail.Overlay.DeviceQueueEntry.DeviceListEntry); - irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_CANCELLED; - IoCompleteRequest(irp, IO_NO_INCREMENT); - } - return; -} - -VOID -NTAPI -gendrv_cancel_queued_irp(PDEVICE_OBJECT dev_obj, PIRP pirp) -{ - // cancel routine for irps queued in the device queue - PUSB_DEV_MANAGER dev_mgr; - PDEVEXT_HEADER pdev_ext_hdr; - - pdev_ext_hdr = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - dev_mgr = pdev_ext_hdr->dev_mgr; - - if (dev_obj->CurrentIrp == pirp) - { - // just before start_io set the cancel routine to null - IoReleaseCancelSpinLock(pirp->CancelIrql); - // we did not IoStartNextPacket, leave it for dev_mgr_cancel_irp, that - // is user have to call CancelIo again. - return; - } - - KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry); - IoReleaseCancelSpinLock(pirp->CancelIrql); - - pirp->IoStatus.Information = 0; - pirp->IoStatus.Status = STATUS_CANCELLED; - IoCompleteRequest(pirp, IO_NO_INCREMENT); - // the device queue is moved on, no need to call IoStartNextPacket - return; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/gendrv.h b/reactos/drivers/usb/nt4compat/usbdrv/gendrv.h deleted file mode 100644 index 9d64a9e314a..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/gendrv.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __GENDRV_H__ -#define __GENDRV_H__ - -#define GENDRV_MAX_EXT_DRVR 2 -#define GENDRV_DRVR_FLAG_IF_DRVR 0x01 - -#define GENDRV_MSG_ADDDEVICE 0x01 -#define GENDRV_MSG_STOPDEVICE 0x02 -#define GENDRV_MSG_DISCDEVICE 0x03 - -typedef struct _GENDRV_EXT_DRVR_ENTRY -{ - LIST_ENTRY drvr_link; // used for dynamic load/unload driver - ULONG drvr_key; // used to find the driver loaded, the key - // is ( vendor_id << 16 )|( product_id ) or - // ( class_id << 16 ) | ( sub_class_id << 8 ) | ( protocol_id )) - PDRIVER_OBJECT pext_drvr; // the external driver count - ULONG ref_count; // number of devices attached - LIST_HEAD dev_list; // link the devices by deviceExtension->dev_obj_link - -} GENDRV_EXT_DRVR_ENTRY, *PGENDRV_EXT_DRVR_ENTRY; - -typedef struct _GENDRV_DRVR_EXTENSION -{ - FAST_MUTEX drvr_ext_mutex; - ULONG ext_drvr_count; // loaded driver count - LIST_HEAD ext_drvr_list; - GENDRV_EXT_DRVR_ENTRY ext_drvr_array[ GENDRV_MAX_EXT_DRVR ]; - -}GENDRV_DRVR_EXTENSION, *PGENDRV_DRVR_EXTENSION; - -typedef struct _GENDRV_IF_CTX -{ - UCHAR if_idx; // valid for if device - PUSB_INTERFACE_DESC pif_desc; - -} GENDRV_IF_CTX, *PGENDRV_IF_IDX; - -typedef struct _GENDRV_DEVICE_EXTENSION -{ - //this structure is the device extension for dev_obj - //created for the device. - DEVEXT_HEADER dev_ext_hdr; - ULONG flags; - LIST_ENTRY dev_obj_link; // this link is used by the driver object to track the existing dev_objs - PGENDRV_EXT_DRVR_ENTRY ext_drvr_entry; - - PDEVICE_OBJECT pdo; // Our device object - DEV_HANDLE dev_handle; // handle to the usb_dev under - PUCHAR desc_buf; - UCHAR dev_id; // used to build symbolic link - GENDRV_IF_CTX if_ctx; - - KEVENT sync_event; - KSPIN_LOCK dev_lock; - - PUSB_DRIVER pdriver; - PUSB_DEV_MANAGER dev_mgr; - -} GENDRV_DEVICE_EXTENSION, *PGENDRV_DEVICE_EXTENSION; - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/hcd.h b/reactos/drivers/usb/nt4compat/usbdrv/hcd.h deleted file mode 100644 index 854e02e3746..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/hcd.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __HCD_H__ -#define __HCD_H__ - -#define HCD_TYPE_MASK 0xf0 -#define HCD_TYPE_UHCI 0x10 -#define HCD_TYPE_OHCI 0x20 -#define HCD_TYPE_EHCI 0x30 - -#define hcd_type( hCD ) ( ( ( hCD )->flags ) & HCD_TYPE_MASK ) -#define usb2( hCD ) ( hcd_type( hCD ) == HCD_TYPE_EHCI ) - -#define HCD_ID_MASK 0xf - -#define HCD_DISP_READ_PORT_COUNT 1 // the param is a pointer to UCHAR -#define HCD_DISP_READ_RH_DEV_CHANGE 2 // the param is a buffer to hold conn change on all the port - // must have the rh dev_lock acquired - -struct _HCD; -struct _USB_DEV_MANAGER; -struct _USB_DEV; -struct _USB_ENDPOINT; -struct _URB; - -typedef VOID ( *PHCD_SET_DEV_MGR )( struct _HCD* hcd, struct _USB_DEV_MANAGER *dev_mgr ); -typedef struct _USB_DEV_MANAGER* ( *PHCD_GET_DEV_MGR )( struct _HCD* hcd ); -typedef ULONG ( *PHCD_GET_TYPE )( struct _HCD* hcd ); -typedef VOID ( *PHCD_SET_ID )( struct _HCD* hcd, UCHAR id ); -typedef UCHAR ( *PHCD_GET_ID )( struct _HCD* hcd ); -typedef UCHAR ( *PHCD_ALLOC_ADDR )( struct _HCD* hcd ); -typedef VOID ( *PHCD_FREE_ADDR )( struct _HCD* hcd, UCHAR addr ); -typedef NTSTATUS ( *PHCD_SUBMIT_URB )( struct _HCD* hcd, struct _USB_DEV *pdev, struct _USB_ENDPOINT *pendp, struct _URB *purb ); -typedef VOID ( *PHCD_GENERIC_URB_COMPLETION )( struct _URB *purb, PVOID context ); //we can get te hcd from purb -typedef struct _USB_DEV* ( *PHCD_GET_ROOT_HUB )( struct _HCD* hcd ); -typedef VOID ( *PHCD_SET_ROOT_HUB )( struct _HCD* hcd, struct _USB_DEV *root_hub ); -typedef BOOLEAN ( *PHCD_REMOVE_DEVICE )( struct _HCD* hcd, struct _USB_DEV *pdev ); -typedef BOOLEAN ( *PHCD_RH_RESET_PORT )( struct _HCD* hcd, UCHAR port_idx ); //must have the rh dev_lock acquired -typedef BOOLEAN ( *PHCD_RELEASE )( struct _HCD* hcd ); //must have the rh dev_lock acquired -typedef NTSTATUS( *PHCD_CANCEL_URB)( struct _HCD* hcd, struct _USB_DEV *pdev, struct _USB_ENDPOINT* pendp, struct _URB *purb ); -typedef BOOLEAN ( *PHCD_START )( struct _HCD* hcd ); //must have the rh dev_lock acquired -typedef NTSTATUS ( *PHCD_DISPATCH )( struct _HCD* hcd, LONG disp_code, PVOID param ); // locking depends on type of code - -typedef struct _HCD -{ - PHCD_SET_DEV_MGR hcd_set_dev_mgr; - PHCD_GET_DEV_MGR hcd_get_dev_mgr; - PHCD_GET_TYPE hcd_get_type; - PHCD_SET_ID hcd_set_id; - PHCD_GET_ID hcd_get_id; - PHCD_ALLOC_ADDR hcd_alloc_addr; - PHCD_FREE_ADDR hcd_free_addr; - PHCD_SUBMIT_URB hcd_submit_urb; - PHCD_GENERIC_URB_COMPLETION hcd_generic_urb_completion; - PHCD_GET_ROOT_HUB hcd_get_root_hub; - PHCD_SET_ROOT_HUB hcd_set_root_hub; - PHCD_REMOVE_DEVICE hcd_remove_device; - PHCD_RH_RESET_PORT hcd_rh_reset_port; - PHCD_RELEASE hcd_release; - PHCD_CANCEL_URB hcd_cancel_urb; - PHCD_START hcd_start; - PHCD_DISPATCH hcd_dispatch; - - //interfaces for all the host controller - ULONG flags; //hcd types | hcd id - ULONG conn_count; //statics for connection activities - struct _USB_DEV_MANAGER *dev_mgr; //pointer manager - UCHAR dev_addr_map[ 128 / 8 ]; //bitmap for the device addrs - struct _DEVICE_EXTENSION *pdev_ext; - -} HCD, *PHCD; - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/hub.c b/reactos/drivers/usb/nt4compat/usbdrv/hub.c deleted file mode 100644 index 5a36821a96b..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/hub.c +++ /dev/null @@ -1,2800 +0,0 @@ -/** - * hub.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -//---------------------------------------------------------- -//event pool routines -#define crash_machine() \ -{ ( ( PUSB_DEV ) 0 )->flags = 0x12345; } - -#define hub_if_from_dev( pdEV, pIF ) \ -{\ - int i;\ - for( i = 0; i < pdEV->usb_config->if_count; i ++ )\ - {\ - if( pdEV->usb_config->interf[ i ].pusb_if_desc->bInterfaceClass\ - == USB_CLASS_HUB )\ - {\ - break;\ - }\ - }\ -\ - if( i < pdEV->usb_config->if_count )\ - pIF = &pdev->usb_config->interf[ i ];\ - else\ - pIF = NULL;\ -\ -} - -extern ULONG cpu_clock_freq; - -BOOLEAN hub_check_reset_port_status(PUSB_DEV pdev, LONG port_idx); - -VOID hub_reexamine_port_status_queue(PUSB_DEV hub_dev, ULONG port_idx, BOOLEAN from_dpc); - -void hub_int_completion(PURB purb, PVOID pcontext); - -VOID hub_get_port_status_completion(PURB purb, PVOID context); - -VOID hub_clear_port_feature_completion(PURB purb, PVOID context); - -VOID hub_event_examine_status_que(PUSB_DEV pdev, ULONG event, ULONG context, //hub_ext - ULONG param //port_idx - ); - -VOID hub_timer_wait_dev_stable(PUSB_DEV pdev, - PVOID context //port-index - ); - -VOID hub_event_dev_stable(PUSB_DEV pdev, - ULONG event, - ULONG context, //hub_ext - ULONG param //port_idx - ); - -VOID hub_post_esq_event(PUSB_DEV pdev, BYTE port_idx, PROCESS_EVENT pe); - -void hub_set_cfg_completion(PURB purb, PVOID pcontext); - -void hub_get_hub_desc_completion(PURB purb, PVOID pcontext); - -NTSTATUS hub_start_int_request(PUSB_DEV pdev); - -BOOLEAN hub_connect(PDEV_CONNECT_DATA init_param, DEV_HANDLE dev_handle); - -BOOLEAN hub_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); - -BOOLEAN hub_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); - -NTSTATUS hub_disable_port_request(PUSB_DEV pdev, UCHAR port_idx); - -VOID hub_start_reset_port_completion(PURB purb, PVOID context); - -BOOLEAN -init_event_pool(PUSB_EVENT_POOL pool) -{ - int i; - - if (pool == NULL) - return FALSE; - - if ((pool->event_array = usb_alloc_mem(NonPagedPool, sizeof(USB_EVENT) * MAX_EVENTS)) == NULL) - return FALSE; - - InitializeListHead(&pool->free_que); - KeInitializeSpinLock(&pool->pool_lock); - pool->total_count = MAX_EVENTS; - pool->free_count = 0; - - for(i = 0; i < MAX_EVENTS; i++) - { - free_event(pool, &pool->event_array[i]); - } - - return TRUE; -} - -BOOLEAN -free_event(PUSB_EVENT_POOL pool, PUSB_EVENT pevent) -{ - if (pool == NULL || pevent == NULL) - { - return FALSE; - } - - RtlZeroMemory(pevent, sizeof(USB_EVENT)); - InsertTailList(&pool->free_que, &pevent->event_link); - pool->free_count++; - usb_dbg_print(DBGLVL_MAXIMUM + 1, - ("free_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, pevent)); - - return TRUE; -} - -//null if failed -PUSB_EVENT -alloc_event(PUSB_EVENT_POOL pool, LONG count) -{ - PUSB_EVENT NewEvent; - if (pool == NULL || count != 1) - return NULL; - - if (pool->free_count == 0) - return NULL; - - NewEvent = (PUSB_EVENT) RemoveHeadList(&pool->free_que); - pool->free_count--; - - usb_dbg_print(DBGLVL_MAXIMUM + 1, - ("alloc_event(): alloced=0x%x, addr=0x%x\n", MAX_EVENTS - pool->free_count, NewEvent)); - return NewEvent; -} - -BOOLEAN -destroy_event_pool(PUSB_EVENT_POOL pool) -{ - if (pool == NULL) - return FALSE; - - InitializeListHead(&pool->free_que); - pool->free_count = pool->total_count = 0; - usb_free_mem(pool->event_array); - pool->event_array = NULL; - - return TRUE; -} - -VOID -event_list_default_process_event(PUSB_DEV pdev, ULONG event, ULONG context, ULONG param) -{ - UNREFERENCED_PARAMETER(param); - UNREFERENCED_PARAMETER(context); - UNREFERENCED_PARAMETER(event); - UNREFERENCED_PARAMETER(pdev); -} - -//---------------------------------------------------------- -//timer_svc pool routines - -BOOLEAN -init_timer_svc_pool(PTIMER_SVC_POOL pool) -{ - int i; - - if (pool == NULL) - return FALSE; - - pool->timer_svc_array = usb_alloc_mem(NonPagedPool, sizeof(TIMER_SVC) * MAX_TIMER_SVCS); - InitializeListHead(&pool->free_que); - pool->free_count = 0; - pool->total_count = MAX_TIMER_SVCS; - KeInitializeSpinLock(&pool->pool_lock); - - for(i = 0; i < MAX_TIMER_SVCS; i++) - { - free_timer_svc(pool, &pool->timer_svc_array[i]); - } - - return TRUE; -} - -BOOLEAN -free_timer_svc(PTIMER_SVC_POOL pool, PTIMER_SVC ptimer) -{ - if (pool == NULL || ptimer == NULL) - return FALSE; - - RtlZeroMemory(ptimer, sizeof(TIMER_SVC)); - InsertTailList(&pool->free_que, &ptimer->timer_svc_link); - pool->free_count++; - - return TRUE; -} - -//null if failed -PTIMER_SVC -alloc_timer_svc(PTIMER_SVC_POOL pool, LONG count) -{ - PTIMER_SVC NewTimer; - - if (pool == NULL || count != 1) - return NULL; - - if (pool->free_count <= 0) - return NULL; - - NewTimer = (PTIMER_SVC) RemoveHeadList(&pool->free_que); - pool->free_count--; - return NewTimer; - -} - -BOOLEAN -destroy_timer_svc_pool(PTIMER_SVC_POOL pool) -{ - if (pool == NULL) - return FALSE; - - usb_free_mem(pool->timer_svc_array); - pool->timer_svc_array = NULL; - InitializeListHead(&pool->free_que); - pool->free_count = 0; - pool->total_count = 0; - - return TRUE; -} - -VOID -event_list_default_process_queue(PLIST_HEAD event_list, - PUSB_EVENT_POOL event_pool, PUSB_EVENT usb_event, PUSB_EVENT out_event) -{ - //remove the first event from the event list, and copy it to - //out_event - - if (event_list == NULL || event_pool == NULL || usb_event == NULL || out_event == NULL) - return; - - RemoveEntryList(&usb_event->event_link); - RtlCopyMemory(out_event, usb_event, sizeof(USB_EVENT)); - free_event(event_pool, usb_event); - return; -} - -BOOLEAN -psq_enqueue(PPORT_STATUS_QUEUE psq, ULONG status) -{ - if (psq == NULL) - return FALSE; - - if (psq_is_full(psq)) - return FALSE; - - psq->port_status[psq->status_count].wPortChange = HIWORD(status); - psq->port_status[psq->status_count].wPortStatus = LOWORD(status); - - psq->status_count++; - - usb_dbg_print(DBGLVL_MAXIMUM, ("psq_enqueue(): last status=0x%x, status count=0x%x, port_flag=0x%x\n", - status, psq->status_count, psq->port_flags)); - return TRUE; - -} - -VOID -psq_init(PPORT_STATUS_QUEUE psq) -{ - RtlZeroMemory(psq, sizeof(PORT_STATUS_QUEUE)); - psq->port_flags = STATE_IDLE | USB_PORT_FLAG_DISABLE; -} - -//return 0xffffffff if no element -ULONG -psq_outqueue(PPORT_STATUS_QUEUE psq) -{ - ULONG status; - - if (psq == NULL) - return 0; - - if (psq_is_empty(psq)) - return 0; - - status = ((PULONG) & psq->port_status)[0]; - psq->port_status[0] = psq->port_status[1]; - psq->port_status[1] = psq->port_status[2]; - psq->port_status[2] = psq->port_status[3]; - psq->status_count--; - - return status; -} - -BOOLEAN -psq_push(PPORT_STATUS_QUEUE psq, ULONG status) -{ - if (psq == NULL) - return FALSE; - - status = ((PULONG) & psq->port_status)[0]; - psq->port_status[3] = psq->port_status[2]; - psq->port_status[2] = psq->port_status[1]; - psq->port_status[1] = psq->port_status[0]; - - ((PULONG) & psq->port_status)[0] = status; - - psq->status_count++; - psq->status_count = ((4 > psq->status_count) ? psq->status_count : 4); - - return TRUE; -} - -BOOLEAN -hub_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - UNREFERENCED_PARAMETER(dev_mgr); - - //init driver structure, no PNP table functions - pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0xffff; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_HUB; // Interface Class - pdriver->driver_desc.if_sub_class = 0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB hub"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_HUB; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - //pdriver->driver_init = hub_driver_init; // initialized in dev_mgr_init_driver - //pdriver->driver_destroy = hub_driver_destroy; - - pdriver->driver_ext = 0; - pdriver->driver_ext_size = 0; - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = hub_connect; - pdriver->disp_tbl.dev_disconnect = hub_disconnect; - pdriver->disp_tbl.dev_stop = hub_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - return TRUE; -} - -BOOLEAN -hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - UNREFERENCED_PARAMETER(dev_mgr); - - pdriver->driver_ext = NULL; - return TRUE; -} - -void -hub_reset_pipe_completion(PURB purb, //only for reference, can not be released - PVOID context) -{ - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(context); - - if (purb == NULL) - { - return; - } - - pdev = purb->pdev; - pendp = purb->pendp; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - return; - } - - if (usb_error(purb->status)) - { - //simply retry it - unlock_dev(pdev, TRUE); - //usb_free_mem( purb ); - return; - } - unlock_dev(pdev, TRUE); - - pdev = purb->pdev; - hub_start_int_request(pdev); - return; -} - -NTSTATUS -hub_start_int_request(PUSB_DEV pdev) -{ - PURB purb; - PUSB_INTERFACE pif; - PHUB2_EXTENSION hub_ext; - NTSTATUS status; - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL) - return STATUS_INVALID_PARAMETER; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - - if (purb == NULL) - { - unlock_dev(pdev, FALSE); - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(purb, sizeof(URB)); - - purb->flags = 0; - purb->status = STATUS_SUCCESS; - hub_ext = hub_ext_from_dev(pdev); - purb->data_buffer = hub_ext->int_data_buf; - purb->data_length = (hub_ext->port_count + 7) / 8; - - hub_if_from_dev(pdev, pif); - usb_dbg_print(DBGLVL_ULTRA, ("hub_start_int_request(): pdev=0x%x, pif=0x%x\n", pdev, pif)); - purb->pendp = &pif->endp[0]; - purb->pdev = pdev; - - purb->completion = hub_int_completion; - purb->context = hub_ext; - - purb->pirp = NULL; - purb->reference = 0; - hcd = pdev->hcd; - unlock_dev(pdev, FALSE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - } - - return status; -} - -void -hub_int_completion(PURB purb, PVOID pcontext) -{ - - PUSB_DEV pdev; - PHUB2_EXTENSION hub_ext; - ULONG port_idx; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - LONG i; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL) - return; - - if (pcontext == NULL) - { - usb_free_mem(purb); - return; - } - - usb_dbg_print(DBGLVL_ULTRA, ("hub_int_completion(): entering...\n")); - - pdev = purb->pdev; - hub_ext = pcontext; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - return; - } - - hcd = pdev->hcd; - - if (purb->status == STATUS_SUCCESS) - { - - for(i = 1; i <= hub_ext->port_count; i++) - { - if (hub_ext->int_data_buf[i >> 3] & (1 << i)) - { - break; - } - } - if (i > hub_ext->port_count) - { - //no status change, re-initialize the int request - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - hub_start_int_request(pdev); - return; - } - - port_idx = (ULONG)i; - - //re-use the urb to get port status - purb->pendp = &pdev->default_endp; - purb->data_buffer = (PUCHAR) & hub_ext->port_status; - - purb->data_length = sizeof(USB_PORT_STATUS); - purb->pdev = pdev; - - purb->context = hub_ext; - purb->pdev = pdev; - purb->completion = hub_get_port_status_completion; - purb->reference = port_idx; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0xa3; //host-device class other recepient - psetup->bRequest = USB_REQ_GET_STATUS; - psetup->wValue = 0; - psetup->wIndex = (USHORT) port_idx; - psetup->wLength = 4; - - purb->pirp = NULL; - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (usb_error(status)) - { - usb_free_mem(purb); - purb = NULL; - } - else if (status == STATUS_SUCCESS) - { - // this is for root hub - hcd->hcd_generic_urb_completion(purb, purb->context); - } - return; - } - else - { - unlock_dev(pdev, TRUE); - if (usb_halted(purb->status)) - { - //let's reset pipe - usb_reset_pipe(pdev, purb->pendp, hub_reset_pipe_completion, NULL); - } - //unexpected error - usb_free_mem(purb); - purb = NULL; - } - return; -} - -VOID -hub_get_port_status_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - BYTE port_idx; - PHUB2_EXTENSION hub_ext; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || context == NULL) - return; - - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_get_port_feature_completion(): entering...\n")); - - pdev = purb->pdev; - pendp = purb->pendp; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - return; - } - - hcd = pdev->hcd; - if (usb_error(purb->status)) - { - unlock_dev(pdev, TRUE); - - purb->status = 0; - //simply retry the request refer to item 55 in document - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - if (status != STATUS_PENDING) - { - if (status == STATUS_SUCCESS) - { - hcd->hcd_generic_urb_completion(purb, purb->context); - - } - else - { - // - // must be fatal error - // FIXME: better to pass it to the completion for further - // processing? - // - usb_free_mem(purb); - } - } - return; - } - - hub_ext = hub_ext_from_dev(pdev); - port_idx = (BYTE) purb->reference; - - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_get_port_stataus_completion(): port_idx=0x%x, hcd =0x%x, \ - pdev=0x%x, purb=0x%x, hub_ext=0x%x, portsc=0x%x \n", port_idx, pdev->hcd, pdev, - purb, hub_ext, *((PULONG) purb->data_buffer))); - - psq_enqueue(&hub_ext->port_status_queue[port_idx], *((PULONG) purb->data_buffer)); - - //reuse the urb to clear the feature - RtlZeroMemory(purb, sizeof(URB)); - - purb->data_buffer = NULL; - purb->data_length = 0; - purb->pendp = &pdev->default_endp; - purb->pdev = pdev; - - purb->context = (PVOID) & hub_ext->port_status; - purb->pdev = pdev; - purb->completion = hub_clear_port_feature_completion; - purb->reference = port_idx; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0x23; //host-device class port recepient - psetup->bRequest = USB_REQ_CLEAR_FEATURE; - psetup->wIndex = port_idx; - psetup->wLength = 0; - purb->pirp = NULL; - - if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION) - { - psetup->wValue = USB_PORT_FEAT_C_CONNECTION; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE) - { - psetup->wValue = USB_PORT_FEAT_C_ENABLE; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND) - { - psetup->wValue = USB_PORT_FEAT_C_SUSPEND; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT) - { - psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET) - { - psetup->wValue = USB_PORT_FEAT_C_RESET; - } - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - - // if( status != STATUS_SUCCESS ) - if (status != STATUS_PENDING) - { - hcd->hcd_generic_urb_completion(purb, purb->context); - } - /*else if( usb_error( status ) ) - { - usb_free_mem( purb ); - return; - } */ - return; - -} - -VOID -hub_clear_port_feature_completion(PURB purb, PVOID context) -{ - BYTE port_idx; - LONG i; - BOOLEAN event_post, brh; - ULONG pc; - PHCD hcd; - NTSTATUS status; - PUSB_DEV pdev; - PHUB2_EXTENSION hub_ext = NULL; - PUSB_DEV_MANAGER dev_mgr; - - PUSB_CTRL_SETUP_PACKET psetup; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL) - return; - - if (context == NULL) - { - usb_free_mem(purb); - return; - } - - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_clear_port_feature_completion(): entering...\n")); - - pdev = purb->pdev; - port_idx = (BYTE) purb->reference; - - lock_dev(pdev, TRUE); - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - brh = (BOOLEAN) (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB); - - if (usb_error(purb->status)) - { - unlock_dev(pdev, TRUE); - - purb->status = 0; - - // retry the request - status = hcd->hcd_submit_urb(hcd, purb->pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - if (status == STATUS_SUCCESS) - { - hcd->hcd_generic_urb_completion(purb, purb->context); - } - else - { - // - // FIXME: should we pass the error to the completion directly - // instead of forstall it here? - // - // do not think the device is workable, no requests to it any more. - // including the int polling - - if (purb) - usb_free_mem(purb); - - if (port_idx) - hub_check_reset_port_status(pdev, port_idx); - } - } - return; - } - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - return; - } - - pc = ((PUSB_PORT_STATUS) context)->wPortChange; - - if (pc) - { - // the bits are tested in ascending order - if (pc & USB_PORT_STAT_C_CONNECTION) - { - pc &= ~USB_PORT_STAT_C_CONNECTION; - } - else if (pc & USB_PORT_STAT_C_ENABLE) - { - pc &= ~USB_PORT_STAT_C_ENABLE; - } - else if (pc & USB_PORT_STAT_C_SUSPEND) - { - pc &= ~USB_PORT_STAT_C_SUSPEND; - } - else if (pc & USB_PORT_STAT_C_OVERCURRENT) - { - pc &= ~USB_PORT_STAT_C_OVERCURRENT; - } - else if (pc & USB_PORT_STAT_C_RESET) - { - pc &= ~USB_PORT_STAT_C_RESET; - } - } - ((PUSB_PORT_STATUS) context)->wPortChange = (USHORT) pc; - - hub_ext = hub_ext_from_dev(pdev); - - if (pc) - { - //some other status change on the port still active - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_CONNECTION) - { - psetup->wValue = USB_PORT_FEAT_C_CONNECTION; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_ENABLE) - { - psetup->wValue = USB_PORT_FEAT_C_ENABLE; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_SUSPEND) - { - psetup->wValue = USB_PORT_FEAT_C_SUSPEND; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_OVERCURRENT) - { - psetup->wValue = USB_PORT_FEAT_C_OVER_CURRENT; - } - else if (hub_ext->port_status.wPortChange & USB_PORT_STAT_C_RESET) - { - psetup->wValue = USB_PORT_FEAT_C_RESET; - } - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - if (status == STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_clear_port_status_completion(): port_idx=0x%x, hcd=0x%x, \ - pdev=0x%x, purb=0x%x, hub_ext=0x%x, wPortChange=0x%x \n", - port_idx, pdev->hcd, pdev, purb, hub_ext, pc)); - - hcd->hcd_generic_urb_completion(purb, purb->context); - } - else - { - usb_dbg_print(DBGLVL_MAXIMUM, (" hub_clear_port_feature_completion(): \ - error=0x%x\n", status)); - - // usb_free_mem( purb ); - goto LBL_SCAN_PORT_STAT; - } - } - return; - } - - for(i = 1; i <= hub_ext->port_count; i++) - { - if (hub_ext->int_data_buf[i >> 3] & (1 << i)) - { - break; - } - } - - //clear the port-change map, we have get port i's status. - hub_ext->int_data_buf[i >> 3] &= ~(1 << i); - - //rescan to find some other port that has status change - for(i = 1; i <= hub_ext->port_count; i++) - { - if (hub_ext->int_data_buf[i >> 3] & (1 << i)) - { - break; - } - } - - if (i <= hub_ext->port_count) - { - //still has port-change pending, get the port status change - port_idx = (UCHAR) i; - - //re-use the urb - purb->data_buffer = (PUCHAR) & hub_ext->port_status; - purb->data_length = sizeof(USB_PORT_STATUS); - purb->pendp = &pdev->default_endp; - purb->pdev = pdev; - - purb->context = hub_ext; - purb->pdev = pdev; - purb->completion = hub_get_port_status_completion; - purb->reference = port_idx; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0xa3; //host-device class other recepient - psetup->bRequest = USB_REQ_GET_STATUS; - psetup->wValue = 0; - psetup->wIndex = port_idx; - psetup->wLength = 4; - - purb->pirp = NULL; - - unlock_dev(pdev, TRUE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - if (status == STATUS_SUCCESS) - { - hcd->hcd_generic_urb_completion(purb, purb->context); - } - else - { //must be fatal error - // usb_free_mem( purb ); - goto LBL_SCAN_PORT_STAT; - } - } - return; - } - - unlock_dev(pdev, TRUE); - -LBL_SCAN_PORT_STAT: - - //all status changes are cleared - if (purb) - usb_free_mem(purb); - - purb = NULL; - - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - // - // if reset is in process, the dev_mgr_disconnect_dev will continue - // the following resets - // - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return; - } - - //at last we wake up thread if some port have status change to process - port_idx = 0; - for(i = 1, event_post = FALSE; i <= hub_ext->port_count; i++) - { - if (psq_is_empty(&hub_ext->port_status_queue[i]) == FALSE) - { - if (port_state(hub_ext->port_status_queue[i].port_flags) == STATE_IDLE || - port_state(hub_ext->port_status_queue[i].port_flags) == STATE_WAIT_ADDRESSED) - { - // have status in the queue pending - // STATE_WAIT_ADDRESSED is added to avoid some bad mannered - // hub to disturb the reset process - hub_post_esq_event(pdev, (BYTE) i, hub_event_examine_status_que); - } - else if (port_state(hub_ext->port_status_queue[i].port_flags) == STATE_WAIT_RESET_COMPLETE) - { - //there is only one reset at one time - port_idx = (BYTE) i; - } - } - } - - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - - - if (port_idx) - hub_check_reset_port_status(pdev, port_idx); - - //reinitialize the int request, here to reduce some uncertainty of concurrency - hub_start_int_request(pdev); - - return; -} - -VOID -hub_event_examine_status_que(PUSB_DEV pdev, - ULONG event, - ULONG context, //hub_ext - ULONG param //port_idx - ) -{ - PHUB2_EXTENSION hub_ext; - USB_PORT_STATUS ps; - PUSB_DEV pchild_dev; - PTIMER_SVC ptimer; - PUSB_DEV_MANAGER dev_mgr; - - USE_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(event); - - if (pdev == NULL || context == 0 || param == 0) - return; - - while (TRUE) - { - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - break; - } - - dev_mgr = dev_mgr_from_dev(pdev); - hub_ext = hub_ext_from_dev(pdev); - - if (psq_is_empty(&hub_ext->port_status_queue[param])) - { - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_IDLE); - unlock_dev(pdev, FALSE); - break; - } - - *((ULONG *) & ps) = psq_outqueue(&hub_ext->port_status_queue[param]); - - - pchild_dev = hub_ext->child_dev[param]; - hub_ext->child_dev[param] = 0; - - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_event_examine_status_queue(): dev_addr=0x%x, port=0x%x, wPortChange=0x%x, wPortStatus=0x%x\n", - pdev->dev_addr, param, ps.wPortChange, ps.wPortStatus)); - - unlock_dev(pdev, FALSE); - - if (pchild_dev != NULL) - dev_mgr_disconnect_dev(pchild_dev); - - if (((ps.wPortChange & USB_PORT_STAT_C_ENABLE) && - ((pdev->flags & USB_DEV_CLASS_MASK) != USB_DEV_CLASS_ROOT_HUB)) - || (ps.wPortChange & USB_PORT_STAT_C_OVERCURRENT) - || (ps.wPortChange & USB_PORT_STAT_C_RESET) - || ((ps.wPortChange & USB_PORT_STAT_C_CONNECTION) && - !(ps.wPortStatus & USB_PORT_STAT_CONNECTION))) - { - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_event_examine_status_queue(): error occured, portc=0x%x, ports=0x%x\n", - ps.wPortChange, ps.wPortStatus)); - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - break; - } - if (psq_is_empty(&hub_ext->port_status_queue[param])) - { - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_IDLE); - } - else - { - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_EXAMINE_STATUS_QUE); - } - unlock_dev(pdev, FALSE); - continue; - - } - else if ((ps.wPortChange & USB_PORT_STAT_C_CONNECTION) - && (ps.wPortStatus & USB_PORT_STAT_CONNECTION) - && psq_is_empty(&hub_ext->port_status_queue[param])) - { - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): dev lost\n")); - break; - } - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (ptimer == NULL) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_event_examine_status_queue(): timer can not allocated\n")); - break; - } - - //a new connection - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): new connection comes\n")); - - ptimer->counter = 0; - ptimer->threshold = 21; //100 ms - - if (ps.wPortStatus & USB_PORT_STAT_LOW_SPEED) - ptimer->threshold = 51; //500 ms - - ptimer->context = param; - ptimer->pdev = pdev; - ptimer->func = hub_timer_wait_dev_stable; - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - pdev->ref_count++; - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_STABLE); - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - break; - - } - else - { - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_event_examine_status_queue(): unknown error\n")); - continue; - } - } - return; -} - -VOID -hub_timer_wait_dev_stable(PUSB_DEV pdev, - PVOID context //port-index - ) -{ - - PHUB2_EXTENSION hub_ext; - ULONG param; - PUSB_DEV_MANAGER dev_mgr; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || context == 0) - return; - - dev_mgr = dev_mgr_from_dev(pdev); - param = (ULONG) context; - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - lock_dev(pdev, TRUE); - - pdev->ref_count--; - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - goto LBL_OUT; - } - - hub_ext = hub_ext_from_dev(pdev); - - if (!psq_is_empty(&hub_ext->port_status_queue[param])) - { - //error occured, normally we should not receive event here - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_EXAMINE_STATUS_QUE); - - hub_post_esq_event(pdev, (BYTE) param, hub_event_examine_status_que); - } - else - { - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_RESET); - - hub_post_esq_event(pdev, (BYTE) param, hub_event_dev_stable); - - } - -LBL_OUT: - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - return; -} - -VOID -hub_event_dev_stable(PUSB_DEV pdev, - ULONG event, - ULONG context, //hub_ext - ULONG param //port_idx - ) -{ - - PHUB2_EXTENSION hub_ext; - PUSB_EVENT pevent, pevent1; - PLIST_ENTRY pthis, pnext; - BOOLEAN que_exist; - PHCD hcd; - PUSB_DEV_MANAGER dev_mgr; - NTSTATUS status; - PURB purb; - PUSB_CTRL_SETUP_PACKET psetup; - - USE_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(event); - - if (pdev == NULL || context == 0 || param == 0) - return; - - dev_mgr = dev_mgr_from_dev(pdev); - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - goto LBL_OUT; - - hub_ext = hub_ext_from_dev(pdev); - hcd = pdev->hcd; - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - goto LBL_OUT; - - pevent->event = USB_EVENT_WAIT_RESET_PORT; - pevent->pdev = pdev; - pevent->context = (ULONG) hub_ext; - pevent->param = param; - pevent->flags = USB_EVENT_FLAG_QUE_RESET; - pevent->process_event = NULL; //hub_event_reset_port_complete; - pevent->process_queue = NULL; //hub_event_reset_process_queue; - pevent->pnext = NULL; - - ListFirst(&dev_mgr->event_list, pthis); - que_exist = FALSE; - - while (pthis) - { - //insert the event in to the wait-queue - pevent1 = (PUSB_EVENT) pthis; - if (pevent1->event == USB_EVENT_WAIT_RESET_PORT) - { - while (pevent1->pnext) - pevent1 = pevent1->pnext; - - pevent1->pnext = pevent; - que_exist = TRUE; - break; - } - ListNext(&dev_mgr->event_list, pthis, pnext); - pthis = pnext; - } - - if (!que_exist) - { - //Let's start a reset port request - InsertHeadList(&dev_mgr->event_list, &pevent->event_link); - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (!purb) goto LBL_OUT; - RtlZeroMemory(purb, sizeof(URB)); - - purb->data_buffer = NULL; - purb->data_length = 0; - purb->pendp = &pdev->default_endp; - - purb->context = hub_ext; - purb->pdev = pdev; - purb->completion = hub_start_reset_port_completion; //hub_int_completion; - purb->reference = param; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0x23; //host-device other recepient - psetup->bRequest = USB_REQ_SET_FEATURE; - psetup->wValue = USB_PORT_FEAT_RESET; - psetup->wIndex = (USHORT) param; - psetup->wLength = 0; - - purb->pirp = NULL; - //enter another state - set_port_state(hub_ext->port_status_queue[param].port_flags, STATE_WAIT_RESET_COMPLETE); - - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - //must be fatal error - usb_free_mem(purb); - hub_reexamine_port_status_queue(pdev, param, FALSE); - if (hub_remove_reset_event(pdev, param, FALSE)) - hub_start_next_reset_port(dev_mgr, FALSE); - } - return; - } - -LBL_OUT: - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - return; -} - -VOID -hub_start_reset_port_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - PUSB_DEV_MANAGER dev_mgr = NULL; - NTSTATUS status = STATUS_SUCCESS; - ULONG port_idx; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - if (purb == NULL) - return; - - if (context == NULL) - { - //fatal error no retry. - usb_free_mem(purb); - return; - } - - pdev = purb->pdev; - pendp = purb->pendp; - port_idx = purb->reference; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - goto LBL_FREE_EVENT; - } - - hcd = pdev->hcd; - dev_mgr = dev_mgr_from_dev(pdev); - unlock_dev(pdev, TRUE); - - status = purb->status; - usb_free_mem(purb); - - if (!usb_error(status)) - { - return; - } - -LBL_FREE_EVENT: - //since we have no patient to retry the dev, we should remove the event of - //wait_reset_port on the port from the event list. and if possible, start - //another reset process. note other port on the dev still have chance to be - //reset if necessary. - hub_reexamine_port_status_queue(pdev, port_idx, TRUE); - if (hub_remove_reset_event(pdev, port_idx, TRUE)) - hub_start_next_reset_port(dev_mgr, TRUE); - return; -} - - -VOID -hub_set_address_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev, hub_dev; - PUSB_ENDPOINT pendp; - PUSB_DEV_MANAGER dev_mgr; - NTSTATUS status; - ULONG port_idx; - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - hcd_dbg_print(DBGLVL_MAXIMUM, ("hub_set_address_completion: purb=%p context=%p\n", purb, context)); - - if (purb == NULL) - return; - - if (context == NULL) - { - //fatal error no retry. - usb_free_mem(purb); - return; - } - - pdev = purb->pdev; - pendp = purb->pendp; - port_idx = purb->reference; - - lock_dev(pdev, TRUE); - - hcd = pdev->hcd; - dev_mgr = dev_mgr_from_dev(pdev); - hub_dev = pdev->parent_dev; - port_idx = pdev->port_idx; - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - //some error occured, let's start the next reset event - goto LBL_RESET_NEXT; - } - - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_ADDRESSED; - - unlock_dev(pdev, TRUE); - status = purb->status; - - if (usb_error(status)) - { - //retry the urb - purb->status = 0; - hcd_dbg_print(DBGLVL_MAXIMUM, ("hub_set_address_completion: can not set address\n")); - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - //some error occured, disable the port - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - status = hub_disable_port_request(hub_dev, (UCHAR) port_idx); - } - return; - } - - usb_free_mem(purb); - //let address settle - usb_wait_ms_dpc(10); - - //let's config the dev - dev_mgr_start_config_dev(pdev); - -LBL_RESET_NEXT: - //second, remove the event in the queue - hub_reexamine_port_status_queue(hub_dev, port_idx, TRUE); - if (hub_remove_reset_event(hub_dev, port_idx, TRUE)) - hub_start_next_reset_port(dev_mgr, TRUE); - return; -}; - -VOID -hub_disable_port_completion(PURB purb, PVOID pcontext) -{ - PUSB_DEV pdev; - PUSB_DEV_MANAGER dev_mgr; - UCHAR port_idx; - PUSB_ENDPOINT pendp; - PUSB_CTRL_SETUP_PACKET psetup; - - UNREFERENCED_PARAMETER(pcontext); - - if (purb == NULL) - return; - - pdev = purb->pdev; - pendp = purb->pendp; - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - port_idx = (UCHAR) psetup->wIndex; - - dev_mgr = dev_mgr_from_dev(pdev); - - usb_free_mem(purb); - - hub_reexamine_port_status_queue(pdev, port_idx, TRUE); - if (hub_remove_reset_event(pdev, port_idx, TRUE)) - hub_start_next_reset_port(dev_mgr, TRUE); - - return; -} - -//caller should guarantee the validity of the dev -NTSTATUS -hub_disable_port_request(PUSB_DEV pdev, UCHAR port_idx) -{ - PURB purb; - PUSB_ENDPOINT pendp; - PHUB2_EXTENSION hub_ext; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || port_idx == 0) - return STATUS_INVALID_PARAMETER; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - { - unlock_dev(pdev, FALSE); - return STATUS_NO_MEMORY; - } - - RtlZeroMemory(purb, sizeof(URB)); - - purb->flags = 0; - purb->status = STATUS_SUCCESS; - - hub_ext = hub_ext_from_dev(pdev); - - purb->data_buffer = NULL; - purb->data_length = 0; - - pendp = purb->pendp = &pdev->default_endp; - purb->pdev = pdev; - - purb->completion = hub_disable_port_completion; - purb->context = hub_ext; - - purb->pirp = NULL; - purb->reference = 0; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0x23; //host-device other recepient - psetup->bRequest = USB_REQ_CLEAR_FEATURE; //clear_feature - psetup->wValue = USB_PORT_FEAT_ENABLE; - psetup->wIndex = (USHORT) port_idx; - psetup->wLength = 0; - - purb->pirp = NULL; - //enter another state - hcd = pdev->hcd; - unlock_dev(pdev, FALSE); - - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb); - if (status == STATUS_PENDING) - return status; - - usb_free_mem(purb); - return status; -} - - -BOOLEAN -hub_remove_reset_event(PUSB_DEV pdev, ULONG port_idx, BOOLEAN from_dpc) -{ - PUSB_DEV_MANAGER dev_mgr; - PLIST_ENTRY pthis, pnext; - PUSB_EVENT pevent, pnext_event; - BOOLEAN found; - - KIRQL old_irql = 0; - - if (pdev == NULL) - return FALSE; - - if (port_idx == 0) - return FALSE; - - dev_mgr = dev_mgr_from_dev(pdev); - found = FALSE; - - if (from_dpc) - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - else - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - - ListFirst(&dev_mgr->event_list, pthis); - while (pthis) - { - pevent = (PUSB_EVENT) pthis; - if (pevent->event == USB_EVENT_WAIT_RESET_PORT && - (pevent->flags & USB_EVENT_FLAG_QUE_TYPE) == USB_EVENT_FLAG_QUE_RESET) - { - if (pevent->pdev == pdev && pevent->param == port_idx) - { - //remove it - RemoveEntryList(&pevent->event_link); - pnext_event = pevent->pnext; - free_event(&dev_mgr->event_pool, pevent); - - if (pnext_event) - InsertHeadList(&dev_mgr->event_list, &pnext_event->event_link); - - found = TRUE; - break; - } - } - ListNext(&dev_mgr->event_list, pthis, pnext); - pthis = pnext; - } - - if (from_dpc) - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - else - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - return found; -} - -BOOLEAN -hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr, BOOLEAN from_dpc) -{ - PLIST_ENTRY pthis, pnext; - PUSB_EVENT pevent, pnext_event; - PUSB_DEV pdev = NULL; - PHUB2_EXTENSION hub_ext; - BOOLEAN bret; - PURB purb = NULL; - BOOLEAN processed; - PUSB_CTRL_SETUP_PACKET psetup; - PHCD hcd = NULL; - - USE_NON_PENDING_IRQL; - - if (dev_mgr == NULL) - return FALSE; - - bret = FALSE; - processed = FALSE; - - if (from_dpc) - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - else - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - - ListFirst(&dev_mgr->event_list, pthis); - - while ((pevent = (PUSB_EVENT) pthis)) - { - while (pevent->event == USB_EVENT_WAIT_RESET_PORT && - (pevent->flags & USB_EVENT_FLAG_QUE_TYPE) == USB_EVENT_FLAG_QUE_RESET) - { - - processed = TRUE; - - pdev = pevent->pdev; - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - pnext_event = pevent->pnext; - free_event(&dev_mgr->event_pool, pevent); - pevent = pnext_event; - if (pevent == NULL) - { - bret = FALSE; - break; - } - continue; - } - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (!purb) - { - if (from_dpc) - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - else - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - return FALSE; - } - - RtlZeroMemory(purb, sizeof(URB)); - - purb->data_buffer = NULL; - purb->data_length = 0; - purb->pendp = &pdev->default_endp; - - hub_ext = hub_ext_from_dev(pdev); - purb->context = hub_ext; - purb->pdev = pdev; - purb->completion = hub_start_reset_port_completion; - purb->reference = pevent->param; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - psetup->bmRequestType = 0x23; //host-device other recepient - psetup->bRequest = 3; //set_feature - psetup->wValue = USB_PORT_FEAT_RESET; - psetup->wIndex = (USHORT) pevent->param; - psetup->wLength = 0; - - purb->pirp = NULL; - hcd = pdev->hcd; - set_port_state(hub_ext->port_status_queue[pevent->param].port_flags, STATE_WAIT_RESET_COMPLETE); - unlock_dev(pdev, TRUE); - - bret = TRUE; - break; - } - - if (!processed) - { - ListNext(&dev_mgr->event_list, pthis, pnext); - pthis = pnext; - } - else - break; - } - - if (from_dpc) - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - else - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - if (processed && bret) - { - if (hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb) != STATUS_PENDING) - { - //fatal error - usb_free_mem(purb); - bret = FALSE; - //do not know what to do - } - } - - if (pthis == NULL) - bret = TRUE; - - return bret; -} - -// -//must have event-list-lock and dev-lock acquired -// -VOID -hub_post_esq_event(PUSB_DEV pdev, BYTE port_idx, PROCESS_EVENT pe) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_EVENT pevent; - - if (pdev == NULL || port_idx == 0 || pe == NULL) - return; - - dev_mgr = dev_mgr_from_dev(pdev); - - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (!pevent) return; - pevent->event = USB_EVENT_DEFAULT; - pevent->process_queue = event_list_default_process_queue; - pevent->process_event = pe; - pevent->context = (ULONG) hub_ext_from_dev(pdev); - pevent->param = port_idx; - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->pdev = pdev; - pevent->pnext = NULL; - - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - // usb_dbg_print( DBGLVL_MAXIMUM, ( "hub_post_esq_event(): current element in event list is 0x%x\n", - // dbg_count_list( &dev_mgr->event_list ) ) ); - return; -} - -// called only in hub_clear_port_feature_completion -BOOLEAN -hub_check_reset_port_status(PUSB_DEV pdev, LONG port_idx) -{ - PUSB_DEV_MANAGER dev_mgr; - PHUB2_EXTENSION hub_ext; - BOOLEAN bReset; - USB_PORT_STATUS port_status; - PUSB_DEV pdev2; - PURB purb2; - PHCD hcd; - - PUSB_CTRL_SETUP_PACKET psetup; - ULONG status; - - USE_BASIC_NON_PENDING_IRQL; - - //let's check whether the status change is a reset complete - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_check_reset_port_status(): entering...\n")); - dev_mgr = dev_mgr_from_dev(pdev); - KeAcquireSpinLockAtDpcLevel(&dev_mgr->dev_list_lock); - lock_dev(pdev, TRUE); - - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock); - return FALSE; - } - - hub_ext = hub_ext_from_dev(pdev); - port_status = psq_peek(&hub_ext->port_status_queue[port_idx], 0); - - bReset = FALSE; - if (port_status.wPortChange & USB_PORT_STAT_C_RESET) - bReset = TRUE; - - pdev2 = NULL; - purb2 = NULL; - - if (bReset - && (port_state(hub_ext->port_status_queue[port_idx].port_flags) == STATE_WAIT_RESET_COMPLETE) - && (psq_count(&hub_ext->port_status_queue[port_idx]) == 1)) - { - // a port-reset complete, empty the queue, keep the state - psq_outqueue(&hub_ext->port_status_queue[port_idx]); - set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_WAIT_ADDRESSED); - - //let's new a dev, and start the set-addr request - if (hub_ext->child_dev[port_idx] == 0) - { - pdev2 = hub_ext->child_dev[port_idx] = dev_mgr_alloc_device(dev_mgr, hcd); - if (pdev2) - { - purb2 = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (!purb2) - { - dev_mgr_free_device(dev_mgr, pdev2); - pdev2 = hub_ext->child_dev[port_idx] = NULL; - } - else - { - if (port_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) - { - pdev2->flags |= USB_DEV_FLAG_LOW_SPEED; - } - else if (port_status.wPortStatus & USB_PORT_STAT_HIGH_SPEED) - pdev2->flags |= USB_DEV_FLAG_HIGH_SPEED; - - pdev2->parent_dev = pdev; - pdev2->port_idx = (UCHAR) port_idx; - pdev2->ref_count++; - - RtlZeroMemory(purb2, sizeof(URB)); - - purb2->pdev = pdev2; - purb2->pendp = &pdev2->default_endp; - purb2->context = hub_ext; - purb2->completion = hub_set_address_completion; - - InitializeListHead(&purb2->trasac_list); - purb2->reference = port_idx; - purb2->pirp = 0; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb2->setup_packet; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_ADDRESS; - psetup->wValue = pdev2->dev_addr; - } - } - } - - if (pdev2 && purb2) - { - //creation success, emit the urb - //add to dev list - InsertTailList(&dev_mgr->dev_list, &pdev2->dev_link); - - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock); - - status = hcd->hcd_submit_urb(hcd, pdev2, purb2->pendp, purb2); - - lock_dev(pdev2, TRUE); - pdev2->ref_count--; - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_check_reset_port_status(): new dev ref_count=0x%x\n", pdev2->ref_count)); - unlock_dev(pdev2, TRUE); - - if (status != STATUS_PENDING) - { - usb_free_mem(purb2); - //??? do we need to lock it for SMP? - //dev_mgr_free_device( dev_mgr, pdev2 ), let dev_mgr_thread to clean it; - // disable the port - if (hub_disable_port_request(pdev, (UCHAR) port_idx) != STATUS_PENDING) - goto LBL_RESET_FAIL; - } - - return TRUE; - } - } - else - { - usb_dbg_print(DBGLVL_MAXIMUM, ("hub_check_reset_port_status(): not a correct reset status\n")); - } - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&dev_mgr->dev_list_lock); - -LBL_RESET_FAIL: - //Any event other than reset cause the reset process stall and another - //pending reset-port requeset is serviced - hub_reexamine_port_status_queue(pdev, port_idx, TRUE); - if (hub_remove_reset_event(pdev, port_idx, TRUE)) - hub_start_next_reset_port(dev_mgr, TRUE); - - return FALSE; -} - -VOID -hub_reexamine_port_status_queue(PUSB_DEV hub_dev, ULONG port_idx, BOOLEAN from_dpc) -{ - - PHUB2_EXTENSION hub_ext; - PUSB_DEV_MANAGER dev_mgr; - - USE_NON_PENDING_IRQL; - - if (hub_dev == NULL || port_idx == 0) - return; - - dev_mgr = dev_mgr_from_dev(hub_dev); - if (from_dpc) - KeAcquireSpinLockAtDpcLevel(&dev_mgr->event_list_lock); - else - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - - lock_dev(hub_dev, TRUE); - if (dev_state(hub_dev) != USB_DEV_STATE_ZOMB) - { - - hub_ext = hub_ext_from_dev(hub_dev); - if (psq_is_empty(&hub_ext->port_status_queue[port_idx])) - { - set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_IDLE); - - } - else - { - set_port_state(hub_ext->port_status_queue[port_idx].port_flags, STATE_EXAMINE_STATUS_QUE); - - hub_post_esq_event(hub_dev, (UCHAR) port_idx, hub_event_examine_status_que); - } - } - unlock_dev(hub_dev, TRUE); - - if (from_dpc) - KeReleaseSpinLockFromDpcLevel(&dev_mgr->event_list_lock); - else - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - return; -} - -BOOLEAN -hub_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - URB urb, *purb; - CHAR buf[512]; - DEV_HANDLE endp_handle; - USB_DEVICE_DESC dev_desc; - PUSB_CONFIGURATION_DESC pcfg_desc; - PUSB_INTERFACE_DESC pif_desc; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - LONG i, j, found, cfg_val = 0; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DEV pdev; - - - if (param == NULL || dev_handle == 0) - return FALSE; - - dev_mgr = param->dev_mgr; - - pcfg_desc = (PUSB_CONFIGURATION_DESC) buf; - endp_handle = dev_handle | 0xffff; - UsbBuildGetDescriptorRequest(&urb, - endp_handle, - USB_DT_DEVICE, 0, 0, (&dev_desc), (sizeof(USB_DEVICE_DESC)), NULL, 0, 0); - - status = usb_submit_urb(dev_mgr, &urb); - if (status != STATUS_SUCCESS) - return FALSE; - - found = FALSE; - for(i = 0; i < dev_desc.bNumConfigurations; i++) - { - UsbBuildGetDescriptorRequest(&urb, endp_handle, USB_DT_CONFIG, (USHORT) i, 0, buf, 512, NULL, 0, 0); - - status = usb_submit_urb(dev_mgr, &urb); - if (status != STATUS_SUCCESS) - { - return FALSE; - } - - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - return FALSE; - - pif_desc = (PUSB_INTERFACE_DESC) & buf[sizeof(USB_CONFIGURATION_DESC)]; - for(j = 0; j < pcfg_desc->bNumInterfaces; j++) - { - if (pif_desc->bInterfaceClass == USB_CLASS_HUB - && pif_desc->bInterfaceSubClass == 0 && pif_desc->bNumEndpoints == 1) - { - if ((pif_desc->bInterfaceProtocol > 0 && pif_desc->bInterfaceProtocol < 3) - || (pif_desc->bInterfaceProtocol == 0 && pdev->flags & USB_DEV_FLAG_HIGH_SPEED) - || (pif_desc->bInterfaceProtocol == 0 && !usb2(pdev->hcd))) - { - found = TRUE; - cfg_val = pcfg_desc->bConfigurationValue; - break; - } - } - if (usb_skip_if_and_altif((PBYTE *) & pif_desc) == FALSE) - { - break; - } - } - usb_unlock_dev(pdev); - - if (found) - break; - - if (usb_skip_one_config((PBYTE *) & pcfg_desc) == FALSE) - { - break; - } - - } - if (found) - { - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - - purb->endp_handle = endp_handle; - purb->data_buffer = NULL; - purb->data_length = 0; - purb->completion = hub_set_cfg_completion; - purb->context = dev_mgr; - purb->reference = (LONG) param->pdriver; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_CONFIGURATION; - psetup->wValue = (USHORT) cfg_val; - psetup->wIndex = 0; - psetup->wLength = 0; - - status = usb_submit_urb(dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - return FALSE; - } - return TRUE; - } - - return FALSE; -} - -VOID hub_set_interface_completion(PURB purb, PVOID pcontext); - -VOID -hub_set_cfg_completion(PURB purb, PVOID pcontext) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdriver; - ULONG endp_handle, dev_handle; - PUSB_CTRL_SETUP_PACKET psetup; - UCHAR if_idx = 0; - PUSB_DEV pdev; - PUSB_INTERFACE pif; - BOOLEAN high_speed, multiple_tt; - NTSTATUS status; - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || pcontext == NULL) - return; - - //pdev = NULL; - dev_mgr = (PUSB_DEV_MANAGER) pcontext; - endp_handle = purb->endp_handle; - dev_handle = endp_handle & 0xffff0000; - pdriver = (PUSB_DRIVER) purb->reference; - high_speed = FALSE; - multiple_tt = FALSE; - - if (purb->status != STATUS_SUCCESS) - { - goto LBL_ERROR; - } - - status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - goto LBL_ERROR; - } - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - usb_unlock_dev(pdev); - goto LBL_ERROR; - } - if (pdev->flags & USB_DEV_FLAG_HIGH_SPEED) - { - high_speed = TRUE; - hub_if_from_dev(pdev, pif); - if (pif->altif_count) - { - multiple_tt = TRUE; - if_idx = pif - &pdev->usb_config->interf[0]; - } - } - unlock_dev(pdev, TRUE); - usb_unlock_dev(pdev); - - if (!high_speed || !multiple_tt) - { - hub_set_interface_completion(purb, pcontext); - return; - } - - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - - // set the mult-tt if exist - purb->endp_handle = endp_handle; - purb->data_buffer = NULL; - purb->data_length = 0; - purb->completion = hub_set_interface_completion; - purb->context = dev_mgr; - purb->reference = (LONG) pdriver; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_INTERFACE; - psetup->wValue = (USHORT) 1; // alternate tt - psetup->wIndex = if_idx; // if index - psetup->wLength = 0; - - status = usb_submit_urb(dev_mgr, purb); - if (status == STATUS_PENDING) - return; - - LBL_ERROR: - usb_free_mem(purb); - purb = NULL; - return; -} - -void -hub_set_interface_completion(PURB purb, PVOID pcontext) -{ - NTSTATUS status; - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_DEV_MANAGER dev_mgr; - PBYTE dev_ext; - DEV_HANDLE endp_handle; - PUSB_DRIVER pdriver; - - if (purb == NULL || pcontext == NULL) - return; - - //pdev = NULL; - dev_mgr = (PUSB_DEV_MANAGER) pcontext; - endp_handle = purb->endp_handle; - pdriver = (PUSB_DRIVER) purb->reference; - - if (purb->status != STATUS_SUCCESS) - { - usb_free_mem(purb); - return; - } - - dev_ext = usb_alloc_mem(NonPagedPool, sizeof(HUB2_EXTENSION)); - if (dev_ext == NULL) - { - goto LBL_OUT; - } - - // - //acquire hub descriptor - // - RtlZeroMemory(dev_ext, sizeof(HUB2_EXTENSION)); - urb_init(purb); - - purb->data_buffer = (PUCHAR) & ((HUB2_EXTENSION *) dev_ext)->hub_desc; - purb->endp_handle = endp_handle; - purb->data_length = sizeof(USB_HUB_DESCRIPTOR); - purb->completion = hub_get_hub_desc_completion; - purb->context = (PVOID) dev_mgr; - purb->reference = (ULONG) dev_ext; - purb->pirp = (PIRP) pdriver; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - psetup->bmRequestType = 0xa0; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = (0x29 << 8); - psetup->wLength = sizeof(USB_HUB_DESCRIPTOR); - status = usb_submit_urb(dev_mgr, purb); - - if (status != STATUS_PENDING) - { - usb_free_mem(dev_ext); - goto LBL_OUT; - } - return; - -LBL_OUT: - //clear the dev_driver fields in the dev. - usb_free_mem(purb); - return; -} - - -VOID -hub_power_on_port_completion(PURB purb, PVOID pcontext) -{ - PUSB_DEV_MANAGER dev_mgr; - - if (purb == NULL) - return; - if (pcontext == NULL) - goto LBL_OUT; - - dev_mgr = (PUSB_DEV_MANAGER) pcontext; - - if (purb->status != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_power_on_port_completion(): port%d power on failed\n", purb->reference)); - } - else - { - usb_dbg_print(DBGLVL_MAXIMUM, - ("hub_power_on_port_completion(): port%d power on succeed\n", purb->reference)); - } - -LBL_OUT: - usb_free_mem(purb); - return; -} - -NTSTATUS -hub_power_on_port(PUSB_DEV pdev, UCHAR port_idx) -{ - NTSTATUS status; - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_DEV_MANAGER dev_mgr; - PURB purb; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - if (pdev == NULL || port_idx == 0) - return STATUS_INVALID_PARAMETER; - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return STATUS_NO_MEMORY; - - urb_init(purb); - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - - purb->completion = hub_power_on_port_completion; - purb->context = (PVOID) dev_mgr; - purb->reference = (ULONG) port_idx; - purb->pdev = pdev; - purb->pendp = &pdev->default_endp; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - psetup->bmRequestType = 0x23; - psetup->bRequest = USB_REQ_SET_FEATURE; - psetup->wValue = USB_PORT_FEAT_POWER; - psetup->wIndex = (WORD) port_idx; - psetup->wLength = 0; - - unlock_dev(pdev, FALSE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - - if (status != STATUS_PENDING) - { - goto LBL_OUT; - } - return STATUS_PENDING; - -LBL_OUT: - usb_free_mem(purb); - return status; -} - -void -hub_get_hub_desc_completion(PURB purb, PVOID pcontext) -{ - PUSB_DEV_MANAGER dev_mgr; - PHUB2_EXTENSION hub_ext; - PUSB_DEV pdev; - LONG i; - PUSB_INTERFACE pif = NULL; - ULONG status; - LONG port_count; - PUSB_DRIVER pdriver; - DEV_HANDLE dev_handle; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL) - { - return; - } - - dev_mgr = (PUSB_DEV_MANAGER) pcontext; - hub_ext = (PHUB2_EXTENSION) purb->reference; - pdriver = (PUSB_DRIVER) purb->pirp; - dev_handle = purb->endp_handle & 0xffff0000; - - if (pcontext == NULL || purb->reference == 0) - goto LBL_OUT; - - if (purb->status != STATUS_SUCCESS) - { - goto LBL_OUT; - } - - // obtain the pointer to the dev - status = usb_query_and_lock_dev(dev_mgr, purb->endp_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_unlock_dev(pdev); - goto LBL_OUT; - } - // safe to release the pdev ref since we are in urb completion - usb_unlock_dev(pdev); - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || - dev_mgr_set_driver(dev_mgr, dev_handle, pdriver, pdev) == FALSE) - { - unlock_dev(pdev, TRUE); - goto LBL_OUT; - } - - //transit the state to configured - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - - pdev->dev_ext = (PBYTE) hub_ext; - pdev->dev_ext_size = sizeof(HUB2_EXTENSION); - - port_count = hub_ext->port_count = hub_ext->hub_desc.bNbrPorts; - hub_ext->pdev = pdev; - for(i = 0; i < pdev->usb_config->if_count; i++) - { - pif = &pdev->usb_config->interf[i]; - if (pif->pusb_if_desc->bInterfaceClass == USB_CLASS_HUB - && pif->pusb_if_desc->bInterfaceSubClass == 0 - && pif->pusb_if_desc->bInterfaceProtocol < 3 && pif->pusb_if_desc->bNumEndpoints == 1) - { - hub_ext->pif = pif; - break; - } - } - for(i = 0; i < MAX_HUB_PORTS + 1; i++) - { - psq_init((PPORT_STATUS_QUEUE) hub_ext->port_status_queue); - } - - hub_ext->multiple_tt = (pif->pusb_if_desc->bInterfaceProtocol == 2); - - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - - hub_start_int_request(pdev); - - for(i = 0; i < port_count; i++) - { - hub_power_on_port(pdev, (UCHAR) (i + 1)); - } - return; - -LBL_OUT: - if (purb) - usb_free_mem(purb); - - if (hub_ext) - usb_free_mem(hub_ext); - return; -} - -BOOLEAN -hub_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - UNREFERENCED_PARAMETER(dev_mgr); - UNREFERENCED_PARAMETER(dev_handle); - return TRUE; -} - -BOOLEAN -hub_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PUSB_DEV pdev; - //special use of usb_query and lock dev - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) != STATUS_SUCCESS) - { - //will never be success, since the dev is already in zomb state - //at this point, the dev is valid, ref_count is of none use, - //no need to lock it - if (pdev) - { - usb_free_mem(pdev->dev_ext); - } - } - - return TRUE; -} - -static BOOLEAN -hub_lock_unlock_tt(PUSB_DEV pdev, UCHAR port_idx, UCHAR type, BOOLEAN lock) -{ - PHUB2_EXTENSION dev_ext; - PULONG pmap = NULL; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || port_idx > 127) - return FALSE; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - - dev_ext = hub_ext_from_dev(pdev); - if (dev_ext == NULL) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - if (type == USB_ENDPOINT_XFER_INT || type == USB_ENDPOINT_XFER_ISOC) - { - pmap = dev_ext->tt_status_map; - } - else if (type == USB_ENDPOINT_XFER_BULK || type == USB_ENDPOINT_XFER_CONTROL) - { - pmap = dev_ext->tt_bulk_map; - } - - if (lock) - { - if (pmap[port_idx >> 5] & (1 << port_idx)) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - pmap[port_idx >> 5] |= (1 << port_idx); - } - else - { - pmap[port_idx >> 5] &= ~(1 << port_idx); - } - - unlock_dev(pdev, FALSE); - return TRUE; -} - -BOOLEAN -hub_lock_tt(PUSB_DEV pdev, - UCHAR port_idx, - UCHAR type // transfer type - ) -{ - return hub_lock_unlock_tt(pdev, port_idx, type, TRUE); -} - -BOOLEAN -hub_unlock_tt(PUSB_DEV pdev, UCHAR port_idx, UCHAR type) -{ - return hub_lock_unlock_tt(pdev, port_idx, type, FALSE); -} - -VOID -hub_clear_tt_buffer_completion(PURB purb, PVOID context) -{ - PUSB_CTRL_SETUP_PACKET psetup; - PURB_HS_PIPE_CONTENT pipe_content; - PHUB2_EXTENSION hub_ext; - PHCD hcd; - - if (purb == NULL || context == NULL) - return; - - hub_ext = (PHUB2_EXTENSION) context; - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - pipe_content = (PURB_HS_PIPE_CONTENT) & purb->reference; - hub_unlock_tt(purb->pdev, (UCHAR) psetup->wIndex, (UCHAR) pipe_content->trans_type); - usb_free_mem(purb); - purb = NULL; - hcd = hub_ext->pdev->hcd; - - // let those blocked urbs ( sharing the same tt )have chance to be scheduled - if (hcd && usb2(hcd)) - hcd->hcd_submit_urb(hcd, NULL, NULL, NULL); - - return; -} - -// send CLEAR_TT_BUFFER to the hub -BOOLEAN -hub_clear_tt_buffer(PUSB_DEV pdev, URB_HS_PIPE_CONTENT pipe_content, UCHAR port_idx) -{ - PURB purb; - PUSB_CTRL_SETUP_PACKET psetup; - PHUB2_EXTENSION hub_ext; - PHCD hcd; - NTSTATUS status; - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL) - return FALSE; - - if (pipe_content.speed_high) - return FALSE; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - - hub_ext = hub_ext_from_dev(pdev); - if (hub_ext == NULL) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - - if (purb == NULL) - { - unlock_dev(pdev, FALSE); - return FALSE; - } - - RtlZeroMemory(purb, sizeof(URB)); - - purb->flags = 0; - purb->status = STATUS_SUCCESS; - purb->data_buffer = NULL; - purb->data_length = 0; // ( hub_ext->port_count + 7 ) / 8; - - // hub_if_from_dev( pdev, pif ); - purb->pendp = &pdev->default_endp; - purb->pdev = pdev; - - purb->completion = hub_clear_tt_buffer_completion; - purb->context = hub_ext; - purb->reference = *((PLONG) & pipe_content); - - purb->pirp = NULL; - hcd = pdev->hcd; - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - psetup->bmRequestType = 0x23; //host-device class other recepient - psetup->bRequest = HUB_REQ_CLEAR_TT_BUFFER; - psetup->wValue = (USHORT) ((pipe_content.endp_addr) | (pipe_content.dev_addr << 4) | - (pipe_content.trans_type << 10) | (pipe_content.trans_dir << 15)); - - if (hub_ext->multiple_tt) - { - psetup->wIndex = (USHORT) port_idx; - } - else - psetup->wIndex = 1; - - psetup->wLength = 0; - unlock_dev(pdev, FALSE); - - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - return FALSE; - } - return TRUE; -} - -VOID -hub_event_clear_tt_buffer(PUSB_DEV pdev, //always null. we do not use this param - ULONG event, - ULONG context, - ULONG param) -{ - UNREFERENCED_PARAMETER(event); - hub_clear_tt_buffer(pdev, *((PURB_HS_PIPE_CONTENT) & context), (UCHAR) param); - return; -} - -VOID -hub_post_clear_tt_event(PUSB_DEV pdev, BYTE port_idx, ULONG pipe) -{ - PUSB_DEV_MANAGER dev_mgr; - PUSB_EVENT pevent; - USE_NON_PENDING_IRQL; - - dev_mgr = dev_mgr_from_dev(pdev); - - KeAcquireSpinLock(&dev_mgr->event_list_lock, &old_irql); - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - return; - } - pevent = alloc_event(&dev_mgr->event_pool, 1); - if (pevent == NULL) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - TRAP(); - return; - } - - pevent->event = USB_EVENT_WAIT_RESET_PORT; - pevent->pdev = pdev; - pevent->context = pipe; - pevent->param = port_idx; - pevent->flags = USB_EVENT_FLAG_ACTIVE; - pevent->process_queue = event_list_default_process_queue; - pevent->process_event = hub_event_clear_tt_buffer; - pevent->pnext = NULL; - InsertTailList(&dev_mgr->event_list, &pevent->event_link); - - unlock_dev(pdev, TRUE); - KeReleaseSpinLock(&dev_mgr->event_list_lock, old_irql); - - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - return; -} - -BOOLEAN -init_irp_list(PIRP_LIST irp_list) -{ - LONG i; - KeInitializeSpinLock(&irp_list->irp_list_lock); - InitializeListHead(&irp_list->irp_busy_list); - InitializeListHead(&irp_list->irp_free_list); - irp_list->irp_list_element_array = - usb_alloc_mem(NonPagedPool, sizeof(IRP_LIST_ELEMENT) * MAX_IRP_LIST_SIZE); - - if (irp_list->irp_list_element_array == NULL) - return FALSE; - - RtlZeroMemory(irp_list->irp_list_element_array, sizeof(IRP_LIST_ELEMENT) * MAX_IRP_LIST_SIZE); - for(i = 0; i < MAX_IRP_LIST_SIZE; i++) - { - InsertTailList(&irp_list->irp_free_list, &irp_list->irp_list_element_array[i].irp_link); - } - irp_list->irp_free_list_count = MAX_IRP_LIST_SIZE; - return TRUE; -} - -VOID -destroy_irp_list(PIRP_LIST irp_list) -{ - InitializeListHead(&irp_list->irp_busy_list); - InitializeListHead(&irp_list->irp_free_list); - usb_free_mem(irp_list->irp_list_element_array); - irp_list->irp_list_element_array = NULL; - irp_list->irp_free_list_count = 0; - return; -} - -BOOLEAN -add_irp_to_list(PIRP_LIST irp_list, PIRP pirp, PURB purb) -{ - KIRQL old_irql; - PIRP_LIST_ELEMENT pile; - - if (irp_list == NULL || pirp == NULL || purb == NULL) - return FALSE; - - IoAcquireCancelSpinLock(&old_irql); - KeAcquireSpinLockAtDpcLevel(&irp_list->irp_list_lock); - - if (irp_list->irp_free_list_count == 0) - { - KeReleaseSpinLockFromDpcLevel(&irp_list->irp_list_lock); - IoReleaseCancelSpinLock(old_irql); - return FALSE; - } - pile = (PIRP_LIST_ELEMENT) RemoveHeadList(&irp_list->irp_free_list); - - pile->pirp = pirp; - pile->purb = purb; - - irp_list->irp_free_list_count--; - InsertTailList(&irp_list->irp_busy_list, &pile->irp_link); - (void)IoSetCancelRoutine(pirp, dev_mgr_cancel_irp); - - KeReleaseSpinLockFromDpcLevel(&irp_list->irp_list_lock); - IoReleaseCancelSpinLock(old_irql); - return TRUE; -} - -PURB -remove_irp_from_list(PIRP_LIST irp_list, - PIRP pirp, - PUSB_DEV_MANAGER dev_mgr //if dev_mgr is not NULL, the urb needs to be canceled - ) -{ - PIRP_LIST_ELEMENT pile; - PLIST_ENTRY pthis, pnext; - PURB purb; - DEV_HANDLE endp_handle; - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - PHCD hcd; - - USE_NON_PENDING_IRQL; - - if (irp_list == NULL || pirp == NULL) - return NULL; - - KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql); - - if (irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE) - { - KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql); - return NULL; - } - - purb = NULL; - ListFirst(&irp_list->irp_busy_list, pthis); - while (pthis) - { - pile = struct_ptr(pthis, IRP_LIST_ELEMENT, irp_link); - if (pile->pirp == pirp) - { - purb = pile->purb; - pile->pirp = NULL; - pile->purb = NULL; - RemoveEntryList(pthis); - InsertTailList(&irp_list->irp_free_list, pthis); - irp_list->irp_free_list_count++; - break; - } - ListNext(&irp_list->irp_busy_list, pthis, pnext); - pthis = pnext; - } - - if (purb == NULL) - { - // not found - KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql); - return NULL; - } - - endp_handle = purb->endp_handle; - KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql); - - if (dev_mgr) - { - // indicate we needs to cancel the urb, this condition happens only in cancel routine - // we should notice that even the hcd_cancel_urb is called, the irp may not be canceled - // if the urb does not exist in any queue of the host controller driver, indicating - // it is being processed by dpc. Thus, the dpc will certainly prevent the irp in - // completion from being canceled at the same time. On the other hand, if the - // hcd_cancel_urb succeeds, it either directly complete the irp or queue the dpc for - // irp completion. So, there won't be two simutaneous threads processing the same - // irp. - - if (usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev) != STATUS_SUCCESS) - return NULL; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - return NULL; - } - - hcd = pdev->hcd; - endp_from_handle(pdev, endp_handle, pendp); - unlock_dev(pdev, TRUE); - hcd->hcd_cancel_urb(hcd, pdev, pendp, purb); - usb_unlock_dev(pdev); - return NULL; - } - return purb; -} - -BOOLEAN -irp_list_empty(PIRP_LIST irp_list) -{ - KIRQL old_irql; - BOOLEAN ret; - KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql); - ret = (BOOLEAN) (irp_list->irp_free_list_count == MAX_IRP_LIST_SIZE); - KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql); - return ret; -} - -BOOLEAN -irp_list_full(PIRP_LIST irp_list) -{ - KIRQL old_irql; - BOOLEAN ret; - KeAcquireSpinLock(&irp_list->irp_list_lock, &old_irql); - ret = (BOOLEAN) (irp_list->irp_free_list_count == 0); - KeReleaseSpinLock(&irp_list->irp_list_lock, old_irql); - return ret; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/hub.h b/reactos/drivers/usb/nt4compat/usbdrv/hub.h deleted file mode 100644 index 940d401bfac..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/hub.h +++ /dev/null @@ -1,346 +0,0 @@ - -#ifndef __HUB_H__ -#define __HUB_H__ - -/* - * Hub Class feature numbers - */ -#define C_HUB_LOCAL_POWER 0 -#define C_HUB_OVER_CURRENT 1 - -/* - * Port feature numbers - */ -#define USB_PORT_FEAT_CONNECTION 0 -#define USB_PORT_FEAT_ENABLE 1 -#define USB_PORT_FEAT_SUSPEND 2 -#define USB_PORT_FEAT_OVER_CURRENT 3 -#define USB_PORT_FEAT_RESET 4 -#define USB_PORT_FEAT_POWER 8 -#define USB_PORT_FEAT_LOWSPEED 9 -#define USB_PORT_FEAT_C_CONNECTION 16 -#define USB_PORT_FEAT_C_ENABLE 17 -#define USB_PORT_FEAT_C_SUSPEND 18 -#define USB_PORT_FEAT_C_OVER_CURRENT 19 -#define USB_PORT_FEAT_C_RESET 20 - -/* wPortStatus bits */ -#define USB_PORT_STAT_CONNECTION 0x0001 -#define USB_PORT_STAT_ENABLE 0x0002 -#define USB_PORT_STAT_SUSPEND 0x0004 -#define USB_PORT_STAT_OVERCURRENT 0x0008 -#define USB_PORT_STAT_RESET 0x0010 -#define USB_PORT_STAT_POWER 0x0100 -#define USB_PORT_STAT_LOW_SPEED 0x0200 - -/* usb 2.0 features */ -#define USB_PORT_STAT_HIGH_SPEED 0x0400 -#define USB_PORT_STAT_PORT_TEST 0x0800 -#define USB_PORT_STAT_PORT_INDICATOR 0x1000 - -/* wPortChange bits */ -#define USB_PORT_STAT_C_CONNECTION 0x0001 -#define USB_PORT_STAT_C_ENABLE 0x0002 -#define USB_PORT_STAT_C_SUSPEND 0x0004 -#define USB_PORT_STAT_C_OVERCURRENT 0x0008 -#define USB_PORT_STAT_C_RESET 0x0010 - -/* wHubCharacteristics (masks) */ -#define HUB_CHAR_LPSM 0x0003 -#define HUB_CHAR_COMPOUND 0x0004 -#define HUB_CHAR_OCPM 0x0018 - -/* - *Hub Status & Hub Change bit masks - */ -#define HUB_STATUS_LOCAL_POWER 0x0001 -#define HUB_STATUS_OVERCURRENT 0x0002 - -#define HUB_CHANGE_LOCAL_POWER 0x0001 -#define HUB_CHANGE_OVERCURRENT 0x0002 - -#define HUB_DESCRIPTOR_MAX_SIZE 39 /* enough for 127 ports on a hub */ - -#define MAX_HUB_PORTS 8 -#define USB_HUB_INTERVAL 0xff - -#define USB_PORT_FLAG_STATE_MASK ( 0xf << 16 ) -#define USB_PORT_FLAG_ENABLE ( 0x1 << 16 ) -#define USB_PORT_FLAG_DISABLE ( 0x2 << 16 ) -#define USB_PORT_FLAG_DISCONNECT ( 0x3 << 16 ) - -#define USB_PORT_QUE_STATE_MASK 0xff // for detail, refer to document.txt -#define STATE_IDLE 0x00 -#define STATE_EXAMINE_STATUS_QUE 0x01 // set when post a event to examine the status queue -#define STATE_WAIT_STABLE 0x02 // set when a new connection comes and about to wait some ms -#define STATE_WAIT_RESET 0x03 // set when dev stable and about to reset, may pending in the event queue -#define STATE_WAIT_RESET_COMPLETE 0x04 // set when reset signal is about to assert on the port -#define STATE_WAIT_ADDRESSED 0x05 // set when reset complete and before address is assigned - -#define port_state( port_FLAG ) \ -( port_FLAG & USB_PORT_QUE_STATE_MASK ) - -#define set_port_state( port_FLAG, stATE ) \ -{ port_FLAG = ( port_FLAG & (~USB_PORT_QUE_STATE_MASK ) ) | ( stATE & USB_PORT_QUE_STATE_MASK ) ;} - -#define default_endp_handle( endp_HANDLE ) \ -( ( endp_HANDLE & 0xffff ) == 0xffff ) - -#define is_if_dev( pdev ) ( pdev->flags & USB_DEV_FLAG_IF_DEV ) - -#define is_composite_dev( pdev ) \ -( is_if_dev( pdev ) == FALSE \ -&& pdev->pusb_dev_desc->bDeviceClass == 0 \ -&& pdev->pusb_dev_desc->bDeviceSubClass == 0 ) - -#define dev_handle_from_dev( pdev ) ( pdev->dev_id << 16 ) -#define hub_ext_from_dev( pdEV ) ( ( PHUB2_EXTENSION )pdEV->dev_ext ) - -#pragma pack( push, hub_align, 1 ) -typedef struct _USB_PORT_STATUS -{ - USHORT wPortStatus; - USHORT wPortChange; - -} USB_PORT_STATUS, *PUSB_PORT_STATUS; - - -typedef struct _USB_HUB_STATUS -{ - USHORT wHubStatus; - USHORT wHubChange; - -} USB_HUB_STATUS, *PUSB_HUB_STATUS; - - -typedef struct _USB_HUB_DESCRIPTOR -{ - BYTE bLength; - BYTE bDescriptorType; - BYTE bNbrPorts; - USHORT wHubCharacteristics; - BYTE bPwrOn2PwrGood; - BYTE bHubContrCurrent; - - /* DeviceRemovable and PortPwrCtrlMask want to be variable-length - bitmaps that hold max 256 entries, but for now they're ignored */ - BYTE bitmap[0]; -} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR; -#pragma pack( pop, hub_align ) - -typedef struct _PORT_STATUS_QUEUE -{ - USB_PORT_STATUS port_status[ 4 ]; - BYTE status_count; - ULONG port_flags; - -} PORT_STATUS_QUEUE, *PPORT_STATUS_QUEUE; - -VOID -psq_init( -PPORT_STATUS_QUEUE psq -); - -BOOLEAN -psq_enqueue( -PPORT_STATUS_QUEUE psq, -ULONG status -); -ULONG -psq_outqueue( -PPORT_STATUS_QUEUE psq -); //return 0xffffffff if no element - -BOOLEAN -psq_push( -PPORT_STATUS_QUEUE psq, -ULONG status -); - -#define psq_is_empty( pSQ ) ( ( pSQ )->status_count == 0 ) -#define psq_is_full( pSQ ) ( ( pSQ )->status_count == 4 ) -#define psq_count( psq ) ( ( psq )->status_count ) -#define psq_peek( psq, i ) \ -( ( ( ULONG )i ) < 3 ? ( psq )->port_status[ i ] : ( psq )->port_status[ 3 ] ) - -#define MAX_DEVS 127 -#define EHCI_MAX_ROOT_PORTS 15 - -typedef struct _HUB_EXTENSION -{ - - LONG port_count; - PUSB_DEV child_dev[ MAX_HUB_PORTS + 1 ]; - - PORT_STATUS_QUEUE port_status_queue[ MAX_HUB_PORTS + 1]; - PUSB_DEV pdev; - PUSB_INTERFACE pif; - BYTE int_data_buf[ 64 ]; - - USB_HUB_STATUS hub_status; - USB_PORT_STATUS port_status; //working data buf for get port feature - - USB_PORT_STATUS rh_port1_status; //working buf for get rh port1 feature - USB_PORT_STATUS rh_port2_status; //working buf for get rh port2 feature - - USB_HUB_DESCRIPTOR hub_desc; - -} HUB_EXTENSION, *PHUB_EXTENSION; - -typedef struct _HUB2_PORT_TT -{ - ULONG tt_busy : 1; - -} HUB2_PORT_TT, *PHUB2_PORT_TT; - -typedef struct _HUB2_EXTENSION -{ - - LONG port_count; - PUSB_DEV child_dev[ MAX_HUB_PORTS + 1 ]; - - PORT_STATUS_QUEUE port_status_queue[ MAX_HUB_PORTS + 1]; - - PUSB_DEV pdev; - PUSB_INTERFACE pif; - BYTE int_data_buf[ 32 ]; // for ports up to 127 - - USB_HUB_STATUS hub_status; - USB_PORT_STATUS port_status; //working data buf for get port feature - - USB_PORT_STATUS rh_port_status[ EHCI_MAX_ROOT_PORTS + 1 ]; //working buf for get rh ports feature - - UCHAR multiple_tt; // boolean - ULONG tt_status_map[ 4 ]; // bit map to indicate the indexed tt's periodic buffer busy or not - ULONG tt_bulk_map[ 4 ]; // bit map to indicate the indexed tt's bulk/control buffer busy or not - USB_HUB_DESCRIPTOR hub_desc; - -} HUB2_EXTENSION, *PHUB2_EXTENSION; - - -VOID -event_list_default_process_queue( -PLIST_HEAD event_list, -PUSB_EVENT_POOL event_pool, -PUSB_EVENT usb_event, -PUSB_EVENT out_event -); - -VOID -event_list_default_process_event( -PUSB_DEV dev, -ULONG event, -ULONG context, -ULONG param -); - -// root hub routines and definitions - -#define RH_INTERVAL ( USB_HUB_INTERVAL / DEV_MGR_TIMER_INTERVAL_MS ) - -BOOLEAN -rh_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -rh_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -rh_destroy( -PUSB_DEV pdev -); - -VOID -rh_timer_svc( -PUSB_DEV dev, -PVOID context -); - -BOOLEAN -rh_submit_urb( -PUSB_DEV pdev, -PURB urb -); - -BOOLEAN -hub_init( -PUSB_DEV pdev -); - -BOOLEAN -hub_destroy( -PUSB_DEV pdev -); - -BOOLEAN -hub_lock_tt( -PUSB_DEV pdev, -UCHAR port_idx, -UCHAR type // transfer type -); - -BOOLEAN -hub_unlock_tt( -PUSB_DEV pdev, -UCHAR port_idx, -UCHAR type -); - - -VOID -hub_post_clear_tt_event( -PUSB_DEV pdev, -BYTE port_idx, -ULONG pipe -); - -BOOLEAN -compdev_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -compdev_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -gendrv_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -gendrv_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -gendrv_if_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -gendrv_if_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN hub_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); -BOOLEAN hub_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); -BOOLEAN hub_remove_reset_event(PUSB_DEV pdev, ULONG port_idx, BOOLEAN from_dpc); -BOOLEAN hub_start_next_reset_port(PUSB_DEV_MANAGER dev_mgr, BOOLEAN from_dpc); -NTSTATUS hub_start_int_request(PUSB_DEV pdev); - -#endif - - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/irplist.h b/reactos/drivers/usb/nt4compat/usbdrv/irplist.h deleted file mode 100644 index f6dbe064d5e..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/irplist.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef __IRPLIST_H -#define __IRPLIST_H - -#define MAX_IRP_LIST_SIZE 32 - -typedef struct _IRP_LIST_ELEMENT -{ - LIST_ENTRY irp_link; - PIRP pirp; - struct _URB *purb; - -} IRP_LIST_ELEMENT, *PIRP_LIST_ELEMENT; - -typedef struct _IRP_LIST -{ - KSPIN_LOCK irp_list_lock; - LIST_HEAD irp_busy_list; - LONG irp_free_list_count; - LIST_HEAD irp_free_list; - PIRP_LIST_ELEMENT irp_list_element_array; - -} IRP_LIST, *PIRP_LIST; - -BOOLEAN -init_irp_list( -PIRP_LIST irp_list -); - -VOID -destroy_irp_list( -PIRP_LIST irp_list -); - -BOOLEAN -add_irp_to_list( -PIRP_LIST irp_list, -PIRP pirp, -PURB purb -); - -PURB -remove_irp_from_list( -PIRP_LIST irp_list, -PIRP pirp, -struct _USB_DEV_MANAGER *dev_mgr -); - -BOOLEAN -irp_list_empty( -PIRP_LIST irp_list -); - -BOOLEAN -irp_list_full( -PIRP_LIST irp_list -); - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/keyboard.c b/reactos/drivers/usb/nt4compat/usbdrv/keyboard.c deleted file mode 100644 index cc61daac0c9..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/keyboard.c +++ /dev/null @@ -1,581 +0,0 @@ -/* - * PROJECT: ReactOS USB Drivers - * COPYRIGHT: GPL - See COPYING in the top level directory - * FILE: keyboard.c - * PURPOSE: Generic USB keyboard driver - * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) - */ - -#include "usbdriver.h" - -NTSTATUS -AddRegistryEntry(IN PCWSTR PortTypeName, - IN PUNICODE_STRING DeviceName, - IN PCWSTR RegistryPath); - -BOOLEAN kbd_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN kbd_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN kbd_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -VOID kbd_irq(PURB purb, PVOID pcontext); -static NTSTATUS -KeyboardCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PKEYBOARD_DRVR_EXTENSION DriverExtension); -void * memscan(void * addr, int c, size_t size); - -static UCHAR usb_kbd_keycode[256] = -{ - 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, - 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, - 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, - 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, - 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, - 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, - 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, - 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, - 150,158,159,128,136,177,178,176,142,152,173,140 -}; - -/* This structure starts with the same layout as KEYBOARD_INDICATOR_TRANSLATION */ -typedef struct _LOCAL_KEYBOARD_INDICATOR_TRANSLATION { - USHORT NumberOfIndicatorKeys; - INDICATOR_LIST IndicatorList[3]; -} LOCAL_KEYBOARD_INDICATOR_TRANSLATION, *PLOCAL_KEYBOARD_INDICATOR_TRANSLATION; - -static LOCAL_KEYBOARD_INDICATOR_TRANSLATION IndicatorTranslation = { 3, { - {0x3A, KEYBOARD_CAPS_LOCK_ON}, - {0x45, KEYBOARD_NUM_LOCK_ON}, - {0x46, KEYBOARD_SCROLL_LOCK_ON}}}; - - -BOOLEAN -kbd_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PKEYBOARD_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //init driver structure, no PNP table functions - pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_HID; // Interface Class - pdriver->driver_desc.if_sub_class = 1; // Interface SubClass - pdriver->driver_desc.if_protocol = 1; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB Keyboard driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_HID; - pdriver->driver_desc.dev_sub_class = 1; // Device Subclass - pdriver->driver_desc.dev_protocol = 1; // Protocol Info. - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(KEYBOARD_DRVR_EXTENSION)); - if (!pdriver->driver_ext) return FALSE; - pdriver->driver_ext_size = sizeof(KEYBOARD_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, sizeof(KEYBOARD_DRVR_EXTENSION)); - pdrvr_ext = (PKEYBOARD_DRVR_EXTENSION) pdriver->driver_ext; - pdrvr_ext->dev_mgr = dev_mgr; - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = kbd_connect; - pdriver->disp_tbl.dev_disconnect = kbd_disconnect; - pdriver->disp_tbl.dev_stop = kbd_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - // Create the device - KeyboardCreateDevice(dev_mgr->usb_driver_obj, pdrvr_ext); - - usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_driver_init(): keyboard driver is initialized\n")); - return TRUE; -} - -BOOLEAN -kbd_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - //PMOUSE_DRVR_EXTENSION pdrvr_ext; - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext; - //umss_delete_port_device(pdrvr_ext->port_dev_obj); - //pdrvr_ext->port_dev_obj = NULL; - - //ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE); - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_driver_destroy(): keyboard driver is destroyed\n")); - return TRUE; -} - -BOOLEAN -kbd_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - PURB purb; - NTSTATUS status; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdrvr; - PUSB_DEV pdev; - PKEYBOARD_DRVR_EXTENSION pdev_ext; - PUSB_ENDPOINT_DESC pendp_desc = NULL; - ULONG MaxPacketSize; - - usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_connect(): entering...\n")); - - dev_mgr = param->dev_mgr; - pdrvr = param->pdriver; - pdev_ext = (PKEYBOARD_DRVR_EXTENSION)pdrvr->driver_ext; - pdev_ext->dev_handle = dev_handle; - - // Lock USB Device - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MEDIUM, ("kbd_connect(): unable to query&lock device, status=0x%x\n", status)); - return FALSE; - } - - // Get pointer to the endpoint descriptor - pendp_desc = pdev->usb_config->interf[0].endp[0].pusb_endp_desc; - - // Store max packet size - MaxPacketSize = pendp_desc->wMaxPacketSize; - if (MaxPacketSize > 8) - MaxPacketSize = 8; - - // Unlock USB Device - usb_unlock_dev(pdev); - - // Send interrupt URB - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - RtlZeroMemory(purb, sizeof(URB)); - - RtlZeroMemory(pdev_ext->kbd_old, 8); - - // Build a URB for our interrupt transfer - UsbBuildInterruptOrBulkTransferRequest(purb, - usb_make_handle((dev_handle >> 16), 0, 0), - (PUCHAR)&pdev_ext->kbd_data, - MaxPacketSize, //use max packet size - kbd_irq, - pdev_ext->device_ext, - 0); - - // Call USB driver stack - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - } - - return TRUE; -} - -VOID -kbd_irq(PURB purb, PVOID pcontext) -{ - KEYBOARD_INPUT_DATA KeyboardInputData[20]; - ULONG DataPrepared=0, DataConsumed, i; - UCHAR ScanCode; - NTSTATUS status; - PKEYBOARD_DRVR_EXTENSION pdev_ext; - PKEYBOARD_DEVICE_EXTENSION DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)pcontext; - PUCHAR data, data_old; - usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_irq(): called\n")); - - ASSERT(purb); - - if (purb->status != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("kbd_irq(): purb->status 0x%08X\n", purb->status)); - return; - } - - pdev_ext = DeviceExtension->DriverExtension; - data = pdev_ext->kbd_data; - data_old = pdev_ext->kbd_old; - - usb_dbg_print(DBGLVL_MAXIMUM, ("Kbd input: %d %d %d %d %d %d %d %d\n", data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7])); - - // Zero initial kbd data array - RtlZeroMemory(&KeyboardInputData[0], sizeof(KeyboardInputData)); - - // Scan modifier keys - for (i=0; i<8; i++) - { - ScanCode = usb_kbd_keycode[i + 224]; - - if (((data[0] >> i) & 1) != ((data_old[0] >> i) & 1)) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key p/r %d\n", ScanCode, (data[0] >> i) & 1)); - - KeyboardInputData[DataPrepared].MakeCode = ScanCode; - if ((data[0] >> i) & 1) - KeyboardInputData[DataPrepared].Flags |= KEY_MAKE; - else - KeyboardInputData[DataPrepared].Flags |= KEY_BREAK; - DataPrepared++; - } - } - - // Scan normal keys - for (i=2; i<8; i++) - { - if (data_old[i] > 3 && memscan(data + 2, data_old[i], 6) == data + 8) - { - if (usb_kbd_keycode[data_old[i]]) - { - // key released - usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key released 1\n", usb_kbd_keycode[data_old[i]])); - - KeyboardInputData[DataPrepared].MakeCode = usb_kbd_keycode[data_old[i]]; - KeyboardInputData[DataPrepared].Flags |= KEY_BREAK; - DataPrepared++; - } - } - - if (data[i] > 3 && memscan(data_old + 2, data[i], 6) == data_old + 8) - { - if (usb_kbd_keycode[data[i]]) - { - // key pressed - usb_dbg_print(DBGLVL_MAXIMUM, ("Scan %d key pressed 1\n", usb_kbd_keycode[data[i]])); - - KeyboardInputData[DataPrepared].MakeCode = usb_kbd_keycode[data[i]]; - KeyboardInputData[DataPrepared].Flags |= KEY_MAKE; - DataPrepared++; - } - } - } - - // Commit the input data somewhere... - if (DeviceExtension->ConnectData.ClassService && DataPrepared > 0) - { - KIRQL OldIrql; - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)( - DeviceExtension->ConnectData.ClassDeviceObject, - &KeyboardInputData[0], - (&KeyboardInputData[0])+DataPrepared, - &DataConsumed); - KeLowerIrql(OldIrql); - } - - // Save old keyboard data - RtlCopyMemory(pdev_ext->kbd_old, data, 8); - - // resubmit the urb - status = usb_submit_urb(pdev_ext->dev_mgr, purb); -} - -BOOLEAN -kbd_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(dev_mgr); - return TRUE; -} - -BOOLEAN -kbd_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PDEVICE_OBJECT dev_obj; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - pdev = NULL; - //special use of the lock dev, simply use this routine to get the dev - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (pdev == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - // must be a bug - TRAP(); - usb_unlock_dev(pdev); - } - pdrvr = pdev->dev_driver; - dev_obj = pdev->dev_obj; - pdev = NULL; - - return TRUE;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE); -} - -VOID -kbd_setleds(PKEYBOARD_DEVICE_EXTENSION DeviceExtension) -{ - PURB Urb; - PUSB_CTRL_SETUP_PACKET Setup; - NTSTATUS Status; - - // Set LEDs request - Urb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (!Urb) return; - RtlZeroMemory(Urb, sizeof(URB)); - - DeviceExtension->DriverExtension->leds_old = 0; - DeviceExtension->DriverExtension->leds = 7; - - // Convert from LedFlags to USB format - //DeviceExtension->KeyboardIndicators.LedFlags - - // Build a URB for setting LEDs - Setup = (PUSB_CTRL_SETUP_PACKET)Urb->setup_packet; - urb_init((Urb)); - - Urb->endp_handle = usb_make_handle((DeviceExtension->DriverExtension->dev_handle >> 16), 0, 0) | 0xffff; - Urb->data_buffer = &DeviceExtension->DriverExtension->leds; - Urb->data_length = 1; - Urb->completion = NULL; - Urb->context = NULL; - Urb->reference = 0; - Setup->bmRequestType = USB_DT_HID; - Setup->bRequest = USB_REQ_SET_CONFIGURATION; - Setup->wValue = USB_DT_CONFIG << 8; - Setup->wIndex = 0; - Setup->wLength = 1; - - // Call USB driver stack - Status = usb_submit_urb(DeviceExtension->DriverExtension->dev_mgr, Urb); - if (Status != STATUS_PENDING) - { - usb_free_mem(Urb); - } -} - -// Dispatch routine for our IRPs -NTSTATUS -KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; - PKEYBOARD_DEVICE_EXTENSION DeviceExtension; - - DeviceExtension = DeviceObject->DeviceExtension; - - usb_dbg_print(DBGLVL_MAXIMUM, ("KbdDispatch(DO %p, code 0x%lx) called\n", - DeviceObject, - IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)); - - if (DeviceObject == DeviceExtension->Fdo) - { - // it's keyboard's IOCTL - PIO_STACK_LOCATION Stack; - - Irp->IoStatus.Information = 0; - Stack = IoGetCurrentIrpStackLocation(Irp); - - switch (Stack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_KEYBOARD_CONNECT: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_INTERNAL_KEYBOARD_CONNECT\n")); - if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) { - usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_INTERNAL_KEYBOARD_CONNECT " - "invalid buffer size\n")); - Status = STATUS_INVALID_PARAMETER; - break; - } - - RtlCopyMemory(&DeviceExtension->ConnectData, - Stack->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - - Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_ATTRIBUTES: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n")); - if (Stack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_ATTRIBUTES)) { - usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_QUERY_ATTRIBUTES: " - "invalid buffer size\n")); - Status = STATUS_BUFFER_TOO_SMALL; - break; - } - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardAttributes, - sizeof(KEYBOARD_ATTRIBUTES));*/ - - Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_INDICATORS: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_INDICATORS\n")); - if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS)) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - RtlCopyMemory( - Irp->AssociatedIrp.SystemBuffer, - &DeviceExtension->KeyboardIndicators, - sizeof(KEYBOARD_INDICATOR_PARAMETERS)); - Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS); - Status = STATUS_SUCCESS; - } - break; - case IOCTL_KEYBOARD_QUERY_TYPEMATIC: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_QUERY_TYPEMATIC\n")); - if (Stack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_QUERY_TYPEMATIC: " - "invalid buffer size\n")); - Status = STATUS_BUFFER_TOO_SMALL; - break; - } - /*RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, - &DevExt->KeyboardTypematic, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/ - - Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_SET_INDICATORS: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_SET_INDICATORS\n")); - if (Stack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_INDICATOR_PARAMETERS)) { - usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_SET_INDICTATORS: " - "invalid buffer size\n")); - Status = STATUS_BUFFER_TOO_SMALL; - break; - } - - RtlCopyMemory(&DeviceExtension->KeyboardIndicators, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_INDICATOR_PARAMETERS)); - - //DPRINT("%x\n", DevExt->KeyboardIndicators.LedFlags); - kbd_setleds(DeviceExtension); - Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_SET_TYPEMATIC: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_KEYBOARD_SET_TYPEMATIC\n")); - if (Stack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) { - usb_dbg_print(DBGLVL_MAXIMUM, ("Keyboard IOCTL_KEYBOARD_SET_TYPEMATIC " - "invalid buffer size\n")); - Status = STATUS_BUFFER_TOO_SMALL; - break; - } - - /*RtlCopyMemory(&DevExt->KeyboardTypematic, - Irp->AssociatedIrp.SystemBuffer, - sizeof(KEYBOARD_TYPEMATIC_PARAMETERS));*/ - - Status = STATUS_SUCCESS; - break; - case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION: - if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)) - { - Status = STATUS_BUFFER_TOO_SMALL; - } - else - { - RtlCopyMemory( - Irp->AssociatedIrp.SystemBuffer, - &IndicatorTranslation, - sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION)); - Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION); - Status = STATUS_SUCCESS; - } - break; - default: - Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST; - break; - } - } - - if (Status == STATUS_INVALID_DEVICE_REQUEST) - { - usb_dbg_print(DBGLVL_MINIMUM, ("Invalid internal device request!\n")); - } - - Irp->IoStatus.Status = Status; - if (Status != STATUS_PENDING) - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} - -static NTSTATUS -KeyboardCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PKEYBOARD_DRVR_EXTENSION DriverExtension) -{ - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardPortUSB"); - PKEYBOARD_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT Fdo; - NTSTATUS Status; - - Status = AddRegistryEntry(L"KeyboardPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver"); - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("AddRegistryEntry() for usb keyboard driver failed with status 0x%08lx\n", Status)); - return Status; - } - - Status = IoCreateDevice(DriverObject, - sizeof(KEYBOARD_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_KEYBOARD, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("IoCreateDevice() for usb keyboard driver failed with status 0x%08lx\n", Status)); - return Status; - } - DeviceExtension = (PKEYBOARD_DEVICE_EXTENSION)Fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(KEYBOARD_DEVICE_EXTENSION)); - - DeviceExtension->hdr.dispatch = KbdDispatch; - DeviceExtension->DriverExtension = DriverExtension; - DriverExtension->device_ext = DeviceExtension; - - DeviceExtension->Fdo = Fdo; - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - usb_dbg_print(DBGLVL_MEDIUM, ("Created keyboard Fdo: %p\n", Fdo)); - - return STATUS_SUCCESS; -} - -/** - * memscan - Find a character in an area of memory. - * @addr: The memory area - * @c: The byte to search for - * @size: The size of the area. - * - * returns the address of the first occurrence of @c, or 1 byte past - * the area if @c is not found - */ -void * memscan(void * addr, int c, size_t size) -{ - unsigned char * p = (unsigned char *) addr; - - while (size) { - if (*p == c) - return (void *) p; - p++; - size--; - } - return (void *) p; -} - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/keyboard.h b/reactos/drivers/usb/nt4compat/usbdrv/keyboard.h deleted file mode 100644 index fc4105c5696..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/keyboard.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __KEYBOARD_H__ -#define __KEYBOARD_H__ - -#include "kbdmou.h" - -typedef struct _KEYBOARD_DRVR_EXTENSION -{ - PUSB_INTERFACE_DESC pif_desc; - DEV_HANDLE dev_handle; - - PUSB_DEV_MANAGER dev_mgr; - - UCHAR kbd_data[8]; - UCHAR kbd_old[8]; - - UCHAR leds; - UCHAR leds_old; - - struct _KEYBOARD_DEVICE_EXTENSION *device_ext; // back pointer -} KEYBOARD_DRVR_EXTENSION, *PKEYBOARD_DRVR_EXTENSION; - -typedef struct _KEYBOARD_DEVICE_EXTENSION -{ - DEVEXT_HEADER hdr; // mandatory header - PKEYBOARD_DRVR_EXTENSION DriverExtension; - KEYBOARD_INDICATOR_PARAMETERS KeyboardIndicators; - CONNECT_DATA ConnectData; - PDEVICE_OBJECT Fdo; -} KEYBOARD_DEVICE_EXTENSION, *PKEYBOARD_DEVICE_EXTENSION; - -BOOLEAN -kbd_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); - -BOOLEAN -kbd_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/mouse.c b/reactos/drivers/usb/nt4compat/usbdrv/mouse.c deleted file mode 100644 index 1dc7442dc33..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/mouse.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - * PROJECT: ReactOS USB Drivers - * COPYRIGHT: GPL - See COPYING in the top level directory - * FILE: mouse.c - * PURPOSE: Generic USB mouse driver - * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) - */ - -#include "usbdriver.h" - -BOOLEAN mouse_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN mouse_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -VOID mouse_irq(PURB purb, PVOID pcontext); -static NTSTATUS MouseCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PMOUSE_DRVR_EXTENSION DriverExtension); - -BOOLEAN -mouse_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PMOUSE_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //init driver structure, no PNP table functions - pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 1; // Configuration Value - pdriver->driver_desc.if_num = 1; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_HID; // Interface Class - pdriver->driver_desc.if_sub_class = 1; // Interface SubClass - pdriver->driver_desc.if_protocol = 2; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB Mouse driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_HID; - pdriver->driver_desc.dev_sub_class = 1; // Device Subclass - pdriver->driver_desc.dev_protocol = 2; // Protocol Info. - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(MOUSE_DRVR_EXTENSION)); - if (!pdriver->driver_ext) return FALSE; - - pdriver->driver_ext_size = sizeof(MOUSE_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, sizeof(MOUSE_DRVR_EXTENSION)); - pdrvr_ext = (PMOUSE_DRVR_EXTENSION) pdriver->driver_ext; - pdrvr_ext->dev_mgr = dev_mgr; - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = mouse_connect; - pdriver->disp_tbl.dev_disconnect = mouse_disconnect; - pdriver->disp_tbl.dev_stop = mouse_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - // Create the device - MouseCreateDevice(dev_mgr->usb_driver_obj, pdrvr_ext); - - usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_driver_init(): mouse driver is initialized\n")); - return TRUE; -} - -BOOLEAN -mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - //PMOUSE_DRVR_EXTENSION pdrvr_ext; - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext; - //umss_delete_port_device(pdrvr_ext->port_dev_obj); - //pdrvr_ext->port_dev_obj = NULL; - - //ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE); - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_driver_destroy(): mouse driver is destroyed\n")); - return TRUE; -} - -BOOLEAN -mouse_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - PURB purb; - NTSTATUS status; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdrvr; - PUSB_DEV pdev; - PMOUSE_DRVR_EXTENSION pdev_ext; -// LONG i; - PUSB_ENDPOINT_DESC pendp_desc = NULL; - ULONG MaxPacketSize; - - usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_connect(): entering...\n")); - - dev_mgr = param->dev_mgr; - pdrvr = param->pdriver; - pdev_ext = (PMOUSE_DRVR_EXTENSION)pdrvr->driver_ext; - - // Lock USB Device - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - { - //usb_free_mem(desc_buf); - usb_dbg_print(DBGLVL_MEDIUM, ("mouse_connect(): unable to query&lock device, status=0x%x\n", status)); - return FALSE; - } - - // Get pointer to the endpoint descriptor - pendp_desc = pdev->usb_config->interf[0].endp[0].pusb_endp_desc; - - // Store max packet size - MaxPacketSize = pendp_desc->wMaxPacketSize; - if (MaxPacketSize > 8) - MaxPacketSize = 8; - - // Unlock USB Device - usb_unlock_dev(pdev); - - // Send URB - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - RtlZeroMemory(purb, sizeof(URB)); - - // Build a URB for our interrupt transfer - UsbBuildInterruptOrBulkTransferRequest(purb, - usb_make_handle((dev_handle >> 16), 0, 0), - (PUCHAR)&pdev_ext->mouse_data, - MaxPacketSize, //use max packet size - mouse_irq, - pdev_ext->device_ext, - 0); - - // Call USB driver stack - status = usb_submit_urb(pdev_ext->dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - } - - return TRUE; -} - -VOID -mouse_irq(PURB purb, PVOID pcontext) -{ - MOUSE_INPUT_DATA MouseInputData; - ULONG InputDataConsumed; - NTSTATUS status; - PMOUSE_DRVR_EXTENSION pdev_ext; - PMOUSE_DEVICE_EXTENSION DeviceExtension = (PMOUSE_DEVICE_EXTENSION)pcontext; - signed char *data; - usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): called\n")); - - ASSERT(purb); - - if (purb->status != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("mouse_irq(): purb->status 0x%08X\n", purb->status)); - return; - } - - pdev_ext = DeviceExtension->DriverExtension; - data = pdev_ext->mouse_data; - - usb_dbg_print(DBGLVL_MAXIMUM, ("Mouse input: x %d, y %d, w %d, btn: 0x%02x\n", data[1], data[2], data[3], data[0])); - - // Fill mouse input data structure - MouseInputData.Flags = MOUSE_MOVE_RELATIVE; - MouseInputData.LastX = data[1]; - MouseInputData.LastY = data[2]; - - MouseInputData.ButtonFlags = 0; - MouseInputData.ButtonData = 0; - - if ((data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01))) - MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_DOWN; - else if (!(data[0] & 0x01) && ((pdev_ext->btn_old & 0x01) != (data[0] & 0x01))) - MouseInputData.ButtonFlags |= MOUSE_LEFT_BUTTON_UP; - - if ((data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02))) - MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_DOWN; - else if (!(data[0] & 0x02) && ((pdev_ext->btn_old & 0x02) != (data[0] & 0x02))) - MouseInputData.ButtonFlags |= MOUSE_RIGHT_BUTTON_UP; - - if ((data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04))) - MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_DOWN; - else if (!(data[0] & 0x04) && ((pdev_ext->btn_old & 0x04) != (data[0] & 0x04))) - MouseInputData.ButtonFlags |= MOUSE_MIDDLE_BUTTON_UP; - - if ((data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_DOWN; - else if (!(data[0] & 0x08) && ((pdev_ext->btn_old & 0x08) != (data[0] & 0x08))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_4_UP; - - if ((data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_DOWN; - else if (!(data[0] & 0x10) && ((pdev_ext->btn_old & 0x10) != (data[0] & 0x10))) - MouseInputData.ButtonFlags |= MOUSE_BUTTON_5_UP; - - if (data[3]) - { - MouseInputData.ButtonFlags |= MOUSE_WHEEL; - MouseInputData.ButtonData = data[3]; - } - - // Commit the input data somewhere... - if (DeviceExtension->ConnectData.ClassService) - { - KIRQL OldIrql; - - KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); - (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->ConnectData.ClassService)( - DeviceExtension->ConnectData.ClassDeviceObject, - &MouseInputData, - (&MouseInputData)+1, - &InputDataConsumed); - KeLowerIrql(OldIrql); - } - - // Save old button data - pdev_ext->btn_old = data[0]; - - // resubmit the urb - status = usb_submit_urb(pdev_ext->dev_mgr, purb); -} - -BOOLEAN -mouse_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(dev_mgr); - return TRUE; -} - -BOOLEAN -mouse_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PDEVICE_OBJECT dev_obj; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - pdev = NULL; - //special use of the lock dev, simply use this routine to get the dev - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (pdev == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - // must be a bug - TRAP(); - usb_unlock_dev(pdev); - } - pdrvr = pdev->dev_driver; - dev_obj = pdev->dev_obj; - pdev = NULL; - - return TRUE;//umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE); -} - -// Dispatch routine for our IRPs -NTSTATUS -MouseDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp) -{ - NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST; - PMOUSE_DEVICE_EXTENSION DeviceExtension; - - DeviceExtension = DeviceObject->DeviceExtension; - - usb_dbg_print(DBGLVL_MAXIMUM, ("MouseDispatch(DO %p, code 0x%lx) called\n", - DeviceObject, - IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)); - - if (DeviceObject == DeviceExtension->Fdo) - { - // it's mouse's IOCTL - PIO_STACK_LOCATION Stk; - - Irp->IoStatus.Information = 0; - Stk = IoGetCurrentIrpStackLocation(Irp); - - switch (Stk->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_INTERNAL_MOUSE_CONNECT: - usb_dbg_print(DBGLVL_MAXIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT\n")); - if (Stk->Parameters.DeviceIoControl.InputBufferLength < sizeof(CONNECT_DATA)) { - usb_dbg_print(DBGLVL_MINIMUM, ("IOCTL_INTERNAL_MOUSE_CONNECT: " - "invalid buffer size\n")); - Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; - goto intcontfailure2; - } - - RtlCopyMemory(&DeviceExtension->ConnectData, - Stk->Parameters.DeviceIoControl.Type3InputBuffer, - sizeof(CONNECT_DATA)); - - Irp->IoStatus.Status = STATUS_SUCCESS; - break; - - default: - Irp->IoStatus.Status = STATUS_SUCCESS;//STATUS_INVALID_DEVICE_REQUEST; - break; - } -intcontfailure2: - Status = Irp->IoStatus.Status; - } - - if (Status == STATUS_INVALID_DEVICE_REQUEST) - { - usb_dbg_print(DBGLVL_MINIMUM, ("Invalid internal device request!\n")); - } - - if (Status != STATUS_PENDING) - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; -} - -NTSTATUS -AddRegistryEntry( - IN PCWSTR PortTypeName, - IN PUNICODE_STRING DeviceName, - IN PCWSTR RegistryPath) -{ - UNICODE_STRING PathU = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP"); - OBJECT_ATTRIBUTES ObjectAttributes; - HANDLE hDeviceMapKey = (HANDLE)-1; - HANDLE hPortKey = (HANDLE)-1; - UNICODE_STRING PortTypeNameU; - NTSTATUS Status; - - InitializeObjectAttributes(&ObjectAttributes, &PathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&hDeviceMapKey, 0, &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("ZwOpenKey() failed with status 0x%08lx\n", Status)); - goto cleanup; - } - - RtlInitUnicodeString(&PortTypeNameU, PortTypeName); - InitializeObjectAttributes(&ObjectAttributes, &PortTypeNameU, OBJ_KERNEL_HANDLE, hDeviceMapKey, NULL); - Status = ZwCreateKey(&hPortKey, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("ZwCreateKey() failed with status 0x%08lx\n", Status)); - goto cleanup; - } - - Status = ZwSetValueKey(hPortKey, DeviceName, 0, REG_SZ, (PVOID)RegistryPath, (ULONG)(wcslen(RegistryPath) * sizeof(WCHAR) + sizeof(UNICODE_NULL))); - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("ZwSetValueKey() failed with status 0x%08lx\n", Status)); - goto cleanup; - } - - Status = STATUS_SUCCESS; - -cleanup: - if (hDeviceMapKey != (HANDLE)-1) - ZwClose(hDeviceMapKey); - if (hPortKey != (HANDLE)-1) - ZwClose(hPortKey); - return Status; -} - -static NTSTATUS -MouseCreateDevice(IN PDRIVER_OBJECT DriverObject, IN PMOUSE_DRVR_EXTENSION DriverExtension) -{ - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerPortUSB"); - PMOUSE_DEVICE_EXTENSION DeviceExtension; - PDEVICE_OBJECT Fdo; - NTSTATUS Status; - - Status = AddRegistryEntry(L"PointerPort", &DeviceName, L"REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\usbdriver"); - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("AddRegistryEntry() for usb mouse driver failed with status 0x%08lx\n", Status)); - return Status; - } - - Status = IoCreateDevice(DriverObject, - sizeof(MOUSE_DEVICE_EXTENSION), - &DeviceName, - FILE_DEVICE_MOUSE, - FILE_DEVICE_SECURE_OPEN, - TRUE, - &Fdo); - - if (!NT_SUCCESS(Status)) - { - usb_dbg_print(DBGLVL_MINIMUM, ("IoCreateDevice() for usb mouse driver failed with status 0x%08lx\n", Status)); - return Status; - } - DeviceExtension = (PMOUSE_DEVICE_EXTENSION)Fdo->DeviceExtension; - RtlZeroMemory(DeviceExtension, sizeof(MOUSE_DEVICE_EXTENSION)); - - DeviceExtension->hdr.dispatch = MouseDispatch; - DeviceExtension->DriverExtension = DriverExtension; - DriverExtension->device_ext = DeviceExtension; - - DeviceExtension->Fdo = Fdo; - Fdo->Flags &= ~DO_DEVICE_INITIALIZING; - usb_dbg_print(DBGLVL_MEDIUM, ("Created mouse Fdo: %p\n", Fdo)); - - return STATUS_SUCCESS; -} - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/mouse.h b/reactos/drivers/usb/nt4compat/usbdrv/mouse.h deleted file mode 100644 index 7fa32bdf680..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/mouse.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __MOUSE_H__ -#define __MOUSE_H__ - -#include "kbdmou.h" - -typedef struct _MOUSE_DRVR_EXTENSION -{ - PUSB_INTERFACE_DESC pif_desc; - - PUSB_DEV_MANAGER dev_mgr; - signed char mouse_data[8]; - UCHAR btn_old; - - struct _MOUSE_DEVICE_EXTENSION *device_ext; // back pointer -} MOUSE_DRVR_EXTENSION, *PMOUSE_DRVR_EXTENSION; - -typedef struct _MOUSE_DEVICE_EXTENSION -{ - DEVEXT_HEADER hdr; // mandatory header - PMOUSE_DRVR_EXTENSION DriverExtension; - CONNECT_DATA ConnectData; - PDEVICE_OBJECT Fdo; -} MOUSE_DEVICE_EXTENSION, *PMOUSE_DEVICE_EXTENSION; - -BOOLEAN -mouse_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); - -BOOLEAN -mouse_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver); - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/ohci.c b/reactos/drivers/usb/nt4compat/usbdrv/ohci.c deleted file mode 100644 index c4b2f213cd1..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/ohci.c +++ /dev/null @@ -1,1656 +0,0 @@ -/** - * ohci.c - USB driver stack project - * - * Copyright (c) 2007 Aleksey Bragin - * based on some code by Zhiming - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" -#include "ehci.h" -#include "ohci.h" - -PDEVICE_OBJECT ohci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, - ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr); -//BOOLEAN ohci_release(PDEVICE_OBJECT pdev); -//static VOID ohci_stop(PEHCI_DEV ehci); -PDEVICE_OBJECT ohci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, - PUSB_DEV_MANAGER dev_mgr); -PDEVICE_OBJECT ohci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr); -//BOOLEAN ohci_delete_device(PDEVICE_OBJECT pdev); -//VOID ohci_get_capabilities(PEHCI_DEV ehci, PBYTE base); -//BOOLEAN NTAPI ohci_isr(PKINTERRUPT interrupt, PVOID context); -//BOOLEAN ohci_start(PHCD hcd); -VOID ohci_init_hcd_interface(POHCI_DEV ohci); -BOOLEAN ohci_rh_reset_port(PHCD hcd, UCHAR port_idx); -VOID ohci_generic_urb_completion(PURB purb, PVOID context); - -// shared with EHCI -NTSTATUS ehci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp); -PUSB_DEV_MANAGER ehci_get_dev_mgr(PHCD hcd); -VOID ehci_set_dev_mgr(PHCD hcd, PUSB_DEV_MANAGER dev_mgr); -VOID ehci_set_id(PHCD hcd, UCHAR id); -UCHAR ehci_get_id(PHCD hcd); -UCHAR ehci_alloc_addr(PHCD hcd); -VOID ehci_free_addr(PHCD hcd, UCHAR addr); -BOOLEAN NTAPI ehci_cal_cpu_freq(PVOID context); - -VOID rh_timer_svc_int_completion(PUSB_DEV pdev, PVOID context); -VOID rh_timer_svc_reset_port_completion(PUSB_DEV pdev, PVOID context); - -extern USB_DEV_MANAGER g_dev_mgr; - -/* wrap-aware logic morphed from */ -#define tick_before(t1,t2) ((SHORT)(((SHORT)(t1))-((SHORT)(t2))) < 0) - -#define OHCI_READ_PORT_ULONG( pul ) ( *pul ) -#define OHCI_WRITE_PORT_ULONG( pul, src ) \ -{\ - *pul = ( ULONG )src;\ -} - -#define OHCI_READ_PORT_UCHAR( pch ) ( *pch ) -#define OHCI_WRITE_PORT_UCHAR( pch, src ) ( *pch = ( UCHAR )src ) -#define OHCI_READ_PORT_USHORT( psh ) ( *psh ) -#define OHCI_WRITE_PORT_USHORT( psh, src ) ( *psh = ( USHORT )src ) - -/* AMD-756 (D2 rev) reports corrupt register contents in some cases. - * The erratum (#4) description is incorrect. AMD's workaround waits - * till some bits (mostly reserved) are clear; ok for all revs. - */ -ULONG -FORCEINLINE -read_roothub(POHCI_DEV hc, PULONG reg, ULONG mask) -{ - ULONG temp = OHCI_READ_PORT_ULONG(reg); - if (temp == -1) - /*disable (hc)*/; - /*else if (hc->flags & OHCI_QUIRK_AMD756) - while (temp & mask) - temp = ohci_readl (hc, &hc->regs->roothub.register); */ - return temp; -} - -static ULONG roothub_a (POHCI_DEV hc) - { return read_roothub (hc, &hc->regs->roothub.a, 0xfc0fe000); } -/* -static inline u32 roothub_b (struct ohci_hcd *hc) - { return ohci_readl (hc, &hc->regs->roothub.b); } -static inline u32 roothub_status (struct ohci_hcd *hc) - { return ohci_readl (hc, &hc->regs->roothub.status); } -static u32 roothub_portstatus (struct ohci_hcd *hc, int i) - { return read_roothub (hc, &hc->regs->roothub.portstatus [i], 0xffe0fce0); } -*/ - - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR -#define OHCI_INTR_INIT \ - (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH) - -/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling, - * not necessarily continuous ... to guard against resume signaling. - * The short timeout is safe for non-root hubs, and is backward-compatible - * with earlier Linux hosts. - */ -#ifdef CONFIG_USB_SUSPEND -#define PORT_RESET_MSEC 50 -#else -#define PORT_RESET_MSEC 10 -#endif - -/* this timer value might be vendor-specific ... */ -#define PORT_RESET_HW_MSEC 10 - -#define DEFAULT_ENDP( enDP ) \ -( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP ) - -#define dev_from_endp( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( PUSB_DEV )( enDP )->pusb_if )\ - : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) ) - -#define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK ) - -#define endp_num( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0 \ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) ) - -#define endp_dir( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0L\ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ) - -#define dev_set_state( pdEV, staTE ) \ -( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) ) - -#define endp_max_packet_size( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \ - ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\ - : 8 )\ - : ( enDP->pusb_endp_desc->wMaxPacketSize & 0x7ff ) ) - -#define endp_mult_count( endp ) ( ( ( endp->pusb_endp_desc->wMaxPacketSize & 0x1800 ) >> 11 ) + 1 ) - -#define get_parent_hs_hub( pDEV, parent_HUB, port_IDX ) \ -{\ - parent_HUB = pDEV->parent_dev;\ - port_IDX = pdev->port_idx;\ - while( parent_HUB )\ - {\ - if( ( parent_HUB->flags & USB_DEV_CLASS_MASK ) != USB_DEV_CLASS_HUB )\ - {\ - parent_HUB = NULL;\ - break;\ - }\ - if( ( parent_HUB->flags & USB_DEV_FLAG_HIGH_SPEED ) == 0 )\ - {\ - port_IDX = parent_HUB->port_idx;\ - parent_HUB = parent_HUB->parent_dev;\ - continue;\ - }\ - break;\ - }\ -} - -VOID -ohci_wait_ms(POHCI_DEV ohci, LONG ms) -{ - LARGE_INTEGER lms; - if (ms <= 0) - return; - - lms.QuadPart = -10 * ms; - KeSetTimer(&ohci->reset_timer, lms, NULL); - - KeWaitForSingleObject(&ohci->reset_timer, Executive, KernelMode, FALSE, NULL); - - return; -} - -PDEVICE_OBJECT ohci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, - PUSB_DEV_MANAGER dev_mgr) -{ - LONG bus, i, j, ret = 0; - PCI_SLOT_NUMBER slot_num; - PPCI_COMMON_CONFIG pci_config; - PDEVICE_OBJECT pdev; - BYTE buffer[sizeof(PCI_COMMON_CONFIG)]; - POHCI_DEVICE_EXTENSION pdev_ext; - - slot_num.u.AsULONG = 0; - pci_config = (PPCI_COMMON_CONFIG) buffer; - pdev = NULL; - - //scan the bus to find ohci controller - for(bus = 0; bus < 2; bus++) /*enum only bus0 and bus1 */ - { - for(i = 0; i < PCI_MAX_DEVICES; i++) - { - slot_num.u.bits.DeviceNumber = i; - for(j = 0; j < PCI_MAX_FUNCTIONS; j++) - { - slot_num.u.bits.FunctionNumber = j; - - ret = HalGetBusData(PCIConfiguration, - bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH); - - /* Don't look further on this device */ - if ((ret == 0) || (ret == 2)) - break; - - if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03 - && pci_config->ProgIf == 0x10) - { - // we found our usb host controller( OHCI ), create device - pdev = ohci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr); - - if (!pdev) - continue; - } - } - - if (ret == 0) - break; - } - } - - if (pdev) - { - pdev_ext = pdev->DeviceExtension; - if (pdev_ext) - { - // acquire higher irql to eliminate pre-empty - //KeSynchronizeExecution(pdev_ext->ohci_int, ehci_cal_cpu_freq, NULL); - } - } - return pdev; -} - -BOOLEAN ohci_mem_init (POHCI_DEVICE_EXTENSION dev_ext) -{ - dev_ext->ohci->td_cache = HalAllocateCommonBuffer(dev_ext->padapter, - sizeof(OHCI_TD), &dev_ext->ohci->td_logic_addr, FALSE); - - if (!dev_ext->ohci->td_cache) - return FALSE; - - dev_ext->ohci->ed_cache = HalAllocateCommonBuffer(dev_ext->padapter, - sizeof(OHCI_ED), &dev_ext->ohci->ed_logic_addr, FALSE); - - if (!dev_ext->ohci->ed_cache) - { - HalFreeCommonBuffer(dev_ext->padapter, sizeof(OHCI_TD), dev_ext->ohci->td_logic_addr, - dev_ext->ohci->td_cache, FALSE); - return FALSE; - } - - return TRUE; -} - - -PDEVICE_OBJECT -ohci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr) -{ - LONG frd_num, prd_num; - PDEVICE_OBJECT pdev = NULL; - POHCI_DEVICE_EXTENSION pdev_ext; - ULONG addr_space; - //ULONG vector; - LONG bus; - //KIRQL irql; - //KAFFINITY affinity; - - DEVICE_DESCRIPTION dev_desc; - CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd; - PCI_SLOT_NUMBER slot_num; - NTSTATUS status; - - pdev = ohci_create_device(drvr_obj, dev_mgr); - - if (pdev == NULL) - return NULL; - - pdev_ext = pdev->DeviceExtension; - - pdev_ext->pci_addr = bus_addr; - bus = (bus_addr >> 8); - - slot_num.u.AsULONG = 0; - slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3); - slot_num.u.bits.FunctionNumber = (bus_addr & 0x07); - - //now create adapter object - RtlZeroMemory(&dev_desc, sizeof(dev_desc)); - - dev_desc.Version = DEVICE_DESCRIPTION_VERSION; - dev_desc.Master = TRUE; - dev_desc.ScatterGather = TRUE; - dev_desc.Dma32BitAddresses = TRUE; - dev_desc.BusNumber = bus; - dev_desc.InterfaceType = PCIBus; - dev_desc.MaximumLength = EHCI_MAX_SIZE_TRANSFER; - pdev_ext->map_regs = 2; // we do not use it seriously - pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs); - - DbgPrint("ohci_alloc(): reg_path=0x%x, \n \ - ohci_alloc(): bus=0x%x, bus_addr=0x%x \n \ - ohci_alloc(): slot_num=0x%x \n \ - ", (DWORD) reg_path, (DWORD) bus, (DWORD) bus_addr, (DWORD) slot_num.u.AsULONG); - - //let's allocate resources for this device - DbgPrint("ohci_alloc(): about to assign slot res\n"); - if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet - drvr_obj, NULL, //no support of another ehci controller - PCIBus, - bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS) - { - DbgPrint("ohci_alloc(): error assign slot res, 0x%x\n", status); -#if 0 - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ohci_delete_device(pdev); -#endif - return NULL; - } - - //parse the resource list - for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++) - { - for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count; - prd_num++) - { - pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num]; - if (pprd->Type == CmResourceTypePort) - { - RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port)); - - } - else if (pprd->Type == CmResourceTypeInterrupt) - { - RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt)); - } - else if (pprd->Type == CmResourceTypeMemory) - { - RtlCopyMemory(&pdev_ext->res_memory, &pprd->u.Memory, sizeof(pprd->u.Memory)); - } - } - } - - //for port, translate them to system address - addr_space = 0; - if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space - &pdev_ext->ohci->ohci_reg_base) != (BOOLEAN) TRUE) - { - DbgPrint("ohci_alloc(): error, can not translate bus address\n"); -#if 0 - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev); -#endif - return NULL; - } - - DbgPrint("ohci_alloc(): address space=0x%x\n, reg_base=0x%x\n", - addr_space, pdev_ext->ohci->ohci_reg_base.u.LowPart); - - if (addr_space == 0) - { - //port has been mapped to memory space - pdev_ext->ohci->port_mapped = TRUE; - pdev_ext->ohci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->ohci->ohci_reg_base, - pdev_ext->res_port.Length, FALSE); - - //fatal error can not map the registers - if (pdev_ext->ohci->port_base == NULL) - { -#if 0 - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev); -#endif - return NULL; - } - } - else - { - //io space - pdev_ext->ohci->port_mapped = FALSE; - pdev_ext->ohci->port_base = (PBYTE) pdev_ext->ohci->ohci_reg_base.LowPart; - } - - //before we connect the interrupt, we have to init ohci - pdev_ext->ohci->pdev_ext = pdev_ext; - pdev_ext->ohci->regs = (POHCI_REGS)pdev_ext->ohci->port_base; - - KeInitializeTimer(&pdev_ext->ohci->reset_timer); - - // take it over from SMM/BIOS/whoever has it - if (OHCI_READ_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_CONTROL)) & OHCI_CTRL_IR) - { - ULONG temp; - - DbgPrint("USB HC TakeOver from BIOS/SMM\n"); - - /* this timeout is arbitrary. we make it long, so systems - * depending on usb keyboards may be usable even if the - * BIOS/SMM code seems pretty broken. - */ - temp = 500; /* arbitrary: five seconds */ - - OHCI_WRITE_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_INTRENABLE), OHCI_INTR_OC); - OHCI_WRITE_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_CMDSTATUS), OHCI_OCR); - - while (OHCI_READ_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_CONTROL)) & OHCI_CTRL_IR) - { - ohci_wait_ms(pdev_ext->ohci, 10); - if (--temp == 0) { - DbgPrint("USB HC takeover failed!" - " (BIOS/SMM bug)\n"); - return NULL; - } - } - //ohci_usb_reset (ohci); - } - - /* Disable HC interrupts */ - OHCI_WRITE_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_INTRDISABLE), OHCI_INTR_MIE); - // flush the writes - (VOID)OHCI_READ_PORT_ULONG((PULONG)(pdev_ext->ohci->port_base + OHCI_CONTROL)); - - /* Read the number of ports unless overridden */ - pdev_ext->ohci->num_ports = roothub_a(pdev_ext->ohci) & RH_A_NDP; - - DbgPrint("OHCI: %d ports\n", pdev_ext->ohci->num_ports); - - pdev_ext->ohci->hcca = HalAllocateCommonBuffer(pdev_ext->padapter, - sizeof(*pdev_ext->ohci->hcca), &pdev_ext->ohci->hcca_logic_addr, FALSE); - - if (!pdev_ext->ohci->hcca) - { - DbgPrint("OHCI: HCCA allocation failed!\n"); - return NULL; - } - - if (!ohci_mem_init(pdev_ext)) - { - DbgPrint("OHCI: Mem init failed!\n"); - return NULL; - } - -#if 0 - if (ehci_init_schedule(pdev_ext->ehci, pdev_ext->padapter) == FALSE) - { - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - ehci_delete_device(pdev); - return NULL; - } -#endif - - InitializeListHead(&pdev_ext->ohci->urb_list); - KeInitializeSpinLock(&pdev_ext->ohci->pending_endp_list_lock); - InitializeListHead(&pdev_ext->ohci->pending_endp_list); - - ohci_dbg_print(DBGLVL_MAXIMUM, ("ohci_alloc(): pending_endp_list=0x%x\n", - &pdev_ext->ohci->pending_endp_list)); - - init_pending_endp_pool(&pdev_ext->ohci->pending_endp_pool); - -#if 0 - vector = HalGetInterruptVector(PCIBus, - bus, - pdev_ext->res_interrupt.level, - pdev_ext->res_interrupt.vector, &irql, &affinity); - - KeInitializeDpc(&pdev_ext->ehci_dpc, ehci_dpc_callback, (PVOID) pdev_ext->ehci); - - //connect the interrupt - DbgPrint("ehci_alloc(): the int=0x%x\n", vector); - if ((status = IoConnectInterrupt(&pdev_ext->ehci_int, ehci_isr, pdev_ext->ehci, NULL, //&pdev_ext->ehci->frame_list_lock, - vector, irql, irql, LevelSensitive, TRUE, //share the vector - affinity, FALSE)) //No float save - != STATUS_SUCCESS) - { - DbgPrint("ehci_alloc(): Failed to connect interrupt, status = 0x%x!\n", status); - ehci_release(pdev); - return NULL; - } -#endif - - return pdev; -} - -PDEVICE_OBJECT -ohci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr) -{ - NTSTATUS status; - PDEVICE_OBJECT pdev; - POHCI_DEVICE_EXTENSION pdev_ext; - - UNICODE_STRING dev_name; - UNICODE_STRING symb_name; - - STRING string, another_string; - CHAR str_dev_name[64], str_symb_name[64]; - UCHAR hcd_id; - - if (drvr_obj == NULL) - return NULL; - - //note: hcd count wont increment till the hcd is registered in dev_mgr - sprintf(str_dev_name, "%s%d", OHCI_DEVICE_NAME, dev_mgr->hcd_count); - sprintf(str_symb_name, "%s%d", OHCI_DOS_DEVICE_NAME, dev_mgr->hcd_count); - - RtlInitString(&string, str_dev_name); - RtlAnsiStringToUnicodeString(&dev_name, &string, TRUE); - - pdev = NULL; - status = IoCreateDevice(drvr_obj, - sizeof(OHCI_DEVICE_EXTENSION) + sizeof(OHCI_DEV), - &dev_name, FILE_OHCI_DEV_TYPE, 0, FALSE, &pdev); - - if (status != STATUS_SUCCESS || pdev == NULL) - { - RtlFreeUnicodeString(&dev_name); - ehci_dbg_print(DBGLVL_MAXIMUM, ("ohci_create_device(): error create device 0x%x\n", status)); - return NULL; - } - - pdev_ext = pdev->DeviceExtension; - RtlZeroMemory(pdev_ext, sizeof(OHCI_DEVICE_EXTENSION) + sizeof(OHCI_DEV)); - - pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD; - pdev_ext->dev_ext_hdr.dispatch = ehci_dispatch_irp; - pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio - pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr; - - pdev_ext->pdev_obj = pdev; - pdev_ext->pdrvr_obj = drvr_obj; - - pdev_ext->ohci = (POHCI_DEV) & (pdev_ext[1]); - - RtlInitString(&another_string, str_symb_name); - RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE); - //RtlInitUnicodeString( &symb_name, DOS_DEVICE_NAME ); - - IoCreateSymbolicLink(&symb_name, &dev_name); - - ehci_dbg_print(DBGLVL_MAXIMUM, - ("ohci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, ehci=0x%x, dev_mgr=0x%x\n", pdev, - pdev_ext, pdev_ext->ohci, dev_mgr)); - - RtlFreeUnicodeString(&dev_name); - RtlFreeUnicodeString(&symb_name); - - //register with dev_mgr though it is not initilized - ohci_init_hcd_interface(pdev_ext->ohci); - hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->ohci->hcd_interf); - - pdev_ext->ohci->hcd_interf.hcd_set_id(&pdev_ext->ohci->hcd_interf, hcd_id); - pdev_ext->ohci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->ohci->hcd_interf, dev_mgr); - - return pdev; -} - -BOOLEAN -ohci_start(PHCD hcd) -{ - ULONG temp, mask; - //PBYTE base; - //PEHCI_USBCMD_CONTENT usbcmd; - POHCI_DEV ohci; - ULONG hc_control; - - if (hcd == NULL) - return FALSE; - - ohci = struct_ptr(hcd, OHCI_DEV, hcd_interf); - - /* Reset USB nearly "by the book". RemoteWakeupConnected - * saved if boot firmware (BIOS/SMM/...) told us it's connected - * (for OHCI integrated on mainboard, it normally is) - */ - hc_control = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control); - DbgPrint("OHCI: resetting from state %x, control = 0x%x\n", - (hc_control & OHCI_CTRL_HCFS), - hc_control); - - //if (hc_control & OHCI_CTRL_RWC - // && !(ohci->flags & OHCI_QUIRK_AMD756)) - // ohci_to_hcd(ohci)->can_wakeup = 1; - - switch (hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: - temp = 0; - break; - case OHCI_USB_SUSPEND: - case OHCI_USB_RESUME: - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_USB_RESUME; - temp = 10 /* msec wait */; - break; - // case OHCI_USB_RESET: - default: - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_USB_RESET; - temp = 50 /* msec wait */; - break; - } - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->control, hc_control); - - // flush the writes - (VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control); - - ohci_wait_ms(ohci, temp); - temp = roothub_a (ohci); - if (!(temp & RH_A_NPS)) { - /* power down each port */ - for (temp = 0; temp < ohci->num_ports; temp++) - { - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus [temp], RH_PS_LSDA); - } - } - // flush those writes - (VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control); - RtlZeroMemory(ohci->hcca, sizeof(OHCI_HCCA)); - - /* 2msec timelimit here means no irqs/preempt */ - //spin_lock_irq (&ohci->lock); - -//retry: - /* HC Reset requires max 10 us delay */ - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->cmdstatus, OHCI_HCR); - temp = 30; /* ... allow extra time */ - while ((OHCI_READ_PORT_ULONG ((PULONG)&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { - if (--temp == 0) { - //spin_unlock_irq (&ohci->lock); - //ohci_err (ohci, "USB HC reset timed out!\n"); - DbgPrint("OHCI: USB HC reset timed out!\n"); - return FALSE; - } - KeStallExecutionProcessor(1); - } - - /* now we're in the SUSPEND state ... must go OPERATIONAL - * within 2msec else HC enters RESUME - * - * ... but some hardware won't init fmInterval "by the book" - * (SiS, OPTi ...), so reset again instead. SiS doesn't need - * this if we write fmInterval after we're OPERATIONAL. - * Unclear about ALi, ServerWorks, and others ... this could - * easily be a longstanding bug in chip init on Linux. - */ -#if 0 - if (ohci->flags & OHCI_QUIRK_INITRESET) { - ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); - // flush those writes - (void) ohci_readl (ohci, &ohci->regs->control); - } -#endif - /* Tell the controller where the control and bulk lists are - * The lists are empty now. */ - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->ed_controlhead, 0); - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->ed_bulkhead, 0); - - /* a reset clears this */ - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->hcca, (ULONG)ohci->hcca_logic_addr.LowPart); - - //periodic_reinit (ohci); - - /* start controller operations */ - hc_control &= OHCI_CTRL_RWC; - hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->control, hc_control); - //ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; - - /* wake on ConnectStatusChange, matching external hubs */ - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.status, RH_HS_DRWE); - - /* Choose the interrupts we care about now, others later on demand */ - mask = OHCI_INTR_INIT; - //OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrstatus, mask); - //OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->intrenable, mask); - - /* handle root hub init quirks ... */ - temp = roothub_a(ohci); - temp &= ~(RH_A_PSM | RH_A_OCPM); - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.status, RH_HS_LPSC); - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.b, (temp & RH_A_NPS) ? 0 : RH_B_PPCM); - // flush those writes - (VOID)OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->control); - - //spin_unlock_irq (&ohci->lock); - - // POTPGT delay is bits 24-31, in 2 ms units. - ohci_wait_ms(ohci, (temp >> 23) & 0x1fe); - //ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; - - - // Debug code follows! - /*(VOID)ohci_rh_reset_port(hcd, 1); - (VOID)ohci_rh_reset_port(hcd, 2); - (VOID)ohci_rh_reset_port(hcd, 3); - (VOID)ohci_rh_reset_port(hcd, 4);*/ - // Debug code ends! - - - return TRUE; -} - -static VOID NTAPI -ohci_cancel_pending_endp_urb(IN PVOID Parameter) -{ - PLIST_ENTRY abort_list; - PUSB_DEV pdev; - PURB purb; - USE_BASIC_NON_PENDING_IRQL; - - abort_list = (PLIST_ENTRY) Parameter; - - if (abort_list == NULL) - return; - - while (IsListEmpty(abort_list) == FALSE) - { - //these devs are protected by purb's ref-count - purb = (PURB) RemoveHeadList(abort_list); - pdev = purb->pdev; - // purb->status is set when they are added to abort_list - - ohci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, FALSE); - pdev->ref_count--; - unlock_dev(pdev, FALSE); - } - usb_free_mem(abort_list); - return; -} - -static NTSTATUS -ohci_internal_submit_bulk(POHCI_DEV ohci, PURB purb) -{ - return STATUS_SUCCESS; -} - -static NTSTATUS -ohci_internal_submit_ctrl(POHCI_DEV ohci, PURB purb) -{ - return STATUS_SUCCESS; -} - -static NTSTATUS -ohci_internal_submit_int(POHCI_DEV ohci, PURB purb) -{ - return STATUS_SUCCESS; -} - -static NTSTATUS -ohci_internal_submit_iso(POHCI_DEV ohci, PURB purb) -{ - return STATUS_SUCCESS; -} - - -static BOOLEAN -ohci_process_pending_endp(POHCI_DEV ehci) -{ - PUSB_DEV pdev; - LIST_ENTRY temp_list, abort_list; - PLIST_ENTRY pthis; - PURB purb; - PUSB_ENDPOINT pendp; - NTSTATUS can_submit = STATUS_SUCCESS; - PWORK_QUEUE_ITEM pwork_item; - PLIST_ENTRY cancel_list; - PUSB_DEV pparent = NULL; - UCHAR port_idx = 0; - BOOLEAN tt_needed; - UCHAR hub_addr = 0; - USE_BASIC_IRQL; - - if (ehci == NULL) - return FALSE; - - InitializeListHead(&temp_list); - InitializeListHead(&abort_list); - - purb = NULL; - ohci_dbg_print(DBGLVL_MEDIUM, ("ohci_process_pending_endp(): entering..., ehci=0x%x\n", ehci)); - - lock_pending_endp_list(&ehci->pending_endp_list_lock); - while (IsListEmpty(&ehci->pending_endp_list) == FALSE) - { - - ehci_dbg_print(DBGLVL_MAXIMUM, ("ohci_process_pending_endp(): pending_endp_list=0x%x\n", - &ehci->pending_endp_list)); - - tt_needed = FALSE; - pthis = RemoveHeadList(&ehci->pending_endp_list); - pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp; - pdev = dev_from_endp(pendp); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - //delegate to ehci_remove_device for remiving the purb queue on the endpoint - continue; - } - if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0) - { - // prepare split transaction - unlock_dev(pdev, TRUE); - - // pparent won't be removed when pending_endp_list_lock is acquired. - get_parent_hs_hub(pdev, pparent, port_idx); - - if (pparent == NULL) - { - TRAP(); - ehci_dbg_print(DBGLVL_MEDIUM, - ("ohci_process_pending_endp(): full/low speed device with no parent!!!\n")); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - continue; - } - - if (hub_lock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)) == FALSE) - { - lock_dev(pdev, TRUE); - if (dev_state(pdev) != USB_DEV_STATE_ZOMB) - { - // reinsert the pending-endp to the list - InsertTailList(&temp_list, pthis); - unlock_dev(pdev, TRUE); - } - else - { - // delegate to ehci_remove_device for purb removal - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, - struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - } - continue; - } - - // backup the hub address for future use - hub_addr = pparent->dev_addr; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - tt_needed = TRUE; - // go on processing - } - - if (endp_state(pendp) == USB_ENDP_FLAG_STALL) - { - while (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - purb->status = USB_STATUS_ENDPOINT_HALTED; - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - } - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - if (tt_needed) - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - - if (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - ASSERT(purb); - } - else - { - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - if (tt_needed) - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - continue; - } - - if (tt_needed) - { - ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->hub_addr = hub_addr; - ((PURB_HS_CONTEXT_CONTENT) & purb->hs_context)->port_idx = port_idx; - } - - // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule - switch (endp_type(pendp)) - { - case USB_ENDPOINT_XFER_BULK: - { - can_submit = ohci_internal_submit_bulk(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_CONTROL: - { - can_submit = ohci_internal_submit_ctrl(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_INT: - { - can_submit = ohci_internal_submit_int(ehci, purb); - break; - } - case USB_ENDPOINT_XFER_ISOC: - { - can_submit = ohci_internal_submit_iso(ehci, purb); - break; - } - } - - if (can_submit == STATUS_NO_MORE_ENTRIES) - { - //no enough bandwidth or tds - InsertHeadList(&pendp->urb_list, &purb->urb_link); - InsertTailList(&temp_list, pthis); - } - else - { - // otherwise error or success - free_pending_endp(&ehci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - - if (can_submit != STATUS_SUCCESS) - { - //abort these URBs - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - purb->status = can_submit; - } - } - unlock_dev(pdev, TRUE); - if (can_submit != STATUS_SUCCESS && tt_needed) - { - hub_unlock_tt(pparent, port_idx, (UCHAR) endp_type(pendp)); - } - } - - if (IsListEmpty(&temp_list) == FALSE) - { - //re-append them to the pending_endp_list - ListFirst(&temp_list, pthis); - RemoveEntryList(&temp_list); - MergeList(&ehci->pending_endp_list, pthis); - } - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - - if (IsListEmpty(&abort_list) == FALSE) - { - PLIST_ENTRY pthis; - cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY)); - ASSERT(cancel_list); - - ListFirst(&abort_list, pthis); - RemoveEntryList(&abort_list); - InsertTailList(pthis, cancel_list); - - pwork_item = (PWORK_QUEUE_ITEM) & cancel_list[1]; - - // we do not need to worry the ehci_cancel_pending_endp_urb running when the - // driver is unloading since purb-reference count will prevent the dev_mgr to - // quit till all the reference count to the dev drop to zero. - ExInitializeWorkItem(pwork_item, ohci_cancel_pending_endp_urb, (PVOID) cancel_list); - ExQueueWorkItem(pwork_item, DelayedWorkQueue); - } - return TRUE; -} - -NTSTATUS -ohci_rh_submit_urb(PUSB_DEV pdev, PURB purb) -{ - PUSB_DEV_MANAGER dev_mgr; - PTIMER_SVC ptimer; - PUSB_CTRL_SETUP_PACKET psetup; - POHCI_DEV ohci; - NTSTATUS status; - PHUB2_EXTENSION hub_ext; - PUSB_PORT_STATUS ps, psret; - UCHAR port_count; - ULONG i; - - USE_NON_PENDING_IRQL; - if (pdev == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - dev_mgr = dev_mgr_from_dev(pdev); - - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - ohci = ohci_from_hcd(pdev->hcd); - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext); - port_count = ohci->num_ports; - - switch (endp_type(purb->pendp)) - { - case USB_ENDPOINT_XFER_CONTROL: - { - if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS) - { - //get-port-status - if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength < 4) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - ps = &hub_ext->rh_port_status[psetup->wIndex]; - psret = (PUSB_PORT_STATUS) purb->data_buffer; - - status = - OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[psetup->wIndex-1]); - - ps->wPortStatus = 0; - - if (status & RH_PS_CCS) - { - ps->wPortStatus |= USB_PORT_STAT_CONNECTION; - } - if (status & RH_PS_PES) - { - ps->wPortStatus |= USB_PORT_STAT_ENABLE; - //ps->wPortStatus |= USB_PORT_STAT_HIGH_SPEED; // ehci spec - } - if (status & RH_PS_PRS) - { - ps->wPortStatus |= USB_PORT_STAT_RESET; - } - if (status & RH_PS_PSS) - { - ps->wPortStatus |= USB_PORT_STAT_SUSPEND; - } - if (status & RH_PS_LSDA) - { - ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED; - } - - //always power on - ps->wPortStatus |= USB_PORT_STAT_POWER; - - //now set change field - if ((status & RH_PS_CSC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED)) - { - ps->wPortChange |= USB_PORT_STAT_C_CONNECTION; - } - if ((status & RH_PS_PESC) && !(ps->wPortStatus & USB_PORT_STAT_LOW_SPEED)) - { - ps->wPortChange |= USB_PORT_STAT_C_ENABLE; - } - - //don't touch other fields, might be filled by - //other function - - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n", - ps->wPortStatus, ps->wPortChange, ps)); - - psret->wPortChange = ps->wPortChange; - psret->wPortStatus = ps->wPortStatus; - - purb->status = STATUS_SUCCESS; - - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE) - { - //clear-port-feature - if (psetup->wIndex == 0 || psetup->wIndex > port_count) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - i = psetup->wIndex - 1; - ps = &hub_ext->rh_port_status[psetup->wIndex]; - - purb->status = STATUS_SUCCESS; - switch (psetup->wValue) - { - case USB_PORT_FEAT_C_CONNECTION: - { - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i], RH_PS_CSC); - status = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i]); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex, status)); - ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION; - break; - } - case USB_PORT_FEAT_C_ENABLE: - { - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i], RH_PS_PESC); - status = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i]); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex, status)); - ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE; - break; - } - case USB_PORT_FEAT_C_RESET: - { - ps->wPortChange &= ~USB_PORT_STAT_C_RESET; - //the reset signal is down in rh_timer_svc_reset_port_completion - // enable or not is set by host controller - // status = EHCI_READ_PORT_ULONG( ( PUSHORT ) ( ehci->port_base + i ) ); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n", - psetup->wIndex, 0)); - break; - } - case USB_PORT_FEAT_ENABLE: - { - ps->wPortStatus &= ~USB_PORT_STAT_ENABLE; - OHCI_WRITE_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i], RH_PS_PES); - status = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[i]); - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex, status)); - break; - } - default: - purb->status = STATUS_UNSUCCESSFUL; - } - - break; - } - else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE) - { - // get bus state - if (psetup->wIndex == 0 || psetup->wIndex > port_count || psetup->wLength == 0) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } -#if 0 - i = EHCI_PORTSC + 4 * (psetup->wIndex - 1); // USBPORTSC1; - status = EHCI_READ_PORT_ULONG((PULONG) (ehci->port_base + i)); - purb->data_buffer[0] = (status & USBPORTSC_LS); - - // reverse the order - purb->data_buffer[0] ^= 0x3; -#endif - purb->status = STATUS_SUCCESS; - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_SET_FEATURE) - { - //reset port - if (psetup->wValue != USB_PORT_FEAT_RESET) - { - purb->status = STATUS_INVALID_PARAMETER; - ehci_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue)); - break; - } - - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - - ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_reset_port_completion; - - //start the timer - pdev->ref_count += 2; //one for timer and one for purb - - status = - OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->roothub.portstatus[psetup->wIndex-1]); - - usb_dbg_print(DBGLVL_MAXIMUM, - ("ohci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status)); - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - purb->status = STATUS_PENDING; - } - else - { - purb->status = STATUS_INVALID_PARAMETER; - } - break; - } - case USB_ENDPOINT_XFER_INT: - { - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - - ptimer->threshold = RH_INTERVAL; - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_int_completion; - - //start the timer - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - - //usb_dbg_print(DBGLVL_MAXIMUM, - // ("ehci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count)); - pdev->ref_count += 2; //one for timer and one for purb - - purb->status = STATUS_PENDING; - break; - } - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_ISOC: - default: - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - } - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return purb->status; -} - -NTSTATUS -ohci_submit_urb(POHCI_DEV ehci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - int i; - PUHCI_PENDING_ENDP pending_endp; - NTSTATUS status; - USE_BASIC_IRQL; - - if (ehci == NULL) - return STATUS_INVALID_PARAMETER; - - if (pdev == NULL || pendp == NULL || purb == NULL) - { - // give a chance to those pending urb, especially for clearing hub tt - ohci_process_pending_endp(ehci); - return STATUS_INVALID_PARAMETER; - } - - lock_pending_endp_list(&ehci->pending_endp_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - - if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB) - { - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - status = ohci_rh_submit_urb(pdev, purb); - return status; - } - - if (pendp) - purb->pendp = pendp; - else - purb->pendp = &pdev->default_endp; - - if (dev_from_endp(purb->pendp) != pdev) - { - status = purb->status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - - if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL) - { - status = purb->status = USB_STATUS_ENDPOINT_HALTED; - goto LBL_OUT; - } - - if ((pdev->flags & USB_DEV_FLAG_HIGH_SPEED) == 0) - { - // wait one ms - usb_wait_ms_dpc(1); - } - - purb->pdev = pdev; - purb->rest_bytes = purb->data_length; - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK) - purb->bytes_to_transfer = (purb->data_length > EHCI_MAX_SIZE_TRANSFER ? EHCI_MAX_SIZE_TRANSFER : purb->data_length); //multiple transfer for large data block - else - purb->bytes_to_transfer = purb->data_length; - - ehci_dbg_print(DBGLVL_MEDIUM, ("ohci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer)); - - purb->bytes_transfered = 0; - InitializeListHead(&purb->trasac_list); - purb->last_finished_td = &purb->trasac_list; - purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL); - purb->flags |= URB_FLAG_STATE_PENDING; - - - i = IsListEmpty(&pendp->urb_list); - InsertTailList(&pendp->urb_list, &purb->urb_link); - - pdev->ref_count++; //for purb reference - - if (i == FALSE) - { - //there is purb pending, simply queue it and return - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC) - { - // - //No purb waiting but purb overlap not allowed, - //so leave it in queue and return, will be scheduled - //later - // - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - - pending_endp = alloc_pending_endp(&ehci->pending_endp_pool, 1); - if (pending_endp == NULL) - { - //panic - status = purb->status = STATUS_UNSUCCESSFUL; - goto LBL_OUT2; - } - - pending_endp->pendp = purb->pendp; - InsertTailList(&ehci->pending_endp_list, &pending_endp->endp_link); - - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - - ohci_process_pending_endp(ehci); - return STATUS_PENDING; - - LBL_OUT2: - pdev->ref_count--; - RemoveEntryList(&purb->urb_link); - - LBL_OUT: - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&ehci->pending_endp_list_lock); - ohci_process_pending_endp(ehci); - return status; -} - -ULONG -ohci_get_type(PHCD hcd) -{ - return HCD_TYPE_OHCI; // ( hcd->flags & HCD_TYPE_MASK ); -} - -NTSTATUS -ohci_submit_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - return ohci_submit_urb(ohci_from_hcd(hcd), pdev, pendp, purb); -} - -PUSB_DEV -ohci_get_root_hub(PHCD hcd) -{ - return ohci_from_hcd(hcd)->root_hub; -} - -VOID -ohci_set_root_hub(PHCD hcd, PUSB_DEV root_hub) -{ - if (hcd == NULL || root_hub == NULL) - return; - ohci_from_hcd(hcd)->root_hub = root_hub; - return; -} - -BOOLEAN -ohci_remove_device2(PHCD hcd, PUSB_DEV pdev) -{ - if (hcd == NULL || pdev == NULL) - return FALSE; - - return FALSE; - //return ehci_remove_device(ehci_from_hcd(hcd), pdev); -} - -BOOLEAN -ohci_hcd_release(PHCD hcd) -{ - POHCI_DEV ohci; - POHCI_DEVICE_EXTENSION pdev_ext; - - if (hcd == NULL) - return FALSE; - - ohci = ohci_from_hcd(hcd); - pdev_ext = ohci->pdev_ext; - return FALSE;//ehci_release(pdev_ext->pdev_obj); -} - -NTSTATUS -ohci_cancel_urb2(PHCD hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - POHCI_DEV ohci; - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - - ohci = ohci_from_hcd(hcd); - DbgPrint("ohci_cancel_urb2 called, but not implemented!\n"); - return STATUS_UNSUCCESSFUL;//ehci_cancel_urb(ehci, pdev, pendp, purb); -} - -VOID -ohci_generic_urb_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - BOOLEAN is_ctrl = FALSE; - USE_NON_PENDING_IRQL; - - old_irql = KeGetCurrentIrql(); - if (old_irql > DISPATCH_LEVEL) - TRAP(); - - if (old_irql < DISPATCH_LEVEL) - KeRaiseIrql(DISPATCH_LEVEL, &old_irql); - - if (purb == NULL) - goto LBL_LOWER_IRQL; - - pdev = purb->pdev; - - if (pdev == NULL) - goto LBL_LOWER_IRQL; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - // no need to do following statistics - unlock_dev(pdev, TRUE); - goto LBL_CLIENT_PROCESS; - } - if (usb_error(purb->status)) - { - pdev->error_count++; - } - - if (purb->pendp == &pdev->default_endp) - { - if (usb_halted(purb->status)) - { - pdev->time_out_count++; - if (pdev->time_out_count > 3) - { - dev_set_state(pdev, USB_DEV_STATE_ZOMB); - ohci_dbg_print(DBGLVL_MAXIMUM, - ("ohci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n", - pdev)); - } - } - else - pdev->time_out_count = 0; - - } - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_CONTROL) - is_ctrl = TRUE; - - unlock_dev(pdev, TRUE); - - LBL_CLIENT_PROCESS: - if (!is_ctrl) - { - if (purb->completion) - purb->completion(purb, context); - } - else - { - if (purb->ctrl_req_context.ctrl_stack_count == 0) - { - if (purb->completion) - purb->completion(purb, context); - } - else - { - // pstack = &purb->ctrl_req_stack[ purb->ctrl_req_context.ctrl_cur_stack ]; - // if( pstack->urb_completion ) - // pstack->urb_completion( purb, pstack->context ); - usb_call_ctrl_completion(purb); - } - } - - LBL_LOWER_IRQL: - if (old_irql < DISPATCH_LEVEL) - KeLowerIrql(old_irql); - - return; -} - -BOOLEAN -ohci_rh_reset_port(PHCD hcd, UCHAR port_idx) -{ - POHCI_DEV ohci; - ULONG status, temp; - PULONG PortStatus; - USHORT Now, ResetDone; - - if (hcd == NULL) - return FALSE; - - ohci = ohci_from_hcd(hcd); - - if (port_idx < 1 || port_idx > ohci->num_ports) - return FALSE; - - port_idx--; - - PortStatus = &ohci->regs->roothub.portstatus[port_idx]; - - Now = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->fmnumber); - ResetDone = Now + PORT_RESET_MSEC; - - /* build a "continuous enough" reset signal, with up to - * 3msec gap between pulses. scheduler HZ==100 must work; - * this might need to be deadline-scheduled. - */ - do { - /* spin until any current reset finishes */ - for (;;) { - temp = OHCI_READ_PORT_ULONG(PortStatus); - if (!(temp & RH_PS_PRS)) - break; - usb_wait_us_dpc(500); - } - - if (!(temp & RH_PS_CCS)) - break; - if (temp & RH_PS_PRSC) - { - OHCI_WRITE_PORT_ULONG(PortStatus, RH_PS_PRSC); - } - - /* start the next reset, sleep till it's probably done */ - OHCI_WRITE_PORT_ULONG(PortStatus, RH_PS_PRS); - usb_wait_ms_dpc(PORT_RESET_HW_MSEC); - Now = OHCI_READ_PORT_ULONG((PULONG)&ohci->regs->fmnumber); - } while (tick_before(Now, ResetDone)); - - status = OHCI_READ_PORT_ULONG((PULONG)(&ohci->regs->roothub.portstatus[port_idx])); - usb_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_reset_port(): status after written=0x%x\n", status)); - return TRUE; -} - -BOOLEAN -ohci_rh_get_dev_change(PHCD hcd, PBYTE buf) //must have the rh dev_lock acquired -{ - POHCI_DEV ohci; - LONG i; - ULONG status; - - if (hcd == NULL) - return FALSE; - - ohci = ohci_from_hcd(hcd); - - for(i = 0; i < ohci->num_ports; i++) - { - status = OHCI_READ_PORT_ULONG((PULONG)(&ohci->regs->roothub.portstatus[i])); - - if (status != 0) - { - ohci_dbg_print(DBGLVL_MAXIMUM, ("ohci_rh_get_dev_change(): erh port%d status=0x%x\n", i, status)); - } - - if (status & (RH_PS_PESC | RH_PS_CSC | RH_PS_OCIC)) - { - buf[(i + 1) >> 3] |= (1 << ((i + 1) & 7)); - } - } - return TRUE; -} - - -NTSTATUS -ohci_hcd_dispatch(PHCD hcd, LONG disp_code, PVOID param) -{ - POHCI_DEV ohci; - - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - ohci = ohci_from_hcd(hcd); - - switch (disp_code) - { - case HCD_DISP_READ_PORT_COUNT: - { - if (param == NULL) - return STATUS_INVALID_PARAMETER; - *((PUCHAR) param) = ohci->num_ports; - return STATUS_SUCCESS; - } - case HCD_DISP_READ_RH_DEV_CHANGE: - { - if (ohci_rh_get_dev_change(hcd, param) == FALSE) - return STATUS_INVALID_PARAMETER; - return STATUS_SUCCESS; - } - } - - return STATUS_NOT_IMPLEMENTED; -} - -VOID -ohci_init_hcd_interface(POHCI_DEV ohci) -{ - ohci->hcd_interf.hcd_set_dev_mgr = ehci_set_dev_mgr; - ohci->hcd_interf.hcd_get_dev_mgr = ehci_get_dev_mgr; - ohci->hcd_interf.hcd_get_type = ohci_get_type; - ohci->hcd_interf.hcd_set_id = ehci_set_id; - ohci->hcd_interf.hcd_get_id = ehci_get_id; - ohci->hcd_interf.hcd_alloc_addr = ehci_alloc_addr; - ohci->hcd_interf.hcd_free_addr = ehci_free_addr; - ohci->hcd_interf.hcd_submit_urb = ohci_submit_urb2; - ohci->hcd_interf.hcd_generic_urb_completion = ohci_generic_urb_completion; - ohci->hcd_interf.hcd_get_root_hub = ohci_get_root_hub; - ohci->hcd_interf.hcd_set_root_hub = ohci_set_root_hub; - ohci->hcd_interf.hcd_remove_device = ohci_remove_device2; - ohci->hcd_interf.hcd_rh_reset_port = ohci_rh_reset_port; - ohci->hcd_interf.hcd_release = ohci_hcd_release; - ohci->hcd_interf.hcd_cancel_urb = ohci_cancel_urb2; - ohci->hcd_interf.hcd_start = ohci_start; - ohci->hcd_interf.hcd_dispatch = ohci_hcd_dispatch; - - ohci->hcd_interf.flags = HCD_TYPE_OHCI; //hcd types | hcd id -} - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/ohci.h b/reactos/drivers/usb/nt4compat/usbdrv/ohci.h deleted file mode 100644 index a7bd6362723..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/ohci.h +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 2007 by Aleksey Bragin - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef __OHCI_H__ -#define __OHCI_H__ - -#define OHCI_DEVICE_NAME "\\Device\\OHCI" -#define OHCI_DOS_DEVICE_NAME "\\DosDevices\\OHCI" - -/* Host Controller Operational Registers */ - -#define OHCI_REVISION 0x0 -#define OHCI_CONTROL 0x4 -#define OHCI_CMDSTATUS 0x8 -#define OHCI_INTRSTATUS 0xc -#define OHCI_INTRENABLE 0x10 -#define OHCI_INTRDISABLE 0x14 - -/* OHCI CONTROL AND STATUS REGISTER MASKS */ - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ -#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ -#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ -#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ -#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_CLF (1 << 1) /* control list filled */ -#define OHCI_BLF (1 << 2) /* bulk list filled */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - - -/* OHCI ROOT HUB REGISTER MASKS */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -/* - * OHCI Endpoint Descriptor (ED) ... holds TD queue - * See OHCI spec, section 4.2 - * - * This is a "Queue Head" for those transfers, which is why - * both EHCI and UHCI call similar structures a "QH". - */ -typedef struct _OHCI_ED { - /* first fields are hardware-specified */ - ULONG hwINFO; /* endpoint config bitmap */ - /* info bits defined by hcd */ -#define ED_DEQUEUE (1 << 27) - /* info bits defined by the hardware */ -#define ED_ISO (1 << 15) -#define ED_SKIP (1 << 14) -#define ED_LOWSPEED (1 << 13) -#define ED_OUT (0x01 << 11) -#define ED_IN (0x02 << 11) - ULONG hwTailP; /* tail of TD list */ - ULONG hwHeadP; /* head of TD list (hc r/w) */ -#define ED_C (0x02) /* toggle carry */ -#define ED_H (0x01) /* halted */ - ULONG hwNextED; /* next ED in list */ - - /* rest are purely for the driver's use */ -#if 0 - dma_addr_t dma; /* addr of ED */ - struct _OHCI_TD *dummy; /* next TD to activate */ - - /* host's view of schedule */ - struct _OHCI_ED *ed_next; /* on schedule or rm_list */ - struct _OHCI_ED *ed_prev; /* for non-interrupt EDs */ - struct list_head td_list; /* "shadow list" of our TDs */ - - /* create --> IDLE --> OPER --> ... --> IDLE --> destroy - * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... - */ - UCHAR state; /* ED_{IDLE,UNLINK,OPER} */ -#define ED_IDLE 0x00 /* NOT linked to HC */ -#define ED_UNLINK 0x01 /* being unlinked from hc */ -#define ED_OPER 0x02 /* IS linked to hc */ - - UCHAR type; /* PIPE_{BULK,...} */ - - /* periodic scheduling params (for intr and iso) */ - UCHAR branch; - USHORT interval; - USHORT load; - USHORT last_iso; /* iso only */ - - /* HC may see EDs on rm_list until next frame (frame_no == tick) */ - USHORT tick; -#endif -} OHCI_ED, *POHCI_ED; - -#define ED_MASK ((u32)~0x0f) /* strip hw status in low addr bits */ - - -/* - * OHCI Transfer Descriptor (TD) ... one per transfer segment - * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) - * and 4.3.2 (iso) - */ -typedef struct _OHCI_TD { - /* first fields are hardware-specified */ - ULONG hwINFO; /* transfer info bitmask */ - - /* hwINFO bits for both general and iso tds: */ -#define TD_CC 0xf0000000 /* condition code */ -#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) -//#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) -#define TD_DI 0x00E00000 /* frames before interrupt */ -#define TD_DI_SET(X) (((X) & 0x07)<< 21) - /* these two bits are available for definition/use by HCDs in both - * general and iso tds ... others are available for only one type - */ -#define TD_DONE 0x00020000 /* retired to donelist */ -#define TD_ISO 0x00010000 /* copy of ED_ISO */ - - /* hwINFO bits for general tds: */ -#define TD_EC 0x0C000000 /* error count */ -#define TD_T 0x03000000 /* data toggle state */ -#define TD_T_DATA0 0x02000000 /* DATA0 */ -#define TD_T_DATA1 0x03000000 /* DATA1 */ -#define TD_T_TOGGLE 0x00000000 /* uses ED_C */ -#define TD_DP 0x00180000 /* direction/pid */ -#define TD_DP_SETUP 0x00000000 /* SETUP pid */ -#define TD_DP_IN 0x00100000 /* IN pid */ -#define TD_DP_OUT 0x00080000 /* OUT pid */ - /* 0x00180000 rsvd */ -#define TD_R 0x00040000 /* round: short packets OK? */ - - /* (no hwINFO #defines yet for iso tds) */ - - ULONG hwCBP; /* Current Buffer Pointer (or 0) */ - ULONG hwNextTD; /* Next TD Pointer */ - ULONG hwBE; /* Memory Buffer End Pointer */ - - /* PSW is only for ISO. Only 1 PSW entry is used, but on - * big-endian PPC hardware that's the second entry. - */ -#define MAXPSW 2 - USHORT hwPSW [MAXPSW]; - - /* rest are purely for the driver's use */ -#if 0 - UCHAR index; - struct ed *ed; - struct td *td_hash; /* dma-->td hashtable */ - struct td *next_dl_td; - struct urb *urb; - - dma_addr_t td_dma; /* addr of this TD */ - dma_addr_t data_dma; /* addr of data it points to */ - - struct list_head td_list; /* "shadow list", TDs on same ED */ -#endif -} OHCI_TD, *POHCI_TD; - -/* - * The HCCA (Host Controller Communications Area) is a 256 byte - * structure defined section 4.4.1 of the OHCI spec. The HC is - * told the base address of it. It must be 256-byte aligned. - */ -typedef struct _OHCI_HCCA -{ -#define NUM_INTS 32 - ULONG int_table [NUM_INTS]; /* periodic schedule */ - - /* - * OHCI defines u16 frame_no, followed by u16 zero pad. - * Since some processors can't do 16 bit bus accesses, - * portable access must be a 32 bits wide. - */ - ULONG frame_no; /* current frame number */ - ULONG done_head; /* info returned for an interrupt */ - UCHAR reserved_for_hc [116]; - UCHAR what [4]; /* spec only identifies 252 bytes :) */ -} OHCI_HCCA, *POHCI_HCCA; - -/* - * This is the structure of the OHCI controller's memory mapped I/O region. - * You must use readl() and writel() (in ) to access these fields!! - * Layout is in section 7 (and appendix B) of the spec. - */ -typedef struct _OHCI_REGS -{ - /* control and status registers (section 7.1) */ - ULONG revision; - ULONG control; - ULONG cmdstatus; - ULONG intrstatus; - ULONG intrenable; - ULONG intrdisable; - - /* memory pointers (section 7.2) */ - ULONG hcca; - ULONG ed_periodcurrent; - ULONG ed_controlhead; - ULONG ed_controlcurrent; - ULONG ed_bulkhead; - ULONG ed_bulkcurrent; - ULONG donehead; - - /* frame counters (section 7.3) */ - ULONG fminterval; - ULONG fmremaining; - ULONG fmnumber; - ULONG periodicstart; - ULONG lsthresh; - - /* Root hub ports (section 7.4) */ - struct ohci_roothub_regs { - ULONG a; - ULONG b; - ULONG status; -#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */ - ULONG portstatus [MAX_ROOT_PORTS]; - } roothub; - - /* and optional "legacy support" registers (appendix B) at 0x0100 */ -} OHCI_REGS, *POHCI_REGS; - -typedef struct _OHCI_DEV -{ - HCD hcd_interf; - - PHYSICAL_ADDRESS ohci_reg_base; // io space - BOOLEAN port_mapped; - PBYTE port_base; // note: added by ehci_caps.length, operational regs base addr, not the actural base - struct _OHCI_REGS *regs; - struct _OHCI_HCCA *hcca; - PVOID td_cache; - PVOID ed_cache; - - PHYSICAL_ADDRESS hcca_logic_addr; - PHYSICAL_ADDRESS td_logic_addr; - PHYSICAL_ADDRESS ed_logic_addr; - - USHORT num_ports; - - LIST_HEAD urb_list; // active urb-list - - // - //for iso and int bandwidth claim, bandwidth schedule - // - KSPIN_LOCK pending_endp_list_lock; //lock to access the following two - LIST_HEAD pending_endp_list; - UHCI_PENDING_ENDP_POOL pending_endp_pool; - - KTIMER reset_timer; //used to reset the host controller - struct _OHCI_DEVICE_EXTENSION *pdev_ext; - PUSB_DEV root_hub; //root hub -} OHCI_DEV, *POHCI_DEV; - -typedef struct _OHCI_DEVICE_EXTENSION -{ - DEVEXT_HEADER dev_ext_hdr; - PDEVICE_OBJECT pdev_obj; - PDRIVER_OBJECT pdrvr_obj; - POHCI_DEV ohci; - - //device resources - PADAPTER_OBJECT padapter; - ULONG map_regs; - PCM_RESOURCE_LIST res_list; - ULONG pci_addr; // bus number | slot number | funciton number - UHCI_INTERRUPT res_interrupt; - union - { - UHCI_PORT res_port; - EHCI_MEMORY res_memory; - }; - - PKINTERRUPT ohci_int; - KDPC ohci_dpc; -} OHCI_DEVICE_EXTENSION, *POHCI_DEVICE_EXTENSION; - -#define ohci_from_hcd( hCD ) ( struct_ptr( ( hCD ), OHCI_DEV, hcd_interf ) ) - -#endif /* __OHCI_H__ */ diff --git a/reactos/drivers/usb/nt4compat/usbdrv/roothub.c b/reactos/drivers/usb/nt4compat/usbdrv/roothub.c deleted file mode 100644 index d76b2da0df1..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/roothub.c +++ /dev/null @@ -1,433 +0,0 @@ -/** - * roothub.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -//---------------------------------------------------------- - -BOOLEAN -rh_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - LONG i; - PHCD hcd; - - if (dev_mgr == NULL) - return FALSE; - - for(i = 0; i < dev_mgr->hcd_count; i++) - { - hcd = dev_mgr->hcd_array[i]; - // if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI ) - // continue; - rh_destroy(hcd->hcd_get_root_hub(hcd)); - } - return TRUE; -} - -BOOLEAN -rh_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - - PUSB_DEV rh; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_INTERFACE_DESC pif_desc; - PUSB_ENDPOINT_DESC pendp_desc; - PUSB_CONFIGURATION pconfig; - PUSB_INTERFACE pif; - PUSB_ENDPOINT pendp; - PHUB2_EXTENSION phub_ext; - NTSTATUS status; - PHCD hcd; - LONG i; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //init driver structure, no PNP table functions - pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE; - pdriver->driver_desc.vendor_id = 0xffff; // USB Vendor ID - pdriver->driver_desc.product_id = 0xffff; // USB Product ID. - pdriver->driver_desc.release_num = 0xffff; // Release Number of Device - - pdriver->driver_desc.config_val = 0; // Configuration Value - pdriver->driver_desc.if_num = 0; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_HUB; // Interface Class - pdriver->driver_desc.if_sub_class = 0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB root hub"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_HUB; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - //pdriver->driver_init = rh_driver_init; // initialized in dev_mgr_init_driver - //pdriver->driver_destroy = rh_driver_destroy; - pdriver->disp_tbl.version = 1; // other fields of the dispatch table is not used since rh needs no pnp - - pdriver->driver_ext = 0; - pdriver->driver_ext_size = 0; - - for(i = 0; i < dev_mgr->hcd_count; i++) - { - hcd = dev_mgr->hcd_array[i]; - //if( hcd->hcd_get_type( hcd ) != HCD_TYPE_UHCI ) - // continue; - - if ((rh = dev_mgr_alloc_device(dev_mgr, hcd)) == NULL) - return FALSE; - - rh->parent_dev = NULL; - rh->port_idx = 0; - rh->hcd = hcd; - rh->flags = USB_DEV_CLASS_ROOT_HUB | USB_DEV_STATE_CONFIGURED; - - if (usb2(hcd)) - rh->flags |= USB_DEV_FLAG_HIGH_SPEED; - - rh->dev_driver = pdriver; - - rh->desc_buf_size = sizeof(USB_DEVICE_DESC) - + sizeof(USB_CONFIGURATION_DESC) - + sizeof(USB_INTERFACE_DESC) - + sizeof(USB_ENDPOINT_DESC) + sizeof(USB_CONFIGURATION) + sizeof(HUB2_EXTENSION); - - rh->desc_buf = usb_alloc_mem(NonPagedPool, rh->desc_buf_size); - - if (rh->desc_buf == NULL) - { - return FALSE; - } - else - RtlZeroMemory(rh->desc_buf, rh->desc_buf_size); - - rh->pusb_dev_desc = (PUSB_DEVICE_DESC) rh->desc_buf; - - rh->pusb_dev_desc->bLength = sizeof(USB_DEVICE_DESC); - rh->pusb_dev_desc->bDescriptorType = USB_DT_DEVICE; - rh->pusb_dev_desc->bcdUSB = 0x110; - if (usb2(hcd)) - rh->pusb_dev_desc->bcdUSB = 0x200; - rh->pusb_dev_desc->bDeviceClass = USB_CLASS_HUB; - rh->pusb_dev_desc->bDeviceSubClass = 0; - rh->pusb_dev_desc->bDeviceProtocol = 0; - rh->pusb_dev_desc->bMaxPacketSize0 = 8; - if (usb2(hcd)) - { - rh->pusb_dev_desc->bDeviceProtocol = 1; - rh->pusb_dev_desc->bMaxPacketSize0 = 64; - } - rh->pusb_dev_desc->idVendor = 0; - rh->pusb_dev_desc->idProduct = 0; - rh->pusb_dev_desc->bcdDevice = 0x100; - rh->pusb_dev_desc->iManufacturer = 0; - rh->pusb_dev_desc->iProduct = 0; - rh->pusb_dev_desc->iSerialNumber = 0; - rh->pusb_dev_desc->bNumConfigurations = 1; - - pconfig_desc = (PUSB_CONFIGURATION_DESC) & rh->desc_buf[sizeof(USB_DEVICE_DESC)]; - pif_desc = (PUSB_INTERFACE_DESC) & pconfig_desc[1]; - pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1]; - - pconfig_desc->bLength = sizeof(USB_CONFIGURATION_DESC); - pconfig_desc->bDescriptorType = USB_DT_CONFIG; - - pconfig_desc->wTotalLength = sizeof(USB_CONFIGURATION_DESC) - + sizeof(USB_INTERFACE_DESC) + sizeof(USB_ENDPOINT_DESC); - - pconfig_desc->bNumInterfaces = 1; - pconfig_desc->bConfigurationValue = 1; - pconfig_desc->iConfiguration = 0; - pconfig_desc->bmAttributes = 0Xe0; //self-powered and support remoke wakeup - pconfig_desc->MaxPower = 0; - - pif_desc->bLength = sizeof(USB_INTERFACE_DESC); - pif_desc->bDescriptorType = USB_DT_INTERFACE; - pif_desc->bInterfaceNumber = 0; - pif_desc->bAlternateSetting = 0; - pif_desc->bNumEndpoints = 1; - pif_desc->bInterfaceClass = USB_CLASS_HUB; - pif_desc->bInterfaceSubClass = 0; - pif_desc->bInterfaceProtocol = 0; - pif_desc->iInterface = 0; - - pendp_desc->bLength = sizeof(USB_ENDPOINT_DESC); - pendp_desc->bDescriptorType = USB_DT_ENDPOINT; - pendp_desc->bEndpointAddress = 0x81; - pendp_desc->bmAttributes = 0x03; - pendp_desc->wMaxPacketSize = 8; - pendp_desc->bInterval = USB_HUB_INTERVAL; - if (usb2(hcd)) - pendp_desc->bInterval = 0x0c; - - pconfig = rh->usb_config = (PUSB_CONFIGURATION) & pendp_desc[1]; - rh->active_config_idx = 0; - pconfig->pusb_config_desc = pconfig_desc; - pconfig->if_count = 1; - pconfig->pusb_dev = rh; - pif = &pconfig->interf[0]; - - pif->endp_count = 1; - pendp = &pif->endp[0]; - pif->pusb_config = pconfig; - pif->pusb_if_desc = pif_desc; - - pif->if_ext_size = 0; - pif->if_ext = NULL; - - phub_ext = (PHUB2_EXTENSION) & pconfig[1]; - phub_ext->port_count = 2; - - if (usb2(hcd)) - { - // port count is configurable in usb2 - hcd->hcd_dispatch(hcd, HCD_DISP_READ_PORT_COUNT, &phub_ext->port_count); - } - - { - int j; - for(j = 0; j < phub_ext->port_count; j++) - { - psq_init(&phub_ext->port_status_queue[j]); - phub_ext->child_dev[j] = NULL; - usb_dbg_print(DBGLVL_MAXIMUM, ("rh_driver_init(): port[ %d ].flag=0x%x\n", - j, phub_ext->port_status_queue[j].port_flags)); - } - } - - phub_ext->pif = pif; - phub_ext->hub_desc.bLength = sizeof(USB_HUB_DESCRIPTOR); - phub_ext->hub_desc.bDescriptorType = USB_DT_HUB; - phub_ext->hub_desc.bNbrPorts = (UCHAR) phub_ext->port_count; - phub_ext->hub_desc.wHubCharacteristics = 0; - phub_ext->hub_desc.bPwrOn2PwrGood = 0; - phub_ext->hub_desc.bHubContrCurrent = 50; - - rh->dev_ext = (PBYTE) phub_ext; - rh->dev_ext_size = sizeof(HUB2_EXTENSION); - - rh->default_endp.flags = USB_ENDP_FLAG_DEFAULT_ENDP; - InitializeListHead(&rh->default_endp.urb_list); - rh->default_endp.pusb_if = (PUSB_INTERFACE) rh; - rh->default_endp.pusb_endp_desc = NULL; //??? - rh->time_out_count = 0; - rh->error_count = 0; - - InitializeListHead(&pendp->urb_list); - pendp->flags = 0; - pendp->pusb_endp_desc = pendp_desc; - pendp->pusb_if = pif; - - //add to device list - InsertTailList(&dev_mgr->dev_list, &rh->dev_link); - hcd->hcd_set_root_hub(hcd, rh); - status = hub_start_int_request(rh); - pdriver->driver_ext = 0; - } - return TRUE; -} - -//to be the reverse of what init does, we assume that the timer is now killed -//int is disconnected and the hub thread will not process event anymore -BOOLEAN -rh_destroy(PUSB_DEV pdev) -{ - PUSB_DEV rh; - PUSB_DEV_MANAGER dev_mgr; - - if (pdev == NULL) - return FALSE; - - dev_mgr = dev_mgr_from_dev(pdev); - - //??? - rh = pdev->hcd->hcd_get_root_hub(pdev->hcd); - if (rh == pdev) - { - //free all the buf - dev_mgr_free_device(dev_mgr, rh); - //dev_mgr->root_hub = NULL; - } - - return TRUE; -} - -VOID -rh_timer_svc_int_completion(PUSB_DEV pdev, PVOID context) -{ - PURB purb; - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || context == NULL) - return; - - purb = (PURB) context; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - pdev->ref_count -= 2; // one for timer_svc and one for urb, for those rh requests - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - usb_dbg_print(DBGLVL_MAXIMUM, ("rh_timer_svc_int_completion(): the dev is zomb, 0x%x\n", pdev)); - return; - } - - hcd = pdev->hcd; - if (purb->data_length < 1) - { - purb->status = STATUS_INVALID_PARAMETER; - unlock_dev(pdev, TRUE); - goto LBL_OUT; - } - - pdev->hcd->hcd_dispatch(pdev->hcd, HCD_DISP_READ_RH_DEV_CHANGE, purb->data_buffer); - purb->status = STATUS_SUCCESS; - unlock_dev(pdev, TRUE); - - LBL_OUT: - hcd->hcd_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, TRUE); - pdev->ref_count -= 2; - // one for timer_svc and one for urb, for those rh requests - // that completed immediately, the ref_count of the dev for - // that urb won't increment and for normal hub request - // completion, hcd_generic_urb_completion will be called - // by the xhci_dpc_callback, and the ref_count for the urb - // is maintained there. So only rh's timer-svc cares refcount - // when hcd_generic_urb_completion is called. - usb_dbg_print(DBGLVL_ULTRA, ("rh_timer_svc_int_completion(): rh's ref_count=0x%x\n", pdev->ref_count)); - unlock_dev(pdev, TRUE); - usb_dbg_print(DBGLVL_ULTRA, ("rh_timer_svc_int_completion(): exitiing...\n")); - return; -} - -VOID -rh_timer_svc_reset_port_completion(PUSB_DEV pdev, PVOID context) -{ - PURB purb; - ULONG i; - PHUB2_EXTENSION hub_ext; - PLIST_ENTRY pthis, pnext; - PUSB_DEV_MANAGER dev_mgr; - PUSB_CTRL_SETUP_PACKET psetup; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || context == NULL) - return; - - dev_mgr = dev_mgr_from_dev(pdev); //readonly and hold ref_count - - //block the rh polling - KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock); - if (IsListEmpty(&dev_mgr->timer_svc_list) == FALSE) - { - ListFirst(&dev_mgr->timer_svc_list, pthis); - while (pthis) - { - if (((PTIMER_SVC) pthis)->pdev == pdev && ((PTIMER_SVC) pthis)->threshold == RH_INTERVAL) - { - ((PTIMER_SVC) pthis)->threshold = RH_INTERVAL + 0x800000; - break; - } - - ListNext(&dev_mgr->timer_svc_list, pthis, pnext); - pthis = pnext; - } - } - KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock); - - purb = (PURB) context; - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - //purb->status = STATUS_ERROR; - //pdev->hcd->hcd_generic_urb_completion( purb, purb->context ); - - pdev->ref_count -= 2; - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - return; - } - - i = pdev->hcd->hcd_rh_reset_port(pdev->hcd, (UCHAR) psetup->wIndex); - - hub_ext = hub_ext_from_dev(pdev); - - { - USHORT temp; - PUCHAR pbuf; - if (psetup->wIndex < 16) - { - temp = 1 << psetup->wIndex; - pbuf = (PUCHAR) & temp; - if (temp > 128) - pbuf++; - hub_ext->int_data_buf[psetup->wIndex / 8] |= *pbuf; - if (i == TRUE) - hub_ext->rh_port_status[psetup->wIndex].wPortChange |= USB_PORT_STAT_C_RESET; - else // notify that is not a high speed device, will lost definitely - hub_ext->rh_port_status[psetup->wIndex].wPortChange |= USB_PORT_STAT_C_CONNECTION; - } - } - - //???how to construct port status map - // decrease the timer_svc ref-count - pdev->ref_count--; - unlock_dev(pdev, TRUE); - - purb->status = STATUS_SUCCESS; - //we delegate the completion to the rh_timer_svc_int_completion. - //this function is equivalent to hub_start_reset_port_completion - - usb_free_mem(purb); - - //expire the rh polling timer - KeAcquireSpinLockAtDpcLevel(&dev_mgr->timer_svc_list_lock); - if (IsListEmpty(&dev_mgr->timer_svc_list) == FALSE) - { - ListFirst(&dev_mgr->timer_svc_list, pthis); - while (pthis) - { - if (((PTIMER_SVC) pthis)->pdev == pdev && - ((PTIMER_SVC) pthis)->threshold == RH_INTERVAL + 0x800000) - { - ((PTIMER_SVC) pthis)->counter = RH_INTERVAL; - ((PTIMER_SVC) pthis)->threshold = RH_INTERVAL; - break; - } - - ListNext(&dev_mgr->timer_svc_list, pthis, pnext); - pthis = pnext; - } - } - KeReleaseSpinLockFromDpcLevel(&dev_mgr->timer_svc_list_lock); - - lock_dev(pdev, TRUE); - pdev->ref_count--; - unlock_dev(pdev, TRUE); - return; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/td.c b/reactos/drivers/usb/nt4compat/usbdrv/td.c deleted file mode 100644 index 1f1bfe00e28..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/td.c +++ /dev/null @@ -1,603 +0,0 @@ -/** - * td.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -#define UHCI_MIN_TD_POOLS 4 - -BOOLEAN free_td_to_pool(PUHCI_TD_POOL ptd_pool, PUHCI_TD ptd); //add tds till pnext == NULL - - -PUHCI_QH alloc_qh(PUHCI_QH_POOL pqh_pool); //null if failed - -BOOLEAN -init_td_pool(PUHCI_TD_POOL ptd_pool) -{ - int i, pages; - PTD_EXTENSION ptde; - - if (ptd_pool == NULL) - return FALSE; - - if (ptd_pool->padapter == NULL) - return FALSE; - - pages = sizeof(UHCI_TD) * UHCI_MAX_POOL_TDS / PAGE_SIZE; - RtlZeroMemory(ptd_pool->td_array, sizeof(ptd_pool->td_array)); - RtlZeroMemory(ptd_pool->logic_addr, sizeof(ptd_pool->logic_addr)); - - for(i = 0; i < pages; i++) - { - ptd_pool->td_array[i] = - HalAllocateCommonBuffer(ptd_pool->padapter, PAGE_SIZE, &ptd_pool->logic_addr[i], FALSE); - if (ptd_pool->td_array[i] == NULL) - goto failed; - } - - ptd_pool->tde_array = (PTD_EXTENSION) usb_alloc_mem(NonPagedPool, - sizeof(TD_EXTENSION) * UHCI_MAX_POOL_TDS); - - if (ptd_pool->tde_array == NULL) - goto failed; - - for(i = 0; i < pages; i++) - { - RtlZeroMemory(ptd_pool->td_array[i], PAGE_SIZE); - } - - RtlZeroMemory(ptd_pool->tde_array, sizeof(TD_EXTENSION) * UHCI_MAX_POOL_TDS); - - ptde = ptd_pool->tde_array; - ptd_pool->free_count = 0; - ptd_pool->total_count = UHCI_MAX_POOL_TDS; - InitializeListHead(&ptd_pool->free_que); - - for(i = 0; i < UHCI_MAX_POOL_TDS; i++) - { - //link tde and the td one by one, fixed since this init - ptd_pool->td_array[i >> 7][i & 0x7f].ptde = &ptde[i]; - ptde[i].ptd = &ptd_pool->td_array[i >> 7][i & 0x7f]; - ptde[i].flags = UHCI_ITEM_FLAG_TD; - ptd_pool->td_array[i >> 7][i & 0x7f].phy_addr = - ptd_pool->logic_addr[i >> 7].LowPart + (i & 0x7f) * sizeof(UHCI_TD); - ptd_pool->td_array[i >> 7][i & 0x7f].pool = ptd_pool; - ptd_pool->td_array[i >> 7][i & 0x7f].purb = NULL; - free_td_to_pool(ptd_pool, &ptd_pool->td_array[i >> 7][i & 0x7f]); - - } - return TRUE; - -failed: - for(i = 0; i < pages; i++) - { - if (ptd_pool->td_array[i]) - { - HalFreeCommonBuffer(ptd_pool->padapter, - PAGE_SIZE, ptd_pool->logic_addr[i], ptd_pool->td_array[i], FALSE); - ptd_pool->td_array[i] = NULL; - ptd_pool->logic_addr[i].QuadPart = 0; - } - } - - if (ptd_pool->tde_array) - usb_free_mem(ptd_pool->tde_array); - - uhci_dbg_print(DBGLVL_MAXIMUM, ("init_td_pool(): failed to init the td pool\n")); - TRAP(); - - ptd_pool->free_count = ptd_pool->total_count = 0; - return FALSE; -} - -//add tds till pnext == NULL -BOOLEAN -free_td_to_pool(PUHCI_TD_POOL ptd_pool, PUHCI_TD ptd) -{ - if (ptd_pool == NULL || ptd == NULL) - { - return FALSE; - } - - ptd->link = ptd->status = ptd->info = ptd->buffer = 0; - ptd->purb = NULL; - ptd_pool->free_count++; - - InsertTailList(&ptd_pool->free_que, &ptd->ptde->vert_link); - - return TRUE; - -} - -// qh routines - -//null if failed -PUHCI_TD -alloc_td_from_pool(PUHCI_TD_POOL ptd_pool) -{ - PTD_EXTENSION ptde; - PLIST_ENTRY temp; - - if (ptd_pool == NULL) - return FALSE; - - if (IsListEmpty(&ptd_pool->free_que)) - return FALSE; - - temp = RemoveHeadList(&ptd_pool->free_que); - - if (temp == NULL) - return FALSE; - - ptde = struct_ptr(temp, TD_EXTENSION, vert_link); - - ptd_pool->free_count--; - - InitializeListHead(&ptde->vert_link); - InitializeListHead(&ptde->hori_link); - - return ptde->ptd; - -} - -//test whether the pool is all free -BOOLEAN -is_pool_free(PUHCI_TD_POOL pool) -{ - if (pool == NULL) - return FALSE; - - if (pool->free_count == pool->total_count) - return TRUE; - - return FALSE; -} - -BOOLEAN -is_pool_empty(PUHCI_TD_POOL pool) -{ - if (pool == NULL) - return FALSE; - - return (BOOLEAN) (pool->free_count == 0); -} - -BOOLEAN -destroy_td_pool(PUHCI_TD_POOL ptd_pool) -{ - int i, pages; - PADAPTER_OBJECT padapter; //we need this garbage for allocation - - padapter = ptd_pool->padapter; - - pages = sizeof(UHCI_TD) * UHCI_MAX_POOL_TDS / PAGE_SIZE; - if (ptd_pool && ptd_pool->padapter) - { - usb_free_mem(ptd_pool->tde_array); - ptd_pool->tde_array = NULL; - for(i = 0; i < pages; i++) - { - if (ptd_pool->td_array[i]) - { - HalFreeCommonBuffer(ptd_pool->padapter, - PAGE_SIZE, ptd_pool->logic_addr[i], ptd_pool->td_array[i], FALSE); - ptd_pool->td_array[i] = NULL; - ptd_pool->logic_addr[i].QuadPart = 0; - } - } - RtlZeroMemory(ptd_pool, sizeof(UHCI_TD_POOL)); - ptd_pool->padapter = padapter; - ptd_pool->free_count = ptd_pool->total_count = 0; - } - else - return FALSE; - - return TRUE; -} - -BOOLEAN -init_td_pool_list(PUHCI_TD_POOL_LIST pool_list, PADAPTER_OBJECT padapter) -{ - int i; - RtlZeroMemory(pool_list, sizeof(UHCI_TD_POOL_LIST)); - InitializeListHead(&pool_list->busy_pools); - InitializeListHead(&pool_list->free_pools); - - pool_list->free_count = UHCI_MAX_TD_POOLS; - pool_list->free_tds = 0; - - for(i = 0; i < UHCI_MAX_TD_POOLS; i++) - { - pool_list->pool_array[i].padapter = padapter; - InsertTailList(&pool_list->free_pools, &pool_list->pool_array[i].pool_link); - } - - KeInitializeSpinLock(&pool_list->pool_lock); - return expand_pool_list(pool_list, UHCI_MIN_TD_POOLS); -} - -BOOLEAN -destroy_td_pool_list(PUHCI_TD_POOL_LIST pool_list) -{ - PUHCI_TD_POOL pool; - while (IsListEmpty(&pool_list->busy_pools) == FALSE) - { - pool = (PUHCI_TD_POOL) RemoveHeadList(&pool_list->busy_pools); - destroy_td_pool(pool); - } - - RtlZeroMemory(pool_list, sizeof(UHCI_TD_POOL_LIST)); - return TRUE; -} - -BOOLEAN -expand_pool_list(PUHCI_TD_POOL_LIST pool_list, LONG pool_count) //private -{ - PUHCI_TD_POOL pool; - int i; - - if (IsListEmpty(&pool_list->free_pools) == TRUE) - return FALSE; - - if (pool_list->free_count < pool_count) - return FALSE; - - for(i = 0; i < pool_count; i++) - { - pool = (PUHCI_TD_POOL) RemoveHeadList(&pool_list->free_pools); - - if (init_td_pool(pool) == FALSE) - { - //reverse the allocation - InsertHeadList(&pool_list->free_pools, &pool->pool_link); - // collect_garbage( pool_list ); - return FALSE; - } - - InsertTailList(&pool_list->busy_pools, &pool->pool_link); - pool_list->free_tds += UHCI_MAX_POOL_TDS; - pool_list->free_count--; - } - return TRUE; -} - -BOOLEAN -collect_garbage(PUHCI_TD_POOL_LIST pool_list) -{ - PLIST_ENTRY prev, next; - - // no garbage - if (pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS) - return TRUE; - - ListFirstPrev(&pool_list->busy_pools, prev); - ListNext(&pool_list->busy_pools, prev, next); - - while (next && next != &pool_list->busy_pools) - { - if (is_pool_free((PUHCI_TD_POOL) next)) - { - RemoveEntryList(next); - destroy_td_pool((PUHCI_TD_POOL) next); - InsertTailList(&pool_list->free_pools, next); - pool_list->free_count++; - pool_list->free_tds -= UHCI_MAX_POOL_TDS; - ListNext(&pool_list->busy_pools, prev, next); - if (pool_list->free_count >= UHCI_MAX_TD_POOLS - UHCI_MIN_TD_POOLS) - break; - } - else - { - prev = next; - ListNext(&pool_list->busy_pools, prev, next); - } - } - return TRUE; - -} - -//private -LONG -get_num_free_tds(PUHCI_TD_POOL_LIST pool_list) -{ - return pool_list->free_tds; -} - -//private -LONG -get_max_free_tds(PUHCI_TD_POOL_LIST pool_list) -{ - return pool_list->free_tds + pool_list->free_count * UHCI_MAX_POOL_TDS; -} - -//add tds till pnext == NULL -BOOLEAN -free_td(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd) -{ - if (pool_list == NULL || ptd == NULL) - return FALSE; - - if (free_td_to_pool(ptd->pool, ptd) == FALSE) - return FALSE; - - pool_list->free_tds++; - - if (is_pool_free(ptd->pool)) - { - collect_garbage(pool_list); - } - return TRUE; -} - -//null if failed -PUHCI_TD -alloc_td(PUHCI_TD_POOL_LIST pool_list) -{ - PLIST_ENTRY prev, next; - PUHCI_TD new_td; - - if (pool_list == NULL) - return NULL; - - if (pool_list->free_tds == 0) - { - if (expand_pool_list(pool_list, 1) == FALSE) - return NULL; - } - - ListFirst(&pool_list->busy_pools, prev); - - while (prev && prev != &pool_list->busy_pools) - { - if (is_pool_empty((PUHCI_TD_POOL) prev) == FALSE) - { - new_td = alloc_td_from_pool((PUHCI_TD_POOL) prev); - - if (new_td == NULL) - TRAP(); - - pool_list->free_tds--; - - return new_td; - } - - ListNext(&pool_list->busy_pools, prev, next); - prev = next; - } - - return NULL; -} - -PUHCI_TD -alloc_tds(PUHCI_TD_POOL_LIST pool_list, LONG count) -{ - //return value is a list of tds, vert_link chain. - - LONG i; - PUHCI_TD ptd, pnext; - - if (pool_list == NULL || count <= 0) - return NULL; - - if (count >= get_max_free_tds(pool_list)) - return NULL; - - ptd = alloc_td(pool_list); - if (!ptd) return NULL; - - for(i = 1; i < count; i++) - { - pnext = alloc_td(pool_list); - - if (pnext) - { - InsertTailList(&ptd->ptde->vert_link, &pnext->ptde->vert_link); - } - else - TRAP(); - } - - uhci_dbg_print(DBGLVL_MEDIUM, ("alloc_tds(): td pool-list free_tds=0x%x, free pools=0x%x\n", - pool_list->free_tds, pool_list->free_count)); - - return ptd; - -} - -VOID -free_tds(PUHCI_TD_POOL_LIST pool_list, PUHCI_TD ptd) -{ - PUHCI_TD ptofree; - PLIST_ENTRY pthis; - - if (pool_list == NULL || ptd == NULL) - return; - - while (IsListEmpty(&ptd->ptde->vert_link) == FALSE) - { - pthis = RemoveHeadList(&ptd->ptde->vert_link); - ptofree = ((PTD_EXTENSION) pthis)->ptd; - free_td(pool_list, ptofree); - } - - free_td(pool_list, ptd); - return; -} - - - -BOOLEAN -can_transfer(PUHCI_TD_POOL_LIST pool_list, LONG td_count) -{ - if (td_count > get_max_free_tds(pool_list)) - return FALSE; - - return TRUE; -} - -VOID -lock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOLEAN at_dpc) -{ - //if( !at_dpc ) - // KeAcquireSpinLock( &pool_list->pool_lock ); - //else - // KeAcquireSpinLockAtDpcLevel( &pool_list->pool_lock ); -} - -VOID -unlock_td_pool(PUHCI_TD_POOL_LIST pool_list, BOOLEAN at_dpc) -{ - //if( !at_dpc ) - // KeReleaseSpinLock( &pool_list->pool_lock ); - //else - // KeReleaseSpinLockFromDpcLevel( &pool_list->pool_lock ); -} - -BOOLEAN -init_qh_pool(PUHCI_QH_POOL pqh_pool, PADAPTER_OBJECT padapter) -{ - PQH_EXTENSION pqhe; - LONG i; - - if (pqh_pool == NULL || padapter == NULL) - return FALSE; - - pqh_pool->padapter = padapter; - - pqh_pool->qhe_array = (PQH_EXTENSION) usb_alloc_mem(NonPagedPool, - sizeof(QH_EXTENSION) * UHCI_MAX_POOL_QHS); - - if (pqh_pool->qhe_array == NULL) - return FALSE; - - pqh_pool->qh_array = - (PUHCI_QH) HalAllocateCommonBuffer(padapter, - sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS, &pqh_pool->logic_addr, FALSE); - - if (pqh_pool->qh_array == NULL) - { - usb_free_mem(pqh_pool->qhe_array); - pqh_pool->qhe_array = NULL; - return FALSE; - } - - pqhe = pqh_pool->qhe_array; - - pqh_pool->free_count = 0; - pqh_pool->total_count = UHCI_MAX_POOL_TDS; - - KeInitializeSpinLock(&pqh_pool->pool_lock); - InitializeListHead(&pqh_pool->free_que); - - - for(i = 0; i < UHCI_MAX_POOL_QHS; i++) - { - pqh_pool->qh_array[i].pqhe = &pqhe[i]; - pqhe[i].pqh = &pqh_pool->qh_array[i]; - - pqh_pool->qh_array[i].phy_addr = (pqh_pool->logic_addr.LowPart + (sizeof(UHCI_QH) * i)) | UHCI_PTR_QH; - //pqh_pool->qh_array[i].reserved = 0; - - //always breadth first - pqhe[i].flags = UHCI_ITEM_FLAG_QH; - - free_qh(pqh_pool, &pqh_pool->qh_array[i]); - - } - return TRUE; - -} - -//add qhs till pnext == NULL -BOOLEAN -free_qh(PUHCI_QH_POOL pqh_pool, PUHCI_QH pqh) -{ - if (pqh_pool == NULL || pqh == NULL) - return FALSE; - - pqh->link = pqh->element = 0; - pqh->pqhe->purb = NULL; - InsertTailList(&pqh_pool->free_que, &pqh->pqhe->vert_link); - pqh_pool->free_count++; - - return TRUE; -} - -//null if failed -PUHCI_QH -alloc_qh(PUHCI_QH_POOL pqh_pool) -{ - PQH_EXTENSION pqhe; - - if (pqh_pool == NULL) - return FALSE; - - if (IsListEmpty(&pqh_pool->free_que)) - return FALSE; - - pqhe = (PQH_EXTENSION) RemoveHeadList(&pqh_pool->free_que); - - if (pqhe) - { - InitializeListHead(&pqhe->hori_link); - InitializeListHead(&pqhe->vert_link); - return pqhe->pqh; - } - return NULL; - -} - -BOOLEAN -destroy_qh_pool(PUHCI_QH_POOL pqh_pool) -{ - if (pqh_pool) - { - usb_free_mem(pqh_pool->qhe_array); - - HalFreeCommonBuffer(pqh_pool->padapter, - sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS, - pqh_pool->logic_addr, pqh_pool->qh_array, FALSE); - - RtlZeroMemory(pqh_pool, sizeof(UHCI_QH_POOL)); - - } - else - return FALSE; - - return TRUE; -} - -VOID -lock_qh_pool(PUHCI_QH_POOL pool, BOOLEAN at_dpc) -{ - //if( !at_dpc ) - // KeAcquireSpinLock( &pool->pool_lock ); - //else - // KeAcquireSpinLockAtDpcLevel( &pool->pool_lock ); -} - -VOID -unlock_qh_pool(PUHCI_QH_POOL pool, BOOLEAN at_dpc) -{ - //if( !at_dpc ) - // KeReleaseSpinLock( &pool->pool_lock ); - //else - // KeReleaseSpinLockFromDpcLevel( &pool->pool_lock ); -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/td.h b/reactos/drivers/usb/nt4compat/usbdrv/td.h deleted file mode 100644 index ec2afa8ac8a..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/td.h +++ /dev/null @@ -1,1049 +0,0 @@ -/* - * NOTE!!!: part of the code is pasted from linux/driver/usb/uhci.h - */ - -#ifndef __UHCI_H__ -#define __UHCI_H__ - -#define LIST_HEAD LIST_ENTRY -#define PLIST_HEAD PLIST_ENTRY -#define BYTE UCHAR -#define PBYTE PUCHAR -#define WORD USHORT -#define DWORD ULONG - -#ifndef LOWORD -#define LOWORD(l) ( (WORD) ( ( l ) & 0xffff ) ) -#endif -#ifndef HIWORD -#define HIWORD(l) ( (WORD) ( ( l ) >> 16 ) ) -#endif - -#define PCI_MAX_FUNCTIONS 8 - - -#define UHCI_MAX_POOL_TDS 1024 //8 pages of 4k -#define UHCI_MAX_POOL_QHS 256 //1 page of 4k -#define UHCI_MAX_ANT_TDS 0x20e82 - -#define UHCI_MAX_TD_POOLS 8 -#define UHCI_MAX_TDS_PER_TRANSFER UHCI_MAX_POOL_TDS - -#define UHCI_FULL_SPEED_BANDWIDHT ( 12 * 1000 * 1000 ) -#define UHCI_LOW_SPEED_BANDWIDHT ( 15 * 100 * 1000 ) -/* - * Universal Host Controller Interface data structures and defines - */ - -/* Command register */ -#define USBCMD 0 -#define USBCMD_RS 0x0001 /* Run/Stop */ -#define USBCMD_HCRESET 0x0002 /* Host reset */ -#define USBCMD_GRESET 0x0004 /* Global reset */ -#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define USBCMD_FGR 0x0010 /* Force Global Resume */ -#define USBCMD_SWDBG 0x0020 /* SW Debug mode */ -#define USBCMD_CF 0x0040 /* Config Flag (sw only) */ -#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */ - -/* Status register */ -#define USBSTS 2 -#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */ -#define USBSTS_ERROR 0x0002 /* Interrupt due to error */ -#define USBSTS_RD 0x0004 /* Resume Detect */ -#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */ -#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */ -#define USBSTS_HCH 0x0020 /* HC Halted */ - -/* Interrupt enable register */ -#define USBINTR 4 -#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */ -#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */ -#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */ -#define USBINTR_SP 0x0008 /* Short packet interrupt enable */ - -#define USBFRNUM 6 -#define USBFLBASEADD 8 -#define USBSOF 12 - -/* USB port status and control registers */ -#define USBPORTSC1 16 -#define USBPORTSC2 18 -#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */ -#define USBPORTSC_CSC 0x0002 /* Connect Status Change */ -#define USBPORTSC_PE 0x0004 /* Port Enable */ -#define USBPORTSC_PEC 0x0008 /* Port Enable Change */ -#define USBPORTSC_LS 0x0020 /* Line Status */ -#define USBPORTSC_RD 0x0040 /* Resume Detect */ -#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */ -#define USBPORTSC_PR 0x0200 /* Port Reset */ -#define USBPORTSC_SUSP 0x1000 /* Suspend */ - -/* Legacy support register */ -#define USBLEGSUP 0xc0 -#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ -#define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ -#define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ - - -#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */ - -#define UHCI_PTR_BITS 0x000F -#define UHCI_PTR_TERM 0x0001 -#define UHCI_PTR_QH 0x0002 -#define UHCI_PTR_DEPTH 0x0004 - -#define UHCI_MAX_FRAMES 1024 /* in the frame list [array] */ -#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ -#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */ - - -//from linux's uhci.h -#define UHCI_MAX_SKELTDS 10 -#define skel_int1_td skel_td[0] -#define skel_int2_td skel_td[1] -#define skel_int4_td skel_td[2] -#define skel_int8_td skel_td[3] -#define skel_int16_td skel_td[4] -#define skel_int32_td skel_td[5] -#define skel_int64_td skel_td[6] -#define skel_int128_td skel_td[7] -#define skel_int256_td skel_td[8] -#define skel_term_td skel_td[9] /* To work around PIIX UHCI bug */ - -#define UHCI_MAX_SKELQHS 4 -#define skel_ls_control_qh skel_qh[0] -#define skel_hs_control_qh skel_qh[1] -#define skel_bulk_qh skel_qh[2] -#define skel_term_qh skel_qh[3] - - - -struct URB; - -/* - * for TD : - */ -#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */ -#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */ -#define TD_CTRL_C_ERR_SHIFT 27 -#define TD_CTRL_LS (1 << 26) /* Low Speed Device */ -#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */ -#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ -#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */ -#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */ -#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */ -#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */ -#define TD_CTRL_NAK (1 << 19) /* NAK Received */ -#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */ -#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ -#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ - -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIMEO | TD_CTRL_BITSTUFF) - -#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000) -#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ - -/* - * for TD : (a.k.a. Token) - */ -#define TD_TOKEN_TOGGLE 19 -#define TD_PID 0xFF - -#define uhci_maxlen(token) ((token) >> 21) -#define uhci_expected_length(info) (((info >> 21) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ -#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1) -#define uhci_endpoint(token) (((token) >> 15) & 0xf) -#define uhci_devaddr(token) (((token) >> 8) & 0x7f) -#define uhci_devep(token) (((token) >> 8) & 0x7ff) -#define uhci_packetid(token) ((token) & 0xff) -#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN) -#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN) - -/* - * The documentation says "4 dwords for hardware, 4 dwords for software". - * - * That's silly, the hardware doesn't care. The hardware only cares that - * the hardware words are 16-byte aligned, and we can have any amount of - * sw space after the TD entry as far as I can tell. - * - * But let's just go with the documentation, at least for 32-bit machines. - * On 64-bit machines we probably want to take advantage of the fact that - * hw doesn't really care about the size of the sw-only area. - * - * Alas, not anymore, we have more than 4 dwords for software, woops. - * Everything still works tho, surprise! -jerdfelt - */ - -#define UHCI_ITEM_FLAG_TYPE 0x3 -#define UHCI_ITEM_FLAG_TD 0x0 -#define UHCI_ITEM_FLAG_QH 0x1 - -#ifndef offsetof -#define offsetof( s, m ) ( ( ULONG )( &( ( s* )0 )->m ) ) -#endif - -#define struct_ptr( meMBER_ptr, stRUCT_name, meMBER_name ) \ -( ( stRUCT_name* ) ( ( (CHAR*)( meMBER_ptr ) ) - offsetof( stRUCT_name, meMBER_name ) ) ) - -#define dev_state( pdEV ) ( ( pdEV )->flags & USB_DEV_STATE_MASK ) - -#define dev_class( pdev ) ( pdev->flags & USB_DEV_CLASS_MASK ) - -#define uhci_from_hcd( hCD ) ( struct_ptr( ( hCD ), UHCI_DEV, hcd_interf ) ) -#define uhci_from_dev( dEV ) ( struct_ptr( ( dEV->hcd ), UHCI_DEV, hcd_interf ) ) - -typedef struct _TD_EXTENSION -{ - LIST_ENTRY vert_link; // urb will use this to link qh and tds - LIST_ENTRY hori_link; - ULONG flags; - struct _UHCI_TD *ptd; //link to is companion td, constant since initialized - -} TD_EXTENSION, *PTD_EXTENSION; - -typedef struct _UHCI_TD -{ - /* Hardware fields */ - ULONG link; - ULONG status; - ULONG info; - ULONG buffer; - - /* Software fields */ - ULONG phy_addr; - PTD_EXTENSION ptde; - struct _URB *purb; - struct _UHCI_TD_POOL *pool; //pool this td belongs to - -} UHCI_TD, *PUHCI_TD; - -typedef struct _UHCI_TD_POOL -{ - - LIST_ENTRY pool_link; //link to next and prev td pool - PUHCI_TD td_array[ sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE ]; //would be allcated in common buffer - PHYSICAL_ADDRESS logic_addr[ sizeof( UHCI_TD ) * UHCI_MAX_POOL_TDS / PAGE_SIZE ]; //logical addr of the array - - PTD_EXTENSION tde_array; - LIST_ENTRY free_que; //list of free tds - LONG free_count; //free tds in this pool - LONG total_count; //total count of the tds - PADAPTER_OBJECT padapter; - -} UHCI_TD_POOL, *PUHCI_TD_POOL; - -BOOLEAN -init_td_pool( -PUHCI_TD_POOL pool -); - -BOOLEAN -free_td_to_pool( -PUHCI_TD_POOL pool, -PUHCI_TD ptd -); //add tds till pnext == NULL - -PUHCI_TD -alloc_td_from_pool( -PUHCI_TD_POOL ptd_pool -); //null if failed] - -BOOLEAN -is_pool_free( -PUHCI_TD_POOL pool -); //test whether the pool is all free - -BOOLEAN -is_pool_full( -PUHCI_TD_POOL pool -); - -BOOLEAN -destroy_td_pool( -PUHCI_TD_POOL pool -); - -typedef struct _UHCI_TD_POOL_LIST -{ - LIST_ENTRY busy_pools; - KSPIN_LOCK pool_lock; - LONG free_tds; //free tds in all the pool - LONG free_count; //free pool count - LIST_ENTRY free_pools; - UHCI_TD_POOL pool_array[UHCI_MAX_TD_POOLS]; //max transfer is 640k - -} UHCI_TD_POOL_LIST, *PUHCI_TD_POOL_LIST; - -BOOLEAN -init_td_pool_list( -PUHCI_TD_POOL_LIST pool_list, -PADAPTER_OBJECT padapter -); - -BOOLEAN -destroy_td_pool_list( -PUHCI_TD_POOL_LIST pool_list -); - -BOOLEAN -expand_pool_list( -PUHCI_TD_POOL_LIST pool_list, -LONG pool_count -); //private - -BOOLEAN -collect_garbage( -PUHCI_TD_POOL_LIST pool_list -); - -LONG -get_free_tds( -PUHCI_TD_POOL_LIST pool_list -); //private - -LONG -get_max_free_tds( -PUHCI_TD_POOL_LIST pool_list -); //private - -BOOLEAN -can_transfer( -PUHCI_TD_POOL_LIST pool_list, -LONG td_count); - -BOOLEAN -free_td( -PUHCI_TD_POOL_LIST pool_list, -PUHCI_TD ptd -); //add tds till pnext == NULL - -PUHCI_TD -alloc_td( -PUHCI_TD_POOL_LIST pool_list -); //null if failed - -VOID -lock_td_pool( -PUHCI_TD_POOL_LIST pool_list, -BOOLEAN at_dpc -); - -VOID -unlock_td_pool( -PUHCI_TD_POOL_LIST pool_list, -BOOLEAN at_dpc -); - -typedef struct _UHCI_QH -{ - /* Hardware fields */ - ULONG link; // Next queue - ULONG element; // Queue element pointer - - /* Software fields */ - ULONG phy_addr; //constant since initialized - struct _QH_EXTENSION *pqhe; - -} UHCI_QH, *PUHCI_QH; - -typedef struct _QH_EXTENSION -{ - - LIST_ENTRY vert_link; - LIST_ENTRY hori_link; - ULONG flags; - PUHCI_QH pqh; //constant since initialized - struct _URB *purb; - -} QH_EXTENSION, *PQH_EXTENSION; - -typedef struct _UHCI_QH_POOL -{ - - PUHCI_QH qh_array; - PHYSICAL_ADDRESS logic_addr; //logical addr of the array - - PQH_EXTENSION qhe_array; - LIST_ENTRY free_que; - LONG free_count; - LONG total_count; - KSPIN_LOCK pool_lock; - PADAPTER_OBJECT padapter; //we need this garbage for allocation - -} UHCI_QH_POOL, *PUHCI_QH_POOL; - - -BOOLEAN -init_qh_pool( -PUHCI_QH_POOL pool, -PADAPTER_OBJECT padapter -); - -BOOLEAN -free_qh( -PUHCI_QH_POOL pool, -PUHCI_QH ptd -); //add qhs till pnext == NULL - -PUHCI_QH -alloc_qh( -PUHCI_QH_POOL pool -); //null if failed - -BOOLEAN -destroy_qh_pool( -PUHCI_QH_POOL pool -); - -VOID -lock_qh_pool( -PUHCI_QH_POOL pool, -BOOLEAN at_dpc -); - -VOID -unlock_qh_pool( -PUHCI_QH_POOL pool, -BOOLEAN at_dpc -); - -/* - * Search tree for determining where fits in the - * skelqh[] skeleton. - * - * An interrupt request should be placed into the slowest skelqh[] - * which meets the interval/period/frequency requirement. - * An interrupt request is allowed to be faster than but not slower. - * - * For a given , this function returns the appropriate/matching - * skelqh[] index value. - * - * NOTE: For UHCI, we don't really need int256_qh since the maximum interval - * is 255 ms. However, we do need an int1_qh since 1 is a valid interval - * and we should meet that frequency when requested to do so. - * This will require some change(s) to the UHCI skeleton. - */ -#if 0 -static int __interval_to_skel(int interval) -{ - if (interval < 16) { - if (interval < 4) { - if (interval < 2) - return 0; /* int1 for 0-1 ms */ - return 1; /* int2 for 2-3 ms */ - } - if (interval < 8) - return 2; /* int4 for 4-7 ms */ - return 3; /* int8 for 8-15 ms */ - } - if (interval < 64) { - if (interval < 32) - return 4; /* int16 for 16-31 ms */ - return 5; /* int32 for 32-63 ms */ - } - if (interval < 128) - return 6; /* int64 for 64-127 ms */ - return 7; /* int128 for 128-255 ms (Max.) */ -} -#endif - -#define USB_ENDP_FLAG_BUSY_MASK 0x0000ff00 -#define USB_ENDP_FLAG_STAT_MASK 0xff -#define USB_ENDP_FLAG_STALL 0x01 -#define USB_ENDP_FLAG_DATATOGGLE 0x80000000 -#define USB_ENDP_FLAG_DEFAULT_ENDP 0x40000000 - -#define usb_endp_busy_count( peNDP ) \ -( ( ( peNDP )->flags & USB_ENDP_FLAG_BUSY_MASK ) >> 8 ) - -#define usb_endp_busy_count_inc( peNDP ) \ -( peNDP->flags = ( ( ( ( usb_endp_busy_count( peNDP ) + 1 ) << 8 ) & USB_ENDP_FLAG_BUSY_MASK ) | \ -( ( peNDP )->flags & ~USB_ENDP_FLAG_BUSY_MASK ) ) ) - -#define usb_endp_busy_count_dec( peNDP ) \ -( peNDP->flags = ( ( ( ( usb_endp_busy_count( peNDP ) - 1 ) << 8 ) & USB_ENDP_FLAG_BUSY_MASK )| \ -( ( peNDP )->flags & ~USB_ENDP_FLAG_BUSY_MASK ) ) ) - -typedef struct _USB_ENDPOINT -{ - ULONG flags; //toggle | busy-count | stall | default-endp; busy count( usually 1 when busy, may be greater if iso endp ) - LIST_ENTRY urb_list; //pending urb queue - - struct _USB_INTERFACE *pusb_if; - struct _USB_ENDPOINT_DESC *pusb_endp_desc; - -} USB_ENDPOINT, *PUSB_ENDPOINT; - -#define MAX_ENDPS_PER_IF 10 - -typedef struct _USB_INTERFACE -{ - UCHAR endp_count; - USB_ENDPOINT endp[MAX_ENDPS_PER_IF]; - - - struct _USB_CONFIGURATION *pusb_config; - PUSB_INTERFACE_DESC pusb_if_desc; - - struct _USB_DRIVER *pif_drv; //for hub_dev use - PVOID if_ext; - LONG if_ext_size; - UCHAR altif_count; - LIST_ENTRY altif_list; - - -} USB_INTERFACE, *PUSB_INTERFACE; - -#define MAX_INTERFACES_PER_CONFIG 4 -#define MAX_CONFIGS_PER_DEV 4 - -typedef struct _USB_CONFIGURATION -{ - //only for active configuration - struct _USB_CONFIGURATION_DESC *pusb_config_desc; - UCHAR if_count; - USB_INTERFACE interf[MAX_INTERFACES_PER_CONFIG]; - struct _USB_DEV *pusb_dev; - -} USB_CONFIGURATION, *PUSB_CONFIGURATION; - -#define USE_IRQL \ -KIRQL _pending_endp_lock_old_irql=0, _pending_endp_list_lock_old_irql=0, _dev_lock_old_irql=0, old_irql=0; - -#define USE_BASIC_IRQL \ -KIRQL _pending_endp_list_lock_old_irql=0, _dev_lock_old_irql=0; - -#define USE_NON_PENDING_IRQL \ -KIRQL _dev_lock_old_irql=0, old_irql=0; - -#define USE_BASIC_NON_PENDING_IRQL \ -KIRQL _dev_lock_old_irql=0; - - -#define USB_DEV_STATE_MASK ( 0xff << 8 ) -#define USB_DEV_STATE_POWERED ( 0x01 << 8 ) -#define USB_DEV_STATE_RESET ( 0x02 << 8 ) -#define USB_DEV_STATE_ADDRESSED ( 0x03 << 8 ) -#define USB_DEV_STATE_FIRST_CONFIG ( 0x04 << 8 ) -#define USB_DEV_STATE_RECONFIG ( 0x05 << 8 ) -#define USB_DEV_STATE_CONFIGURED ( 0x06 << 8 ) -#define USB_DEV_STATE_SUSPENDED ( 0x07 << 8 ) -#define USB_DEV_STATE_BEFORE_ZOMB ( 0x08 << 8 ) -#define USB_DEV_STATE_ZOMB ( 0x09 << 8 ) - -#define USB_DEV_CLASS_MASK ( 0xff << 16 ) -#define USB_DEV_CLASS_HUB ( USB_CLASS_HUB << 16 ) -#define USB_DEV_CLASS_MASSSTOR ( USB_CLASS_MASS_STORAGE << 16 ) -#define USB_DEV_CLASS_ROOT_HUB ( ( USB_CLASS_VENDOR_SPEC - 2 ) << 16 ) -#define USB_DEV_CLASS_SCANNER ( ( USB_DEV_CLASS_ROOT_HUB - 1 ) << 16 ) - -#define USB_DEV_FLAG_HIGH_SPEED 0x20 // high speed dev for usb2.0 -#define USB_DEV_FLAG_LOW_SPEED 0x40 // note: this bit is shared in urb->pipe -#define USB_DEV_FLAG_IF_DEV 0x01 // this dev is a virtual dev, that is a interface - -#define lock_dev( pdev, at_dpc ) \ -{\ - KIRQL cur_irql;\ - cur_irql = KeGetCurrentIrql();\ - if( cur_irql == DISPATCH_LEVEL )\ - {\ - KeAcquireSpinLockAtDpcLevel( &pdev->dev_lock );\ - _dev_lock_old_irql = DISPATCH_LEVEL;\ - }\ - else if( cur_irql < DISPATCH_LEVEL )\ - KeAcquireSpinLock( &pdev->dev_lock, &_dev_lock_old_irql );\ - else\ - TRAP();\ -} - -#define unlock_dev( pdev, from_dpc ) \ -{\ - if( _dev_lock_old_irql == DISPATCH_LEVEL )\ - KeReleaseSpinLockFromDpcLevel( &pdev->dev_lock );\ - else if( _dev_lock_old_irql < DISPATCH_LEVEL )\ - KeReleaseSpinLock( &pdev->dev_lock, _dev_lock_old_irql );\ - else\ - TRAP();\ -} - -typedef struct _USB_DEV -{ - LIST_ENTRY dev_link; //for dev-list - - KSPIN_LOCK dev_lock; - PDEVICE_OBJECT dev_obj; - ULONG flags; //class | cur_state | low speed - LONG ref_count; //client count - - UCHAR dev_addr; //usb addr - ULONG dev_id; //will be used to compose dev handle - - struct _USB_DEV *parent_dev; - UCHAR port_idx; //parent hub's port idx, to which the dev attached - - struct _HCD *hcd; //point to the hcd the dev belongs to - - USB_ENDPOINT default_endp; //control endp. its interfac pointer is to the first interface - - LONG desc_buf_size; - PUCHAR desc_buf; - struct _USB_DEVICE_DESC *pusb_dev_desc; - - UCHAR active_config_idx; - PUSB_CONFIGURATION usb_config; //the active configuration - - struct _USB_DRIVER *dev_driver; - PVOID dev_ext; - LONG dev_ext_size; - - LONG time_out_count; //default pipe error counter, three time-outs will cause the dev not function - LONG error_count; //usb transfer error counter for statics only - -} USB_DEV, *PUSB_DEV; - -// pending endpoint pool definitions - -#define UHCI_MAX_PENDING_ENDPS 32 - -typedef struct _UHCI_PENDING_ENDP -{ - LIST_ENTRY endp_link; - PUSB_ENDPOINT pendp; - -} UHCI_PENDING_ENDP, *PUHCI_PENDING_ENDP; - -typedef struct _UHCI_PENDING_ENDP_POOL -{ - PUHCI_PENDING_ENDP pending_endp_array; - LIST_ENTRY free_que; - LONG free_count; - LONG total_count; - KSPIN_LOCK pool_lock; - -} UHCI_PENDING_ENDP_POOL, *PUHCI_PENDING_ENDP_POOL; - -BOOLEAN -init_pending_endp_pool( -PUHCI_PENDING_ENDP_POOL pool -); - -BOOLEAN -free_pending_endp( -PUHCI_PENDING_ENDP_POOL pool, -PUHCI_PENDING_ENDP pending_endp -); - -PUHCI_PENDING_ENDP -alloc_pending_endp( -PUHCI_PENDING_ENDP_POOL pool, -LONG count -); - -BOOLEAN -destroy_pending_endp_pool( -PUHCI_PENDING_ENDP_POOL pool -); - -// pool type is PUHCI_PENDING_ENDP_POOL -#define lock_pending_endp_pool( pool ) \ -{\ - KeAcquireSpinLock( &pool->pool_lock, &_pending_endp_lock_old_irql );\ -} - -#define unlock_pending_endp_pool( pool ) \ -{\ - KeReleaseSpinLock( &pool->pool_lock, &_pending_endp_lock_old_irql );\ -} - - -// end of pending endpoint pool -typedef struct _FRAME_LIST_CPU_ENTRY -{ - LIST_ENTRY td_link; - -} FRAME_LIST_CPU_ENTRY, *PFRAME_LIST_CPU_ENTRY; - -#define uhci_public_res_lock pending_endp_list_lock -#define uhci_status( _uhci_ ) ( READ_PORT_USHORT( ( PUSHORT )( ( _uhci_ )->port_base + USBSTS ) ) ) - -typedef struct _UHCI -{ - PHYSICAL_ADDRESS uhci_reg_base; // io space - BOOLEAN port_mapped; - PBYTE port_base; - - PHYSICAL_ADDRESS io_buf_logic_addr; - PBYTE io_buf; - - PHYSICAL_ADDRESS frame_list_logic_addr; - - KSPIN_LOCK frame_list_lock; //run at DIRQL - PULONG frame_list; - PFRAME_LIST_CPU_ENTRY frame_list_cpu; - LIST_HEAD urb_list; //active urb-list - PUHCI_TD skel_td[UHCI_MAX_SKELTDS]; - PUHCI_QH skel_qh[UHCI_MAX_SKELQHS]; //skeltons - - - - UHCI_TD_POOL_LIST td_pool; - UHCI_QH_POOL qh_pool; - - - //for iso and int bandwidth claim, bandwidth schedule - KSPIN_LOCK pending_endp_list_lock; //lock to access the following two - LIST_HEAD pending_endp_list; - UHCI_PENDING_ENDP_POOL pending_endp_pool; - PLONG frame_bw; - LONG fsbr_cnt; //used to record number of fsbr users - - KTIMER reset_timer; //used to reset the host controller - - //struct _USB_DEV_MANAGER dev_mgr; //it is in hcd_interf - struct _DEVICE_EXTENSION *pdev_ext; - - PUSB_DEV root_hub; //root hub - HCD hcd_interf; - -} UHCI_DEV, *PUHCI_DEV; - -#define lock_pending_endp_list( list_lock ) \ -{\ - KeAcquireSpinLock( list_lock, &_pending_endp_list_lock_old_irql );\ -} - -#define unlock_pending_endp_list( list_lock ) \ -{\ - KeReleaseSpinLock( list_lock, _pending_endp_list_lock_old_irql );\ -} -typedef struct _UHCI_INTERRUPT -{ - ULONG level; - ULONG vector; - ULONG affinity; - -} UHCI_INTERRUPT, *PUHCI_INTERRUPT; - -typedef struct _UHCI_PORT -{ - PHYSICAL_ADDRESS Start; - ULONG Length; - -} UHCI_PORT, *PUHCI_PORT; - -typedef NTSTATUS ( *PDISPATCH_ROUTINE )( PDEVICE_OBJECT dev_obj, PIRP irp ); - -#define NTDEV_TYPE_HCD 1 -#define NTDEV_TYPE_CLIENT_DEV 2 - -typedef struct _DEVEXT_HEADER -{ - ULONG type; - PDISPATCH_ROUTINE dispatch; - PDRIVER_STARTIO start_io; - - struct _USB_DEV_MANAGER *dev_mgr; //mainly for use by cancel irp - -} DEVEXT_HEADER, *PDEVEXT_HEADER; - -typedef struct _DEVICE_EXTENSION -{ - //struct _USB_DEV_MANAGER *pdev_mgr; - DEVEXT_HEADER dev_ext_hdr; - PDEVICE_OBJECT pdev_obj; - PDRIVER_OBJECT pdrvr_obj; - PUHCI_DEV uhci; - - //device resources - PADAPTER_OBJECT padapter; - ULONG map_regs; - PCM_RESOURCE_LIST res_list; - ULONG pci_addr; // bus number | slot number | funciton number - UHCI_INTERRUPT res_interrupt; - UHCI_PORT res_port; - - PKINTERRUPT uhci_int; - KDPC uhci_dpc; - -} DEVICE_EXTENSION, *PDEVICE_EXTENSION; - -//helper macro -#define ListFirst( heAD, firST) \ -{\ - if( IsListEmpty( ( heAD ) ) )\ - firST = NULL;\ - else\ - firST = ( heAD )->Flink;\ -} - -#define ListNext( heAD, curreNT, neXT) \ -{\ - if( IsListEmpty( ( heAD ) ) == FALSE )\ - {\ - neXT = (curreNT)->Flink;\ - if( neXT == heAD )\ - neXT = NULL;\ - }\ - else\ - neXT = NULL;\ -} - -#define ListPrev( heAD, curreNT, prEV) \ -{\ - if( IsListEmpty( ( heAD ) ) == FALSE )\ - {\ - prEV = (curreNT)->Blink;\ - if( prEV == heAD )\ - prEV = NULL;\ - else\ - prEV = NULL;\ -} - -#define ListFirstPrev( heAD, firST) \ -{\ - if( IsListEmpty( ( heAD ) ) )\ - firST = NULL;\ - else\ - firST = ( heAD )->Blink;\ -} - -#define MergeList( liST1, liST2 )\ -{\ - PLIST_ENTRY taIL1, taIL2;\ - if( IsListEmpty( liST2 ) == TRUE )\ - {\ - InsertTailList( liST1, liST2 );\ - }\ - else if( IsListEmpty( liST1 ) == TRUE )\ - {\ - InsertTailList( liST2, liST1 );\ - }\ - else\ - {\ - ListFirstPrev( liST1, taIL1 );\ - ListFirstPrev( liST2, taIL2 );\ -\ - taIL1->Flink = ( liST2 );\ - ( liST2 )->Blink = taIL1;\ -\ - taIL2->Flink = ( liST1 );\ - ( liST1 )->Blink = taIL2;\ - }\ -} - -PUHCI_TD -alloc_tds( -PUHCI_TD_POOL_LIST pool_list, -LONG count -); - -VOID -free_tds( -PUHCI_TD_POOL_LIST pool_list, -PUHCI_TD ptd -); - -BOOLEAN -uhci_init( -PUHCI_DEV uhci, -PADAPTER_OBJECT padapter -); - -BOOLEAN -uhci_destroy( -PUHCI_DEV uhci -); - -// funcitons exported to dev-manager -BOOLEAN -uhci_add_device( -PUHCI_DEV uhci, -PUSB_DEV dev -); - -BOOLEAN -uhci_remove_device( -PUHCI_DEV uhci, -PUSB_DEV dev -); - -//helpers -VOID NTAPI -uhci_dpc_callback( -PKDPC dpc, -PVOID context, -PVOID sysarg1, -PVOID sysarg2 -); - -#if 0 -static VOID -uhci_flush_adapter_buf() -{ -#ifdef _X86 - __asm invd; -#endif -} -#endif - -NTSTATUS -uhci_submit_urb( -PUHCI_DEV uhci, -PUSB_DEV pdev, -PUSB_ENDPOINT pendp, -struct _URB *urb -); - -//must have dev_lock acquired -NTSTATUS -uhci_internal_submit_bulk( -PUHCI_DEV uhci, -struct _URB *urb -); - -NTSTATUS -uhci_internal_submit_iso( -PUHCI_DEV uhci, -struct _URB *urb -); - -NTSTATUS -uhci_internal_submit_ctrl( -PUHCI_DEV uhci, -struct _URB *urb -); - -NTSTATUS -uhci_internal_submit_int( -PUHCI_DEV uhci, -struct _URB *urb -); - -BOOLEAN -uhci_remove_bulk_from_schedule( -PUHCI_DEV uhci, -struct _URB *urb -); - -#define uhci_remove_ctrl_from_schedule uhci_remove_bulk_from_schedule - -BOOLEAN -uhci_remove_iso_from_schedule( -PUHCI_DEV uhci, -struct _URB *urb -); - -BOOLEAN -uhci_remove_int_from_schedule( -PUHCI_DEV uhci, -struct _URB *urb -); - -BOOLEAN -uhci_remove_urb_from_schedule( -PUHCI_DEV uhci, -struct _URB *urb -); - -BOOLEAN -uhci_is_xfer_finished( //will set urb error code here -struct _URB *urb -); - -NTSTATUS -uhci_set_error_code( -struct _URB *urb, -ULONG raw_status -); - -BOOLEAN -uhci_insert_tds_qh( -PUHCI_QH pqh, -PUHCI_TD td_chain -); - -BOOLEAN -uhci_insert_qh_urb( -struct _URB *urb, -PUHCI_QH qh_chain -); - -BOOLEAN -uhci_insert_urb_schedule( -PUHCI_DEV uhci, -struct _URB *urb -); - -BOOLEAN -uhci_claim_bandwidth( -PUHCI_DEV uhci, -struct _URB *urb, -BOOLEAN claim_bw -); - -BOOLEAN -uhci_process_pending_endp( -PUHCI_DEV uhci -); - -NTSTATUS -uhci_cancel_urb( -PUHCI_DEV uhci, -PUSB_DEV pdev, -PUSB_ENDPOINT endp, -struct _URB *urb -); - -VOID -uhci_generic_urb_completion( -struct _URB *urb, -PVOID context -); - -// the following are NT driver definitions - -// NT device name -#define UHCI_DEVICE_NAME "\\Device\\UHCI" - -// File system device name. When you execute a CreateFile call to open the -// device, use "\\.\GpdDev", or, given C's conversion of \\ to \, use -// "\\\\.\\GpdDev" - -#define DOS_DEVICE_NAME "\\DosDevices\\UHCI" - - -#define CLR_RH_PORTSTAT( port_idx, x ) \ -{\ - PUSHORT addr; \ - addr = ( PUSHORT )( uhci->port_base + port_idx ); \ - status = READ_PORT_USHORT( addr ); \ - status = ( status & 0xfff5 ) & ~( x ); \ - WRITE_PORT_USHORT( addr, ( USHORT )status ); \ -} - -#define SET_RH_PORTSTAT( port_idx, x ) \ -{\ - PUSHORT addr; \ - addr = ( PUSHORT )( uhci->port_base + port_idx ); \ - status = READ_PORT_USHORT( addr ); \ - status = ( status & 0xfff5 ) | ( x ); \ - WRITE_PORT_USHORT( addr, ( USHORT )status ); \ -} - -//this is for dispatch routine -#define EXIT_DISPATCH( nTstatUs, iRp)\ -{\ - if( nTstatUs != STATUS_PENDING)\ - {\ - iRp->IoStatus.Status = nTstatUs;\ - IoCompleteRequest( iRp, IO_NO_INCREMENT);\ - return nTstatUs;\ - }\ - IoMarkIrpPending( iRp);\ - return nTstatUs;\ -} - -#endif - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/uhci.c b/reactos/drivers/usb/nt4compat/usbdrv/uhci.c deleted file mode 100644 index 857498c4e00..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/uhci.c +++ /dev/null @@ -1,3897 +0,0 @@ -/** - * uhci.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -//---------------------------------------------------------- -// uhci routines -//#define DEMO - -#ifdef INCLUDE_EHCI - -#define rh_port1_status rh_port_status[ 1 ] -#define rh_port2_status rh_port_status[ 2 ] - -extern PDEVICE_OBJECT ehci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr); - -#endif - -#define DEFAULT_ENDP( enDP ) \ -( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP ) - -#define dev_from_endp( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( PUSB_DEV )( enDP )->pusb_if )\ - : ( ( enDP )->pusb_if->pusb_config->pusb_dev ) ) - -#define endp_state( enDP ) ( ( enDP )->flags & USB_ENDP_FLAG_STAT_MASK ) - -#define endp_num( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0 \ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & 0x0f ) ) - -#define endp_dir( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? 0L\ - : ( ( enDP )->pusb_endp_desc->bEndpointAddress & USB_DIR_IN ) ) - -#define dev_set_state( pdEV, staTE ) \ -( pdEV->flags = ( ( pdEV )->flags & ( ~USB_DEV_STATE_MASK ) ) | ( staTE ) ) - -#define endp_max_packet_size( enDP ) \ -( DEFAULT_ENDP( enDP )\ - ? ( ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc ? \ - ( ( PUSB_DEV )enDP->pusb_if )->pusb_dev_desc->bMaxPacketSize0\ - : 8 )\ - : enDP->pusb_endp_desc->wMaxPacketSize ) - - -#define release_adapter( padapTER ) HalPutDmaAdapter(padapTER) - -#define get_int_idx( _urb, _idx ) \ -{\ - UCHAR interVAL;\ - interVAL = ( UCHAR )( ( _urb )->pipe >> 24 );\ - for( _idx = 1; _idx < 9; _idx++ )\ - {\ - interVAL >>= 1;\ - if( !interVAL )\ - break;\ - }\ - _idx --;\ -} - -#define uhci_insert_urb_to_schedule( uHCI, pURB, rET ) \ -{\ - SYNC_PARAM sync_param;\ - sync_param.uhci = uHCI;\ - sync_param.context = pURB;\ -\ - rET = KeSynchronizeExecution( uHCI->pdev_ext->uhci_int, uhci_sync_insert_urb_schedule, &sync_param );\ -} - -//declarations -typedef struct -{ - PUHCI_DEV uhci; - PVOID context; - ULONG ret; -} SYNC_PARAM, *PSYNC_PARAM; - -PDEVICE_OBJECT -uhci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr); - -BOOLEAN uhci_init_schedule(PUHCI_DEV uhci, PADAPTER_OBJECT padapter); - -BOOLEAN uhci_release(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr); - -static VOID uhci_stop(PUHCI_DEV uhci); - -BOOLEAN uhci_destroy_schedule(PUHCI_DEV uhci); - -BOOLEAN NTAPI uhci_sync_insert_urb_schedule(PVOID context); - -VOID uhci_init_hcd_interface(PUHCI_DEV uhci); - -NTSTATUS uhci_rh_submit_urb(PUSB_DEV rh, PURB purb); - -NTSTATUS uhci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp); - -extern VOID rh_timer_svc_reset_port_completion(PUSB_DEV dev, PVOID context); - -extern VOID rh_timer_svc_int_completion(PUSB_DEV dev, PVOID context); - -ULONG debug_level = DBGLVL_MINIMUM;//DBGLVL_MAXIMUM; -PDRIVER_OBJECT usb_driver_obj = NULL; -extern USB_DEV_MANAGER g_dev_mgr; - -//pending endpoint pool funcs -VOID -uhci_wait_ms(PUHCI_DEV uhci, LONG ms) -{ - LARGE_INTEGER lms; - if (ms <= 0) - return; - - lms.QuadPart = -10 * ms; - KeSetTimer(&uhci->reset_timer, lms, NULL); - - KeWaitForSingleObject(&uhci->reset_timer, Executive, KernelMode, FALSE, NULL); - - return; -} - -BOOLEAN -init_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool) -{ - int i; - if (pool == NULL) - return FALSE; - - pool->pending_endp_array = - usb_alloc_mem(NonPagedPool, sizeof(UHCI_PENDING_ENDP) * UHCI_MAX_PENDING_ENDPS); - InitializeListHead(&pool->free_que); - pool->free_count = 0; - pool->total_count = UHCI_MAX_PENDING_ENDPS; - KeInitializeSpinLock(&pool->pool_lock); - - for(i = 0; i < MAX_TIMER_SVCS; i++) - { - free_pending_endp(pool, &pool->pending_endp_array[i]); - } - - return TRUE; - -} - -BOOLEAN -free_pending_endp(PUHCI_PENDING_ENDP_POOL pool, PUHCI_PENDING_ENDP pending_endp) -{ - if (pool == NULL || pending_endp == NULL) - { - return FALSE; - } - - RtlZeroMemory(pending_endp, sizeof(UHCI_PENDING_ENDP)); - InsertTailList(&pool->free_que, &pending_endp->endp_link); - pool->free_count++; - - return TRUE; -} - -PUHCI_PENDING_ENDP -alloc_pending_endp(PUHCI_PENDING_ENDP_POOL pool, LONG count) -{ - PUHCI_PENDING_ENDP new_endp; - if (pool == NULL || count != 1) - return NULL; - - if (pool->free_count <= 0) - return NULL; - - new_endp = (PUHCI_PENDING_ENDP) RemoveHeadList(&pool->free_que); - pool->free_count--; - return new_endp; -} - -BOOLEAN -destroy_pending_endp_pool(PUHCI_PENDING_ENDP_POOL pool) -{ - if (pool == NULL) - return FALSE; - - InitializeListHead(&pool->free_que); - pool->free_count = pool->total_count = 0; - usb_free_mem(pool->pending_endp_array); - pool->pending_endp_array = NULL; - - return TRUE; - -} - - -//end of pending endpoint pool funcs - -static void -uhci_fill_td(PUHCI_TD td, ULONG status, ULONG info, ULONG buffer) -{ - td->status = status; - td->info = info; - td->buffer = buffer; -} - -BOOLEAN -uhci_insert_td_fl(PUHCI_TD prev_td, PUHCI_TD ptd) -{ - PLIST_ENTRY temp_entry; - - if (prev_td == NULL || ptd == NULL) - return FALSE; - - temp_entry = &prev_td->ptde->hori_link; - - ptd->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr; - prev_td->link = ptd->phy_addr; - - InsertHeadList(&prev_td->ptde->hori_link, &ptd->ptde->hori_link); - return TRUE; -} - -BOOLEAN -uhci_remove_td_fl(PUHCI_TD ptd) -{ - PUHCI_TD prev_td; - - if (ptd == NULL) - return FALSE; - - prev_td = (struct_ptr(ptd->ptde->hori_link.Blink, TD_EXTENSION, hori_link))->ptd; - prev_td->link = ptd->link; - ptd->link = UHCI_PTR_TERM; - - RemoveEntryList(&ptd->ptde->hori_link); - - return FALSE; -} - -BOOLEAN -uhci_insert_qh_fl(PVOID prev_item, PUHCI_QH pqh) -{ - //only horizontal link allowed - PUHCI_QH pprev_qh; - PUHCI_TD pprev_td; - PLIST_ENTRY temp_entry; - - if (prev_item == NULL || pqh == NULL) - return FALSE; - - if ((((PUHCI_TD) prev_item)->ptde->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH) - { - pprev_qh = (PUHCI_QH) prev_item; - temp_entry = pprev_qh->pqhe->hori_link.Flink; - pqh->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr; - pprev_qh->link = pqh->phy_addr; - - InsertHeadList(&pprev_qh->pqhe->hori_link, &pqh->pqhe->hori_link); - } - else - { - pprev_td = ((PUHCI_TD) prev_item); - - temp_entry = pprev_td->ptde->hori_link.Flink; - pprev_td->link = pqh->phy_addr; - pqh->link = (struct_ptr(temp_entry, TD_EXTENSION, hori_link))->ptd->phy_addr; - - InsertHeadList(&pprev_td->ptde->hori_link, &pqh->pqhe->hori_link); - } - - return FALSE; -} - -BOOLEAN -uhci_remove_qh_fl(PUHCI_QH pqh) -{ - PVOID prev_item; - PUHCI_QH pprevqh; - PUHCI_TD pprevtd; - - if (pqh == NULL) - return FALSE; - - prev_item = (struct_ptr(pqh->pqhe->hori_link.Blink, TD_EXTENSION, hori_link))->ptd; - - if ((((PUHCI_TD) prev_item)->ptde->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH) - { - pprevqh = (PUHCI_QH) prev_item; - pprevqh->link = pqh->link; - } - else - { - pprevtd = ((PUHCI_TD) prev_item); - pprevtd->link = pqh->link; - } - - RemoveEntryList(&pqh->pqhe->hori_link); - - pqh->link = UHCI_PTR_TERM; - pqh->pqhe->hori_link.Flink = pqh->pqhe->hori_link.Blink = NULL; - - return TRUE; -} - -BOOLEAN -uhci_init_frame_list(PUHCI_DEV uhci, PADAPTER_OBJECT padapter) -{ - int i; - if (uhci == NULL || padapter == NULL) - return FALSE; - - //note: frame_list_lock will be connected to interrupt - KeInitializeSpinLock(&uhci->frame_list_lock); - - uhci->io_buf = HalAllocateCommonBuffer(padapter, 4096, &uhci->io_buf_logic_addr, FALSE); - - if (uhci->io_buf == NULL) - return FALSE; - - uhci->frame_list = - HalAllocateCommonBuffer(padapter, - sizeof(ULONG) * UHCI_MAX_FRAMES, &uhci->frame_list_logic_addr, FALSE); - - if (uhci->frame_list == NULL) - return FALSE; - - RtlZeroMemory(uhci->frame_list, sizeof(ULONG) * UHCI_MAX_FRAMES); - - uhci->frame_list_cpu = usb_alloc_mem(NonPagedPool, sizeof(FRAME_LIST_CPU_ENTRY) * UHCI_MAX_FRAMES); - - if (uhci->frame_list_cpu == NULL) - return FALSE; - - for(i = 0; i < UHCI_MAX_FRAMES; i++) - InitializeListHead(&uhci->frame_list_cpu[i].td_link); - - uhci->frame_bw = usb_alloc_mem(NonPagedPool, sizeof(LONG) * UHCI_MAX_FRAMES); - - if (uhci->frame_bw == NULL) - return FALSE; - - for(i = 0; i < UHCI_MAX_FRAMES; i++) - { - uhci->frame_bw[i] = FRAME_TIME_MAX_USECS_ALLOC; - } - uhci->fsbr_cnt = 0; - - return TRUE; - -} - -BOOLEAN -uhci_destroy_frame_list(PUHCI_DEV uhci) -{ - if (uhci == NULL) - return FALSE; - - if (uhci->frame_list) - HalFreeCommonBuffer(uhci->pdev_ext->padapter, - sizeof(ULONG) * UHCI_MAX_FRAMES, - uhci->frame_list_logic_addr, uhci->frame_list, FALSE); - - uhci->frame_list = NULL; - uhci->frame_list_logic_addr.LowPart = 0; - uhci->frame_list_logic_addr.HighPart = 0; - - if (uhci->frame_list_cpu) - usb_free_mem(uhci->frame_list_cpu); - - uhci->frame_list_cpu = NULL; - - if (uhci->frame_bw) - usb_free_mem(uhci->frame_bw); - - uhci->frame_bw = NULL; - - return TRUE; -} - -PDEVICE_OBJECT -uhci_create_device(PDRIVER_OBJECT drvr_obj, PUSB_DEV_MANAGER dev_mgr) -{ - NTSTATUS status; - PDEVICE_OBJECT pdev; - PDEVICE_EXTENSION pdev_ext; - - UNICODE_STRING dev_name; - UNICODE_STRING symb_name; - - STRING string, another_string; - CHAR str_dev_name[64], str_symb_name[64]; - UCHAR hcd_id; - - if (drvr_obj == NULL) - return NULL; - - ASSERT(dev_mgr != NULL); - - //note: hcd count wont increment till the hcd is registered in dev_mgr - sprintf(str_dev_name, "%s%d", UHCI_DEVICE_NAME, dev_mgr->hcd_count); - sprintf(str_symb_name, "%s%d", DOS_DEVICE_NAME, dev_mgr->hcd_count); - - RtlInitString(&string, str_dev_name); - RtlAnsiStringToUnicodeString(&dev_name, &string, TRUE); - - pdev = NULL; - status = IoCreateDevice(drvr_obj, - sizeof(DEVICE_EXTENSION) + sizeof(UHCI_DEV), - &dev_name, FILE_UHCI_DEV_TYPE, 0, FALSE, &pdev); - - if (status != STATUS_SUCCESS || pdev == NULL) - { - RtlFreeUnicodeString(&dev_name); - return NULL; - } - - pdev_ext = pdev->DeviceExtension; - RtlZeroMemory(pdev_ext, sizeof(DEVICE_EXTENSION) + sizeof(UHCI_DEV)); - - pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_HCD; - pdev_ext->dev_ext_hdr.dispatch = uhci_dispatch_irp; - pdev_ext->dev_ext_hdr.start_io = NULL; //we do not support startio - pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr; - - pdev_ext->pdev_obj = pdev; - pdev_ext->pdrvr_obj = drvr_obj; - - pdev_ext->uhci = (PUHCI_DEV) & (pdev_ext[1]); - - RtlInitString(&another_string, str_symb_name); - RtlAnsiStringToUnicodeString(&symb_name, &another_string, TRUE); - - IoCreateSymbolicLink(&symb_name, &dev_name); - - uhci_dbg_print(DBGLVL_MAXIMUM, - ("uhci_create_device(): dev=0x%x\n, pdev_ext= 0x%x, uhci=0x%x, dev_mgr=0x%x\n", pdev, - pdev_ext, pdev_ext->uhci, dev_mgr)); - - RtlFreeUnicodeString(&dev_name); - RtlFreeUnicodeString(&symb_name); - - //register with dev_mgr though it is not initilized - uhci_init_hcd_interface(pdev_ext->uhci); - hcd_id = dev_mgr_register_hcd(dev_mgr, &pdev_ext->uhci->hcd_interf); - - pdev_ext->uhci->hcd_interf.hcd_set_id(&pdev_ext->uhci->hcd_interf, hcd_id); - pdev_ext->uhci->hcd_interf.hcd_set_dev_mgr(&pdev_ext->uhci->hcd_interf, dev_mgr); - return pdev; -} - -BOOLEAN -uhci_delete_device(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr) -{ - STRING string; - UNICODE_STRING symb_name; - PDEVICE_EXTENSION pdev_ext; - CHAR str_symb_name[64]; - - - if (pdev == NULL) - return FALSE; - - pdev_ext = pdev->DeviceExtension; - - sprintf(str_symb_name, - "%s%d", DOS_DEVICE_NAME, pdev_ext->uhci->hcd_interf.hcd_get_id(&pdev_ext->uhci->hcd_interf)); - RtlInitString(&string, str_symb_name); - RtlAnsiStringToUnicodeString(&symb_name, &string, TRUE); - IoDeleteSymbolicLink(&symb_name); - RtlFreeUnicodeString(&symb_name); - - dev_mgr_deregister_hcd(dev_mgr, pdev_ext->uhci->hcd_interf.hcd_get_id(&pdev_ext->uhci->hcd_interf)); - - if (pdev_ext->res_list) - ExFreePool(pdev_ext->res_list); // not allocated by usb_alloc_mem - - IoDeleteDevice(pdev); - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_delete_device(): device deleted\n")); - return TRUE; -} - -// we can not use endp here for it is within the dev scope, and -// we can not acquire the dev-lock, fortunately we saved some -// info in urb->pipe in uhci_internal_submit_XXX. -BOOLEAN NTAPI -uhci_isr(PKINTERRUPT interrupt, PVOID context) -{ - PUHCI_DEV uhci; - USHORT status; - PLIST_ENTRY pthis, pnext; - PURB purb; - - UNREFERENCED_PARAMETER(interrupt); - UNREFERENCED_PARAMETER(context); - - uhci_dbg_print(DBGLVL_ULTRA, ("uhci_isr(): context=0x%x\n", context)); - - /* - * Read the interrupt status, and write it back to clear the - * interrupt cause - */ - uhci = (PUHCI_DEV) context; - if (uhci == NULL) - return FALSE; - - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS)); - if (!status) /* shared interrupt, not mine */ - return FALSE; - - if (status != 1) - { - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): current uhci status=0x%x\n", status)); - } - else - { - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_isr(): congratulations, no error occurs\n")); - } - - /* clear it */ - WRITE_PORT_USHORT((PUSHORT) (uhci->port_base + USBSTS), status); - - if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) - { - if (status & USBSTS_HSE) - { - DbgPrint("uhci_isr(): host system error, PCI problems?\n"); - //for( ; ; ); - } - if (status & USBSTS_HCPE) - { - DbgPrint("uhci_isr(): host controller process error. something bad happened\n"); - //for( ; ; ); - //for( ; ; ); - } - if ((status & USBSTS_HCH)) //&& !uhci->is_suspended - { - DbgPrint("uhci_isr(): host controller halted. very bad\n"); - /* FIXME: Reset the controller, fix the offending TD */ - } - } - - // don't no how to handle it yet - //if (status & USBSTS_RD) - //{ - //uhci_wakeup(uhci); - //}*/ - - //let's remove those force-cancel urbs from the schedule first - ListFirst(&uhci->urb_list, pthis); - while (pthis) - { - purb = (PURB) pthis; - if (purb->flags & URB_FLAG_FORCE_CANCEL) - { - uhci_remove_urb_from_schedule(uhci, purb); - } - ListNext(&uhci->urb_list, pthis, pnext); - pthis = pnext; - } - - //clear the interrupt if the urb is force canceled - uhci->skel_term_td->status &= ~TD_CTRL_IOC; - - //next we need to find if anything fininshed - ListFirst(&uhci->urb_list, pthis); - while (pthis) - { - purb = (PURB) pthis; - if (purb->flags & URB_FLAG_IN_SCHEDULE) - { - if (uhci_is_xfer_finished(purb)) - uhci_remove_urb_from_schedule(uhci, purb); - } - ListNext(&uhci->urb_list, pthis, pnext); - pthis = pnext; - } - - KeInsertQueueDpc(&uhci->pdev_ext->uhci_dpc, uhci, 0); - return TRUE; -} - -BOOLEAN NTAPI -uhci_cal_cpu_freq(PVOID context) -{ - UNREFERENCED_PARAMETER(context); - - usb_cal_cpu_freq(); - return TRUE; -} - -PDEVICE_OBJECT -uhci_probe(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, PUSB_DEV_MANAGER dev_mgr) -{ - LONG bus, i, j, ret = 0; - PCI_SLOT_NUMBER slot_num; - PPCI_COMMON_CONFIG pci_config; - PDEVICE_OBJECT pdev; - BYTE buffer[sizeof(PCI_COMMON_CONFIG)]; - LONG count; - PDEVICE_EXTENSION pdev_ext; - - slot_num.u.AsULONG = 0; - pci_config = (PPCI_COMMON_CONFIG) buffer; - count = 0; - pdev = NULL; - - //scan the PCI buses to find uhci controller - for (bus = 0; bus <= PCI_MAX_BRIDGE_NUMBER; bus++) - { - for(i = 0; i <= PCI_MAX_DEVICES; i++) - { - slot_num.u.bits.DeviceNumber = i; - for(j = 0; j <= PCI_MAX_FUNCTION; j++) - { - slot_num.u.bits.FunctionNumber = j; - - ret = HalGetBusData(PCIConfiguration, - bus, slot_num.u.AsULONG, pci_config, PCI_COMMON_HDR_LENGTH); - - if (ret == 0) /*no this bus */ - break; - - if (ret == 2) /*no device on the slot */ - break; - - if (pci_config->BaseClass == 0x0c && pci_config->SubClass == 0x03 && - pci_config->ProgIf == 0x00) - { - // well, we find our usb host controller, create device - pdev = uhci_alloc(drvr_obj, reg_path, ((bus << 8) | (i << 3) | j), dev_mgr); - if (pdev) -#ifdef _MULTI_UHCI - count++; -#else - goto LBL_LOOPOUT; -#endif - } - } - if (ret == 0) - break; - } - } - -#ifndef _MULTI_UHCI -LBL_LOOPOUT: -#endif - DbgPrint("Found %d UHCI controllers\n", count); - - if (pdev) - { - pdev_ext = pdev->DeviceExtension; - if (pdev_ext) - { - // acquire higher irql to eliminate pre-empty - KeSynchronizeExecution(pdev_ext->uhci_int, uhci_cal_cpu_freq, NULL); - } - } - return pdev; -} - -PDEVICE_OBJECT -uhci_alloc(PDRIVER_OBJECT drvr_obj, PUNICODE_STRING reg_path, ULONG bus_addr, PUSB_DEV_MANAGER dev_mgr) -{ - LONG frd_num, prd_num; - PDEVICE_OBJECT pdev; - PDEVICE_EXTENSION pdev_ext; - ULONG vector, addr_space; - LONG bus; - KIRQL irql; - KAFFINITY affinity; - - DEVICE_DESCRIPTION dev_desc; - CM_PARTIAL_RESOURCE_DESCRIPTOR *pprd; - PCI_SLOT_NUMBER slot_num; - NTSTATUS status; - - - pdev = uhci_create_device(drvr_obj, dev_mgr); - if (pdev == NULL) - return pdev; - pdev_ext = pdev->DeviceExtension; - - pdev_ext->pci_addr = bus_addr; - bus = (bus_addr >> 8); - - slot_num.u.AsULONG = 0; - slot_num.u.bits.DeviceNumber = ((bus_addr & 0xff) >> 3); - slot_num.u.bits.FunctionNumber = (bus_addr & 0x07); - - //now create adapter object - RtlZeroMemory(&dev_desc, sizeof(dev_desc)); - - dev_desc.Version = DEVICE_DESCRIPTION_VERSION; - dev_desc.Master = TRUE; - dev_desc.ScatterGather = TRUE; - dev_desc.Dma32BitAddresses = TRUE; - dev_desc.BusNumber = bus; - dev_desc.InterfaceType = PCIBus; - dev_desc.MaximumLength = - UHCI_MAX_POOL_TDS * sizeof(UHCI_TD) * UHCI_MAX_TD_POOLS - + sizeof(UHCI_QH) * UHCI_MAX_POOL_QHS + sizeof(ULONG) * UHCI_MAX_FRAMES; - - pdev_ext->map_regs = 2; // UHCI_MAX_TD_POOLS + - //+ BYTES_TO_PAGES( ( UHCI_MAX_POOL_TDS * 64 ) * UHCI_MAX_TD_POOLS ) ; - - pdev_ext->padapter = HalGetAdapter(&dev_desc, &pdev_ext->map_regs); - - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): padapter=0x%x\n", pdev_ext->padapter)); - if (pdev_ext->padapter == NULL) - { - //fatal error - uhci_delete_device(pdev, dev_mgr); - return NULL; - } - - DbgPrint("uhci_alloc(): reg_path=%p, \n \ - uhci_alloc(): PCIBus=0x%x, bus=0x%x, bus_addr=0x%x \n \ - uhci_alloc(): slot_num=0x%x, &res_list=%p \n", reg_path, (DWORD) PCIBus, (DWORD) bus, - (DWORD) bus_addr, (DWORD) slot_num.u.AsULONG, & pdev_ext->res_list); - - //let's allocate resources for this device - DbgPrint("uhci_alloc(): about to assign slot res\n"); - if ((status = HalAssignSlotResources(reg_path, NULL, //no class name yet - drvr_obj, NULL, //no support of another uhci controller - PCIBus, - bus, slot_num.u.AsULONG, &pdev_ext->res_list)) != STATUS_SUCCESS) - { - DbgPrint("uhci_alloc(): error assign slot res, 0x%x\n", status); - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - uhci_delete_device(pdev, dev_mgr); - return NULL; - } - - //parse the resource list - for(frd_num = 0; frd_num < (LONG) pdev_ext->res_list->Count; frd_num++) - { - for(prd_num = 0; prd_num < (LONG) pdev_ext->res_list->List[frd_num].PartialResourceList.Count; - prd_num++) - { - pprd = &pdev_ext->res_list->List[frd_num].PartialResourceList.PartialDescriptors[prd_num]; - if (pprd->Type == CmResourceTypePort) - { - RtlCopyMemory(&pdev_ext->res_port, &pprd->u.Port, sizeof(pprd->u.Port)); - } - else if (pprd->Type == CmResourceTypeInterrupt) - { - RtlCopyMemory(&pdev_ext->res_interrupt, &pprd->u.Interrupt, sizeof(pprd->u.Interrupt)); - } - } - } - - //for port, translate them to system address - addr_space = 1; - if (HalTranslateBusAddress(PCIBus, bus, pdev_ext->res_port.Start, &addr_space, //io space - &pdev_ext->uhci->uhci_reg_base) != (BOOLEAN) TRUE) - { - DbgPrint("uhci_alloc(): error, can not translate bus address\n"); - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - uhci_delete_device(pdev, dev_mgr); - return NULL; - } - - DbgPrint("uhci_alloc(): address space=0x%x\n, reg_base=0x%x\n", - addr_space, pdev_ext->uhci->uhci_reg_base.u.LowPart); - - if (addr_space == 0) - { - //port has been mapped to memory space - pdev_ext->uhci->port_mapped = TRUE; - pdev_ext->uhci->port_base = (PBYTE) MmMapIoSpace(pdev_ext->uhci->uhci_reg_base, - pdev_ext->res_port.Length, FALSE); - - //fatal error can not map the registers - if (pdev_ext->uhci->port_base == NULL) - { - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - uhci_delete_device(pdev, dev_mgr); - return NULL; - } - } - else - { - //io space - pdev_ext->uhci->port_mapped = FALSE; - pdev_ext->uhci->port_base = (PBYTE) pdev_ext->uhci->uhci_reg_base.LowPart; - } - - //before we connect the interrupt, we have to init uhci - pdev_ext->uhci->fsbr_cnt = 0; - pdev_ext->uhci->pdev_ext = pdev_ext; - - if (uhci_init_schedule(pdev_ext->uhci, pdev_ext->padapter) == FALSE) - { - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - uhci_delete_device(pdev, dev_mgr); - return NULL; - } - - InitializeListHead(&pdev_ext->uhci->urb_list); - KeInitializeSpinLock(&pdev_ext->uhci->pending_endp_list_lock); - InitializeListHead(&pdev_ext->uhci->pending_endp_list); - - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_alloc(): pending_endp_list=0x%x\n", - &pdev_ext->uhci->pending_endp_list)); - - init_pending_endp_pool(&pdev_ext->uhci->pending_endp_pool); - KeInitializeTimer(&pdev_ext->uhci->reset_timer); - - vector = HalGetInterruptVector(PCIBus, - bus, - pdev_ext->res_interrupt.level, - pdev_ext->res_interrupt.vector, - &irql, - &affinity); - - KeInitializeDpc(&pdev_ext->uhci_dpc, uhci_dpc_callback, (PVOID) pdev_ext->uhci); - - //connect the interrupt - DbgPrint("uhci_alloc(): the int=0x%x\n", vector); - if (IoConnectInterrupt(&pdev_ext->uhci_int, - uhci_isr, - pdev_ext->uhci, - NULL, //&pdev_ext->uhci->frame_list_lock, - vector, - irql, - irql, - LevelSensitive, - TRUE, //share the vector - affinity, - FALSE) //No float save - != STATUS_SUCCESS) - { - uhci_release(pdev, dev_mgr); - return NULL; - } - - return pdev; -} - -BOOLEAN -uhci_release(PDEVICE_OBJECT pdev, PUSB_DEV_MANAGER dev_mgr) -{ - PDEVICE_EXTENSION pdev_ext; - PUHCI_DEV uhci; - - if (pdev == NULL) - return FALSE; - - pdev_ext = pdev->DeviceExtension; - - if (pdev_ext == NULL) - return FALSE; - - uhci = pdev_ext->uhci; - if (uhci == NULL) - return FALSE; - - uhci_stop(uhci); - //pdev_ext->uhci->conn_count = 0; - pdev_ext->uhci->fsbr_cnt = 0; - - if (pdev_ext->uhci_int) - { - IoDisconnectInterrupt(pdev_ext->uhci_int); - pdev_ext->uhci_int = NULL; - } - else - TRAP(); - destroy_pending_endp_pool(&pdev_ext->uhci->pending_endp_pool); - //pdev_ext->uhci->pending_endp_pool = NULL; - - uhci_destroy_schedule(uhci); - - release_adapter(pdev_ext->padapter); - pdev_ext->padapter = NULL; - - uhci_delete_device(pdev, dev_mgr); - - return FALSE; - -} - -// send cmds to start the uhc -// shamelessly copied from linux's uhci.c (reset_hc(), configure_hc() routines) -BOOLEAN -uhci_start(PHCD hcd) -{ - PUHCI_DEV uhci; - PBYTE io_addr; - USHORT pirq; - PCI_SLOT_NUMBER SlotNum; - int timeout = 10000; - - uhci = uhci_from_hcd(hcd); - io_addr = uhci->port_base; - - /* - * Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_HCRESET); - while (READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD)) & USBCMD_HCRESET) - { - if (!--timeout) - { - break; - } - } - - /* Turn on all interrupts */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBINTR), - USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP); - - /* Start at frame 0 */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBFRNUM), 0); - WRITE_PORT_ULONG((PULONG) (io_addr + USBFLBASEADD), uhci->frame_list_logic_addr.LowPart); - - /* Run and mark it configured with a 64-byte max packet */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_RS | USBCMD_CF | USBCMD_MAXP); - - DbgPrint("uhci_start(): current uhci status=0x%x\n", uhci_status(uhci)); - - /* Enable PIRQ */ - pirq = USBLEGSUP_DEFAULT; - SlotNum.u.AsULONG = 0; - SlotNum.u.bits.DeviceNumber = ((uhci->pdev_ext->pci_addr & 0xff) >> 3); - SlotNum.u.bits.FunctionNumber = (uhci->pdev_ext->pci_addr & 0x07); - - DbgPrint("uhci_start(): set bus %d data at slot 0x%x\n", (uhci->pdev_ext->pci_addr >> 8), - SlotNum.u.AsULONG); - - HalSetBusDataByOffset(PCIConfiguration, (uhci->pdev_ext->pci_addr >> 8), SlotNum.u.AsULONG, - &pirq, USBLEGSUP, sizeof(pirq)); - - return TRUE; -} - -VOID -uhci_stop(PUHCI_DEV uhci) -{ - PBYTE io_addr = uhci->port_base; - // turn off all the interrupt - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBINTR), 0); - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0); -} - -static VOID -uhci_reset(PUHCI_DEV uhci) -{ - PBYTE io_addr = uhci->port_base; - - uhci_stop(uhci); - /* Global reset for 50ms */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_GRESET); - //uhci_wait_ms( uhci, 50 ); - usb_wait_ms_dpc(50); - - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0); - //uhci_wait_ms( uhci, 10 ); - usb_wait_ms_dpc(10); -} - -VOID -uhci_suspend(PUHCI_DEV uhci) -{ - PBYTE io_addr = uhci->port_base; - - //uhci->is_suspended = 1; - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_EGSM); - -} - -VOID -uhci_wakeup(PUHCI_DEV uhci) -{ - PBYTE io_addr; - unsigned int status; - - io_addr = uhci->port_base; - - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), 0); - - /* wait for EOP to be sent */ - status = READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD)); - while (status & USBCMD_FGR) - status = READ_PORT_USHORT((PUSHORT) (io_addr + USBCMD)); - - //uhci->is_suspended = 0; - - /* Run and mark it configured with a 64-byte max packet */ - WRITE_PORT_USHORT((PUSHORT) (io_addr + USBCMD), USBCMD_RS | USBCMD_CF | USBCMD_MAXP); - -} - -BOOLEAN -uhci_init_schedule(PUHCI_DEV uhci, PADAPTER_OBJECT padapter) -{ - int i, irq; - - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_init_schedule(): entering..., uhci=0x%x\n", uhci)); - if (uhci == NULL || padapter == NULL) - return FALSE; - - if (init_td_pool_list(&uhci->td_pool, padapter) == FALSE) - { - return FALSE; - } - if (init_qh_pool(&uhci->qh_pool, padapter) == FALSE) - { - return FALSE; - } - - //since uhci is not started we can freely access all resources. - for(i = 0; i < UHCI_MAX_SKELTDS; i++) - { - uhci->skel_td[i] = alloc_td(&uhci->td_pool); - uhci_fill_td(uhci->skel_td[i], 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); - - if (i > 0) - { - uhci->skel_td[i]->link = uhci->skel_td[i - 1]->phy_addr; - } - } - - /*for( i = UHCI_MAX_SKELTDS - 3; i >= 0; i-- ) - { - InsertTailList( &uhci->skel_int256_td->ptde->hori_link, - &uhci->skel_td[ i ]->ptde->hori_link ); - } */ - - for(i = 0; i < UHCI_MAX_SKELQHS; i++) - { - uhci->skel_qh[i] = alloc_qh(&uhci->qh_pool); - if (i > 0) - { - uhci->skel_qh[i - 1]->link = uhci->skel_qh[i]->phy_addr; - } - - uhci->skel_qh[i]->element = UHCI_PTR_TERM; - } - - uhci->skel_int1_td->link = uhci->skel_ls_control_qh->phy_addr; - - // Hack for PIIX - uhci_fill_td(uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0); - uhci->skel_term_td->link = uhci->skel_term_td->phy_addr; - - uhci->skel_term_qh->link = UHCI_PTR_TERM; - uhci->skel_term_qh->element = uhci->skel_term_td->phy_addr; - - InsertTailList(&uhci->skel_term_qh->pqhe->vert_link, &uhci->skel_term_td->ptde->vert_link); - - /*for( i = 0; i < UHCI_MAX_SKELQHS; i++ ) - { - InsertTailList( &uhci->skel_int256_td->ptde->hori_link, - &uhci->skel_qh[ i ]->pqhe->hori_link ); - } */ - - if (uhci_init_frame_list(uhci, uhci->pdev_ext->padapter) == FALSE) - uhci_destroy_frame_list(uhci); - - //well all have been chained, now scatter the int tds to frame-list - //shamelessly pasted from linux's uhci.c :-) - for(i = 0; i < UHCI_MAX_FRAMES; i++) - { - irq = 0; - if (i & 1) - { - irq++; - if (i & 2) - { - irq++; - if (i & 4) - { - irq++; - if (i & 8) - { - irq++; - if (i & 16) - { - irq++; - if (i & 32) - { - irq++; - if (i & 64) - irq++; - } - } - } - } - } - } - - /* Only place we don't use the frame list routines */ - uhci->frame_list[i] = uhci->skel_td[irq]->phy_addr; - } - return TRUE; -} - -BOOLEAN -uhci_destroy_schedule(PUHCI_DEV uhci) -{ - BOOLEAN ret; - - ret = uhci_destroy_frame_list(uhci); - ret = destroy_qh_pool(&uhci->qh_pool); - ret = destroy_td_pool_list(&uhci->td_pool); - - return ret; - -} - -VOID NTAPI -uhci_cancel_pending_endp_urb(IN PVOID Parameter) -{ - PLIST_ENTRY abort_list; - PUSB_DEV pdev; - PURB purb; - USE_BASIC_NON_PENDING_IRQL; - - abort_list = (PLIST_ENTRY) Parameter; - - if (abort_list == NULL) - return; - - while (IsListEmpty(abort_list) == FALSE) - { - //these devs are protected by urb's ref-count - purb = (PURB) RemoveHeadList(abort_list); - pdev = purb->pdev; - // purb->status is set when they are added to abort_list - - uhci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, FALSE); - pdev->ref_count--; - unlock_dev(pdev, FALSE); - } - usb_free_mem(abort_list); - return; -} - -BOOLEAN -uhci_process_pending_endp(PUHCI_DEV uhci) -{ - PUSB_DEV pdev; - LIST_ENTRY temp_list, abort_list; - PLIST_ENTRY pthis; - PURB purb; - PUSB_ENDPOINT pendp; - NTSTATUS can_submit = STATUS_UNSUCCESSFUL; - PWORK_QUEUE_ITEM pwork_item; - PLIST_ENTRY cancel_list; - USE_BASIC_IRQL; - - if (uhci == NULL) - return FALSE; - - InitializeListHead(&temp_list); - InitializeListHead(&abort_list); - - purb = NULL; - uhci_dbg_print(DBGLVL_MEDIUM, ("uhci_process_pending_endp(): entering..., uhci=0x%x\n", uhci)); - - lock_pending_endp_list(&uhci->pending_endp_list_lock); - while (IsListEmpty(&uhci->pending_endp_list) == FALSE) - { - - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_process_pending_endp(): pending_endp_list=0x%x\n", - &uhci->pending_endp_list)); - - pthis = RemoveHeadList(&uhci->pending_endp_list); - pendp = ((PUHCI_PENDING_ENDP) pthis)->pendp; - pdev = dev_from_endp(pendp); - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - //delegate to uhci_remove_device for removing the urb queue on the endpoint - continue; - } - - if (endp_state(pendp) == USB_ENDP_FLAG_STALL) - { - while (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - purb->status = USB_STATUS_ENDPOINT_HALTED; - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - } - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - continue; - } - - - if (IsListEmpty(&pendp->urb_list) == FALSE) - { - purb = (PURB) RemoveHeadList(&pendp->urb_list); - ASSERT(purb); - } - else - { - InitializeListHead(&pendp->urb_list); - unlock_dev(pdev, TRUE); - free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - continue; - } - - // if can_submit is STATUS_SUCCESS, the purb is inserted into the schedule - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_process_pending_endp(): endp_type=0x%x\n", - endp_type(pendp))); - switch (endp_type(pendp)) - { - case USB_ENDPOINT_XFER_BULK: - { -#ifdef DEMO - can_submit = STATUS_UNSUCCESSFUL; -#else - can_submit = uhci_internal_submit_bulk(uhci, purb); -#endif - break; - } - case USB_ENDPOINT_XFER_CONTROL: - { - can_submit = uhci_internal_submit_ctrl(uhci, purb); - break; - } - case USB_ENDPOINT_XFER_INT: - { - can_submit = uhci_internal_submit_int(uhci, purb); - break; - } - case USB_ENDPOINT_XFER_ISOC: - { - can_submit = uhci_internal_submit_iso(uhci, purb); - break; - } - } - - if (can_submit == STATUS_NO_MORE_ENTRIES) - { - //no enough bandwidth or tds - InsertHeadList(&pendp->urb_list, &purb->urb_link); - InsertTailList(&temp_list, pthis); - } - else - { - // other error or success - free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - - if (can_submit != STATUS_SUCCESS) - { - //abort these URBs - InsertTailList(&abort_list, (LIST_ENTRY *) purb); - uhci_dbg_print(DBGLVL_MEDIUM, ("uhci_process_pending_endp(): unable to submit urb 0x%x, " - "with status=0x%x\n", purb, can_submit)); - purb->status = can_submit; - } - - } - unlock_dev(pdev, TRUE); - } - - if (IsListEmpty(&temp_list) == FALSE) - { - //re-append them to the pending_endp_list - ListFirst(&temp_list, pthis); - RemoveEntryList(&temp_list); - MergeList(&uhci->pending_endp_list, pthis); - } - unlock_pending_endp_list(&uhci->pending_endp_list_lock); - - if (IsListEmpty(&abort_list) == FALSE) - { - PLIST_ENTRY pthis; - cancel_list = (PLIST_ENTRY) usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(LIST_ENTRY)); - ASSERT(cancel_list); - - ListFirst(&abort_list, pthis); - RemoveEntryList(&abort_list); - InsertTailList(pthis, cancel_list); - - pwork_item = (PWORK_QUEUE_ITEM) (cancel_list + 1); - - // we do not need to worry the uhci_cancel_pending_endp_urb running when the - // driver is unloading since it will prevent the dev_mgr to quit till all the - // reference count to the dev drop to zero. - ExInitializeWorkItem(pwork_item, uhci_cancel_pending_endp_urb, (PVOID) cancel_list); - ExQueueWorkItem(pwork_item, DelayedWorkQueue); - } - return TRUE; -} - -NTSTATUS -uhci_submit_urb(PUHCI_DEV uhci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - int i; - PUHCI_PENDING_ENDP pending_endp; - NTSTATUS status; - USE_BASIC_IRQL; - - if (uhci == NULL || pdev == NULL || pendp == NULL || purb == NULL) - { - uhci_dbg_print(DBGLVL_MEDIUM, - ("uhci_submit_urb(): uhci=0x%x, pdev=0x%x, pendp=0x%x, purb=0x%x " - "called with invalid param!\n", uhci, pdev, pendp, purb)); - return STATUS_INVALID_PARAMETER; - } - - lock_pending_endp_list(&uhci->pending_endp_list_lock); - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - - if (dev_class(pdev) == USB_DEV_CLASS_ROOT_HUB) - { - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&uhci->pending_endp_list_lock); - status = uhci_rh_submit_urb(pdev, purb); - return status; - } - - if (pendp) - purb->pendp = pendp; - else - purb->pendp = &pdev->default_endp; - - if (dev_from_endp(purb->pendp) != pdev) - { - uhci_dbg_print(DBGLVL_MEDIUM, - ("uhci_submit_urb(): dev_from_endp=0x%x\n, pdev=0x%x, pendp=0x%x " - "devices mismatch!\n", dev_from_endp(purb->pendp), pdev, pendp)); - - status = purb->status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - - if (endp_state(purb->pendp) == USB_ENDP_FLAG_STALL) - { - status = purb->status = USB_STATUS_ENDPOINT_HALTED; - goto LBL_OUT; - } - - purb->pdev = pdev; - purb->rest_bytes = purb->data_length; - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_BULK) - purb->bytes_to_transfer = (purb->data_length > purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER ? purb->pendp->pusb_endp_desc->wMaxPacketSize * UHCI_MAX_TDS_PER_TRANSFER : purb->data_length); //multiple transfer for large data block - else - purb->bytes_to_transfer = purb->data_length; - - uhci_dbg_print(DBGLVL_MEDIUM, ("uhci_submit_urb(): bytes_to_transfer=0x%x\n", purb->bytes_to_transfer)); - - purb->bytes_transfered = 0; - InitializeListHead(&purb->trasac_list); - purb->last_finished_td = &purb->trasac_list; - purb->flags &= ~(URB_FLAG_STATE_MASK | URB_FLAG_IN_SCHEDULE | URB_FLAG_FORCE_CANCEL); - purb->flags |= URB_FLAG_STATE_PENDING; - - - i = IsListEmpty(&pendp->urb_list); - InsertTailList(&pendp->urb_list, &purb->urb_link); - - pdev->ref_count++; //for urb reference - - if (i == FALSE) - { - //there is urb pending, simply queue it and return - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - else if (usb_endp_busy_count(purb->pendp) && endp_type(purb->pendp) != USB_ENDPOINT_XFER_ISOC) - { - // - //No urb waiting but urb overlap not allowed, - //so leave it in queue and return, will be scheduled - //later - // - status = purb->status = STATUS_PENDING; - goto LBL_OUT; - } - - pending_endp = alloc_pending_endp(&uhci->pending_endp_pool, 1); - if (pending_endp == NULL) - { - //panic - status = purb->status = STATUS_UNSUCCESSFUL; - goto LBL_OUT2; - } - - pending_endp->pendp = purb->pendp; - InsertTailList(&uhci->pending_endp_list, &pending_endp->endp_link ); - - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&uhci->pending_endp_list_lock); - - uhci_process_pending_endp(uhci); - return STATUS_PENDING; - -LBL_OUT2: - pdev->ref_count--; - RemoveEntryList(&purb->urb_link); - -LBL_OUT: - unlock_dev(pdev, TRUE); - unlock_pending_endp_list(&uhci->pending_endp_list_lock); - return status; -} - -NTSTATUS -uhci_set_error_code(PURB urb, ULONG raw_status) -{ - if ((raw_status & TD_CTRL_ANY_ERROR) == 0) - { - //test if the urb is canceled - if (urb->flags & URB_FLAG_FORCE_CANCEL) - urb->status = STATUS_CANCELLED; - else - urb->status = STATUS_SUCCESS; - } - - else if (raw_status & TD_CTRL_BABBLE) - urb->status = USB_STATUS_DATA_OVERRUN; - - else if (raw_status & TD_CTRL_STALLED) - urb->status = USB_STATUS_STALL_PID; - - else if (raw_status & TD_CTRL_DBUFERR) - urb->status = USB_STATUS_BUFFER_OVERRUN; - - else if (raw_status & TD_CTRL_CRCTIMEO) - urb->status = USB_STATUS_CRC; - - else if (raw_status & TD_CTRL_BITSTUFF) - urb->status = USB_STATUS_BTSTUFF; - - else - urb->status = STATUS_UNSUCCESSFUL; - - return urb->status; -} - -BOOLEAN NTAPI -uhci_sync_remove_urb_finished(PVOID context) -{ - PUHCI_DEV uhci; - PLIST_ENTRY pthis, pnext, ptemp; - PURB purb; - PSYNC_PARAM pparam; - - pparam = (PSYNC_PARAM) context; - uhci = pparam->uhci; - ptemp = (PLIST_ENTRY) pparam->context; - - if (uhci == NULL) - { - return (UCHAR) (pparam->ret = FALSE); - } - - ListFirst(&uhci->urb_list, pthis); - while (pthis) - { - //remove urbs not in the schedule - ListNext(&uhci->urb_list, pthis, pnext); - purb = (PURB) pthis; - - if ((purb->flags & URB_FLAG_IN_SCHEDULE) == 0) - { - //finished or canceled( not apply for split bulk ). - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_FINISHED; - RemoveEntryList(pthis); - InsertTailList(ptemp, pthis); - } - pthis = pnext; - } - pparam->ret = TRUE; - return (UCHAR) TRUE; -} - -BOOLEAN -uhci_drop_fsbr(PUHCI_DEV uhci) -{ - if (uhci == NULL) - return (UCHAR) FALSE; - - uhci->fsbr_cnt--; - - if (uhci->fsbr_cnt <= 0) - { - uhci->skel_term_qh->link = UHCI_PTR_TERM; - uhci->fsbr_cnt = 0; - } - - return (UCHAR) TRUE; -} - -VOID NTAPI -uhci_dpc_callback(PKDPC dpc, PVOID context, PVOID sysarg1, PVOID sysarg2) -{ - PUHCI_DEV uhci; - - LIST_HEAD temp_list; - PLIST_ENTRY pthis, pnext; - PURB purb; - PQH_EXTENSION pqhe; - PUHCI_PENDING_ENDP pending_endp; - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - - BOOLEAN finished; - LONG i, j; - ULONG uhci_status, urb_status, toggle = 0; - - SYNC_PARAM sync_param; - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(dpc); - UNREFERENCED_PARAMETER(sysarg2); - - uhci = (PUHCI_DEV) context; - if (uhci == NULL) - return; - - uhci_status = (ULONG) sysarg1; - - InitializeListHead(&temp_list); - - sync_param.uhci = uhci; - sync_param.context = (PVOID) & temp_list; - - uhci_dbg_print(DBGLVL_MAXIMUM, ("uhci_dpc_callback(): entering..., uhci=0x%x\n", uhci)); - //remove finished urb from uhci's urb-list - KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_remove_urb_finished, &sync_param); - - //release resources( tds, and qhs ) the urb occupied - while (IsListEmpty(&temp_list) == FALSE) - { - //not in any public queue, if do not access into dev, no race - //condition will occur - purb = (PURB) RemoveHeadList(&temp_list); - urb_status = purb->status; - - //the only place we do not use this lock on non-pending-endp-list data ops - KeAcquireSpinLockAtDpcLevel(&uhci->pending_endp_list_lock); - while (IsListEmpty(&purb->trasac_list) == FALSE) - { - pthis = RemoveHeadList(&purb->trasac_list); - - if ((((PTD_EXTENSION) pthis)->flags & UHCI_ITEM_FLAG_TYPE) == UHCI_ITEM_FLAG_QH) - { - pqhe = (PQH_EXTENSION) pthis; - lock_qh_pool(&uhci->qh_pool, TRUE); - free_qh(&uhci->qh_pool, pqhe->pqh); - unlock_qh_pool(&uhci->qh_pool, TRUE); - } - else - { - //must be a td chain - InsertHeadList(&purb->trasac_list, pthis); - for(i = 0, purb->bytes_transfered = 0; i < purb->td_count; i++) - { - PUHCI_TD ptd; - // accumulate data transfered in tds - ptd = ((PTD_EXTENSION) pthis)->ptd; - if ((ptd->status & TD_CTRL_ACTIVE) == 0 && (ptd->status & TD_CTRL_ANY_ERROR) == 0) - { - j = ptd->status & 0x7ff; - purb->bytes_transfered += ((j == 0x7ff) ? 0 : (j + 1)); - - } - ListNext(&purb->trasac_list, pthis, pnext); - pthis = pnext; - } - - if (urb_status & TD_CTRL_ANY_ERROR) - { - if (purb->last_finished_td != NULL && purb->last_finished_td != &purb->trasac_list) - toggle = (((PTD_EXTENSION) purb->last_finished_td)->ptd->info & (1 << 19)); - } - //trick, remove trasac_list - ListFirst(&purb->trasac_list, pthis); - RemoveEntryList(&purb->trasac_list); - lock_td_pool(&uhci->td_pool, TRUE); - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - //termination condition - InitializeListHead(&purb->trasac_list); - purb->last_finished_td = NULL; - } - } - - if (endp_type(purb->pendp) == USB_ENDPOINT_XFER_ISOC - || endp_type(purb->pendp) == USB_ENDPOINT_XFER_INT) - uhci_claim_bandwidth(uhci, purb, FALSE); //release band-width - - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - - uhci_set_error_code(purb, urb_status); - - finished = TRUE; - - //since the ref_count for the urb is not released, we can safely have one - //pointer to dev - pdev = dev_from_endp(purb->pendp); - pendp = purb->pendp; - - if (purb->status == USB_STATUS_BABBLE_DETECTED) - { - usb_dbg_print(DBGLVL_MEDIUM, - ("uhci_dpc_callback(): alert!!!, babble detected, severe error, reset the whole bus\n")); - uhci_reset(uhci); - uhci_start(&uhci->hcd_interf); - } - - //this will let the new request in uhci_generic_urb_completion to this endp - //be processed rather than queued in the pending_endp_list - lock_dev(pdev, TRUE); - usb_endp_busy_count_dec(pendp); - unlock_dev(pdev, TRUE); - - if (usb_success(purb->status) == FALSE) - { - // set error code and complete the urb and purb is invalid from this point - uhci_generic_urb_completion(purb, purb->context); - } - else - { - if ((purb->pipe & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) - { - purb->rest_bytes -= purb->bytes_transfered; - if (purb->rest_bytes) - { - finished = FALSE; - } - else - { - uhci_generic_urb_completion(purb, purb->context); - } - } - else - { - uhci_generic_urb_completion(purb, purb->context); - //purb is now invalid - } - } - - KeAcquireSpinLockAtDpcLevel(&uhci->pending_endp_list_lock); - lock_dev(pdev, TRUE); - - if (finished) - pdev->ref_count--; - - if (urb_status & TD_CTRL_ANY_ERROR && endp_type(pendp) != USB_ENDPOINT_XFER_CONTROL) - { - pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK; - pendp->flags |= USB_ENDP_FLAG_STALL; - } - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - if (finished == FALSE) - { - - purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - uhci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, TRUE); - pdev->ref_count--; - unlock_dev(pdev, TRUE); - } - continue; - } - - if (finished && IsListEmpty(&pendp->urb_list) == TRUE) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - continue; - } - else if (finished == TRUE) - { - //has urb in the endp's urb-list - if (usb_endp_busy_count(pendp) > 0) - { - //the urbs still have chance to be sheduled but not this time - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - continue; - } - } - - if (finished == FALSE) - { - //a split bulk transfer - purb->bytes_transfered = 0; - purb->bytes_to_transfer = - UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize - > purb->rest_bytes - ? purb->rest_bytes : UHCI_MAX_TDS_PER_TRANSFER * purb->pendp->pusb_endp_desc->wMaxPacketSize; - - //the urb is not finished - purb->flags &= ~URB_FLAG_STATE_MASK; - purb->flags |= URB_FLAG_STATE_PENDING; - - InsertHeadList(&pendp->urb_list, &purb->urb_link); - } - - pending_endp = alloc_pending_endp(&uhci->pending_endp_pool, 1); - if (!pending_endp) - { - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - return; - } - - pending_endp->pendp = pendp; - InsertTailList(&uhci->pending_endp_list, &pending_endp->endp_link); - - unlock_dev(pdev, TRUE); - KeReleaseSpinLockFromDpcLevel(&uhci->pending_endp_list_lock); - } - - //ah...exhausted, let's find some in the pending_endp_list to rock - uhci_process_pending_endp(uhci); - return; -} - -BOOLEAN -uhci_add_device(PUHCI_DEV uhci, PUSB_DEV dev) -{ - if (dev == NULL || uhci == NULL) - return FALSE; - - return TRUE; -} - -BOOLEAN NTAPI -uhci_sync_cancel_urbs_dev(PVOID context) -{ - //cancel all the urbs on one dev - PUHCI_DEV uhci; - PUSB_DEV pdev, dest_dev; - PSYNC_PARAM sync_param; - PLIST_ENTRY pthis, pnext; - LONG count; - - sync_param = (PSYNC_PARAM) context; - dest_dev = (PUSB_DEV) sync_param->context; - uhci = sync_param->uhci; - - if (uhci == NULL || dest_dev == NULL) - { - return (UCHAR) (sync_param->ret = FALSE); - } - count = 0; - ListFirst(&uhci->urb_list, pthis); - while (pthis) - { - pdev = dev_from_endp(((PURB) pthis)->pendp); - if (pdev == dest_dev) - { - ((PURB) pthis)->flags |= URB_FLAG_FORCE_CANCEL; - } - ListNext(&uhci->urb_list, pthis, pnext); - pthis = pnext; - count++; - } - if (count) - uhci->skel_term_td->status |= TD_CTRL_IOC; - - return (UCHAR) (sync_param->ret = TRUE); -} - -BOOLEAN -uhci_remove_device(PUHCI_DEV uhci, PUSB_DEV dev) -{ - PUHCI_PENDING_ENDP ppending_endp; - PLIST_ENTRY pthis, pnext; - PURB purb; - LIST_HEAD temp_list; - int i, j, k; - SYNC_PARAM sync_param; - - USE_BASIC_IRQL; - - if (uhci == NULL || dev == NULL) - return FALSE; - - InitializeListHead(&temp_list); - - //free pending endp that has urb queued from pending endp list - lock_pending_endp_list(&uhci->pending_endp_list_lock); - - ListFirst(&uhci->pending_endp_list, pthis); - - while (pthis) - { - ppending_endp = (PUHCI_PENDING_ENDP) pthis; - ListNext(&uhci->pending_endp_list, pthis, pnext); - if (dev_from_endp(ppending_endp->pendp) == dev) - { - RemoveEntryList(pthis); - free_pending_endp(&uhci->pending_endp_pool, struct_ptr(pthis, UHCI_PENDING_ENDP, endp_link)); - } - pthis = pnext; - } - unlock_pending_endp_list(&uhci->pending_endp_list_lock); - - //cancel all the urbs in the urb-list - sync_param.uhci = uhci; - sync_param.context = (PVOID) dev; - - KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_cancel_urbs_dev, &sync_param); - - //cancel all the urb in the endp's urb-list - k = 0; - lock_dev(dev, FALSE); - if (dev->usb_config) - { - //only for configed dev - for(i = 0; i < dev->usb_config->if_count; i++) - { - for(j = 0; j < dev->usb_config->interf[i].endp_count; j++) - { - ListFirst(&dev->usb_config->interf[i].endp[j].urb_list, pthis); - while (pthis) - { - ListNext(&dev->usb_config->interf[i].endp[j].urb_list, pthis, pnext); - - RemoveEntryList(pthis); - InsertHeadList(&temp_list, pthis); - pthis = pnext; - k++; - } - - } - } - } - ListFirst(&dev->default_endp.urb_list, pthis); - - while (pthis) - { - ListNext(&dev->default_endp.urb_list, pthis, pnext); - - RemoveEntryList(pthis); - InsertHeadList(&temp_list, pthis); - pthis = pnext; - k++; - } - unlock_dev(dev, FALSE); - - if (IsListEmpty(&temp_list) == FALSE) - { - for(i = 0; i < k; i++) - { - //complete those urbs with error - pthis = RemoveHeadList(&temp_list); - purb = (PURB) pthis; - purb->status = STATUS_DEVICE_DOES_NOT_EXIST; - { - uhci_generic_urb_completion(purb, purb->context); - } - } - } - - lock_dev(dev, FALSE) dev->ref_count -= k; - unlock_dev(dev, FALSE); - - return TRUE; -} - - -// -// assume that the urb has its rest_bytes and bytes_to_transfer set -// and bytes_transfered is zeroed. -// dev_lock must be acquired outside -// urb comes from dev's endpoint urb-list. it is already removed from -// the endpoint urb-list. -// -NTSTATUS -uhci_internal_submit_bulk(PUHCI_DEV uhci, PURB urb) -{ - - LONG max_packet_size, td_count, offset, bytes_to_transfer, data_load; - PBYTE start_addr; - PUHCI_TD ptd; - PUHCI_QH pqh; - LIST_ENTRY td_list, *pthis, *pnext; - BOOLEAN old_toggle, toggle, ret; - UCHAR pid; - - if (uhci == NULL || urb == NULL) - return STATUS_INVALID_PARAMETER; - - max_packet_size = endp_max_packet_size(urb->pendp); - if (urb->bytes_to_transfer == 0) - { - return STATUS_INVALID_PARAMETER; - } - - td_count = (urb->bytes_to_transfer + max_packet_size - 1) / max_packet_size; - - lock_td_pool(&uhci->td_pool, TRUE); - if (can_transfer(&uhci->td_pool, td_count) == FALSE) - { - unlock_td_pool(&uhci->td_pool, TRUE); - return STATUS_NO_MORE_ENTRIES; - } - - ptd = alloc_tds(&uhci->td_pool, td_count); - unlock_td_pool(&uhci->td_pool, TRUE); - - if (ptd == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - InitializeListHead(&td_list); - InsertTailList(&ptd->ptde->vert_link, &td_list); - - ListFirst(&td_list, pthis); - ListNext(&td_list, pthis, pnext); - - start_addr = &urb->data_buffer[urb->data_length - urb->rest_bytes]; - offset = 0; - - old_toggle = toggle = urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE ? TRUE : FALSE; - bytes_to_transfer = urb->bytes_to_transfer; - - urb->pipe = ((max_packet_size - 1) << 21) - | ((ULONG) endp_num(urb->pendp) << 15) - | (dev_from_endp(urb->pendp)->dev_addr << 8) - | ((ULONG) endp_dir(urb->pendp)) | USB_ENDPOINT_XFER_BULK; - - pid = (((ULONG) urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT); - while (pthis) - { - ptd = ((PTD_EXTENSION) pthis)->ptd; - - data_load = max_packet_size < bytes_to_transfer ? max_packet_size : bytes_to_transfer; - ptd->purb = urb; - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) - | (TD_CTRL_ACTIVE), - ((data_load - 1) << 21) - | (toggle << 19) - | ((ULONG) endp_num(urb->pendp) << 15) - | (dev_from_endp(urb->pendp)->dev_addr << 8) - | pid, MmGetPhysicalAddress(start_addr + offset).LowPart); - - bytes_to_transfer -= data_load; - offset += data_load; - - if (pnext) - { - ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr; - } - else - { - //Last one, enable ioc and short packet detect if necessary - ptd->link = UHCI_PTR_TERM; - ptd->status |= TD_CTRL_IOC; - if (bytes_to_transfer < max_packet_size && (pid == USB_PID_IN)) - { - //ptd->status |= TD_CTRL_SPD; - } - } - - pthis = pnext; - toggle ^= 1; - if (pthis) - ListNext(&td_list, pthis, pnext); - - } - - ListFirst(&td_list, pthis); - RemoveEntryList(&td_list); - - lock_qh_pool(&uhci->qh_pool, TRUE); - pqh = alloc_qh(&uhci->qh_pool); - unlock_qh_pool(&uhci->qh_pool, TRUE); - - if (pqh == NULL) - { - lock_td_pool(&uhci->td_pool, TRUE); - - if (pthis) - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - - unlock_td_pool(&uhci->td_pool, TRUE); - return STATUS_NO_MORE_ENTRIES; - - } - - urb->td_count = td_count; - - uhci_insert_tds_qh(pqh, ((PTD_EXTENSION) pthis)->ptd); - uhci_insert_qh_urb(urb, pqh); - urb->pendp->flags = - (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle ? USB_ENDP_FLAG_DATATOGGLE : 0); - usb_endp_busy_count_inc(urb->pendp); - uhci_insert_urb_to_schedule(uhci, urb, ret); - - if (ret == FALSE) - { - // undo all we have done - RemoveEntryList(&pqh->pqhe->vert_link); //remove qh from td_chain - RemoveEntryList(&urb->trasac_list); - - lock_td_pool(&uhci->td_pool, TRUE); - if (pthis) - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - - lock_qh_pool(&uhci->qh_pool, TRUE); - if (pqh) - free_qh(&uhci->qh_pool, pqh); - unlock_qh_pool(&uhci->qh_pool, TRUE); - - InitializeListHead(&urb->trasac_list); - usb_endp_busy_count_dec(urb->pendp); - urb->pendp->flags = - (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (old_toggle ? USB_ENDP_FLAG_DATATOGGLE : 0); - return STATUS_UNSUCCESSFUL; - } - return STATUS_SUCCESS; -} - -NTSTATUS -uhci_internal_submit_ctrl(PUHCI_DEV uhci, PURB urb) -{ - LIST_ENTRY td_list, *pthis, *pnext; - LONG i, td_count; - LONG toggle; - LONG max_packet_size, bytes_to_transfer, bytes_rest, start_idx; - PUHCI_TD ptd; - PUHCI_QH pqh; - ULONG dev_addr; - PUSB_DEV pdev; - BOOLEAN ret; - - if (uhci == NULL || urb == NULL) - return STATUS_INVALID_PARAMETER; - - toggle = 0; - bytes_rest = urb->rest_bytes; - bytes_to_transfer = urb->bytes_to_transfer; - max_packet_size = endp_max_packet_size(urb->pendp); - start_idx = urb->data_length - urb->rest_bytes; - td_count = 2 + (urb->bytes_to_transfer + max_packet_size - 1) / max_packet_size; - - lock_td_pool(&uhci->td_pool, TRUE); - - if (can_transfer(&uhci->td_pool, td_count) == FALSE) - { - unlock_td_pool(&uhci->td_pool, TRUE); - return STATUS_NO_MORE_ENTRIES; - } - - ptd = alloc_tds(&uhci->td_pool, td_count); - unlock_td_pool(&uhci->td_pool, TRUE); - - if (ptd == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - InsertTailList(&ptd->ptde->vert_link, &td_list); - - ListFirst(&td_list, pthis); - ListNext(&td_list, pthis, pnext); - - ptd = ((PTD_EXTENSION) pthis)->ptd; - - pdev = dev_from_endp(urb->pendp); - dev_addr = pdev->dev_addr; - - if (dev_state(pdev) <= USB_DEV_STATE_RESET) - dev_addr = 0; - - usb_dbg_print(DBGLVL_MAXIMUM, ("uhci_internal_submit_ctrl(): dev_addr =0x%x\n", dev_addr)); - - RtlCopyMemory(uhci->io_buf, urb->setup_packet, 8); - - if ((urb->setup_packet[0] & USB_DIR_IN) == 0) //out - RtlCopyMemory(&uhci->io_buf[8], urb->data_buffer, bytes_to_transfer); - else - RtlZeroMemory(&uhci->io_buf[8], bytes_to_transfer); - - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) | (TD_CTRL_ACTIVE), - (7 << 21) | (((ULONG) endp_num(urb->pendp)) << 15) | (dev_addr << 8) | (USB_PID_SETUP), - //uhci->io_buf_logic_addr.LowPart); - MmGetPhysicalAddress(urb->setup_packet).LowPart); - - ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr; - pthis = pnext; - ListNext(&td_list, pthis, pnext); - - urb->pipe = ((max_packet_size - 1) << 21) - | ((ULONG) endp_num(urb->pendp) << 15) - | (dev_addr << 8) | (pdev->flags & USB_DEV_FLAG_LOW_SPEED) | USB_ENDPOINT_XFER_CONTROL; - - for(i = 0, toggle = 1; ((i < td_count - 2) && pthis); i++, toggle ^= 1) - { - //construct tds for DATA packets of data stage. - ptd = ((PTD_EXTENSION) pthis)->ptd; - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) - | (TD_CTRL_ACTIVE), - ((bytes_to_transfer > - max_packet_size ? max_packet_size - 1 : bytes_to_transfer - - 1) << 21) | (toggle << 19) | (((ULONG) endp_num(urb-> - pendp)) << 15) | (dev_addr << 8) | - ((urb->setup_packet[0] & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT), - //uhci->io_buf_logic_addr.LowPart + 8 + i * max_packet_size ); - MmGetPhysicalAddress(&urb->data_buffer[start_idx + i * max_packet_size]).LowPart); - - if (pnext) - ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr; - - if (i < td_count - 3) - { - bytes_to_transfer -= max_packet_size; - } - else - { - if (bytes_to_transfer > 0) - { - if (bytes_to_transfer < max_packet_size && (urb->setup_packet[0] & USB_DIR_IN)) - ptd->status |= TD_CTRL_SPD; - } - } - pthis = pnext; - - if (pthis) - ListNext(&td_list, pthis, pnext); - } - - if (pnext) - ptd->link = ((PTD_EXTENSION) pnext)->ptd->phy_addr; - - ListFirstPrev(&td_list, pthis); - ptd = ((PTD_EXTENSION) pthis)->ptd; - - //the last is an IN transaction - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) - | (TD_CTRL_ACTIVE | TD_CTRL_IOC), - (UHCI_NULL_DATA_SIZE << 21) - | (1 << 19) - | (((ULONG) endp_num(urb->pendp)) << 15) - | (dev_addr << 8) - | ((td_count > 2) - ? ((urb->setup_packet[0] & USB_DIR_IN) ? USB_PID_OUT : USB_PID_IN) : USB_PID_IN), 0); - - ptd->link = UHCI_PTR_TERM; - - ListFirst(&td_list, pthis); - RemoveEntryList(&td_list); - - lock_qh_pool(&uhci->qh_pool, TRUE); - pqh = alloc_qh(&uhci->qh_pool); - unlock_qh_pool(&uhci->qh_pool, TRUE); - - if (pqh == NULL) - { - lock_td_pool(&uhci->td_pool, TRUE); - if (pthis) - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - - return STATUS_NO_MORE_ENTRIES; - } - - urb->td_count = td_count; - - uhci_insert_tds_qh(pqh, ((PTD_EXTENSION) pthis)->ptd); - uhci_insert_qh_urb(urb, pqh); - - usb_endp_busy_count_inc(urb->pendp); - uhci_insert_urb_to_schedule(uhci, urb, ret); - if (ret == FALSE) - { - RemoveEntryList(&pqh->pqhe->vert_link); - RemoveEntryList(&urb->trasac_list); - - lock_td_pool(&uhci->td_pool, TRUE); - if (pthis) - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - - lock_qh_pool(&uhci->qh_pool, TRUE); - if (pqh) - free_qh(&uhci->qh_pool, pqh); - unlock_qh_pool(&uhci->qh_pool, TRUE); - - InitializeListHead(&urb->trasac_list); - usb_endp_busy_count_dec(urb->pendp); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -uhci_internal_submit_int(PUHCI_DEV uhci, PURB urb) -{ - LONG i; - LONG toggle = 0; - LONG max_packet_size; - PUHCI_TD ptd; - BOOLEAN ret; - - if (uhci == NULL || urb == NULL) - { - uhci_dbg_print(DBGLVL_MEDIUM, - ("uhci_internal_submit_int(): uhci=0x%x, urb=0x%x " - "returning STATUS_INVALID_PARAMETER!\n", uhci, urb)); - return STATUS_INVALID_PARAMETER; - } - - toggle = (urb->pendp->flags & USB_ENDP_FLAG_DATATOGGLE) ? TRUE : FALSE; - max_packet_size = endp_max_packet_size(urb->pendp); - - if (max_packet_size < urb->data_length || max_packet_size == 0 || max_packet_size > 64) - { - uhci_dbg_print(DBGLVL_MEDIUM, - ("uhci_internal_submit_int(): max_packet_size=%d, urb->data_length=%d " - "returning STATUS_INVALID_PARAMETER!\n", max_packet_size, urb->data_length)); - return STATUS_INVALID_PARAMETER; - } - - lock_td_pool(&uhci->td_pool, TRUE); - ptd = alloc_td(&uhci->td_pool); - unlock_td_pool(&uhci->td_pool, TRUE); - - if (ptd == NULL) - return STATUS_NO_MORE_ENTRIES; - - for(i = 1; i <= 7; i++) - { - if (((ULONG) max_packet_size) >> i) - continue; - else - break; - } - - i--; - i &= 7; - - urb->pipe = (((ULONG) urb->pendp->pusb_endp_desc->bInterval) << 24) - | (i << 21) - | (toggle << 19) - | ((ULONG) endp_num(urb->pendp) << 15) - | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8) - | USB_DIR_IN | (dev_from_endp(urb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) | USB_ENDPOINT_XFER_INT; - - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) - | (TD_CTRL_ACTIVE) - | ((urb->data_length < max_packet_size ? TD_CTRL_SPD : 0)) - | (TD_CTRL_IOC), - (((ULONG) max_packet_size - 1) << 21) - | (toggle << 19) - | ((ULONG) endp_num(urb->pendp) << 15) - | (((ULONG) dev_from_endp(urb->pendp)->dev_addr & 0x7f) << 8) - | USB_PID_IN, MmGetPhysicalAddress(urb->data_buffer).LowPart); - - toggle ^= 1; - urb->td_count = 1; - - InitializeListHead(&urb->trasac_list); - InsertTailList(&urb->trasac_list, &ptd->ptde->vert_link); - - //indirectly guarded by pending_endp_list_lock - if (uhci_claim_bandwidth(uhci, urb, TRUE) == FALSE) - { - InitializeListHead(&urb->trasac_list); - - lock_td_pool(&uhci->td_pool, TRUE); - free_td(&uhci->td_pool, ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - - return STATUS_NO_MORE_ENTRIES; - } - - urb->pendp->flags = (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | (toggle << 31); - usb_endp_busy_count_inc(urb->pendp); - - uhci_insert_urb_to_schedule(uhci, urb, ret); - - if (ret == FALSE) - { - lock_td_pool(&uhci->td_pool, TRUE); - if (ptd) - free_td(&uhci->td_pool, ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - - InitializeListHead(&urb->trasac_list); - usb_endp_busy_count_dec(urb->pendp); - urb->pendp->flags = (urb->pendp->flags & ~USB_ENDP_FLAG_DATATOGGLE) | ((toggle ^ 1) << 31); - uhci_claim_bandwidth(uhci, urb, FALSE); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - - -NTSTATUS -uhci_internal_submit_iso(PUHCI_DEV uhci, PURB urb) -{ - PUHCI_TD ptd; - LIST_ENTRY td_list, *pthis, *pnext; - int i; - BOOLEAN toggle = FALSE, ret; - - if (uhci == NULL || urb == NULL) - return STATUS_INVALID_PARAMETER; - - if (urb->iso_frame_count == 0) - return STATUS_INVALID_PARAMETER; - - lock_td_pool(&uhci->td_pool, TRUE); - - if (can_transfer(&uhci->td_pool, urb->iso_frame_count) == FALSE) - { - unlock_td_pool(&uhci->td_pool, TRUE); - return STATUS_NO_MORE_ENTRIES; - } - - ptd = alloc_tds(&uhci->td_pool, urb->iso_frame_count); - unlock_td_pool(&uhci->td_pool, TRUE); - - if (ptd == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - InsertTailList(&ptd->ptde->vert_link, &td_list); - ListFirst(&td_list, pthis); - - urb->td_count = urb->iso_frame_count; - - urb->pipe = (((ULONG) urb->iso_packet_desc[0].length) << 21) - | ((ULONG) endp_num(urb->pendp) << 15) - | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8) - | ((ULONG) endp_dir(urb->pendp)) | USB_ENDPOINT_XFER_ISOC; - - - for(i = 0; i < urb->iso_frame_count && pthis; i++) - { - ptd = ((PTD_EXTENSION) pthis)->ptd; - uhci_fill_td(ptd, - (3 << TD_CTRL_C_ERR_SHIFT) - | (TD_CTRL_ACTIVE) - | (TD_CTRL_IOS), - (((ULONG) urb->iso_packet_desc[i].length - 1) << 21) - | (0 << 19) - | ((ULONG) endp_num(urb->pendp) << 15) - | (((ULONG) dev_from_endp(urb->pendp)->dev_addr) << 8) - | ((urb->pendp->pusb_endp_desc->bEndpointAddress & USB_DIR_IN) - ? USB_PID_OUT : USB_PID_IN), - MmGetPhysicalAddress(&urb->data_buffer[urb->iso_packet_desc[i].offset]).LowPart); - - toggle ^= 1; - ListNext(&td_list, pthis, pnext); - pthis = pnext; - } - - ptd->status |= TD_CTRL_IOC; //need interrupt - - ListFirst(&td_list, pthis); - RemoveEntryList(&td_list); - - InsertTailList(pthis, &urb->trasac_list); - - //indirectly guarded by pending_endp_list_lock - if (uhci_claim_bandwidth(uhci, urb, TRUE) == FALSE) - { - //bad news: we can not allocate the enough bandwidth for the urb - RemoveEntryList(&urb->trasac_list); - InitializeListHead(&urb->trasac_list); - - lock_td_pool(&uhci->td_pool, TRUE); - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - return STATUS_NO_MORE_ENTRIES; - - } - - usb_endp_busy_count_inc(urb->pendp); - uhci_insert_urb_to_schedule(uhci, urb, ret); - if (ret == FALSE) - { - usb_endp_busy_count_dec(urb->pendp); - RemoveEntryList(&urb->trasac_list); - - lock_td_pool(&uhci->td_pool, TRUE); - free_tds(&uhci->td_pool, ((PTD_EXTENSION) pthis)->ptd); - unlock_td_pool(&uhci->td_pool, TRUE); - uhci_claim_bandwidth(uhci, urb, FALSE); - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -// runs in uhci_isr -BOOLEAN -uhci_is_xfer_finished(PURB urb) -{ - PLIST_ENTRY pthis, pnext; - PUHCI_TD ptd; - BOOLEAN ret = TRUE; - PTD_EXTENSION ptde; - - if (urb->last_finished_td == NULL) - { - urb->last_finished_td = &urb->trasac_list; - } - - if (&urb->trasac_list == urb->last_finished_td) - ListFirst(&urb->trasac_list, pthis) - else - ListNext(&urb->trasac_list, urb->last_finished_td, pthis); - - while (pthis) - { - if ((((PTD_EXTENSION) pthis)->flags & UHCI_ITEM_FLAG_TYPE) != UHCI_ITEM_FLAG_TD) - { - ListNext(&urb->trasac_list, pthis, pnext); - pthis = pnext; - continue; - } - else - { - ptde = (PTD_EXTENSION) pthis; - ptd = ptde->ptd; - ASSERT(ptd != NULL); - - if (ptd->status & TD_CTRL_ACTIVE) - { - //still active - ret = FALSE; - break; - } - //let's see whether error occured - if ((ptd->status & TD_CTRL_ANY_ERROR) == 0) - { - urb->last_finished_td = pthis; - ListNext(&urb->trasac_list, pthis, pnext); - pthis = pnext; - continue; - } - else - { - urb->status = ptd->status; - pthis = NULL; - continue; - } - } - - } - - if (pthis == NULL) - ret = TRUE; - - return ret; -} - -// executed in isr, and have frame_list_lock acquired, so -// never try to acquire any spin-lock -// remove the bulk urb from schedule, and mark it not in -// the schedule -BOOLEAN -uhci_remove_urb_from_schedule(PUHCI_DEV uhci, PURB urb) -{ - BOOLEAN ret = FALSE; - { - switch (urb->pipe & USB_ENDPOINT_XFERTYPE_MASK) - { - case USB_ENDPOINT_XFER_BULK: - { - ret = uhci_remove_bulk_from_schedule(uhci, urb); - break; - } - case USB_ENDPOINT_XFER_CONTROL: - { - ret = uhci_remove_ctrl_from_schedule(uhci, urb); - break; - } - case USB_ENDPOINT_XFER_INT: - { - ret = uhci_remove_int_from_schedule(uhci, urb); - break; - } - case USB_ENDPOINT_XFER_ISOC: - { - ret = uhci_remove_iso_from_schedule(uhci, urb); - break; - } - } - } - return ret; -} - -// executed in isr, and have frame_list_lock acquired, so -// never try to acquire any spin-lock -// remove the bulk urb from schedule, and mark it not in -// the schedule -BOOLEAN -uhci_remove_bulk_from_schedule(PUHCI_DEV uhci, PURB urb) -{ - - PUHCI_QH pqh, pnext_qh, pprev_qh; - PLIST_ENTRY pthis, pnext, pprev; - LONG i; - - if (uhci == NULL || urb == NULL) - return FALSE; - - ListFirst(&urb->trasac_list, pthis); - pqh = ((PQH_EXTENSION) pthis)->pqh; - - ListFirst(&pqh->pqhe->hori_link, pnext); - ListFirstPrev(&pqh->pqhe->hori_link, pprev); - - if (pprev == NULL || pnext == NULL) - return FALSE; - - pnext_qh = struct_ptr(pnext, QH_EXTENSION, hori_link)->pqh; - pprev_qh = struct_ptr(pprev, QH_EXTENSION, hori_link)->pqh; - - if (pprev != pnext) - { - //not the last one - pprev_qh->link = pnext_qh->phy_addr; - } - else - { - //only two qhs in the list - for(i = 0; i < UHCI_MAX_SKELQHS; i++) - { - if (pprev_qh == uhci->skel_qh[i]) - { - break; - } - } - ASSERT(i < UHCI_MAX_SKELQHS - 1); - pprev_qh->link = uhci->skel_qh[i + 1]->phy_addr; - } - RemoveEntryList(&pqh->pqhe->hori_link); - - urb->flags &= ~URB_FLAG_IN_SCHEDULE; - - if ((urb->pipe & USB_DEV_FLAG_LOW_SPEED) == 0) - uhci_drop_fsbr(uhci); - - return TRUE; -} - -BOOLEAN -uhci_remove_iso_from_schedule(PUHCI_DEV uhci, PURB urb) -{ - PUHCI_TD ptd, pprev_td; - PLIST_ENTRY pthis, pnext, pprev; - int i, idx; - - if (uhci == NULL || urb == NULL) - return FALSE; - - ListFirst(&urb->trasac_list, pthis); - - for(i = 0; i < urb->iso_frame_count && pthis; i++) - { - ptd = ((PTD_EXTENSION) pthis)->ptd; - idx = (urb->iso_start_frame + i) & (UHCI_MAX_FRAMES - 1); - - ListFirstPrev(&ptd->ptde->hori_link, pprev); - - if (pprev == NULL) - return FALSE; - - if (pprev == &uhci->frame_list_cpu[idx].td_link) - { - uhci->frame_list[idx] = ptd->link; - } - else - { - pprev_td = struct_ptr(pprev, TD_EXTENSION, hori_link)->ptd; - pprev_td->link = ptd->link; - } - - RemoveEntryList(&ptd->ptde->hori_link); - ListNext(&urb->trasac_list, pthis, pnext); - pthis = pnext; - } - - urb->flags &= ~URB_FLAG_IN_SCHEDULE; - return TRUE; -} - -BOOLEAN -uhci_remove_int_from_schedule(PUHCI_DEV uhci, PURB urb) -{ - PUHCI_TD ptd, pnext_td, pprev_td; - PLIST_ENTRY pthis, pnext, pprev; - LONG i; - - if (uhci == NULL || urb == NULL) - return FALSE; - - ListFirst(&urb->trasac_list, pthis); - ptd = ((PTD_EXTENSION) pthis)->ptd; - ListFirst(&ptd->ptde->hori_link, pnext); - ListFirstPrev(&ptd->ptde->hori_link, pprev); - - if (pprev == NULL || pnext == NULL) - return FALSE; - - pnext_td = struct_ptr(pnext, TD_EXTENSION, hori_link)->ptd; - pprev_td = struct_ptr(pprev, TD_EXTENSION, hori_link)->ptd; - - if (pprev_td != pnext_td) - pprev_td->link = pnext_td->phy_addr; - else - { - //the last one - for(i = UHCI_MAX_SKELTDS - 2; i >= 0; i--) - { - //UHCI_MAX_SKELTDS -1 skel tds for int transfer - if (pprev_td == uhci->skel_td[i]) - break; - } - - ASSERT(i >= 0); - if (i == 0) - { - pprev_td->link = uhci->skel_qh[0]->phy_addr; - } - else - { - pprev_td->link = uhci->skel_td[i - 1]->phy_addr; - } - } - RemoveEntryList(&ptd->ptde->hori_link); - - urb->flags &= ~URB_FLAG_IN_SCHEDULE; - return TRUE; -} - -BOOLEAN -uhci_insert_tds_qh(PUHCI_QH pqh, PUHCI_TD td_chain) -{ - if (pqh == NULL || td_chain == NULL) - return FALSE; - - InsertTailList(&td_chain->ptde->vert_link, &pqh->pqhe->vert_link); - pqh->element = td_chain->phy_addr; - return TRUE; -} - -BOOLEAN -uhci_insert_qh_urb(PURB urb, PUHCI_QH qh_chain) -{ - if (urb == NULL || qh_chain == NULL) - return FALSE; - - InsertTailList(&qh_chain->pqhe->vert_link, &urb->trasac_list); - qh_chain->pqhe->purb = urb; - return TRUE; -} - -// must have dev_lock and frame_list_lock acquired -BOOLEAN -uhci_insert_urb_schedule(PUHCI_DEV uhci, PURB urb) -{ - PUHCI_QH pqh, pskel_qh, pnext_qh; - PUHCI_TD ptd, plast_td; - PLIST_ENTRY pthis, pnext; - int i; - - if (uhci == NULL || urb == NULL) - return FALSE; - - ListFirst(&urb->trasac_list, pthis); - if (pthis == NULL) - return FALSE; - - InsertTailList(&uhci->urb_list, &urb->urb_link); - - urb->flags &= ~URB_FLAG_STATE_MASK; - urb->flags |= URB_FLAG_STATE_IN_PROCESS | URB_FLAG_IN_SCHEDULE; - - - switch (endp_type(urb->pendp)) - { - case USB_ENDPOINT_XFER_CONTROL: - { - pqh = ((PQH_EXTENSION) pthis)->pqh; - - if ((dev_from_endp(urb->pendp)->flags & USB_DEV_FLAG_LOW_SPEED) == 0) - { - pskel_qh = uhci->skel_hs_control_qh; - pnext_qh = uhci->skel_bulk_qh; - } - else - { - pskel_qh = uhci->skel_ls_control_qh; - pnext_qh = uhci->skel_hs_control_qh; - } - - ListFirstPrev(&pskel_qh->pqhe->hori_link, pthis); - - if (pthis == NULL) - pthis = &pskel_qh->pqhe->hori_link; - - InsertTailList(&pskel_qh->pqhe->hori_link, &pqh->pqhe->hori_link); - pqh->link = pnext_qh->phy_addr; - struct_ptr(pthis, QH_EXTENSION, hori_link)->pqh->link = pqh->phy_addr; - - //full speed band reclaimation - if ((urb->pipe & USB_DEV_FLAG_LOW_SPEED) == 0) - { - uhci->fsbr_cnt++; - if (uhci->fsbr_cnt == 1) - { - uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr; - } - } - return TRUE; - } - case USB_ENDPOINT_XFER_BULK: - { - pqh = ((PQH_EXTENSION) pthis)->pqh; - - ListFirstPrev(&uhci->skel_bulk_qh->pqhe->hori_link, pthis); - - if (pthis == NULL) - pthis = &uhci->skel_bulk_qh->pqhe->hori_link; - - InsertTailList(&uhci->skel_bulk_qh->pqhe->hori_link, &pqh->pqhe->hori_link); - - pqh->link = uhci->skel_term_qh->phy_addr; - struct_ptr(pthis, QH_EXTENSION, hori_link)->pqh->link = pqh->phy_addr; - - //full speed band reclaimation - uhci->fsbr_cnt++; - if (uhci->fsbr_cnt == 1) - { - uhci->skel_term_qh->link = uhci->skel_hs_control_qh->phy_addr; - } - - return TRUE; - } - case USB_ENDPOINT_XFER_INT: - { - //bandwidth claim is done outside - ptd = ((PTD_EXTENSION) pthis)->ptd; - - get_int_idx(urb, i); - - ListFirstPrev(&uhci->skel_td[i]->ptde->hori_link, pthis); - if (pthis == NULL) - pthis = &uhci->skel_td[i]->ptde->hori_link; - - InsertTailList(&uhci->skel_td[i]->ptde->hori_link, &ptd->ptde->hori_link); - - if (i > 0) - { - ptd->link = uhci->skel_td[i - 1]->phy_addr; - } - else if (i == 0) - { - ptd->link = uhci->skel_qh[0]->phy_addr; - } - //finally link the previous td to this td - struct_ptr(pthis, TD_EXTENSION, hori_link)->ptd->link = ptd->phy_addr; - return TRUE; - } - case USB_ENDPOINT_XFER_ISOC: - { - - for(i = 0; i < urb->iso_frame_count; i++) - { - ptd = ((PTD_EXTENSION) pthis)->ptd; - InsertTailList(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link, - &ptd->ptde->hori_link); - - if (IsListEmpty(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link) == TRUE) - { - ptd->link = uhci->frame_list[(urb->iso_start_frame + i) & 0x3ff]; - uhci->frame_list[i] = ptd->phy_addr; - } - else - { - ListFirstPrev(&uhci->frame_list_cpu[(urb->iso_start_frame + i) & 0x3ff].td_link, pnext); - plast_td = struct_ptr(pnext, TD_EXTENSION, hori_link)->ptd; - ptd->link = plast_td->link; - plast_td->link = ptd->phy_addr; - } - - ListNext(&urb->trasac_list, pthis, pnext); - pthis = pnext; - } - return TRUE; - - } - } - return FALSE; -} - -//this function used as the KeSynchronizeExecution param to delegate control to uhci_insert_urb_schedule -BOOLEAN NTAPI -uhci_sync_insert_urb_schedule(PVOID context) -{ - PSYNC_PARAM sync_param; - PUHCI_DEV uhci; - PURB purb; - - sync_param = (PSYNC_PARAM) context; - if (sync_param == NULL) - return FALSE; - - uhci = sync_param->uhci; - purb = (PURB) sync_param->context; - - if (uhci == NULL || purb == NULL) - return (UCHAR) (sync_param->ret = FALSE); - - return (UCHAR) (sync_param->ret = uhci_insert_urb_schedule(uhci, purb)); -} - -// be sure pending_endp_list_lock acquired -BOOLEAN -uhci_claim_bandwidth(PUHCI_DEV uhci, - PURB urb, - BOOLEAN claim_bw //true to claim bandwidth, false to free bandwidth - ) -{ - - UCHAR type; - BOOLEAN ls, can_alloc; - LONG bus_time, us; - LONG i, idx, j, start_frame, interval; - - if (urb == NULL) - return FALSE; - - can_alloc = TRUE; - - type = (UCHAR) (urb->pipe & USB_ENDPOINT_XFERTYPE_MASK); - if (type == USB_ENDPOINT_XFER_BULK || type == USB_ENDPOINT_XFER_CONTROL) - { - return FALSE; - } - - ls = (urb->pipe & USB_DEV_FLAG_LOW_SPEED) ? TRUE : FALSE; - - if (type == USB_ENDPOINT_XFER_INT) - { - start_frame = 0; - i = urb->data_length; - bus_time = usb_calc_bus_time(ls, FALSE, FALSE, i); - us = ns_to_us(bus_time); - - i = (urb->pipe >> 24); //polling interval - - for(interval = 0, j = 0; j < 8; j++) - { - if (i & (1 << j)) - { - interval = j; - } - } - - interval = 1 << interval; - start_frame = interval - 1; - - if (claim_bw) - { - - for(idx = 0; idx < UHCI_MAX_FRAMES; idx += interval) - { - if (uhci->frame_bw[idx] < us) - { - can_alloc = FALSE; - break; - } - } - - if (!can_alloc) - { - return FALSE; - } - - for(idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval) - { - uhci->frame_bw[idx] -= us; - } - } - else - { - for(idx = start_frame; idx < UHCI_MAX_FRAMES; idx += interval) - { - uhci->frame_bw[idx] += us; - } - } - - } - else if (type == USB_ENDPOINT_XFER_ISOC) - { - if (claim_bw) - { - for(i = 0; i < urb->iso_frame_count; i++) - { - bus_time = usb_calc_bus_time(FALSE, - (urb->pipe & USB_DIR_IN) - ? TRUE : FALSE, TRUE, urb->iso_packet_desc[i].length); - - urb->iso_packet_desc[i].bus_time = ns_to_us(bus_time); - } - - for(i = 0; i < urb->iso_frame_count; i++) - { - if (uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] < urb->iso_packet_desc[i].bus_time) - { - can_alloc = FALSE; - break; - } - } - - if (!can_alloc) - { - return FALSE; - } - - for(i = 0; i < urb->iso_frame_count; i++) - { - uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] -= urb->iso_packet_desc[i].bus_time; - } - } - else - { - for(i = 0; i < urb->iso_frame_count; i++) - { - uhci->frame_bw[(urb->iso_start_frame + i) & 0x3ff] += urb->iso_packet_desc[i].bus_time; - } - } - - } - - return TRUE; -} - - -//cancel a single urb -BOOLEAN NTAPI -uhci_sync_cancel_urb(PVOID context) -{ - PUHCI_DEV uhci; - PSYNC_PARAM sync_param; - PURB purb2, dest_urb; - PLIST_ENTRY pthis, pnext; - BOOLEAN found = FALSE; - - if (context == NULL) - return FALSE; - - sync_param = (PSYNC_PARAM) context; - uhci = sync_param->uhci; - dest_urb = (PURB) sync_param->context; - - if (uhci == NULL || dest_urb == NULL) - return (UCHAR) (sync_param->ret = FALSE); - - ListFirst(&uhci->urb_list, pthis); - while (pthis) - { - purb2 = (PURB) pthis; - if (purb2 == dest_urb) - { - found = TRUE; - purb2->flags |= URB_FLAG_FORCE_CANCEL; - break; - } - ListNext(&uhci->urb_list, pthis, pnext); - pthis = pnext; - } - if (found) - uhci->skel_term_td->status |= TD_CTRL_IOC; - - return (UCHAR) (sync_param->ret = found); -} - -//note any fields of the purb can not be referenced unless it is found in some queue -NTSTATUS -uhci_cancel_urb(PUHCI_DEV uhci, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - PLIST_ENTRY pthis, pnext; - BOOLEAN found; - PURB purb2; - - SYNC_PARAM sync_param; - - USE_BASIC_NON_PENDING_IRQL; - - if (uhci == NULL || purb == NULL || pdev == NULL || pendp == NULL) - return STATUS_INVALID_PARAMETER; - - lock_dev(pdev, FALSE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - //delegate to remove device for this job - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - if (dev_from_endp(pendp) != pdev) - { - unlock_dev(pdev, FALSE); - return STATUS_INVALID_PARAMETER; - } - - if (endp_state(pendp) == USB_ENDP_FLAG_STALL) - { - //it will be canceled in uhci_process_pending_endp - unlock_dev(pdev, FALSE); - return USB_STATUS_ENDPOINT_HALTED; - } - - found = FALSE; - ListFirst(&pendp->urb_list, pthis); - while (pthis) - { - purb2 = (PURB) pthis; - if (purb2 == purb) - { - found = TRUE; - RemoveEntryList(pthis); - InitializeListHead(pthis); - break; - } - ListNext(&pendp->urb_list, pthis, pnext); - pthis = pnext; - } - unlock_dev(pdev, FALSE); - - if (found) - { - purb->status = STATUS_CANCELLED; - - uhci_generic_urb_completion(purb, purb->context); - - lock_dev(pdev, FALSE); - pdev->ref_count--; - unlock_dev(pdev, FALSE); - return STATUS_SUCCESS; - } - - // search the urb in the urb-list and try to cancel - sync_param.uhci = uhci; - sync_param.context = purb; - - KeSynchronizeExecution(uhci->pdev_ext->uhci_int, uhci_sync_cancel_urb, &sync_param); - - found = (BOOLEAN) sync_param.ret; - - if (found) - return USB_STATUS_CANCELING; - - return STATUS_INVALID_PARAMETER; -} - -VOID -uhci_generic_urb_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - USE_NON_PENDING_IRQL; - - old_irql = KeGetCurrentIrql(); - if (old_irql > DISPATCH_LEVEL) - TRAP(); - - if (old_irql < DISPATCH_LEVEL) - KeRaiseIrql(DISPATCH_LEVEL, &old_irql); - - if (purb == NULL) - return; - - pdev = purb->pdev; - - if (pdev == NULL) - return; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - goto LBL_CLIENT_PROCESS; - } - if (usb_error(purb->status)) - { - pdev->error_count++; - } - - if (purb->pendp == &pdev->default_endp) - { - if (usb_halted(purb->status)) - { - pdev->time_out_count++; - if (pdev->time_out_count > 3) - { - dev_set_state(pdev, USB_DEV_STATE_ZOMB); - uhci_dbg_print(DBGLVL_MAXIMUM, - ("uhci_generic_urb_completion(): contiguous error 3 times, dev 0x%x is deactivated\n", - pdev)); - } - } - else - pdev->time_out_count = 0; - - } - unlock_dev(pdev, TRUE); - - LBL_CLIENT_PROCESS: - if (purb->completion) - purb->completion(purb, context); - - if (old_irql < DISPATCH_LEVEL) - KeLowerIrql(old_irql); - - return; -} - - -NTSTATUS -uhci_rh_submit_urb(PUSB_DEV pdev, PURB purb) -{ - PUSB_DEV_MANAGER dev_mgr; - PTIMER_SVC ptimer; - PUSB_CTRL_SETUP_PACKET psetup; - PUHCI_DEV uhci; - NTSTATUS status; - USHORT port_status; -#ifndef INCLUDE_EHCI - PHUB_EXTENSION hub_ext; -#else - PHUB2_EXTENSION hub_ext; -#endif - PUSB_PORT_STATUS ps, psret; - LONG i; - USE_NON_PENDING_IRQL; - - if (pdev == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - dev_mgr = dev_mgr_from_dev(pdev); - - KeAcquireSpinLock(&dev_mgr->timer_svc_list_lock, &old_irql); - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - uhci = uhci_from_hcd(pdev->hcd); - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - -#ifndef INCLUDE_EHCI - hub_ext = ((PHUB_EXTENSION) pdev->dev_ext); -#else - hub_ext = ((PHUB2_EXTENSION) pdev->dev_ext); -#endif - - switch (endp_type(purb->pendp)) - { - case USB_ENDPOINT_XFER_CONTROL: - { - if (psetup->bmRequestType == 0xa3 && psetup->bRequest == USB_REQ_GET_STATUS) - { - //get-port-status - if (psetup->wIndex == 0 || psetup->wIndex > 2 || psetup->wLength < 4) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - if (psetup->wIndex == 1) - { - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC1)); - ps = &hub_ext->rh_port1_status; - } - else - { - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC2)); - ps = &hub_ext->rh_port2_status; - } - - psret = (PUSB_PORT_STATUS) purb->data_buffer; - ps->wPortStatus = 0; - - if (status & USBPORTSC_CCS) - { - ps->wPortStatus |= USB_PORT_STAT_CONNECTION; - } - if (status & USBPORTSC_PE) - { - ps->wPortStatus |= USB_PORT_STAT_ENABLE; - } - if (status & USBPORTSC_PR) - { - ps->wPortStatus |= USB_PORT_STAT_RESET; - } - if (status & USBPORTSC_SUSP) - { - ps->wPortStatus |= USB_PORT_STAT_SUSPEND; - } - if (status & USBPORTSC_LSDA) - { - ps->wPortStatus |= USB_PORT_STAT_LOW_SPEED; - } - - //always power on - ps->wPortStatus |= USB_PORT_STAT_POWER; - - //now set change field - if (status & USBPORTSC_CSC) - { - ps->wPortChange |= USB_PORT_STAT_C_CONNECTION; - } - if (status & USBPORTSC_PEC) - { - ps->wPortChange |= USB_PORT_STAT_C_ENABLE; - } - - //don't touch other fields, will be filled by - //other function - - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): get port status, wPortStatus=0x%x, wPortChange=0x%x, address=0x%x\n", - ps->wPortStatus, ps->wPortChange, ps)); - - psret->wPortChange = ps->wPortChange; - psret->wPortStatus = ps->wPortStatus; - - purb->status = STATUS_SUCCESS; - - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_CLEAR_FEATURE) - { - //clear-port-feature - if (psetup->wIndex == 0 || psetup->wIndex > 2) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - if (psetup->wIndex == 1) - { - i = USBPORTSC1; - ps = &hub_ext->rh_port1_status; - } - else - { - i = USBPORTSC2; - ps = &hub_ext->rh_port2_status; - } - - purb->status = STATUS_SUCCESS; - switch (psetup->wValue) - { - case USB_PORT_FEAT_C_CONNECTION: - { - ps->wPortChange &= ~USB_PORT_STAT_C_CONNECTION; - SET_RH_PORTSTAT(i, USBPORTSC_CSC); - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): clear csc, port%d=0x%x\n", psetup->wIndex, - status)); - break; - } - case USB_PORT_FEAT_C_ENABLE: - { - ps->wPortChange &= ~USB_PORT_STAT_C_ENABLE; - SET_RH_PORTSTAT(i, USBPORTSC_PEC); - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): clear pec, port%d=0x%x\n", psetup->wIndex, - status)); - break; - } - case USB_PORT_FEAT_C_RESET: - { - ps->wPortChange &= ~USB_PORT_STAT_C_RESET; - //the reset signal is down in rh_timer_svc_reset_port_completion - //so enable the port here - status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): clear pr, enable pe, port%d=0x%x\n", - psetup->wIndex, status)); - break; - } - case USB_PORT_FEAT_ENABLE: - { - ps->wPortStatus &= ~USB_PORT_STAT_ENABLE; - CLR_RH_PORTSTAT(i, USBPORTSC_PE); - status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): clear pe, port%d=0x%x\n", psetup->wIndex, - status)); - break; - } - default: - purb->status = STATUS_UNSUCCESSFUL; - } - break; - } - else if (psetup->bmRequestType == 0xd3 && psetup->bRequest == HUB_REQ_GET_STATE) - { - // get bus state - if (psetup->wIndex == 0 || psetup->wIndex > 2 || psetup->wLength == 0) - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - - if (psetup->wIndex == 1) - { - i = USBPORTSC1; - } - else - { - i = USBPORTSC2; - } - port_status = READ_PORT_USHORT((PUSHORT)(uhci->port_base + i)); - purb->data_buffer[0] = (port_status & USBPORTSC_LS); - - // reverse the order - purb->data_buffer[0] ^= 0x3; - purb->status = STATUS_SUCCESS; - break; - } - else if (psetup->bmRequestType == 0x23 && psetup->bRequest == USB_REQ_SET_FEATURE) - { - //reset port - if (psetup->wValue != USB_PORT_FEAT_RESET) - { - purb->status = STATUS_INVALID_PARAMETER; - uhci_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): set feature with wValue=0x%x\n", psetup->wValue)); - break; - } - if (psetup->wIndex == 1) - { - i = USBPORTSC1; - } - else - { - i = USBPORTSC2; - } - - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - - ptimer->threshold = 0; // within [ 50ms, 60ms ], one tick is 10 ms - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_reset_port_completion; - - //start the timer - pdev->ref_count += 2; //one for timer and one for urb - - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, - ("uhci_rh_submit_urb(): reset port, port%d=0x%x\n", psetup->wIndex, status)); - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - purb->status = STATUS_PENDING; - } - else - { - purb->status = STATUS_INVALID_PARAMETER; - } - break; - } - case USB_ENDPOINT_XFER_INT: - { - ptimer = alloc_timer_svc(&dev_mgr->timer_svc_pool, 1); - if (!ptimer) - { - purb->status = STATUS_NO_MEMORY; - break; - } - - ptimer->threshold = RH_INTERVAL; - ptimer->context = (ULONG) purb; - ptimer->pdev = pdev; - ptimer->func = rh_timer_svc_int_completion; - - //start the timer - InsertTailList(&dev_mgr->timer_svc_list, &ptimer->timer_svc_link); - - usb_dbg_print(DBGLVL_ULTRA, - ("uhci_rh_submit_urb(): current rh's ref_count=0x%x\n", pdev->ref_count)); - pdev->ref_count += 2; //one for timer and one for urb - - purb->status = STATUS_PENDING; - break; - } - case USB_ENDPOINT_XFER_BULK: - case USB_ENDPOINT_XFER_ISOC: - default: - { - purb->status = STATUS_INVALID_PARAMETER; - break; - } - } - unlock_dev(pdev, FALSE); - KeReleaseSpinLock(&dev_mgr->timer_svc_list_lock, old_irql); - return purb->status; -} - -//must have rh dev_lock acquired -BOOLEAN -uhci_rh_reset_port(PHCD hcd, UCHAR port_idx) -{ - LONG i; - PUHCI_DEV uhci; - ULONG status; - - if (port_idx != 1 && port_idx != 2) - return FALSE; - - if (hcd == NULL) - return FALSE; - - if (port_idx == 1) - { - i = USBPORTSC1; - } - else - { - i = USBPORTSC2; - } - - uhci = uhci_from_hcd(hcd); - //assert the reset signal,(implicitly disable the port) - SET_RH_PORTSTAT(i, USBPORTSC_PR); - usb_wait_ms_dpc(50); - //clear the reset signal, delay port enable till clearing port feature - CLR_RH_PORTSTAT(i, USBPORTSC_PR); - usb_wait_us_dpc(10); - SET_RH_PORTSTAT(i, USBPORTSC_PE); - //recovery time 10ms - usb_wait_ms_dpc(10); - SET_RH_PORTSTAT(i, 0x0a); - - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + i)); - usb_dbg_print(DBGLVL_MAXIMUM, ("uhci_rh_reset_port(): status after written=0x%x\n", status)); - - return TRUE; -} - -NTSTATUS -uhci_dispatch_irp(IN PDEVICE_OBJECT DeviceObject, IN PIRP irp) -{ - PDEVICE_EXTENSION pdev_ext; - PUSB_DEV_MANAGER dev_mgr; - PUHCI_DEV uhci; - - pdev_ext = DeviceObject->DeviceExtension; - uhci = pdev_ext->uhci; - - dev_mgr = uhci->hcd_interf.hcd_get_dev_mgr(&uhci->hcd_interf); - return dev_mgr_dispatch(dev_mgr, irp); -} - -VOID NTAPI -uhci_unload(IN PDRIVER_OBJECT DriverObject) -{ - PDEVICE_OBJECT pdev; - PDEVICE_EXTENSION pdev_ext; - PUSB_DEV_MANAGER dev_mgr; - - pdev = DriverObject->DeviceObject; - - if (pdev == NULL) - return; - - pdev_ext = pdev->DeviceExtension; - if (pdev_ext == NULL) - return; - - dev_mgr = &g_dev_mgr; - if (dev_mgr == NULL) - return; - // - // set the termination flag - // - dev_mgr->term_flag = TRUE; - - // - // wake up the thread if it is - // - KeSetEvent(&dev_mgr->wake_up_event, 0, FALSE); - KeWaitForSingleObject(dev_mgr->pthread, Executive, KernelMode, TRUE, NULL); - ObDereferenceObject(dev_mgr->pthread); - dev_mgr->pthread = NULL; - // for( i = 0; i < dev_mgr->hcd_count; i++ ) - // dev_mgr->hcd_array[ i ]->hcd_release( dev_mgr->hcd_array[ i ]); - dev_mgr_release_hcd(dev_mgr); - - return; -} - -//the following are for hcd interface methods -VOID -uhci_set_dev_mgr(struct _HCD * hcd, PUSB_DEV_MANAGER dev_mgr) -{ - hcd->dev_mgr = dev_mgr; -} - -PUSB_DEV_MANAGER -uhci_get_dev_mgr(struct _HCD *hcd) -{ - return hcd->dev_mgr; -} - -ULONG -uhci_get_type(struct _HCD * hcd) -{ - return (hcd->flags & HCD_TYPE_MASK); -} - -VOID -uhci_set_id(struct _HCD * hcd, UCHAR id) -{ - hcd->flags &= ~HCD_ID_MASK; - hcd->flags |= (HCD_ID_MASK & id); -} - -UCHAR -uhci_get_id(struct _HCD *hcd) -{ - return (UCHAR) (hcd->flags & HCD_ID_MASK); -} - - -UCHAR -uhci_alloc_addr(struct _HCD * hcd) -{ - LONG i; - if (hcd == NULL) - return 0; - - for(i = 1; i < MAX_DEVS; i++) - { - if (hcd->dev_addr_map[i >> 3] & (1 << (i & 7))) - { - continue; - } - else - { - break; - } - } - - if (i >= MAX_DEVS) - return 0xff; - - hcd->dev_addr_map[i >> 3] |= (1 << (i & 7)); - hcd->conn_count++; - return (BYTE) i; -} - -VOID -uhci_free_addr(struct _HCD * hcd, UCHAR addr) -{ - if (addr & 0x80) - return; - - if (hcd == NULL) - return; - - hcd->dev_addr_map[addr >> 3] &= ~(1 << (addr & 7)); - return; - -} - -NTSTATUS -uhci_submit_urb2(struct _HCD * hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - return uhci_submit_urb(uhci_from_hcd(hcd), pdev, pendp, purb); -} - -PUSB_DEV -uhci_get_root_hub(struct _HCD * hcd) -{ - return uhci_from_hcd(hcd)->root_hub; -} - -VOID -uhci_set_root_hub(struct _HCD * hcd, PUSB_DEV root_hub) -{ - if (hcd == NULL || root_hub == NULL) - return; - uhci_from_hcd(hcd)->root_hub = root_hub; - return; -} - -BOOLEAN -uhci_remove_device2(struct _HCD * hcd, PUSB_DEV pdev) -{ - if (hcd == NULL || pdev == NULL) - return FALSE; - - return uhci_remove_device(uhci_from_hcd(hcd), pdev); -} - -BOOLEAN -uhci_hcd_release(struct _HCD * hcd) -{ - PUHCI_DEV uhci; - PDEVICE_EXTENSION pdev_ext; - - if (hcd == NULL) - return FALSE; - - - uhci = uhci_from_hcd(hcd); - pdev_ext = uhci->pdev_ext; - - return uhci_release(pdev_ext->pdev_obj, hcd->dev_mgr); -} - -NTSTATUS -uhci_cancel_urb2(struct _HCD * hcd, PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURB purb) -{ - PUHCI_DEV uhci; - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - - uhci = uhci_from_hcd(hcd); - return uhci_cancel_urb(uhci, pdev, pendp, purb); -} - -BOOLEAN -uhci_rh_get_dev_change(PHCD hcd, PBYTE buf) -{ - PUHCI_DEV uhci; - ULONG status; - - if (hcd == NULL || buf == NULL) - return FALSE; - - uhci = uhci_from_hcd(hcd); - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC1)); - usb_dbg_print(DBGLVL_ULTRA, ("uhci_rh_get_dev_change(): rh port1 status=0x%x\n", status)); - - if ((status & USBPORTSC_PEC) || (status & USBPORTSC_CSC)) - { - buf[0] |= (1 << 1); - } - - status = READ_PORT_USHORT((PUSHORT) (uhci->port_base + USBPORTSC2)); - usb_dbg_print(DBGLVL_ULTRA, ("uhci_rh_get_dev_change(): rh port2 status=0x%x\n", status)); - - if ((status & USBPORTSC_PEC) || (status & USBPORTSC_CSC)) - { - buf[0] |= (1 << 2); - } - return TRUE; -} - -NTSTATUS -uhci_dispatch(PHCD hcd, LONG disp_code, PVOID param) // locking depends on type of code -{ - if (hcd == NULL) - return FALSE; - - switch (disp_code) - { - case HCD_DISP_READ_PORT_COUNT: - { - if (param == NULL) - return STATUS_INVALID_PARAMETER; - *((PUCHAR) param) = 2; - return STATUS_SUCCESS; - } - case HCD_DISP_READ_RH_DEV_CHANGE: - { - if (uhci_rh_get_dev_change(hcd, param) == FALSE) - return STATUS_INVALID_PARAMETER; - return STATUS_SUCCESS; - } - } - - return STATUS_NOT_IMPLEMENTED; -} - -VOID -uhci_init_hcd_interface(PUHCI_DEV uhci) -{ - uhci->hcd_interf.hcd_set_dev_mgr = uhci_set_dev_mgr; - uhci->hcd_interf.hcd_get_dev_mgr = uhci_get_dev_mgr; - uhci->hcd_interf.hcd_get_type = uhci_get_type; - uhci->hcd_interf.hcd_set_id = uhci_set_id; - uhci->hcd_interf.hcd_get_id = uhci_get_id; - uhci->hcd_interf.hcd_alloc_addr = uhci_alloc_addr; - uhci->hcd_interf.hcd_free_addr = uhci_free_addr; - uhci->hcd_interf.hcd_submit_urb = uhci_submit_urb2; - uhci->hcd_interf.hcd_generic_urb_completion = uhci_generic_urb_completion; - uhci->hcd_interf.hcd_get_root_hub = uhci_get_root_hub; - uhci->hcd_interf.hcd_set_root_hub = uhci_set_root_hub; - uhci->hcd_interf.hcd_remove_device = uhci_remove_device2; - uhci->hcd_interf.hcd_rh_reset_port = uhci_rh_reset_port; - uhci->hcd_interf.hcd_release = uhci_hcd_release; - uhci->hcd_interf.hcd_cancel_urb = uhci_cancel_urb2; - uhci->hcd_interf.hcd_start = uhci_start; - uhci->hcd_interf.hcd_dispatch = uhci_dispatch; - - uhci->hcd_interf.flags = HCD_TYPE_UHCI; //hcd types | hcd id -} - -NTSTATUS NTAPI -generic_dispatch_irp(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - PDEVEXT_HEADER dev_ext; - - dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - - if (dev_ext && dev_ext->dispatch) - return dev_ext->dispatch(dev_obj, irp); - - irp->IoStatus.Information = 0; - - EXIT_DISPATCH(STATUS_UNSUCCESSFUL, irp); -} - - -VOID NTAPI -generic_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - PDEVEXT_HEADER dev_ext; - - KIRQL old_irql; - - IoAcquireCancelSpinLock(&old_irql); - if (irp != dev_obj->CurrentIrp || irp->Cancel) - { - IoReleaseCancelSpinLock(old_irql); - return; - } - else - { - (void)IoSetCancelRoutine(irp, NULL); - IoReleaseCancelSpinLock(old_irql); - } - - dev_ext = (PDEVEXT_HEADER) dev_obj->DeviceExtension; - - if (dev_ext && dev_ext->start_io) - { - dev_ext->start_io(dev_obj, irp); - return; - } - - irp->IoStatus.Information = 0; - irp->IoStatus.Status = STATUS_UNSUCCESSFUL; - - IoStartNextPacket(dev_obj, FALSE); - IoCompleteRequest(irp, IO_NO_INCREMENT); -} - -NTSTATUS -NTAPI -DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) -{ - NTSTATUS ntStatus = STATUS_SUCCESS; - -#if DBG - // should be done before any debug output is done. - // read our debug verbosity level from the registry - //NetacOD_GetRegistryDword( NetacOD_REGISTRY_PARAMETERS_PATH, //absolute registry path - // L"DebugLevel", // REG_DWORD ValueName - // &gDebugLevel ); // Value receiver - - // debug_level = DBGLVL_MAXIMUM; -#endif - - uhci_dbg_print_cond(DBGLVL_MINIMUM, DEBUG_UHCI, - ("Entering DriverEntry(), RegistryPath=\n %ws\n", RegistryPath->Buffer)); - - // Remember our driver object, for when we create our child PDO - usb_driver_obj = DriverObject; - - // - // Create dispatch points for create, close, unload - DriverObject->MajorFunction[IRP_MJ_CREATE] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = generic_dispatch_irp; - DriverObject->DriverUnload = uhci_unload; - - // User mode DeviceIoControl() calls will be routed here - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = generic_dispatch_irp; - - // User mode ReadFile()/WriteFile() calls will be routed here - DriverObject->MajorFunction[IRP_MJ_WRITE] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_READ] = generic_dispatch_irp; - - DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_SCSI] = generic_dispatch_irp; - DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = generic_dispatch_irp; - - DriverObject->DriverStartIo = generic_start_io; - // routines for handling system PNP and power management requests - //DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = generic_dispatch_irp; - - // The Functional Device Object (FDO) will not be created for PNP devices until - // this routine is called upon device plug-in. - RtlZeroMemory(&g_dev_mgr, sizeof(USB_DEV_MANAGER)); - g_dev_mgr.usb_driver_obj = DriverObject; - -#ifdef INCLUDE_EHCI - ehci_probe(DriverObject, RegistryPath, &g_dev_mgr); -#endif - - uhci_probe(DriverObject, RegistryPath, &g_dev_mgr); - - if (dev_mgr_strobe(&g_dev_mgr) == FALSE) - { - - dev_mgr_release_hcd(&g_dev_mgr); - return STATUS_UNSUCCESSFUL; - } - - dev_mgr_start_hcd(&g_dev_mgr); - - /* Wait till all drivers are initialized */ - ntStatus = KeWaitForSingleObject(&g_dev_mgr.drivers_inited, Executive, KernelMode, TRUE, NULL); - - uhci_dbg_print_cond(DBGLVL_DEFAULT, DEBUG_UHCI, ("DriverEntry(): exiting... (%x)\n", ntStatus)); - return STATUS_SUCCESS; -} - -//note: the initialization will be in the following order -// uhci_probe -// dev_mgr_strobe -// uhci_start - -// to kill dev_mgr_thread: -// dev_mgr->term_flag = TRUE; -// KeSetEvent( &dev_mgr->wake_up_event ); -// this piece of code must run at passive-level diff --git a/reactos/drivers/usb/nt4compat/usbdrv/uhciver.h b/reactos/drivers/usb/nt4compat/usbdrv/uhciver.h deleted file mode 100644 index 4ea9e812556..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/uhciver.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __UHCIVER_H__ -#define __UHCIVER_H__ - -//#define _MULTI_UHCI -//#define _TIANSHENG_DRIVER - -#ifdef _MULTI_UHCI -#define UHCI_VER_STR "m564.a\0" -#else -#define UHCI_VER_STR "0564.d\0" -#endif - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/umss.c b/reactos/drivers/usb/nt4compat/usbdrv/umss.c deleted file mode 100644 index 6014606620c..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/umss.c +++ /dev/null @@ -1,2230 +0,0 @@ -/** - * umss.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -#include -#include -#include - -#define UMSS_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \ -{\ - iRp->IoStatus.Status = staTUS;\ - if( staTUS != STATUS_PENDING)\ - {\ - IoCompleteRequest( iRp, IO_NO_INCREMENT);\ - return staTUS;\ - }\ - IoMarkIrpPending( iRp );\ - IoStartPacket( dev_OBJ, iRp, NULL, NULL ); \ - return STATUS_PENDING;\ -} - -#define UMSS_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \ -{\ - iRP->IoStatus.Status = staTUS;\ - if( staTUS != STATUS_PENDING )\ - {\ - IoStartNextPacket( dev_OBJ, FALSE );\ - IoCompleteRequest( iRP, IO_NO_INCREMENT );\ - }\ - return;\ -} - -extern VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp); - -NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName); - -NTSYSAPI -NTSTATUS -NTAPI -ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, - IN POBJECT_TYPE ObjectType OPTIONAL, - IN KPROCESSOR_MODE AccessMode, - IN OUT PACCESS_STATE AccessState OPTIONAL, - IN ACCESS_MASK DesiredAccess OPTIONAL, - IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle); - -VOID NTAPI umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp); -NTSTATUS umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp); -BOOLEAN umss_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -NTSTATUS umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp); -VOID umss_set_cfg_completion(PURB purb, PVOID pcontext); -VOID NTAPI umss_start_create_device(IN PVOID Parameter); -BOOLEAN umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if); -BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle); -NTSTATUS umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp); -VOID umss_load_class_driver(PVOID context); -BOOLEAN umss_tsc_to_sff(PIO_PACKET io_packet); -VOID umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK * srb); - -PDEVICE_OBJECT -umss_create_port_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - - // currently a port device is a connection point - // and upper driver use this to register itself - // with umss driver for future notification of - // pnp event. 2004-03-22 23:12:41 - CHAR dev_name[64]; - STRING string; - NTSTATUS status; - PDEVICE_OBJECT pdev; - UNICODE_STRING name_string, symb_link; - PUMSS_PORT_DEV_EXT pdev_ext; - - sprintf(dev_name, "\\Device\\usbPort_%d", (int)0); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&name_string, &string, TRUE); - pdev = NULL; - - status = IoCreateDevice(dev_mgr->usb_driver_obj, - sizeof(UMSS_PORT_DEV_EXT), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev); - - if (status == STATUS_SUCCESS) - { - // - // We do buffered io - // - pdev->Flags |= DO_BUFFERED_IO; - - pdev->Flags &= ~DO_DEVICE_INITIALIZING; - pdev->StackSize = 2; //one for fdo, one for file device obj - - pdev_ext = (PUMSS_PORT_DEV_EXT) pdev->DeviceExtension; - - pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV; - pdev_ext->dev_ext_hdr.dispatch = umss_port_dispatch_routine; - pdev_ext->dev_ext_hdr.start_io = NULL; - pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr; - pdev_ext->pdriver = pdriver; - - sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoCreateSymbolicLink(&symb_link, &name_string); - RtlFreeUnicodeString(&symb_link); - - } - - RtlFreeUnicodeString(&name_string); - return pdev; -} - -BOOLEAN -umss_delete_port_device(PDEVICE_OBJECT dev_obj) -{ - CHAR dev_name[64]; - STRING string; - UNICODE_STRING symb_link; - - if (dev_obj == NULL) - return FALSE; - - // remove the symbolic link - sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0); - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoDeleteSymbolicLink(&symb_link); - RtlFreeUnicodeString(&symb_link); - - if (dev_obj->ReferenceCount == 0) - { - IoDeleteDevice(dev_obj); - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_port_device(): port device object is removed\n")); - } - return TRUE; -} - -// FIXME!!! there can not be sent IOCTL_SUBMIT_URB_XXX while -// the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device. -// not resolved yet. -// 2004-03-22 23:12:26 -NTSTATUS -umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp) -{ - ULONG ctrl_code; - NTSTATUS status; - PIO_STACK_LOCATION irp_stack; - PUMSS_PORT_DEV_EXT pdev_ext; - PUMSS_DRVR_EXTENSION pdrvr_ext; - - if (pdev_obj == NULL || irp == NULL) - return STATUS_INVALID_PARAMETER; - - status = STATUS_SUCCESS; - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - - pdev_ext = (PUMSS_PORT_DEV_EXT) pdev_obj->DeviceExtension; - - switch (irp_stack->MajorFunction) - { - case IRP_MJ_INTERNAL_DEVICE_CONTROL: - { - switch (ctrl_code) - { - case IOCTL_REGISTER_DRIVER: - { - PCLASS_DRV_REG_INFO pcdri; - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CLASS_DRV_REG_INFO)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - pcdri = irp->AssociatedIrp.SystemBuffer; - if (pcdri->fdo_driver == NULL || pcdri->add_device == NULL || pcdri->pnp_dispatch == NULL) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext; - pdrvr_ext->class_driver_info.fdo_driver = pcdri->fdo_driver; - pdrvr_ext->class_driver_info.add_device = pcdri->add_device; - pdrvr_ext->class_driver_info.pnp_dispatch = pcdri->pnp_dispatch; - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_REVOKE_DRIVER: - { - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext; - pdrvr_ext->class_driver_info.fdo_driver = NULL; - pdrvr_ext->class_driver_info.add_device = NULL; - pdrvr_ext->class_driver_info.pnp_dispatch = NULL; - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - } - break; - } - case IRP_MJ_CREATE: - case IRP_MJ_CLOSE: - { - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - } - EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp); -} - -BOOLEAN -umss_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PUMSS_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //init driver structure, no PNP table functions - pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE; - pdriver->driver_desc.vendor_id = 0x0dd8; // USB Vendor ID - pdriver->driver_desc.product_id = 0x0003; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 1; // Configuration Value - pdriver->driver_desc.if_num = 1; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // Interface Class - pdriver->driver_desc.if_sub_class = 0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB Mass Storage driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_MASS_STORAGE; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION)); - if (!pdriver->driver_ext) return FALSE; - pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION)); - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext; - pdrvr_ext->dev_count = 0; - InitializeListHead(&pdrvr_ext->dev_list); - ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex); - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = umss_connect; - pdriver->disp_tbl.dev_disconnect = umss_disconnect; - pdriver->disp_tbl.dev_stop = umss_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL) - { - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - pdriver->disp_tbl.dev_connect = NULL; - pdriver->disp_tbl.dev_stop = NULL; - pdriver->disp_tbl.dev_disconnect = NULL; - return FALSE; - } - - umss_load_class_driver(NULL); - - // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 ); - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_init(): umss driver is initialized\n")); - return TRUE; -} - -BOOLEAN -umss_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PUMSS_DRVR_EXTENSION pdrvr_ext; - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext; - umss_delete_port_device(pdrvr_ext->port_dev_obj); - pdrvr_ext->port_dev_obj = NULL; - - ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE); - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_destroy(): umss driver is destroyed\n")); - return TRUE; -} - -PDEVICE_OBJECT -umss_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER umss_drvr, DEV_HANDLE dev_handle, BOOLEAN is_if) -{ - - CHAR dev_name[64], dev_id; - STRING string; - NTSTATUS status; - PDEVICE_OBJECT pdev; - UNICODE_STRING name_string, symb_link; - PUMSS_DRVR_EXTENSION pdrvr_ext; - PUMSS_DEVICE_EXTENSION pdev_ext; - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_create_device(): entering...\n")); - pdrvr_ext = (PUMSS_DRVR_EXTENSION) umss_drvr->driver_ext; - dev_id = (UCHAR) dev_id_from_handle(dev_handle); // pdrvr_ext->dev_count; - - if (is_if == FALSE) - sprintf(dev_name, "\\Device\\umssdev_%d", (int)dev_id); - else - sprintf(dev_name, "\\Device\\umssifdev_%d", (int)dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&name_string, &string, TRUE); - pdev = NULL; - - status = IoCreateDevice(dev_mgr->usb_driver_obj, - sizeof(UMSS_DEVICE_EXTENSION), - &name_string, - FILE_USB_DEV_TYPE, - 0, - TRUE, - &pdev); - - if (status == STATUS_SUCCESS) - { - // - // We do direct io - // - pdev->Flags |= DO_DIRECT_IO; - - pdev->Flags &= ~DO_DEVICE_INITIALIZING; - pdev->StackSize = 2; //one for fdo, one for file device obj - - pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev->DeviceExtension; - - //may be accessed by other thread - ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex); - InsertTailList(&pdrvr_ext->dev_list, &pdev_ext->dev_obj_link); - pdrvr_ext->dev_count++; - ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex); - - if (is_if) - pdev_ext->flags |= UMSS_DEV_FLAG_IF_DEV; - - pdev_ext->umss_dev_id = dev_id; - pdev_ext->pdo = pdev; - pdev_ext->dev_handle = dev_handle; - pdev_ext->dev_mgr = dev_mgr; - pdev_ext->pdriver = umss_drvr; - - pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV; - pdev_ext->dev_ext_hdr.dispatch = umss_dispatch_routine; - pdev_ext->dev_ext_hdr.start_io = umss_start_io; - pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr; - - if (is_if == FALSE) - sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)dev_id); - else - sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoCreateSymbolicLink(&symb_link, &name_string); - RtlFreeUnicodeString(&symb_link); - KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE); - KeInitializeSpinLock(&pdev_ext->dev_lock); - - } - RtlFreeUnicodeString(&name_string); - return pdev; -} - -BOOLEAN -umss_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle) -{ - PURB purb; - NTSTATUS status; - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdrvr; - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_connect(): entering...\n")); - - dev_mgr = param->dev_mgr; - pdrvr = param->pdriver; - - //directly set the configuration - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - return FALSE; - - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - - purb->endp_handle = dev_handle | 0xffff; - purb->data_buffer = NULL; - purb->data_length = 0; - purb->completion = umss_set_cfg_completion; - purb->context = dev_mgr; - purb->reference = (LONG) pdrvr; - psetup->bmRequestType = 0; - psetup->bRequest = USB_REQ_SET_CONFIGURATION; - psetup->wValue = 1; - psetup->wIndex = 0; - psetup->wLength = 0; - - status = usb_submit_urb(dev_mgr, purb); - if (status != STATUS_PENDING) - { - usb_free_mem(purb); - return FALSE; - } - return TRUE; -} - -VOID -umss_set_cfg_completion(PURB purb, PVOID pcontext) -{ - PUSB_CTRL_SETUP_PACKET psetup; - PUCHAR buf; - PWORK_QUEUE_ITEM pwork_item; - PUMSS_CREATE_DATA pcd; - DEV_HANDLE dev_handle; - NTSTATUS status; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdrvr; - - if (purb == NULL || pcontext == NULL) - return; - - dev_mgr = (PUSB_DEV_MANAGER) pcontext; - pdrvr = (PUSB_DRIVER) purb->reference; - dev_handle = purb->endp_handle & ~0xffff; - - - if (purb->status != STATUS_SUCCESS) - { - usb_free_mem(purb); - return; - } - - buf = usb_alloc_mem(NonPagedPool, 512); - if (buf == NULL) - { - usb_free_mem(purb); - return; - } - - //now let's get the descs, one configuration, one interface and two endpoint - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - purb->data_buffer = buf; - purb->data_length = 512; - purb->completion = NULL; //this is an immediate request, no needs completion - purb->context = dev_mgr; - purb->reference = 0; - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = USB_DT_CONFIG << 8; - psetup->wIndex = 0; - psetup->wLength = 512; - - status = usb_submit_urb(dev_mgr, purb); - if (status == STATUS_PENDING) - { - TRAP(); - } - usb_free_mem(purb); - purb = NULL; - - if (status != STATUS_SUCCESS) - { - usb_free_mem(buf); - buf = NULL; - return; - } - - pcd = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_CREATE_DATA)); - if (pcd == NULL) - { - usb_free_mem(buf); - buf = NULL; - return; - } - - pcd->desc_buf = buf; - pcd->dev_handle = dev_handle; - pcd->dev_mgr = dev_mgr; - pcd->pdriver = pdrvr; - pwork_item = (PWORK_QUEUE_ITEM) (&pcd[1]); - - ExInitializeWorkItem(pwork_item, umss_start_create_device, (PVOID) pcd); - ExQueueWorkItem(pwork_item, DelayedWorkQueue); -} - -VOID NTAPI -umss_start_create_device(IN PVOID Parameter) -{ - LONG i; - PUCHAR desc_buf; - NTSTATUS status; - PUSB_DEV pdev; - DEV_HANDLE dev_handle; - PUSB_DRIVER pdrvr; - PDEVICE_OBJECT pdev_obj; - PUSB_DEV_MANAGER dev_mgr; - PUMSS_CREATE_DATA pcd; - PUSB_INTERFACE_DESC pif_desc; - PUSB_ENDPOINT_DESC pendp_desc; - PUMSS_DEVICE_EXTENSION pdev_ext; - PUSB_CONFIGURATION_DESC pconfig_desc; - - USE_BASIC_NON_PENDING_IRQL; - - if (Parameter == NULL) - return; - - pcd = (PUMSS_CREATE_DATA) Parameter; - desc_buf = pcd->desc_buf; - dev_mgr = pcd->dev_mgr; - dev_handle = pcd->dev_handle; - pdrvr = pcd->pdriver; - usb_free_mem(pcd); - pcd = NULL; - - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (status != STATUS_SUCCESS) - { - usb_free_mem(desc_buf); - return; - } - - pdev_obj = umss_create_device(dev_mgr, pdrvr, dev_handle, FALSE); - - lock_dev(pdev, FALSE); - if (pdev_obj == NULL || - dev_state(pdev) == USB_DEV_STATE_ZOMB || - dev_mgr_set_driver(dev_mgr, dev_handle, pdrvr, pdev) == FALSE) - { - usb_free_mem(desc_buf); - unlock_dev(pdev, FALSE); - - if (pdev_obj) - umss_delete_device(dev_mgr, pdrvr, pdev_obj, FALSE); - - usb_unlock_dev(pdev); - return; - } - unlock_dev(pdev, FALSE); - - pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension; - - pdev_ext->desc_buf = desc_buf; - pdev_ext->pif_desc = NULL; - pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL; - - pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf; - pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]); - //search for our if - for(i = 0; ((UCHAR) i) < pconfig_desc->bNumInterfaces; i++) - { - if (pif_desc->bLength == sizeof(USB_INTERFACE_DESC) && pif_desc->bDescriptorType == USB_DT_INTERFACE) - { - if (pif_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE) - { - pdev_ext->pif_desc = pif_desc; - pdev_ext->if_idx = (UCHAR) i; - break; - } - else - { - if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE) - break; - } - } - else - { - break; - } - } - - if (pdev_ext->pif_desc) - { - pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1]; - for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++) - { - if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT - && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC)) - { - if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - { - pdev_ext->pint_endp_desc = pendp_desc; - pdev_ext->int_endp_idx = (UCHAR) i; - } - else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) - { - if (pendp_desc->bEndpointAddress & USB_DIR_IN) - { - pdev_ext->pin_endp_desc = pendp_desc; - pdev_ext->in_endp_idx = (UCHAR) i; - } - else - { - pdev_ext->pout_endp_desc = pendp_desc; - pdev_ext->out_endp_idx = (UCHAR) i; - } - } - pendp_desc = &pendp_desc[1]; - } - else - break; - } - } - usb_unlock_dev(pdev); - return; -} - -BOOLEAN -umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - UNREFERENCED_PARAMETER(dev_handle); - UNREFERENCED_PARAMETER(dev_mgr); - return TRUE; -} - -BOOLEAN -umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - PDEVICE_OBJECT dev_obj; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr; - - if (dev_mgr == NULL || dev_handle == 0) - return FALSE; - - pdev = NULL; - //special use of the lock dev, simply use this routine to get the dev - status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev); - if (pdev == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - // must be a bug - TRAP(); - usb_unlock_dev(pdev); - } - pdrvr = pdev->dev_driver; - dev_obj = pdev->dev_obj; - pdev = NULL; - - return umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE); -} - -VOID -umss_deferred_delete_device(PVOID context) -{ - PDEVICE_OBJECT dev_obj; - PUMSS_DEVICE_EXTENSION pdev_ext; - PUMSS_DRVR_EXTENSION pdrvr_ext; - LARGE_INTEGER interval; - - if (context == NULL) - return; - - dev_obj = (PDEVICE_OBJECT) context; - pdev_ext = dev_obj->DeviceExtension; - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext; - - interval.QuadPart = -20000; //two ms - - for(;;) - { - if (dev_obj->ReferenceCount) - KeDelayExecutionThread(KernelMode, TRUE, &interval); - else - { - KeDelayExecutionThread(KernelMode, TRUE, &interval); - if (dev_obj->ReferenceCount == 0) - break; - } - } - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_deferred_delete_device(): delete device, 0x%x\n", dev_obj)); - - ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex); - RemoveEntryList(&pdev_ext->dev_obj_link); - pdrvr_ext->dev_count--; - ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex); - - IoDeleteDevice(dev_obj); - return; -} - -BOOLEAN -umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if) -{ - CHAR dev_name[64]; - STRING string; - UNICODE_STRING symb_link; - PUMSS_DEVICE_EXTENSION pdev_ext; - PUMSS_DRVR_EXTENSION pdrvr_ext; - - if (dev_obj == NULL) - return FALSE; - - if (pdrvr == NULL || dev_mgr == NULL) - return FALSE; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension; - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext; - if (is_if == FALSE) - sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)pdev_ext->umss_dev_id); - else - sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)pdev_ext->umss_dev_id); - - RtlInitString(&string, dev_name); - RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE); - IoDeleteSymbolicLink(&symb_link); - RtlFreeUnicodeString(&symb_link); - - if (pdev_ext->desc_buf) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_device(): delete desc_buf\n")); - usb_free_mem(pdev_ext->desc_buf); - pdev_ext->desc_buf = NULL; - - } - - if (dev_obj->ReferenceCount == 0) - { - ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex); - RemoveEntryList(&pdev_ext->dev_obj_link); - pdrvr_ext->dev_count--; - ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex); - - IoDeleteDevice(dev_obj); - return TRUE; - } - - // - // FIXME: how if the driver unloading happens - // since this is called in dev_mgr_disconnect_dev, umss_schedule_workitem - // can not protect the USB_DEV object from be deleted. so the workitem - // can not access anything relative to the USB_DEV object. In this case - // we will tollerate the usb_query_and_lock_dev failure since it will - // never success when come to this point, and we won't pass dev_mgr - // and pdev to the function. But other scenarios, usb_query_and_lock_dev - // can not fail if dev_mgr and pdev are passed valid. - // When driver is unloading, don't know. Wish NT will unload the driver - // only when all the devices to the driver are deleted. - // - umss_schedule_workitem(dev_obj, umss_deferred_delete_device, NULL, 0); - return TRUE; -} - -VOID -umss_submit_io_packet(PDEVICE_OBJECT dev_obj, PIO_PACKET io_packet) -{ - NTSTATUS status; - PUMSS_DEVICE_EXTENSION pdev_ext; - PUSB_DEV pdev; - - pdev_ext = dev_obj->DeviceExtension; - - // lock the dev, the pdev_ext->pif_desc won't go away. - if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_start_io(): error, device is not valid\n")); - UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp); - return; - } - - if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY) - { - status = umss_bulkonly_startio(pdev_ext, io_packet); - } - else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB - || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI) - { - status = umss_cbi_startio(pdev_ext, io_packet); - } - else - { - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - usb_unlock_dev(pdev); - UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp); - return; -} - -VOID -NTAPI -umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp) -{ - ULONG ctrl_code; - NTSTATUS status; - PIO_STACK_LOCATION irp_stack; - PUMSS_DEVICE_EXTENSION pdev_ext; - IO_PACKET io_packet; - PUSER_IO_PACKET user_io_packet; - - if (dev_obj == NULL || irp == NULL) - return; - - status = STATUS_SUCCESS; - - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension; - - if (irp_stack->MajorFunction == IRP_MJ_SCSI) - { - umss_process_srb(dev_obj, irp); - return; - } - - if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL) - { - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp); - } - - switch (ctrl_code) - { - case IOCTL_UMSS_SUBMIT_CDB_IN: - case IOCTL_UMSS_SUBMIT_CDB_OUT: - case IOCTL_UMSS_SUBMIT_CDB: - { - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(USER_IO_PACKET)) - { - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - } - - user_io_packet = (PUSER_IO_PACKET) irp->AssociatedIrp.SystemBuffer; - - if (user_io_packet->sub_class != pdev_ext->pif_desc->bInterfaceSubClass) - { - // not agree with the dev's subclass - UMSS_COMPLETE_START_IO(dev_obj, STATUS_DEVICE_PROTOCOL_ERROR, irp); - } - - RtlZeroMemory(&io_packet, sizeof(io_packet)); - io_packet.cdb_length = user_io_packet->cdb_length; - io_packet.lun = user_io_packet->lun; - - RtlCopyMemory(io_packet.cdb, user_io_packet->cdb, MAX_CDB_LENGTH); - - if (ctrl_code == IOCTL_UMSS_SUBMIT_CDB_IN) - io_packet.flags |= USB_DIR_IN; - - if (ctrl_code != IOCTL_UMSS_SUBMIT_CDB) - { - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength == 0) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp); - - io_packet.data_buffer = MmGetSystemAddressForMdl(irp->MdlAddress); - io_packet.data_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength; - - if (io_packet.data_length > MAX_BULK_TRANSFER_LENGTH) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp); - - //synchronize the buffer - if (io_packet.flags & USB_DIR_IN) - KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE); - else - KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE); - } - - io_packet.pirp = irp; - umss_submit_io_packet(dev_obj, &io_packet); - return; - } - case IOCTL_SCSI_PASS_THROUGH: - { - PSCSI_PASS_THROUGH pass_through; - IO_PACKET io_packet; - - pass_through = irp->AssociatedIrp.SystemBuffer; - - if (pass_through->DataTransferLength && - pass_through->DataBufferOffset != sizeof(SCSI_PASS_THROUGH)) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - - if (pass_through->SenseInfoLength && - (pass_through->SenseInfoOffset != - pass_through->DataBufferOffset + pass_through->DataTransferLength)) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < - (sizeof(SCSI_PASS_THROUGH) + - pass_through->SenseInfoLength + pass_through->DataTransferLength)) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp); - - RtlZeroMemory(&io_packet, sizeof(io_packet)); - - io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER; - if (pass_through->DataIn) - io_packet.flags |= IOP_FLAG_DIR_IN; - - io_packet.data_buffer = (PVOID) & pass_through[1]; - io_packet.data_length = pass_through->DataTransferLength; - - if (pass_through->SenseInfoLength) - { - io_packet.sense_data = ((PUCHAR) pass_through) + pass_through->SenseInfoOffset; - io_packet.sense_data_length = pass_through->SenseInfoLength; - io_packet.flags |= IOP_FLAG_REQ_SENSE; - } - - io_packet.cdb_length = pass_through->CdbLength; - RtlCopyMemory(io_packet.cdb, pass_through->Cdb, sizeof(io_packet.cdb)); - io_packet.lun = 0; - io_packet.pirp = irp; - umss_submit_io_packet(dev_obj, &io_packet); - return; - } - case IOCTL_SCSI_PASS_THROUGH_DIRECT: - { - PSCSI_PASS_THROUGH_DIRECT pass_through_direct; - IO_PACKET io_packet; - - pass_through_direct = irp->AssociatedIrp.SystemBuffer; - - if (pass_through_direct->SenseInfoLength && - pass_through_direct->SenseInfoOffset != sizeof(SCSI_PASS_THROUGH_DIRECT)) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp); - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < - sizeof(SCSI_PASS_THROUGH_DIRECT) + pass_through_direct->SenseInfoLength) - UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp); - - RtlZeroMemory(&io_packet, sizeof(io_packet)); - - io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER; - if (pass_through_direct->DataIn) - io_packet.flags |= IOP_FLAG_DIR_IN; - - io_packet.data_buffer = pass_through_direct->DataBuffer; - io_packet.data_length = pass_through_direct->DataTransferLength; - - if (pass_through_direct->SenseInfoLength) - { - io_packet.sense_data = ((PUCHAR) pass_through_direct) + pass_through_direct->SenseInfoOffset; - io_packet.sense_data_length = pass_through_direct->SenseInfoLength; - io_packet.flags |= IOP_FLAG_REQ_SENSE; - } - - io_packet.cdb_length = pass_through_direct->CdbLength; - RtlCopyMemory(io_packet.cdb, pass_through_direct->Cdb, sizeof(io_packet.cdb)); - io_packet.lun = 0; - io_packet.pirp = irp; - umss_submit_io_packet(dev_obj, &io_packet); - return; - } - case IOCTL_SUBMIT_URB_RD: - case IOCTL_SUBMIT_URB_NOIO: - case IOCTL_SUBMIT_URB_WR: - { - gendrv_startio(dev_obj, irp); - return; - } - default: - UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp); - } - return; -} - -// bugbug!!! there can not be sent IOCTL_SUBMIT_URB_XXX while -// the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device. -// not resolved yet. -NTSTATUS -umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp) -{ - ULONG ctrl_code; - NTSTATUS status; - PIO_STACK_LOCATION irp_stack; - PUMSS_DEVICE_EXTENSION pdev_ext; - USE_BASIC_NON_PENDING_IRQL; - - if (pdev_obj == NULL || irp == NULL) - return STATUS_INVALID_PARAMETER; - - status = STATUS_SUCCESS; - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension; - - switch (irp_stack->MajorFunction) - { - case IRP_MJ_CREATE: - case IRP_MJ_CLOSE: - { - return dev_mgr_dispatch(pdev_ext->dev_mgr, irp); - } - case IRP_MJ_INTERNAL_DEVICE_CONTROL: - { - // function code to receive scsi request - UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp); - } - case IRP_MJ_DEVICE_CONTROL: - { - switch (ctrl_code) - { - case IOCTL_UMSS_SET_FDO: - { - PDEVICE_OBJECT fdo; - PUSB_DEV pdev; - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PDEVICE_OBJECT)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - fdo = (PDEVICE_OBJECT) ((PULONG) irp->AssociatedIrp.SystemBuffer)[0]; - if (fdo == NULL) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - // - // we have to test the usb dev's state to determine whether set or not the fdo - // - - if (usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev) != - STATUS_SUCCESS) - EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp); - - lock_dev(pdev, FALSE); - - if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB || dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp); - } - - pdev_ext->fdo = fdo; - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - irp->IoStatus.Information = 0; - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - - case IOCTL_GET_DEV_DESC: - { - PGET_DEV_DESC_REQ pgddr; - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - pgddr = irp->AssociatedIrp.SystemBuffer; - if (pgddr->dev_handle != (pdev_ext->dev_handle & 0xffff0000)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - // an immediate request - return dev_mgr_dispatch(pdev_ext->dev_mgr, irp); - } - case IOCTL_SUBMIT_URB_RD: - case IOCTL_SUBMIT_URB_NOIO: - case IOCTL_SUBMIT_URB_WR: - { - PURB purb; - DEV_HANDLE endp_handle; - - if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB)) - { - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - - purb = (PURB) irp->AssociatedIrp.SystemBuffer; - endp_handle = purb->endp_handle; - if (!default_endp_handle(endp_handle)) - { - //no permit to other interface if interface dev - if ((pdev_ext->flags & UMSS_DEV_FLAG_IF_DEV) - && if_idx_from_handle(endp_handle) != pdev_ext->if_idx) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - } - // FIXME: this is dangeous - // return dev_mgr_dispatch( pdev_ext->dev_mgr, irp ); - UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp); - } - case IOCTL_GET_DEV_HANDLE: - { - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG)) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - - *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle; - irp->IoStatus.Information = sizeof(LONG); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - - // - // request from scsi class driver - // - case IOCTL_SCSI_PASS_THROUGH: - case IOCTL_SCSI_PASS_THROUGH_DIRECT: - // - // direct cdb request - // - case IOCTL_UMSS_SUBMIT_CDB: - case IOCTL_UMSS_SUBMIT_CDB_OUT: - case IOCTL_UMSS_SUBMIT_CDB_IN: - { - UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp); - } - case IOCTL_SCSI_GET_INQUIRY_DATA: - { - PSCSI_ADAPTER_BUS_INFO adapter_info; - PSCSI_BUS_DATA bus_data; - PSCSI_INQUIRY_DATA inq_dat; - PINQUIRYDATA inq; - IO_PACKET io_packet; - ULONG required_size; - - required_size = sizeof(SCSI_ADAPTER_BUS_INFO) - + sizeof(SCSI_BUS_DATA) + sizeof(SCSI_INQUIRY_DATA) + INQUIRYDATABUFFERSIZE; - - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < required_size) - UMSS_EXIT_DISPATCH(pdev_obj, STATUS_BUFFER_TOO_SMALL, irp); - - RtlZeroMemory(&io_packet, sizeof(io_packet)); - - adapter_info = irp->AssociatedIrp.SystemBuffer; - adapter_info->NumberOfBuses = 1; - bus_data = &adapter_info->BusData[0]; - bus_data->NumberOfLogicalUnits = 1; - bus_data->InitiatorBusId = 0; - bus_data->InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO); - inq_dat = (PVOID) & bus_data[1]; - inq_dat->PathId = 0; - inq_dat->TargetId = pdev_ext->umss_dev_id; - // - // this is the dev_id for usb dev_manager - // - inq_dat->Lun = (UCHAR) (pdev_ext->dev_handle >> 16); - inq_dat->DeviceClaimed = FALSE; - inq_dat->InquiryDataLength = 36; - inq_dat->NextInquiryDataOffset = 0; - inq = (PINQUIRYDATA) inq_dat->InquiryData; - - RtlZeroMemory(inq, sizeof(INQUIRYDATA)); - inq->DeviceType = DIRECT_ACCESS_DEVICE; - inq->DeviceTypeQualifier = 0; - inq->RemovableMedia = 1; - - // - // pretend to comply scsi primary 2 command set - // - - inq->Versions = 0x04; - - // - // the format is in scsi-2 format - // - - inq->ResponseDataFormat = 0x02; - - // - // we are the poor scsi device - // - - inq->AdditionalLength = 31; - inq->SoftReset = 0; - inq->CommandQueue = 0; - inq->LinkedCommands = 0; - inq->RelativeAddressing = 0; - RtlCopyMemory(&inq->VendorId, "Unknown", 7); - RtlCopyMemory(&inq->ProductId, "USB Mass Storage", 16); - irp->IoStatus.Information = required_size; - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_SCSI_GET_CAPABILITIES: - { - PIO_SCSI_CAPABILITIES port_cap; - - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < - sizeof(IO_SCSI_CAPABILITIES)) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - - port_cap = (PIO_SCSI_CAPABILITIES) irp->AssociatedIrp.SystemBuffer; - port_cap->Length = sizeof(IO_SCSI_CAPABILITIES); - port_cap->MaximumTransferLength = 65536; - port_cap->MaximumPhysicalPages = 65536 / PAGE_SIZE; - port_cap->SupportedAsynchronousEvents = 0; - port_cap->AlignmentMask = 0x10; - port_cap->TaggedQueuing = FALSE; - port_cap->AdapterScansDown = FALSE; - port_cap->AdapterUsesPio = FALSE; - irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_SCSI_GET_ADDRESS: - { - PSCSI_ADDRESS paddr; - if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SCSI_ADDRESS)) - EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp); - - paddr = (PSCSI_ADDRESS) irp->AssociatedIrp.SystemBuffer; - - paddr->Length = sizeof(SCSI_ADDRESS); - paddr->PortNumber = 0; - paddr->PathId = 0; - paddr->TargetId = pdev_ext->umss_dev_id; - paddr->Lun = (UCHAR) (pdev_ext->dev_handle >> 16); - irp->IoStatus.Information = sizeof(SCSI_ADDRESS); - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - case IOCTL_SCSI_RESCAN_BUS: - { - irp->IoStatus.Information = 0; - EXIT_DISPATCH(STATUS_SUCCESS, irp); - } - default: - { - EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp); - } - } - } - } - EXIT_DISPATCH(STATUS_NOT_SUPPORTED, irp); -} - -VOID -umss_reset_pipe_completion(PURB purb, PVOID context) -{ - PUMSS_DEVICE_EXTENSION pdev_ext; - if (context == NULL) - return; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) context; - pdev_ext->reset_pipe_status = purb->status; - KeSetEvent(&pdev_ext->sync_event, 0, FALSE); - return; -} - -//can only be called at passive level -NTSTATUS -umss_reset_pipe(PUMSS_DEVICE_EXTENSION pdev_ext, DEV_HANDLE endp_handle) -{ - NTSTATUS status; - PUSB_DEV pdev; - - if (pdev_ext == NULL) - return STATUS_INVALID_PARAMETER; - - status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev); - - if (status != STATUS_SUCCESS) - return STATUS_UNSUCCESSFUL; - - status = usb_reset_pipe_ex(pdev_ext->dev_mgr, endp_handle, umss_reset_pipe_completion, pdev_ext); - - if (status == STATUS_PENDING) - { - KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL); - status = pdev_ext->reset_pipe_status; - } - usb_unlock_dev(pdev); - return status; -} - -BOOLEAN -umss_gen_result_srb(PIO_PACKET io_packet, PSCSI_REQUEST_BLOCK srb, NTSTATUS status) -{ - - if (srb == NULL || io_packet == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - PULONG dest_buf, src_buf; - ULONG i; - - srb->SrbStatus = SRB_STATUS_SUCCESS; - - io_packet->pirp->IoStatus.Information = srb->DataTransferLength; - if ((io_packet->pirp->Flags & IRP_READ_OPERATION) && !(io_packet->pirp->Flags & IRP_PAGING_IO)) - { - src_buf = (PULONG) io_packet->data_buffer; - dest_buf = (PULONG) srb->DataBuffer; - if (src_buf && dest_buf) - { - for(i = 0; i < (srb->DataTransferLength >> 2); i++) - { - dest_buf[i] = src_buf[i]; - } - } - } - } - else if (status == STATUS_DEVICE_DOES_NOT_EXIST) - { - PSENSE_DATA sense_buf; - srb->SrbStatus = SRB_STATUS_NO_DEVICE; - srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; - - // - // let's build the srb status for class driver - // - - srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; - sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer; - - if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) - { - RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength); - sense_buf->ErrorCode = 0x70; - sense_buf->Valid = 1; - sense_buf->SenseKey = SCSI_SENSE_NOT_READY; - sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE; - sense_buf->AdditionalSenseLength = 10; - } - } - else if (status == USB_STATUS_STALL_PID || status == USB_STATUS_CRC || - status == USB_STATUS_BTSTUFF || status == USB_STATUS_DATA_OVERRUN) - { - PSENSE_DATA sense_buf; - srb->SrbStatus = SRB_STATUS_ERROR; - srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; - - srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; - sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer; - - if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) - { - RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength); - sense_buf->ErrorCode = 0x70; - sense_buf->Valid = 1; - sense_buf->SenseKey = SCSI_SENSE_HARDWARE_ERROR; - sense_buf->AdditionalSenseCode = 0; - sense_buf->AdditionalSenseLength = 10; - } - } - else - { - srb->SrbStatus = SRB_STATUS_ERROR; - } - - if ((io_packet->pirp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION)) - && !(io_packet->pirp->Flags & IRP_PAGING_IO)) - { - if (io_packet->data_buffer) - { - usb_free_mem(io_packet->data_buffer); - io_packet->data_buffer = NULL; - } - } - return TRUE; -} - -BOOLEAN -umss_gen_result_ctrl(PDEVICE_OBJECT dev_obj, PIRP irp, NTSTATUS status) -{ - PIO_STACK_LOCATION irp_stack; - ULONG ctrl_code; - PUMSS_DEVICE_EXTENSION pdev_ext; - - if (irp == NULL) - return FALSE; - - irp->IoStatus.Information = 0; - irp_stack = IoGetCurrentIrpStackLocation(irp); - ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode; - pdev_ext = dev_obj->DeviceExtension; - - switch (ctrl_code) - { - case IOCTL_SCSI_PASS_THROUGH: - { - PSCSI_PASS_THROUGH pass_through; - pass_through = irp->AssociatedIrp.SystemBuffer; - irp->IoStatus.Status = status; - - // we have set these two value in bulkonly.c when data transfer complete - // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length; - // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length; - - if (status == STATUS_SUCCESS) - irp->IoStatus.Information = pass_through->SenseInfoOffset + pass_through->SenseInfoLength; - else - pass_through->ScsiStatus = SCSISTAT_CHECK_CONDITION; - return TRUE; - } - case IOCTL_SCSI_PASS_THROUGH_DIRECT: - { - PSCSI_PASS_THROUGH_DIRECT pass_through_direct; - - pass_through_direct = irp->AssociatedIrp.SystemBuffer; - pass_through_direct->ScsiStatus = 0; - irp->IoStatus.Status = status; - - // we have set these two value in bulkonly.c when data transfer complete - // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length; - // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length; - - if (status == STATUS_SUCCESS) - irp->IoStatus.Information = - pass_through_direct->SenseInfoOffset + pass_through_direct->SenseInfoLength; - else - pass_through_direct->ScsiStatus = SCSISTAT_CHECK_CONDITION; - - return TRUE; - } - } - return FALSE; -} - - -VOID -umss_complete_request(PUMSS_DEVICE_EXTENSION pdev_ext, NTSTATUS status) -{ - PIRP pirp; - KIRQL old_irql; - - PDEVICE_OBJECT dev_obj; - PIO_STACK_LOCATION irp_stack; - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): entering...\n")); - - pirp = pdev_ext->io_packet.pirp; - dev_obj = pdev_ext->pdo; - - irp_stack = IoGetCurrentIrpStackLocation(pirp); - - if (pdev_ext->io_packet.flags & IOP_FLAG_SRB_TRANSFER) - { - if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I) - { - umss_fix_sff_result(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb); - } - umss_gen_result_srb(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb, status); - } - else if (pdev_ext->io_packet.flags & IOP_FLAG_SCSI_CTRL_TRANSFER) - umss_gen_result_ctrl(dev_obj, pirp, status); - - //this device has its irp queued - if (status == STATUS_CANCELLED) - { - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): status of irp is cancelled\n")); - IoAcquireCancelSpinLock(&old_irql); - if (dev_obj->CurrentIrp == pirp) - { - IoReleaseCancelSpinLock(old_irql); - IoStartNextPacket(dev_obj, FALSE); - } - else - { - KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry); - IoReleaseCancelSpinLock(old_irql); - } - } - else - { - // all requests come to this point from the irp queue - IoStartNextPacket(dev_obj, FALSE); - - // we are going to complete the request, so set it's cancel routine to NULL - IoAcquireCancelSpinLock(&old_irql); - (void)IoSetCancelRoutine(pirp, NULL); - IoReleaseCancelSpinLock(old_irql); - } - - pirp->IoStatus.Status = status; - - if (status != STATUS_SUCCESS) - pirp->IoStatus.Information = 0; - - IoCompleteRequest(pirp, IO_NO_INCREMENT); - return; -} - -BOOLEAN -umss_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle) -{ - PURB purb; - LONG if_idx, i; - PUCHAR desc_buf; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr; - PUSB_INTERFACE_DESC pif_desc; - PUSB_CTRL_SETUP_PACKET psetup; - PUMSS_DEVICE_EXTENSION pdev_ext; - PUSB_CONFIGURATION_DESC pconfig_desc; - PUSB_DEV_MANAGER dev_mgr; - PUSB_ENDPOINT_DESC pendp_desc; - PUMSS_DRVR_EXTENSION pdrvr_ext; - PDEVICE_OBJECT pdev_obj; - USE_BASIC_NON_PENDING_IRQL; - - //configuration is already set - purb = NULL; - desc_buf = NULL; - pdev = NULL; - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_connect(): entering...\n")); - - if (params == NULL) - return FALSE; - - dev_mgr = params->dev_mgr; - pdrvr = params->pdriver; - - if_idx = if_idx_from_handle(if_handle); - - purb = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb == NULL) - goto ERROR_OUT; - - desc_buf = usb_alloc_mem(NonPagedPool, 512); - if (desc_buf == NULL) - goto ERROR_OUT; - - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - urb_init((purb)); - - // now let's get the descs, one configuration, one interface and two endpoint - psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet; - purb->endp_handle = if_handle | 0xffff; - purb->data_buffer = desc_buf; - purb->data_length = 512; - purb->completion = NULL; // this is an immediate request, no needs completion - purb->context = dev_mgr; - purb->reference = 0; - psetup->bmRequestType = 0x80; - psetup->bRequest = USB_REQ_GET_DESCRIPTOR; - psetup->wValue = USB_DT_CONFIG << 8; - psetup->wIndex = 0; - psetup->wLength = 512; - - status = usb_submit_urb(dev_mgr, purb); - if (status == STATUS_PENDING) - { - TRAP(); - } - usb_free_mem(purb); - purb = NULL; - - if (status != STATUS_SUCCESS) - { - goto ERROR_OUT; - } - - status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev); - if (status != STATUS_SUCCESS) - { - goto ERROR_OUT; - } - -#ifdef _TIANSHENG_DRIVER - if (!((pdev->pusb_dev_desc->idVendor == 0x03eb && pdev->pusb_dev_desc->idProduct == 0x2002) - || (pdev->pusb_dev_desc->idVendor == 0x0ea0 && pdev->pusb_dev_desc->idProduct == 0x6803) - || (pdev->pusb_dev_desc->idVendor == 0x0ef5 && pdev->pusb_dev_desc->idProduct == 0x2202))) - { - // check TianSheng's product - goto ERROR_OUT; - } -#endif - - pdev_obj = umss_create_device(dev_mgr, pdrvr, if_handle, TRUE); - if (pdev_obj == NULL) - { - goto ERROR_OUT; - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB || - dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE) - { - unlock_dev(pdev, FALSE); - if (pdev_obj) - { - umss_delete_device(dev_mgr, pdrvr, pdev_obj, TRUE); - } - goto ERROR_OUT; - } - - if (pdev->usb_config) - { - pdev->usb_config->interf[if_idx].if_ext = pdev_obj; - pdev->usb_config->interf[if_idx].if_ext_size = 0; - } - // olympus dev needs special care - if (UMSS_OLYMPUS_VENDOR_ID == pdev->pusb_dev_desc->idVendor) - status = TRUE; - else - status = FALSE; - - unlock_dev(pdev, FALSE); - - pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension; - - pdev_ext->desc_buf = desc_buf; - pdev_ext->pif_desc = NULL; - pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL; - pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf; - pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]); - - if (status) - pdev_ext->flags |= UMSS_DEV_FLAG_OLYMPUS_DEV; - - //search for our if - for(i = 0; ((UCHAR) i) < if_idx; i++) - { - if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE) - break; - } - pdev_ext->pif_desc = pif_desc; - - if (pdev_ext->pif_desc) - { - pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1]; - for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++) - { - if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT - && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC)) - { - if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - { - pdev_ext->pint_endp_desc = pendp_desc; - pdev_ext->int_endp_idx = (UCHAR) i; - } - else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) - { - if (pendp_desc->bEndpointAddress & USB_DIR_IN) - { - pdev_ext->pin_endp_desc = pendp_desc; - pdev_ext->in_endp_idx = (UCHAR) i; - } - else - { - pdev_ext->pout_endp_desc = pendp_desc; - pdev_ext->out_endp_idx = (UCHAR) i; - } - } - pendp_desc = &pendp_desc[1]; - } - else - break; - } - } - - // notify the class driver, some device comes - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext; - if (pdrvr_ext && pdrvr_ext->class_driver_info.add_device && pdrvr_ext->class_driver_info.fdo_driver) - pdrvr_ext->class_driver_info.add_device(pdrvr_ext->class_driver_info.fdo_driver, pdev_obj); - - usb_unlock_dev(pdev); - return TRUE; - -ERROR_OUT: - if (desc_buf) - usb_free_mem(desc_buf); - - if (purb) - usb_free_mem(purb); - - usb_unlock_dev(pdev); - - desc_buf = NULL; - purb = NULL; - - return FALSE; -} - -BOOLEAN -umss_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle) -{ - LONG if_idx; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr = NULL; - PDEVICE_OBJECT dev_obj = NULL; - PUMSS_DRVR_EXTENSION pdrvr_ext; - PUMSS_DEVICE_EXTENSION pdev_ext; - - if (dev_mgr == NULL || if_handle == 0) - return FALSE; - - pdev = NULL; - if_idx = if_idx_from_handle(if_handle); - // - // special use of the lock dev, simply use this routine to get the dev - // - status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev); - if (pdev == NULL) - { - return FALSE; - } - if (status == STATUS_SUCCESS) - { - // must be a bug - TRAP(); - } - if (pdev->usb_config) - { - pdrvr = pdev->usb_config->interf[if_idx].pif_drv; - dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext; - } - pdev = NULL; - - // notify the class driver, some device gone - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext; - pdev_ext = dev_obj->DeviceExtension; - if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch) - pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_DISCONNECT, NULL); - - // no need to unlock the dev - return umss_delete_device(dev_mgr, pdrvr, dev_obj, TRUE); -} - -BOOLEAN -umss_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle) -{ - LONG if_idx; - NTSTATUS status; - PUSB_DEV pdev; - PUSB_DRIVER pdrvr = NULL; - PDEVICE_OBJECT dev_obj = NULL; - PUMSS_DRVR_EXTENSION pdrvr_ext; - PUMSS_DEVICE_EXTENSION pdev_ext; - USE_BASIC_NON_PENDING_IRQL; - - if (dev_mgr == NULL || if_handle == 0) - return FALSE; - - pdev = NULL; - if_idx = if_idx_from_handle(if_handle); - - // special use of the lock dev, simply use this routine to get the dev - status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev); - if (status != STATUS_SUCCESS) - { - return FALSE; - } - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - return FALSE; - } - - if (pdev->usb_config) - { - pdrvr = pdev->usb_config->interf[if_idx].pif_drv; - dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext; - } - unlock_dev(pdev, FALSE); - - // notify the class driver, some device stops - pdev_ext = dev_obj->DeviceExtension; - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext; - if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch) - pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_STOP, NULL); - - usb_unlock_dev(pdev); - return TRUE; -} - -VOID -umss_load_class_driver(PVOID context) -{ - NTSTATUS status; - UNICODE_STRING unicode_string; - - UNREFERENCED_PARAMETER(context); - - // - // let's load the class driver - // - RtlInitUnicodeString(&unicode_string, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\usbstor"); - status = ZwLoadDriver(&unicode_string); - usb_dbg_print(DBGLVL_MAXIMUM, - ("umss_load_class_driver(): try to load class driver, status=0x%x\n", status)); -} - -BOOLEAN -umss_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver) -{ - PUMSS_DRVR_EXTENSION pdrvr_ext; - - if (dev_mgr == NULL || pdriver == NULL) - return FALSE; - - //init driver structure, no PNP table functions - - pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE; - pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID - pdriver->driver_desc.product_id = 0x0000; // USB Product ID. - pdriver->driver_desc.release_num = 0x100; // Release Number of Device - - pdriver->driver_desc.config_val = 1; // Configuration Value - pdriver->driver_desc.if_num = 1; // Interface Number - pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // Interface Class - pdriver->driver_desc.if_sub_class = 0; // Interface SubClass - pdriver->driver_desc.if_protocol = 0; // Interface Protocol - - pdriver->driver_desc.driver_name = "USB Mass Storage interface driver"; // Driver name for Name Registry - pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE; - pdriver->driver_desc.dev_sub_class = 0; // Device Subclass - pdriver->driver_desc.dev_protocol = 0; // Protocol Info. - - pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION)); - if (!pdriver->driver_ext) return FALSE; - - pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION); - - RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION)); - - pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext; - pdrvr_ext->dev_count = 0; - InitializeListHead(&pdrvr_ext->dev_list); - ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex); - - pdriver->disp_tbl.version = 1; - pdriver->disp_tbl.dev_connect = umss_if_connect; - pdriver->disp_tbl.dev_disconnect = umss_if_disconnect; - pdriver->disp_tbl.dev_stop = umss_if_stop; - pdriver->disp_tbl.dev_reserved = NULL; - - if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL) - { - usb_free_mem(pdriver->driver_ext); - pdriver->driver_ext = NULL; - pdriver->driver_ext_size = 0; - pdriver->disp_tbl.dev_connect = NULL; - pdriver->disp_tbl.dev_stop = NULL; - pdriver->disp_tbl.dev_disconnect = NULL; - return FALSE; - } - - // - // let's load the class driver - // - umss_load_class_driver(NULL); - - // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 ); - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_driver_init(): umss driver is initialized\n")); - - return TRUE; -} - -// get the driver reg information for pnp notification to class -// driver. -// bug??? how if the driver info is returned while the driver -// is being unloaded. -// So the routine must be called when usb_query_and_lock_dev is -// called. -PCLASS_DRV_REG_INFO -umss_get_if_driver_info(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, DEV_HANDLE if_handle) -{ - PUMSS_DRVR_EXTENSION drvr_ext; - ULONG if_idx; - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(dev_mgr); - - if_idx = if_idx_from_handle(if_handle); - if (if_idx >= 4) // max interfaces per config supports. defined in td.h - return NULL; - - ASSERT(pdev != NULL); - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - return NULL; - } - - drvr_ext = NULL; - - if (pdev->usb_config->interf[if_idx].pif_drv) - drvr_ext = (PUMSS_DRVR_EXTENSION) pdev->usb_config->interf[if_idx].pif_drv->driver_ext; - else - TRAP(); - - unlock_dev(pdev, FALSE); - - if (drvr_ext == NULL) - { - return NULL; - } - - return &drvr_ext->class_driver_info; -} - -VOID NTAPI -umss_worker(IN PVOID reference) -{ - PUMSS_WORKER_PACKET worker_packet; - PUSB_DEV pdev; - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): entering...\n")); - worker_packet = (PUMSS_WORKER_PACKET) reference; - worker_packet->completion(worker_packet->context); - if (worker_packet->dev_mgr && worker_packet->pdev) - { - pdev = (PUSB_DEV) worker_packet->pdev; - usb_unlock_dev(pdev); - pdev = NULL; - } - usb_free_mem(worker_packet); - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): exit\n")); -} - -/*++ -Routine Description: - - Wrapper for handling worker thread callbacks, it is importent to - lock the dev from being deleted by calling usb_query_and_lock_dev - and in umss_worker, call the usb_unlock_dev to release the ref - count. One exception is that the umss_if_disconnect call this - function to delete the device object that is still held by some - others, and deferred deletion is required. - -Arguments: - - Routine - Routine to be called when this work-item is processed - Context - Value to be passed to worker routine - -Return Value: - TRUE if work item queued - FALSE if work item not queued - ---*/ -BOOLEAN -umss_schedule_workitem(PVOID context, - UMSS_WORKER_ROUTINE completion, PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle) -{ - BOOLEAN ret_val = TRUE; - PWORK_QUEUE_ITEM workitem; - PUMSS_WORKER_PACKET worker_packet; - - worker_packet = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET)); - - if (worker_packet) - { - RtlZeroMemory(worker_packet, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET)); - - workitem = (PWORK_QUEUE_ITEM) & worker_packet[1]; - worker_packet->completion = completion; - worker_packet->context = context; - - if (dev_mgr != NULL && dev_handle != 0) - { - PUSB_DEV pdev; - // lock the device until the workitem is executed. - if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) == STATUS_SUCCESS) - { - worker_packet->dev_mgr = dev_mgr; - worker_packet->pdev = pdev; - } - else - { - usb_free_mem(worker_packet); - return FALSE; - } - } - // Initialize the work-item - ExInitializeWorkItem(workitem, umss_worker, worker_packet); - - // Schedule the work-item - ExQueueWorkItem(workitem, DelayedWorkQueue); - - usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): work-item queued\n")); - } - else - { - usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): Failed to allocate work-item\n")); - ret_val = FALSE; - } - - return ret_val; -} - -NTSTATUS -umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp) -{ - NTSTATUS status; - PUSB_DEV pdev; - PIO_STACK_LOCATION cur_stack; - PUMSS_DEVICE_EXTENSION pdev_ext; - PSCSI_REQUEST_BLOCK srb; - - if (dev_obj == NULL || irp == NULL) - return STATUS_INVALID_PARAMETER; - - pdev = NULL; - cur_stack = IoGetCurrentIrpStackLocation(irp); - srb = cur_stack->Parameters.Scsi.Srb; - - if (srb == NULL || srb->DataTransferLength > 65536) - { - status = STATUS_INVALID_PARAMETER; - goto ERROR_OUT; - } - - irp->IoStatus.Status = STATUS_SUCCESS; - irp->IoStatus.Information = 0; - - pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension; - if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS) - { - PSENSE_DATA sense_buf; - srb->SrbStatus = SRB_STATUS_NO_DEVICE; - - // - // let's build the srb status for class driver - // - srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; - RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength); - if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) - { - sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer; - sense_buf->ErrorCode = 0x70; - sense_buf->Valid = 1; - sense_buf->SenseKey = SCSI_SENSE_NOT_READY; - sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE; - sense_buf->AdditionalSenseLength = 10; - } - goto ERROR_OUT; - } - - switch (srb->Function) - { - case SRB_FUNCTION_EXECUTE_SCSI: - { - IO_PACKET io_packet; - RtlZeroMemory(&io_packet, sizeof(io_packet)); - - io_packet.flags |= IOP_FLAG_SRB_TRANSFER; - if (srb->SrbFlags & SRB_FLAGS_DATA_IN) - io_packet.flags |= IOP_FLAG_DIR_IN; - if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)) - io_packet.flags |= IOP_FLAG_REQ_SENSE; - - io_packet.cdb_length = srb->CdbLength; - RtlCopyMemory(io_packet.cdb, srb->Cdb, sizeof(io_packet.cdb)); - io_packet.lun = 0; - - if (srb->SrbFlags & SRB_FLAGS_NO_DATA_TRANSFER) - { - io_packet.data_buffer = NULL; - io_packet.data_length = 0; - } - else - { - if ((irp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION)) - && !(irp->Flags & IRP_PAGING_IO)) - { - // - // since these operations does not allign the buffer on page boundary - // and some unknown traps in window NT, we have to copy to a buffer - // we allocated - io_packet.data_buffer = usb_alloc_mem(NonPagedPool, srb->DataTransferLength); - if (irp->Flags & IRP_WRITE_OPERATION) - { - PULONG dest_buf, src_buf; - ULONG i; - - dest_buf = (PULONG) io_packet.data_buffer; - src_buf = (PULONG) srb->DataBuffer; - - if (src_buf && dest_buf) - { - for(i = 0; i < (srb->DataTransferLength >> 2); i++) - { - dest_buf[i] = src_buf[i]; - } - } - } - } - else - io_packet.data_buffer = srb->DataBuffer; - - io_packet.data_length = srb->DataTransferLength; - } - - if (io_packet.flags & IOP_FLAG_REQ_SENSE) - { - io_packet.sense_data = srb->SenseInfoBuffer; - io_packet.sense_data_length = srb->SenseInfoBufferLength; - } - - io_packet.pirp = irp; - - // do some conversions - if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I) - { - if (umss_tsc_to_sff(&io_packet) == FALSE) - { - status = STATUS_DEVICE_PROTOCOL_ERROR; - - usb_dbg_print(DBGLVL_MAXIMUM, - ("umss_process_srb(): error converting to sff proto, 0x%x\n", status)); - srb->SrbStatus = SRB_STATUS_ERROR; - break; - } - } - - if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY) - { - // - // currently we support only transparent scsi command set - // - if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SCSI_TCS || - pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I) - status = umss_bulkonly_startio(pdev_ext, &io_packet); - else - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB - || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI) - { - status = umss_cbi_startio(pdev_ext, &io_packet); - } - else - { - status = STATUS_DEVICE_PROTOCOL_ERROR; - } - - if (status != STATUS_PENDING && status != STATUS_SUCCESS) - { - // error occured - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): error sending request, 0x%x\n", status)); - srb->SrbStatus = SRB_STATUS_ERROR; - } - break; - } - case SRB_FUNCTION_CLAIM_DEVICE: - { - srb->DataBuffer = (PVOID) dev_obj; - } - case SRB_FUNCTION_SHUTDOWN: - case SRB_FUNCTION_FLUSH: - case SRB_FUNCTION_RESET_BUS: - case SRB_FUNCTION_FLUSH_QUEUE: - case SRB_FUNCTION_RELEASE_QUEUE: - case SRB_FUNCTION_RELEASE_DEVICE: - default: - { - // for usb flash disk, they are luxurious - - usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): current srb->Function=0x%x\n", - srb->Function)); - - status = STATUS_SUCCESS; - srb->SrbStatus = SRB_STATUS_SUCCESS; - break; - } - } - - usb_unlock_dev(pdev); - pdev = NULL; - -ERROR_OUT: - irp->IoStatus.Status = status; - if (status != STATUS_PENDING) - { - IoStartNextPacket(dev_obj, FALSE); - IoCompleteRequest(irp, IO_NO_INCREMENT); - } - - // - // UMSS_COMPLETE_START_IO( dev_obj, status, irp ); - // - return status; -} - -BOOLEAN -umss_tsc_to_sff(PIO_PACKET io_packet) -{ - if (io_packet == NULL) - return FALSE; - - io_packet->cdb_length = 12; - if (io_packet->cdb[0] == SCSIOP_MODE_SENSE) - { - io_packet->cdb[0] = 0x5a; // mode sense( 10 ) - io_packet->cdb[8] = io_packet->cdb[4]; - io_packet->cdb[4] = 0; - if (io_packet->cdb[8] < 8) - io_packet->cdb[8] = 8; - - io_packet->data_length = 8; - return TRUE; - } - if (io_packet->cdb[0] == SCSIOP_REASSIGN_BLOCKS || - io_packet->cdb[0] == SCSIOP_RESERVE_UNIT || io_packet->cdb[0] == SCSIOP_RELEASE_UNIT) - return FALSE; - - return TRUE; -} - -VOID -umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK *srb) -{ - PBYTE buf; - if (io_packet->cdb[0] != 0x5a) - return; - // the following is not right since it has to be 0x3f, return all pages - // if( io_packet->cdb[ 2 ] != 0 ) - // return; - srb->DataTransferLength = 4; - buf = io_packet->data_buffer; - // convert the mode param to scsi II - buf[0] = buf[1]; - buf[1] = buf[2]; - buf[2] = buf[3]; - buf[3] = 0; - return; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/umss.h b/reactos/drivers/usb/nt4compat/usbdrv/umss.h deleted file mode 100644 index ca67e03f027..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/umss.h +++ /dev/null @@ -1,350 +0,0 @@ -#ifndef __UMSS_H__ -#define __UMSS_H__ - -#define MAX_BULK_TRANSFER_LENGTH 0x100000 - -#define PROTOCOL_CBI 0x00 -#define PROTOCOL_CB 0x01 -#define PROTOCOL_BULKONLY 0x50 - -#define PROTOCOL_UNDEFINED 0xFF // Not in spec - -#define UMSS_SUBCLASS_RBC 0x01 -#define UMSS_SUBCLASS_SFF8020I 0X02 -#define UMSS_SUBCLASS_QIC157 0x03 -#define UMSS_SUBCLASS_UFI 0x04 -#define UMSS_SUBCLASS_SFF8070I 0x05 -#define UMSS_SUBCLASS_SCSI_TCS 0x06 - -#define ACCEPT_DEVICE_SPECIFIC_COMMAND 0 - -#define BULK_ONLY_MASS_STORAGE_RESET 0xFF -#define BULK_ONLY_GET_MAX_LUN 0xFE - -#define CBW_SIGNATURE 0x43425355L -#define CSW_SIGNATURE 0x53425355L -#define CSW_OLYMPUS_SIGNATURE 0x55425355L - -#define CSW_STATUS_PASSED 0x00 -#define CSW_STATUS_FAILED 0x01 -#define CSW_STATUS_PHASE_ERROR 0x02 - -#define IOCTL_UMSS_SUBMIT_CDB CTL_CODE( FILE_USB_DEV_TYPE, 4200, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// for request with no other input and output -// input buffer is a _USER_IO_PACKET and input_buffer_length is length of the _USER_IO_PACKET -// output_buffer is NULL, and output_buffer_length is zero - -#define IOCTL_UMSS_SUBMIT_CDB_IN CTL_CODE( FILE_USB_DEV_TYPE, 4201, METHOD_IN_DIRECT, FILE_ANY_ACCESS ) -// for request to read in data -// input_buffer is a _USER_IO_PACKET and input_buffer_length is length to the _USER_IO_PACKET -// output_buffer is a buffer to receive the data from dev, and -// output_buffer_length is the size of the buffer - -#define IOCTL_UMSS_SUBMIT_CDB_OUT CTL_CODE( FILE_USB_DEV_TYPE, 4202, METHOD_OUT_DIRECT, FILE_ANY_ACCESS ) -// for request to write data to device -// input_buffer is a _USER_IO_PACKET and input_buffer_length is length to the _USER_IO_PACKET -// output_buffer is data to send to the device, and -// output_buffer_length is the size of the buffer - -#define IOCTL_REGISTER_DRIVER CTL_CODE( FILE_USB_DEV_TYPE, 4203, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// input_buffer is a CLASS_DRV_REG_INFO, and input_buffer_length is equal to or greater than -// sizeof( CLASS_DRV_REG_INFO ); the output_buffer is null and no output_buffer_length, -// only the following fields in urb can be accessed, others must be zeroed. - -#define IOCTL_REVOKE_DRIVER CTL_CODE( FILE_USB_DEV_TYPE, 4204, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// tell the umss driver to clear the information in the drivers registry -// no other parameters - -#define IOCTL_UMSS_SUBMIT_SRB CTL_CODE( FILE_USB_DEV_TYPE, 4205, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// irpStack->Parameters.Scsi.Srb points to an Srb structure and all the data buffer and buffer -// size are stored in the srb - - -#define IOCTL_UMSS_SET_FDO CTL_CODE( FILE_USB_DEV_TYPE, 4206, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// input_buffer is a pointer to PDEVICE_OBJECT, and input_buffer_length should be -// no less than sizeof( PDEVICE_OBJECT ) -// output buffer is NULL, and output_buffer_length is zero -// if the deivce is accessable, the fdo is set, else, the fdo is not set and return -// STATUS_DEVICE_DOES_NOT_EXIST - -#define SFF_FORMAT_UNIT 0x04 -#define SFF_INQUIRY 0x12 -#define SFF_MODE_SELECT 0x55 -#define SFF_MODE_SENSE 0x5a -#define SFF_ALLOW_REMOVE 0x1e -#define SFF_READ10 0x28 -#define SFF_READ12 0xa8 -#define SFF_READ_CAPACITY 0x25 -#define SFF_REQUEST_SENSEE 0x03 -#define SFF_SEEK 0x2b -#define SFF_START_STOP 0x1b -#define SFF_TUR 0x00 -#define SFF_VERIFY 0x2f -#define SFF_WRITE10 0x2a -#define SFF_WRITE12 0xaa -#define SFF_READ_FMT_CAPACITY 0x23 -#define SFF_WRITE_VERIFY 0x2e - -#define MAX_CDB_LENGTH 0x10 - -typedef struct _USER_IO_PACKET -{ - UCHAR sub_class; - UCHAR lun; - UCHAR cdb_length; - UCHAR cdb[ MAX_CDB_LENGTH ]; - -} USER_IO_PACKET, *PUSER_IO_PACKET; - -//flags for IO_PACKET::flags -#define IOP_FLAG_REQ_SENSE 0x80000000 // sense data would be fetched if error occurs -#define IOP_FLAG_SRB_TRANSFER 0x40000000 // current tranfer is initiated by an srb request, the srb is held by the irp -#define IOP_FLAG_SCSI_CTRL_TRANSFER 0x20000000 // current transfer is initiated by an scsi ioctrl request - -#define IOP_FLAG_DIR_IN USB_DIR_IN -#define IOP_FLAG_STAGE_MASK 0x03 -#define IOP_FLAG_STAGE_NORMAL 0x00 -#define IOP_FLAG_STAGE_SENSE 0x01 - -typedef struct _IO_PACKET -{ - ULONG flags; - UCHAR cdb_length; - UCHAR cdb[ MAX_CDB_LENGTH ]; - UCHAR lun; - PVOID data_buffer; - ULONG data_length; - PVOID sense_data; - ULONG sense_data_length; - PIRP pirp; - -} IO_PACKET, *PIO_PACKET; - -#pragma pack( 1 ) - -typedef struct _COMMAND_BLOCK_WRAPPER -{ - ULONG dCBWSignature; - ULONG dCBWTag; - ULONG dCBWDataTransferLength; - UCHAR bmCBWFlags; - UCHAR bCBWLun; - UCHAR bCBWLength; - UCHAR CBWCB[ MAX_CDB_LENGTH ]; - -} COMMAND_BLOCK_WRAPPER, *PCOMMAND_BLOCK_WRAPPER; - -typedef struct _COMMAND_STATUS_WRAPPER -{ - ULONG dCSWSignature; - ULONG dCSWTag; - ULONG dCSWDataResidue; - UCHAR bCSWStatus; - -} COMMAND_STATUS_WRAPPER, *PCOMMAND_STATUS_WRAPPER; - - -typedef struct _INTERRUPT_DATA_BLOCK -{ - UCHAR bType; - UCHAR bValue; - -} INTERRUPT_DATA_BLOCK, *PINTERRUPT_DATA_BLOCK; - -#pragma pack() - -#define UMSS_PNPMSG_STOP 0x01 -#define UMSS_PNPMSG_DISCONNECT 0x02 - -typedef NTSTATUS ( *PCLASS_DRVR_PNP_DISP )( PDEVICE_OBJECT pdo, ULONG ctrl_code, PVOID context ); - // pdo is the device object umss created - -typedef PDEVICE_OBJECT ( *PCLASS_DRIVER_ADD_DEV )( PDRIVER_OBJECT fdo_drvr, PDEVICE_OBJECT pdo ); - // if the return value is not zero, it is a pointer to the - // fdo sitting over the pdo of this driver. if it is null, - // the add_device failed, and initialization process should - // stall. - -typedef struct _CLASS_DRV_REGISTRY_INFO -{ - // class driver will pass this structure to umss port - // driver after loaded - PDRIVER_OBJECT fdo_driver; - PCLASS_DRIVER_ADD_DEV add_device; - PCLASS_DRVR_PNP_DISP pnp_dispatch; - -} CLASS_DRV_REG_INFO, *PCLASS_DRV_REG_INFO; - -typedef struct _UMSS_PORT_DEVICE_EXTENSION -{ - // this structure is the device extension for port dev_obj - // it is used to has class driver pass CLASS_DRV_REG_INFO - // to our umss driver. - DEVEXT_HEADER dev_ext_hdr; - PUSB_DRIVER pdriver; - -} UMSS_PORT_DEV_EXT, *PUMSS_PORT_DEV_EXT; - -typedef struct _UMSS_DRVR_EXTENSION -{ - LIST_HEAD dev_list; - FAST_MUTEX dev_list_mutex; - UCHAR dev_count; - CLASS_DRV_REG_INFO class_driver_info; - PDEVICE_OBJECT port_dev_obj; // we use this obj as a connection point for class driver, its name usbPort0 - -} UMSS_DRVR_EXTENSION, *PUMSS_DRVR_EXTENSION; - -#define UMSS_DEV_FLAG_IF_DEV 0x01 -#define UMSS_DEV_FLAG_OLYMPUS_DEV 0x02 - -#define UMSS_OLYMPUS_VENDOR_ID 0x07b4 - -typedef struct _UMSS_DEVICE_EXTENSION -{ - //this structure is the device extension for dev_obj - //created for the device. - DEVEXT_HEADER dev_ext_hdr; - - ULONG flags; - LIST_ENTRY dev_obj_link; // this link is used by the driver object to track the existing dev_objs - - PDEVICE_OBJECT pdo; // this is the pdo - PDEVICE_OBJECT fdo; // driver object for the dev_obj - - DEV_HANDLE dev_handle; // handle to the usb_dev under - - PUCHAR desc_buf; - UCHAR umss_dev_id; // used to build symbolic link - - PUSB_INTERFACE_DESC pif_desc; - PUSB_ENDPOINT_DESC pout_endp_desc, pin_endp_desc, pint_endp_desc; - UCHAR if_idx, out_endp_idx, in_endp_idx, int_endp_idx; - - struct _USB_DEV_MANAGER *dev_mgr; - - //working data - COMMAND_BLOCK_WRAPPER cbw; - union - { - INTERRUPT_DATA_BLOCK idb; - COMMAND_STATUS_WRAPPER csw; - }; - - KEVENT sync_event; //for umss_sync_submit_urb - KSPIN_LOCK dev_lock; - IO_PACKET io_packet; - BOOLEAN retry; - - PUSB_DRIVER pdriver; //used by umss_delete_device - NTSTATUS reset_pipe_status; -} UMSS_DEVICE_EXTENSION, *PUMSS_DEVICE_EXTENSION; - -// for device creation workitem -typedef struct _UMSS_CREATE_DATA -{ - DEV_HANDLE dev_handle; - PUCHAR desc_buf; - PUSB_DEV_MANAGER dev_mgr; - PUSB_DRIVER pdriver; - -} UMSS_CREATE_DATA, *PUMSS_CREATE_DATA; - -// for reset pipe item -//typedef void ( _stdcall *COMPLETION_HANDLER )( PVOID ); -typedef void ( *UMSS_WORKER_ROUTINE )( PVOID ); - -typedef struct _UMSS_WORKER_PACKET -{ - UMSS_WORKER_ROUTINE completion; - PVOID context; - PUSB_DEV_MANAGER dev_mgr; - PVOID pdev; - -} UMSS_WORKER_PACKET, *PUMSS_WORKER_PACKET; - -BOOLEAN -umss_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -umss_if_driver_init( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -BOOLEAN -umss_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -#define umss_if_driver_destroy umss_driver_destroy - -BOOLEAN -umss_if_driver_destroy( -PUSB_DEV_MANAGER dev_mgr, -PUSB_DRIVER pdriver -); - -VOID -umss_complete_request( -PUMSS_DEVICE_EXTENSION pdev_ext, -NTSTATUS status -); - -NTSTATUS -umss_reset_pipe( -PUMSS_DEVICE_EXTENSION pdev_ext, -DEV_HANDLE endp_handle -); - -PVOID -umss_get_buffer( -PUMSS_DEVICE_EXTENSION pdev_ext, -ULONG* buf_length -); - -NTSTATUS -umss_bulk_transfer( -IN PUMSS_DEVICE_EXTENSION pdev_ext, -IN UCHAR trans_dir, -IN PVOID buf, -IN ULONG buf_length, -IN PURBCOMPLETION completion -); - -BOOLEAN -umss_schedule_workitem( -PVOID context, -UMSS_WORKER_ROUTINE completion, -PUSB_DEV_MANAGER dev_mgr, -DEV_HANDLE dev_handle -); - -NTSTATUS -umss_bulkonly_startio( -IN PUMSS_DEVICE_EXTENSION pdev_ext, -IN PIO_PACKET io_packet -); - -NTSTATUS -umss_cbi_startio( -IN PUMSS_DEVICE_EXTENSION pdev_ext, -IN PIO_PACKET io_packet -); - -#define UMSS_FORGE_GOOD_SENSE( sense_BUF ) \ -{\ - int i;\ - PUCHAR buf = ( PUCHAR )( sense_BUF ); \ - for( i = 0; i < 18; i++)\ - {\ - buf[i] = 0;\ - }\ - buf[7] = 10;\ -} - -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/usb.c b/reactos/drivers/usb/nt4compat/usbdrv/usb.c deleted file mode 100644 index 65cddd0d7f0..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/usb.c +++ /dev/null @@ -1,1343 +0,0 @@ -/** - * usb.c - USB driver stack project for Windows NT 4.0 - * - * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com - * - * This program/include file 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 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 - * this program (in the main directory of the distribution, the file - * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple - * Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "usbdriver.h" - -LONG g_alloc_cnt = 0; -ULONG cpu_clock_freq = 0; - -NTSTATUS usb_get_descriptor(PUSB_DEV pdev, PURB purb); -VOID usb_set_interface_completion(PURB purb, PVOID context); -NTSTATUS usb_set_interface(PURB purb); - -PVOID -usb_alloc_mem(POOL_TYPE pool_type, LONG size) -{ - PVOID ret; - g_alloc_cnt++; - ret = ExAllocatePool(pool_type, size); - usb_dbg_print(DBGLVL_ULTRA, ("usb_alloc_mem(): alloced=0x%x\n", g_alloc_cnt)); - return ret; -} - -VOID -usb_free_mem(PVOID pbuf) -{ - g_alloc_cnt--; - usb_dbg_print(DBGLVL_ULTRA, ("usb_free_mem(): alloced=0x%x\n", g_alloc_cnt)); - ExFreePool(pbuf); -} - -VOID usb_config_dev_completion(PURB purb, PVOID context); - -//shamelessly pasted from linux's usb.c -LONG -usb_calc_bus_time(LONG speed, LONG input_dir, LONG is_iso, LONG byte_count) -{ - LONG tmp; - - switch (speed & 0x3) /* no isoc. here */ - { - case USB_SPEED_LOW: - { - if (input_dir) - { - tmp = (67667L * (31L + 10L * bit_time(byte_count))) / 1000L; - return (64060L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - else - { - tmp = (66700L * (31L + 10L * bit_time(byte_count))) / 1000L; - return (64107L + (2 * BW_HUB_LS_SETUP) + BW_HOST_DELAY + tmp); - } - break; - } - /* for full-speed: */ - case USB_SPEED_FULL: - { - if (!is_iso) /* Input or Output */ - { - tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L; - return (9107L + BW_HOST_DELAY + tmp); - } /* end not Isoc */ - - /* for isoc: */ - - tmp = (8354L * (31L + 10L * bit_time(byte_count))) / 1000L; - return (((input_dir) ? 7268L : 6265L) + BW_HOST_DELAY + tmp); - } - case USB_SPEED_HIGH: - { - if (!is_iso) - { - tmp = (999 + 926520 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000; - } - else - { - tmp = (999 + 633232 + 2083 * ((LONG) ((19 + 7 * 8 * byte_count) / 6))) / 1000; - } - return tmp + USB2_HOST_DELAY; - } - default: - { - break; - } - } - return 125001; -} - -// -// if the dev is not in the list, return value is not success and the pointer is nulled -// if the dev is in the list but zomb, return value is error code and the pointer is the dev( no ref_count guarded ) -// if the dev is alive and in the list, return is success and the pointer is the dev. -// one must be aware of what his doing before he uses the ppdev -// -NTSTATUS -usb_query_and_lock_dev(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle, PUSB_DEV * ppdev) -{ - int i; - PLIST_ENTRY pthis, pnext; - PUSB_DEV pdev = NULL; - BOOLEAN valid_dev; - - USE_NON_PENDING_IRQL; - - *ppdev = NULL; - - if (dev_mgr == NULL || dev_handle == 0) - return STATUS_INVALID_PARAMETER; - - i = dev_id_from_handle(dev_handle); - - KeAcquireSpinLock(&dev_mgr->dev_list_lock, &old_irql); - ListFirst(&dev_mgr->dev_list, pthis); - - while (pthis) - { - pdev = (PUSB_DEV) pthis; - if (pdev->dev_id != (ULONG) i) - { - ListNext(&dev_mgr->dev_list, pthis, pnext); - pthis = pnext; - continue; - } - else - break; - } - if (pthis == NULL) - { - //no such device - KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql); - return STATUS_INVALID_PARAMETER; - } - - valid_dev = TRUE; - - lock_dev(pdev, TRUE); - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - valid_dev = FALSE; - } - else - pdev->ref_count++; //guard the dev by increasing the ref count - - unlock_dev(pdev, TRUE); - - KeReleaseSpinLock(&dev_mgr->dev_list_lock, old_irql); - - *ppdev = pdev; - - if (!valid_dev) - return STATUS_DEVICE_DOES_NOT_EXIST; - - return STATUS_SUCCESS; - -} - -NTSTATUS -usb_unlock_dev(PUSB_DEV dev) -{ - USE_BASIC_NON_PENDING_IRQL; - - if (dev == NULL) - return STATUS_INVALID_PARAMETER; - - lock_dev(dev, FALSE); - dev->ref_count--; - if (dev->ref_count < 0) - dev->ref_count = 0; - unlock_dev(dev, FALSE); - return STATUS_SUCCESS; -} - -NTSTATUS -usb_reset_pipe_ex(PUSB_DEV_MANAGER dev_mgr, - DEV_HANDLE endp_handle, //endp handle to reset - PURBCOMPLETION reset_completion, //note: this reset completion has no right to delete the urb, that is only for reference - PVOID param) -{ - NTSTATUS status; - PUSB_DEV pdev; - LONG if_idx, endp_idx; - PUSB_ENDPOINT pendp; - USE_BASIC_NON_PENDING_IRQL; - - if (dev_mgr == NULL) - return STATUS_INVALID_PARAMETER; - - status = usb_query_and_lock_dev(dev_mgr, (endp_handle & 0xffff0000), &pdev); - if (status != STATUS_SUCCESS) - return STATUS_UNSUCCESSFUL; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = STATUS_UNSUCCESSFUL; - goto LBL_OUT; - } - - if_idx = if_idx_from_handle(endp_handle); - endp_idx = endp_idx_from_handle(endp_handle); - - if (default_endp_handle(endp_handle)) - { - status = STATUS_UNSUCCESSFUL; - goto LBL_OUT; - } - - if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED) - { - status = STATUS_DEVICE_NOT_READY; - goto LBL_OUT; - } - - pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx]; - unlock_dev(pdev, FALSE) status = usb_reset_pipe(pdev, pendp, reset_completion, param); - usb_unlock_dev(pdev); - return status; - -LBL_OUT: - unlock_dev(pdev, FALSE); - usb_unlock_dev(pdev); - - return status; -} - -// caller must guarantee the pdev exist before the routine exit -NTSTATUS -usb_reset_pipe(PUSB_DEV pdev, PUSB_ENDPOINT pendp, PURBCOMPLETION client_reset_pipe_completion, PVOID param) -{ - - PHCD hcd; - PURB purb; - BYTE endp_addr; - NTSTATUS status; - DEV_HANDLE dev_handle; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || pendp == NULL) - return STATUS_INVALID_PARAMETER; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_DOES_NOT_EXIST; - } - - hcd = pdev->hcd; - endp_addr = pendp->pusb_endp_desc->bEndpointAddress; - dev_handle = usb_make_handle(pdev->dev_id, 0, 0); - unlock_dev(pdev, FALSE); - - purb = (PURB) usb_alloc_mem(NonPagedPool, sizeof(URB) + sizeof(PIRP)); - - if (purb == NULL) - return STATUS_NO_MEMORY; - - UsbBuildResetPipeRequest(purb, - dev_handle, - endp_addr, - usb_reset_pipe_completion, - pendp, - (LONG)client_reset_pipe_completion); - - *((PULONG)&purb[1]) = (ULONG)param; - - if ((status = hcd->hcd_submit_urb(hcd, pdev, &pdev->default_endp, purb)) != STATUS_PENDING) - { - usb_free_mem(purb); - purb = NULL; - } - return status; -} - -VOID -usb_reset_pipe_completion(PURB purb, PVOID context) -{ - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || context == NULL) - return; - - pdev = purb->pdev; - pendp = (PUSB_ENDPOINT) context; - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - goto LBL_OUT; - } - - if (usb_error(purb->status)) - { - goto LBL_OUT; - } - //clear stall - pendp->flags &= ~USB_ENDP_FLAG_STAT_MASK; - - //reset toggle endp_type - if ((pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK || - (pendp->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) - { - pendp->flags &= ~USB_ENDP_FLAG_DATATOGGLE; - } - -LBL_OUT: - unlock_dev(pdev, TRUE); - - if (purb->reference) - ((PURBCOMPLETION) purb->reference) (purb, (PVOID) (*((PULONG) & purb[1]))); - - usb_free_mem(purb); - purb = NULL; - return; - -} - -void -usb_reset_pipe_from_dispatch_completion(PURB purb, PVOID param) -{ - PURB pclient_urb; - if (purb == NULL || param == NULL) - TRAP(); - pclient_urb = (PURB) param; - pclient_urb->status = purb->status; - - if (pclient_urb->completion) - { - pclient_urb->completion(pclient_urb, pclient_urb->context); - } - // the urb can not be freed here because it is owned by the reset - // pipe completion - return; -} - -//used to check descriptor validity -BOOLEAN -is_header_match(PUCHAR pbuf, ULONG type) -{ - BOOLEAN ret; - PUSB_DESC_HEADER phdr; - phdr = (PUSB_DESC_HEADER) pbuf; - - switch (type) - { - case USB_DT_DEVICE: - { - ret = (phdr->bLength == sizeof(USB_DEVICE_DESC) && phdr->bDescriptorType == USB_DT_DEVICE); - break; - } - case USB_DT_CONFIG: - { - ret = (phdr->bLength == sizeof(USB_CONFIGURATION_DESC) && phdr->bDescriptorType == USB_DT_CONFIG); - break; - } - case USB_DT_INTERFACE: - { - ret = (phdr->bLength == sizeof(USB_INTERFACE_DESC) && phdr->bDescriptorType == USB_DT_INTERFACE); - break; - } - case USB_DT_ENDPOINT: - { - ret = (phdr->bLength == sizeof(USB_ENDPOINT_DESC) && phdr->bDescriptorType == USB_DT_ENDPOINT); - break; - } - default: - ret = FALSE; - } - return ret; -} - -BOOLEAN -usb_skip_endp_desc(PBYTE * pbUF, LONG n) -{ - if (is_header_match(*pbUF, USB_DT_ENDPOINT)) - { - (*pbUF) += sizeof(USB_ENDPOINT_DESC) * n; - return TRUE; - } - return FALSE; -} - -BOOLEAN -usb_skip_if_desc(PBYTE * pBUF) -{ - BOOLEAN ret; - PUSB_INTERFACE_DESC pif_desc = (PUSB_INTERFACE_DESC) * pBUF; - LONG endp_count; - ret = is_header_match((PBYTE) * pBUF, USB_DT_INTERFACE); - if (ret == TRUE) - { - endp_count = pif_desc->bNumEndpoints; - if (endp_count < MAX_ENDPS_PER_IF) - { - pif_desc++; - ret = usb_skip_endp_desc((PBYTE *) & pif_desc, endp_count); - if (ret) - *(pBUF) = (PBYTE) pif_desc; - } - else - ret = FALSE; - } - return ret; -} - -BOOLEAN -usb_skip_if_and_altif(PUCHAR * pdesc_BUF) -{ - BOOLEAN ret; - PUSB_INTERFACE_DESC pif_desc1 = (PUSB_INTERFACE_DESC) * pdesc_BUF; - ret = is_header_match(*pdesc_BUF, USB_DT_INTERFACE); - if (ret == TRUE) - { - if (pif_desc1->bAlternateSetting == 0) - ret = usb_skip_if_desc((PUCHAR *) & pif_desc1); - else - //no default interface - ret = FALSE; - - while (ret && pif_desc1->bAlternateSetting != 0) - ret = usb_skip_if_desc((PUCHAR *) & pif_desc1); - } - if (ret) - *pdesc_BUF = (PUCHAR) pif_desc1; - - return ret; -} - -BOOLEAN -usb_skip_one_config(PUCHAR *pconfig_desc_BUF) -{ - LONG if_count, i; - BOOLEAN ret; - PUSB_CONFIGURATION_DESC pcfg_DESC = (PUSB_CONFIGURATION_DESC) * pconfig_desc_BUF; - PUSB_INTERFACE_DESC pif_desc2 = (PUSB_INTERFACE_DESC) & pcfg_DESC[1]; - - ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG); - if (ret) - *pconfig_desc_BUF = &((BYTE *) pcfg_DESC)[pcfg_DESC->wTotalLength]; - return ret; - - ret = is_header_match((PUCHAR) pcfg_DESC, USB_DT_CONFIG) - && is_header_match((PUCHAR) pif_desc2, USB_DT_INTERFACE); - - if (ret) - { - if_count = pcfg_DESC->bNumInterfaces; - if (if_count < MAX_INTERFACES_PER_CONFIG) - { - for(i = 0; i < if_count; i++) - { - ret = usb_skip_if_and_altif((PUCHAR *) & pif_desc2); - if (ret == FALSE) - break; - } - if (ret) - *pconfig_desc_BUF = (PUCHAR) pif_desc2; - } - } - return ret; -} - -PUSB_CONFIGURATION_DESC -usb_find_config_desc_by_idx(PUCHAR pbuf, LONG idx, LONG cfg_count) -{ - LONG i; - BOOLEAN ret; - PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf; - if (pcfg_desc == NULL) - return NULL; - - if (cfg_count > MAX_CONFIGS_PER_DEV) - return NULL; - - if (idx > cfg_count) - return NULL; - - if (idx == 0) - return pcfg_desc; - - for(i = 0; i < idx - 1; i++) - { - ret = usb_skip_one_config((PBYTE *) & pcfg_desc); - if (ret == FALSE) - return NULL; - } - return pcfg_desc; -} - -PUSB_CONFIGURATION_DESC -usb_find_config_desc_by_val(PBYTE pbuf, LONG val, LONG cfg_count) -{ - LONG i; - BOOLEAN ret; - PUSB_CONFIGURATION_DESC pcfg_desc = (PUSB_CONFIGURATION_DESC) pbuf; - if (pcfg_desc == NULL) - return NULL; - - if (cfg_count > MAX_CONFIGS_PER_DEV) - return NULL; - - for(i = 0; i < cfg_count; i++) - { - if (pcfg_desc->bConfigurationValue == val) - return pcfg_desc; - - ret = usb_skip_one_config((PBYTE *) & pcfg_desc); - if (ret == FALSE) - return NULL; - } - - return NULL; -} - -#define if_from_handle( handle ) ( ( handle & 0xff00 ) >> 8 ) - -NTSTATUS -usb_submit_config_urb(PURB purb) -{ - PUSB_DEV pdev; - PUSB_DEV_MANAGER dev_mgr; - PUSB_ENDPOINT pendp; - PURB purb1; - PUSB_CTRL_SETUP_PACKET psetup; - NTSTATUS status; - PHCD hcd; - - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL) - return STATUS_INVALID_PARAMETER; - - pdev = purb->pdev; - pendp = purb->pendp; - - lock_dev(pdev, FALSE); - - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - - if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG || dev_state(pdev) == USB_DEV_STATE_RECONFIG) - { - //outstanding request of set configuration exists in process - status = STATUS_UNSUCCESSFUL; - goto LBL_OUT; - } - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED - && pdev->usb_config->pusb_config_desc->bConfigurationValue == (BYTE) psetup->wValue) - { - //already the current config - status = STATUS_SUCCESS; - goto LBL_OUT; - } - - - if (dev_state(pdev) == USB_DEV_STATE_CONFIGURED) - { - // not support re-configuration yet - status = STATUS_NOT_SUPPORTED; - goto LBL_OUT; - } - - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb1 == NULL) - { - status = STATUS_NO_MEMORY; - goto LBL_OUT; - } - - UsbBuildSelectConfigurationRequest(purb1, - usb_make_handle(pdev->dev_id, 0, 0) | 0xffff, - psetup->wValue, usb_config_dev_completion, 0, ((ULONG) purb)); - purb1->pdev = pdev; - purb1->pendp = pendp; - - //change the dev state - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_FIRST_CONFIG; - - unlock_dev(pdev, FALSE); - - status = hcd->hcd_submit_urb(hcd, pdev, pendp, purb1); - if (status != STATUS_PENDING) - { - usb_free_mem(purb1); - purb1 = NULL; - } - return status; - - LBL_OUT: - unlock_dev(pdev, FALSE); - return status; -} - - -NTSTATUS -usb_submit_urb(PUSB_DEV_MANAGER dev_mgr, PURB purb) -{ - NTSTATUS status; - PUSB_DEV pdev; - LONG if_idx, endp_idx; - DEV_HANDLE endp_handle; - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_ENDPOINT pendp; - - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - if (purb == NULL || dev_mgr == NULL) - return STATUS_INVALID_PARAMETER; - - endp_handle = purb->endp_handle; - - if (endp_handle == 0) - return STATUS_INVALID_PARAMETER; - - status = usb_query_and_lock_dev(dev_mgr, endp_handle, &pdev); - if (status != STATUS_SUCCESS) - { - return status; - } - - if_idx = if_idx_from_handle(endp_handle); - endp_idx = endp_idx_from_handle(endp_handle); - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - status = STATUS_DEVICE_DOES_NOT_EXIST; - goto LBL_OUT; - } - - if (dev_state(pdev) < USB_DEV_STATE_ADDRESSED) - { - unlock_dev(pdev, FALSE); - status = STATUS_DEVICE_NOT_READY; - goto LBL_OUT; - } - - dev_mgr = dev_mgr_from_dev(pdev); - hcd = pdev->hcd; - - if (default_endp_handle(endp_handle)) - { - //default endp - pendp = &pdev->default_endp; - } - else if (if_idx >= MAX_INTERFACES_PER_CONFIG || endp_idx >= MAX_ENDPS_PER_IF) - { - status = STATUS_INVALID_PARAMETER; - unlock_dev(pdev, FALSE); - goto LBL_OUT; - } - else - { - if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED) - { - status = STATUS_DEVICE_NOT_READY; - unlock_dev(pdev, FALSE); - goto LBL_OUT; - } - pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx]; - - } - - purb->pdev = pdev; - purb->pendp = pendp; - - //for default endpoint we have some special process - if (default_endp_handle(endp_handle)) - { - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - if (psetup->bmRequestType == 0 && psetup->bRequest == USB_REQ_SET_CONFIGURATION) - { - unlock_dev(pdev, FALSE); - status = usb_submit_config_urb(purb); - goto LBL_OUT; - } - else if (psetup->bmRequestType == 1 && psetup->bRequest == USB_REQ_SET_INTERFACE) - { - unlock_dev(pdev, FALSE); - // status = STATUS_NOT_SUPPORTED; - status = usb_set_interface(purb); - goto LBL_OUT; - } - else if (psetup->bmRequestType == 0x80 && psetup->bRequest == USB_REQ_GET_DESCRIPTOR) - { - if ((psetup->wValue >> 8) == USB_DT_CONFIG || (psetup->wValue >> 8) == USB_DT_DEVICE) - { - unlock_dev(pdev, FALSE); - status = usb_get_descriptor(pdev, purb); - goto LBL_OUT; - - //get the descriptor directly - //status = hcd->hcd_submit_urb( hcd, pdev, purb->pendp, purb ); - //goto LBL_OUT; - } - } - else if (psetup->bmRequestType == 0x02 && psetup->bRequest == USB_REQ_CLEAR_FEATURE && psetup->wValue == 0) //reset pipe - { - ULONG endp_addr; - BOOLEAN found; - endp_addr = psetup->wIndex; - if ((endp_addr & 0xf) == 0) - { - unlock_dev(pdev, FALSE); - status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - - // search for the endp by the endp addr in the wIndex - found = FALSE; - for(if_idx = 0; if_idx < pdev->usb_config->if_count; if_idx++) - { - for(endp_idx = 0; endp_idx < pdev->usb_config->interf[if_idx].endp_count; endp_idx++) - { - pendp = &pdev->usb_config->interf[if_idx].endp[endp_idx]; - if (pendp->pusb_endp_desc->bEndpointAddress == endp_addr) - { - found = TRUE; - break; - } - } - if (found == TRUE) - break; - } - if (found) - endp_handle = usb_make_handle(pdev->dev_id, if_idx, endp_idx); - else - { - unlock_dev(pdev, FALSE); - status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - unlock_dev(pdev, FALSE); - status = usb_reset_pipe_ex(dev_mgr, endp_handle, usb_reset_pipe_from_dispatch_completion, purb); - - goto LBL_OUT; - } - } - - unlock_dev(pdev, FALSE); - status = hcd->hcd_submit_urb(hcd, pdev, purb->pendp, purb); - -LBL_OUT: - usb_unlock_dev(pdev); - return status; -} - -void -usb_config_dev_completion(PURB purb, PVOID context) -{ - PURB puser_urb; - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - PUSB_CTRL_SETUP_PACKET psetup; - ULONG config_val; - NTSTATUS status; - - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(context); - - if (purb == NULL) - { - return; - } - pdev = purb->pdev; - pendp = purb->pendp; - - if (pdev == NULL) - return; - - if (purb->reference != 0) - puser_urb = (PURB) purb->reference; - else - puser_urb = NULL; - - lock_dev(pdev, TRUE); - - if (puser_urb) - puser_urb->status = purb->status; - - if (purb->status != STATUS_SUCCESS) - { - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - goto LBL_OUT; - } - - if (dev_state(pdev) == USB_DEV_STATE_FIRST_CONFIG) - { - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_ADDRESSED; - } - else if (dev_state(pdev) == USB_DEV_STATE_RECONFIG) - { - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - - } - goto LBL_OUT; - } - // now let's construct usb_config - if (!pdev->usb_config) - { - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - config_val = psetup->wValue; - status = dev_mgr_build_usb_config(pdev, - &pdev->desc_buf[sizeof(USB_DEVICE_DESC)], - config_val, pdev->pusb_dev_desc->bNumConfigurations); - if (status != STATUS_SUCCESS) - { - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_ADDRESSED; - goto LBL_OUT; - } - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - //this usb dev represents physical dev - if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_HUB && pdev->pusb_dev_desc->bDeviceSubClass == 0) - { - pdev->flags &= ~USB_DEV_CLASS_MASK; - pdev->flags |= USB_DEV_CLASS_HUB; - } - else if (pdev->pusb_dev_desc->bDeviceClass == USB_CLASS_MASS_STORAGE - && pdev->pusb_dev_desc->bDeviceSubClass == 0) - { - pdev->flags &= ~USB_DEV_CLASS_MASK; - pdev->flags |= USB_DEV_CLASS_MASSSTOR; - } - else - { - pdev->flags &= ~USB_DEV_CLASS_MASK; - pdev->flags |= USB_DEV_CLASS_SCANNER; - } - } - else - { - //not supported - puser_urb->status = STATUS_NOT_SUPPORTED; - pdev->flags &= ~USB_DEV_STATE_MASK; - pdev->flags |= USB_DEV_STATE_CONFIGURED; - } - -LBL_OUT: - unlock_dev(pdev, TRUE); - usb_free_mem(purb); - if (puser_urb && puser_urb->completion) - puser_urb->completion(puser_urb, puser_urb->context); - - return; -} - -NTSTATUS -usb_get_descriptor(PUSB_DEV pdev, PURB purb) -{ - PUSB_CTRL_SETUP_PACKET psetup; - LONG idx, size, count, i; - PBYTE buf; - PUSB_CONFIGURATION_DESC pcfg_desc1; - - USE_BASIC_NON_PENDING_IRQL; - - if (pdev == NULL || purb == NULL) - return STATUS_INVALID_PARAMETER; - - if (purb->data_buffer == NULL || purb->data_length == 0) - { - return purb->status = STATUS_INVALID_PARAMETER; - } - - lock_dev(pdev, FALSE); - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - if (pdev->desc_buf == NULL) - { - purb->status = STATUS_DEVICE_NOT_READY; - goto LBL_OUT; - } - - if ((psetup->wValue >> 8) == USB_DT_CONFIG) - { - idx = (psetup->wValue & 0xff); - - count = pdev->pusb_dev_desc->bNumConfigurations; - - if (idx >= count) - { - purb->status = STATUS_INVALID_PARAMETER; - goto LBL_OUT; - } - buf = &pdev->desc_buf[sizeof(USB_DEVICE_DESC)]; - pcfg_desc1 = usb_find_config_desc_by_idx(buf, idx, count); - if (pcfg_desc1 == NULL) - { - purb->status = STATUS_UNSUCCESSFUL; - goto LBL_OUT; - } - - size = pcfg_desc1->wTotalLength; - size = size > purb->data_length ? purb->data_length : size; - for(i = 0; i < size; i++) - { - purb->data_buffer[i] = ((PBYTE) pcfg_desc1)[i]; - } - purb->status = STATUS_SUCCESS; - goto LBL_OUT; - - } - else if ((psetup->wValue >> 8) == USB_DT_DEVICE) - { - size = purb->data_length > sizeof(USB_DEVICE_DESC) ? sizeof(USB_DEVICE_DESC) : purb->data_length; - - for(i = 0; i < size; i++) - { - purb->data_buffer[i] = ((PBYTE) pdev->pusb_dev_desc)[i]; - } - purb->status = STATUS_SUCCESS; - } - -LBL_OUT: - unlock_dev(pdev, FALSE); - return purb->status; -} - -LONG -usb_count_list(PLIST_HEAD list_head) -{ - LONG count; - PLIST_ENTRY pthis, pnext; - - if (list_head == NULL) - return 0; - - count = 0; - ListFirst(list_head, pthis); - - while (pthis) - { - ListNext(list_head, pthis, pnext); - pthis = pnext; - count++; - } - return count; -} - -// checks if processor supports Time Stamp Counter -__inline BOOLEAN -usb_query_clicks(PLARGE_INTEGER clicks) -{ - BOOLEAN ret_val = FALSE; - int cpu_info[4]; - //so we have to use intel's cpu??? - -#if defined(_M_IX86) || defined(_M_AMD64) - __cpuid(cpu_info, 1); - if (cpu_info[3] & 0x10) // Time Stamp Counter (TSC) bit - { - clicks->QuadPart = __rdtsc(); - ret_val = TRUE; - } -#endif - return ret_val; -} - -VOID -usb_wait_ms_dpc(ULONG ms) -{ - LARGE_INTEGER Interval; - if (ms <= 0) - return; - - Interval.QuadPart = -ms * 10000; - KeDelayExecutionThread(KernelMode, FALSE, &Interval); -} - - -VOID -usb_wait_us_dpc(ULONG us) -{ - LARGE_INTEGER Interval; - if (us <= 0) - return; - - Interval.QuadPart = -us; - KeDelayExecutionThread(KernelMode, FALSE, &Interval); -} - -VOID -usb_cal_cpu_freq() -{ - LARGE_INTEGER tick1, tick2; - LONG i; - // interval.QuadPart = -40 * 1000 * 1000; - - if (cpu_clock_freq >= 100 * 1000 * 1000) // assume it is valid - return; - - if (usb_query_clicks(&tick1)) - { - for(i = 0; i < 25; i++) - { - usb_query_clicks(&tick1); - KeStallExecutionProcessor(40 * 1000); - usb_query_clicks(&tick2); - cpu_clock_freq += (ULONG) (tick2.QuadPart - tick1.QuadPart); - } - // cpu_clock_freq *= 1000; - usb_dbg_print(DBGLVL_MAXIMUM, ("usb_cal_cpu_freq(): cpu frequency = %d Hz\n", cpu_clock_freq)); - } -} - -NTSTATUS -usb_set_interface(PURB purb) -{ - ULONG u; - PURB purb1; - PCTRL_REQ_STACK pstack; - PUSB_DEV pdev; - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_ENDPOINT pendp; - NTSTATUS status; - - PHCD hcd; - USE_BASIC_NON_PENDING_IRQL; - - purb1 = purb; - pdev = purb->pdev; - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - - lock_dev(pdev, FALSE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_NOT_CONNECTED; - } - if (dev_state(pdev) < USB_DEV_STATE_CONFIGURED) - { - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_NOT_READY; - } - - hcd = pdev->hcd; - - if (psetup->wIndex >= pdev->usb_config->if_count) - { - unlock_dev(pdev, FALSE); - return STATUS_INVALID_PARAMETER; - } - if (psetup->wValue >= pdev->usb_config->interf[psetup->wIndex].altif_count + 1) - { - unlock_dev(pdev, FALSE); - return STATUS_INVALID_PARAMETER; - } - if (pdev->usb_config->interf[psetup->wIndex].pusb_if_desc->bAlternateSetting == psetup->wValue) - { - // already the current interface - unlock_dev(pdev, FALSE); - return STATUS_SUCCESS; - } - // check to see if the endp is busy - for(u = 0; u < pdev->usb_config->interf[psetup->wIndex].endp_count; u++) - { - // This check is not adquate. Since we do not have mechanism to block the new coming - // request during this request. the caller must guarantee no active or pending - // usb request on these endpoint. - pendp = &pdev->usb_config->interf[psetup->wIndex].endp[u]; - if (usb_endp_busy_count(pendp)) - { - // active urb on that endp - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_NOT_READY; - } - if (IsListEmpty(&pendp->urb_list)) - { - // pending urb on that endp - unlock_dev(pdev, FALSE); - return STATUS_DEVICE_NOT_READY; - } - } - unlock_dev(pdev, FALSE); - - if (purb1->ctrl_req_context.ctrl_stack_count == 0) - { - // ok, we have one stack cell for our use - if (purb1->completion != NULL) - { - purb1->ctrl_req_context.ctrl_stack_count = 1; - purb1->ctrl_req_context.ctrl_cur_stack = 0; - } - else - { - // use urb's completion and context - purb1->completion = usb_set_interface_completion; - purb1->context = pdev; - } - } - else - { - if (purb->ctrl_req_context.ctrl_cur_stack + 1 >= purb->ctrl_req_context.ctrl_stack_count) - { - // stack full, let's allocate one new urb, we need stack size one - purb1 = usb_alloc_mem(NonPagedPool, sizeof(URB)); - if (purb1 == NULL) - return STATUS_NO_MEMORY; - - RtlCopyMemory(purb1, purb, sizeof(URB)); - - // we do not use stack - RtlZeroMemory(purb1->ctrl_req_stack, sizeof(CTRL_REQ_STACK)); - purb1->context = pdev; - purb1->completion = usb_set_interface_completion; - purb1->ctrl_parent_urb = purb; - purb1->ctrl_req_context.ctrl_req_flags = CTRL_PARENT_URB_VALID; - - goto LBL_SEND_URB; - } - else - purb->ctrl_req_context.ctrl_cur_stack++; - } - - u = purb1->ctrl_req_context.ctrl_cur_stack; - RtlZeroMemory(&purb1->ctrl_req_stack[u], sizeof(CTRL_REQ_STACK)); - pstack = &purb1->ctrl_req_stack[u]; - pstack->context = pdev; - pstack->urb_completion = usb_set_interface_completion; - -LBL_SEND_URB: - if (hcd == NULL) - return STATUS_INVALID_PARAMETER; - - status = hcd->hcd_submit_urb(hcd, purb->pdev, purb->pendp, purb); - return status; -} - -#define usb_complete_and_free_ctrl_urb( pURB ) \ -{\ - UCHAR i, j;\ - i = pURB->ctrl_req_context.ctrl_cur_stack;\ - j = pURB->ctrl_req_context.ctrl_stack_count;\ - usb_call_ctrl_completion( pURB );\ - if( i == 0xff || j == 0 )\ - usb_free_mem( pURB );\ -} - -VOID -usb_set_interface_completion(PURB purb, PVOID context) -{ - PUSB_CTRL_SETUP_PACKET psetup; - PUSB_INTERFACE pif, palt_if; - USB_INTERFACE temp_if; - UCHAR if_idx, if_alt_idx; - PUSB_DEV pdev; - PUSB_ENDPOINT pendp; - ULONG i; - PLIST_ENTRY pthis, pnext; - - USE_BASIC_NON_PENDING_IRQL; - - UNREFERENCED_PARAMETER(context); - - if (purb == NULL) - return; - - if (purb->status == STATUS_SUCCESS) - { - psetup = (PUSB_CTRL_SETUP_PACKET) purb->setup_packet; - if_idx = (UCHAR) psetup->wIndex; - if_alt_idx = (UCHAR) psetup->wValue; - pdev = purb->pdev; - RtlZeroMemory(&temp_if, sizeof(USB_INTERFACE)); - - lock_dev(pdev, TRUE); - if (dev_state(pdev) == USB_DEV_STATE_ZOMB) - { - unlock_dev(pdev, TRUE); - purb->status = STATUS_DEVICE_NOT_CONNECTED; - purb->data_length = 0; - } - else - { - // let's swap the interface - pif = &pdev->usb_config->interf[if_idx]; - ListFirst(&pif->altif_list, pthis); - pnext = pthis; - do - { - palt_if = struct_ptr(pthis, USB_INTERFACE, altif_list); - if (palt_if->pusb_if_desc->bAlternateSetting == if_alt_idx) - { - break; - } - palt_if = NULL; - ListNext(&pif->altif_list, pthis, pnext); - pthis = pnext; - - } while (pthis); - - if (palt_if != NULL) - { - RtlCopyMemory(&temp_if, palt_if, sizeof(USB_INTERFACE)); - - palt_if->endp_count = pif->endp_count; - RtlCopyMemory(palt_if->endp, pif->endp, sizeof(pif->endp)); - palt_if->pif_drv = pif->pif_drv; - palt_if->pusb_if_desc = pif->pusb_if_desc; - for(i = 0; i < palt_if->endp_count; i++) - { - pendp = &palt_if->endp[i]; - InitializeListHead(&pendp->urb_list); - pendp->flags = 0; - } - - RtlCopyMemory(pif->endp, temp_if.endp, sizeof(temp_if.endp)); - pif->endp_count = temp_if.endp_count; - pif->pusb_if_desc = temp_if.pusb_if_desc; - for(i = 0; i < pif->endp_count; i++) - { - pendp = &pif->endp[i]; - InitializeListHead(&pendp->urb_list); - pendp->flags = 0; - } - } - else - { - TRAP(); - purb->status = STATUS_UNSUCCESSFUL; - } - } - unlock_dev(pdev, TRUE); - } - - // for recursive reason, we have to store the parameter ahead - usb_complete_and_free_ctrl_urb(purb); -} - -// can only be called when current completion finished and called only in -// urb completion. And this func may be called recursively, if this routine -// is called, the urb must be treated as released. -VOID -usb_call_ctrl_completion(PURB purb) -{ - PURB parent_urb; - PCTRL_REQ_STACK pstack; - ULONG i; - - - if (purb == NULL) - return; - - if (purb->ctrl_req_context.ctrl_stack_count != 0) - { - i = purb->ctrl_req_context.ctrl_cur_stack; - if (i > 0 && i < 0x10) - { - i--; - purb->ctrl_req_context.ctrl_cur_stack = (UCHAR) i; - pstack = &purb->ctrl_req_stack[i]; - if (pstack->urb_completion) - { - pstack->urb_completion(purb, pstack->context); - } - else - TRAP(); - } - else if (i == 0) - { - i = purb->ctrl_req_context.ctrl_cur_stack = 0xff; - if (purb->completion) - { - purb->completion(purb, purb->context); - } - else - TRAP(); - } - else if (i == 0xff) - { - // only parent urb's completion, if parent urb exists, can be called - if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID) - { - parent_urb = purb->ctrl_parent_urb; - if (parent_urb) - { - pstack = &parent_urb->ctrl_req_stack[parent_urb->ctrl_req_context.ctrl_cur_stack]; - pstack->urb_completion(parent_urb, pstack->context); - } - else - TRAP(); - } - } - else - TRAP(); - } - else if (purb->ctrl_req_context.ctrl_req_flags & CTRL_PARENT_URB_VALID) - { - // this is the case when the child urb won't use the stack - parent_urb = purb->ctrl_parent_urb; - if (parent_urb) - { - // pstack = &parent_urb->ctrl_req_stack[ parent_urb->ctrl_req_context.ctrl_cur_stack ]; - // pstack->urb_completion( parent_urb, pstack->context ); - usb_call_ctrl_completion(parent_urb); - } - else - TRAP(); - } - else - return; -} diff --git a/reactos/drivers/usb/nt4compat/usbdrv/usb.h b/reactos/drivers/usb/nt4compat/usbdrv/usb.h deleted file mode 100644 index 29a8ce91d50..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/usb.h +++ /dev/null @@ -1,1072 +0,0 @@ -#ifndef __USBD_H__ -#define __USBD_H__ -/* - * Some USB bandwidth allocation constants. - */ - -#define USB2_HOST_DELAY 5 /* nsec, guess */ -#define BW_HOST_DELAY 1000L /* nanoseconds */ -#define BW_HUB_LS_SETUP 333L /* nanoseconds */ - /* 4 full-speed bit times (est.) */ - -#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ -#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) -#define FRAME_TIME_USECS 1000L -#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) - -#define bit_time(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ - /* Trying not to use worst-case bit-stuffing - of (7/6 * 8 * bytecount) = 9.33 * bytecount */ - /* bytecount = data payload byte count */ - -#define ns_to_us(ns) ((ns + 500L) / 1000L) - /* convert & round nanoseconds to microseconds */ - -#define usb_make_handle( dev_Id, if_iDx, endp_iDx) \ -( ( DEV_HANDLE )( ( ( ( ( ULONG )dev_Id ) << 16 ) | ( ( ( ULONG )if_iDx ) << 8 ) ) | ( ( ULONG ) endp_iDx ) ) ) - -#define usb_make_ref( poinTER ) \ -( poinTER ^ 0xffffffff ) - -#define ptr_from_ref uhci_make_ref - -#define dev_id_from_handle( hanDLE ) ( ( ( ULONG ) ( hanDLE ) ) >> 16 ) -#define if_idx_from_handle( hanDLE ) ( ( ( ( ULONG ) ( hanDLE ) ) << 16 ) >> 24 ) -#define endp_idx_from_handle( hanDLE ) ( ( ( ULONG ) ( hanDLE ) ) & 0xff ) - -#define endp_from_handle( pDEV, hanDLE, peNDP ) \ -{\ - LONG if_idx, endp_idx;\ - BOOLEAN def_endp; \ - endp_idx = endp_idx_from_handle( hanDLE );\ - if_idx = if_idx_from_handle( hanDLE );\ - def_endp = ( ( hanDLE & 0xffff ) == 0xffff ); \ - if( def_endp ) \ - peNDP = &pdev->default_endp; \ - else \ - { \ - if( if_idx >= pdev->usb_config->if_count ) \ - peNDP = NULL; \ - else if( endp_idx >= pdev->usb_config->interf[ if_idx ].endp_count ) \ - peNDP = NULL; \ - else \ - peNDP = &( pDEV )->usb_config->interf[ if_idx ].endp[ endp_idx ]; \ - } \ -} - -#define endp_type( enDP ) \ -( ( enDP->flags & USB_ENDP_FLAG_DEFAULT_ENDP ) \ - ? USB_ENDPOINT_XFER_CONTROL\ - : ( ( enDP )->pusb_endp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK ) ) - - -//init work data for urb -#define urb_init( uRb ) \ -{\ - RtlZeroMemory( ( uRb ), sizeof( URB ) ); \ - InitializeListHead( &( uRb )->trasac_list ); \ -} - -#define UsbBuildInterruptOrBulkTransferRequest(uRb, \ - endp_hanDle, \ - data_Buf, \ - data_sIze, \ - completIon, \ - contExt, \ - refereNce ) \ -{ \ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = endp_hanDle;\ - ( uRb )->data_buffer = data_Buf;\ - ( uRb )->data_length = data_sIze;\ - ( uRb )->completion = completIon;\ - ( uRb )->context = contExt; \ - ( uRb )->reference = refereNce; \ -} - - - -#define UsbBuildGetDescriptorRequest(uRb, \ - endp_hAndle, \ - descriPtorType, \ - descriPtorIndex, \ - languaGeId, \ - data_bUffer, \ - data_sIze, \ - compleTion, \ - contexT, \ - refereNce ) \ -{ \ - PUSB_CTRL_SETUP_PACKET pseTup;\ - pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hAndle );\ - ( uRb )->data_length = ( data_sIze ); \ - ( uRb )->data_buffer = ( ( PUCHAR )data_bUffer ); \ - ( uRb )->completion = ( compleTion );\ - ( uRb )->context = ( ( PVOID )contexT ); \ - ( uRb )->reference = ( ULONG )refereNce; \ - pseTup->wValue = ( ( descriPtorType ) << 8 )| ( descriPtorIndex ); \ - pseTup->wLength = ( data_sIze ); \ - pseTup->wIndex = ( languaGeId );\ - pseTup->bRequest = USB_REQ_GET_DESCRIPTOR;\ - pseTup->bmRequestType = 0x80;\ -} - - - -#define UsbBuildGetStatusRequest(uRb, \ - endp_hanDle, \ - recipiEnt, \ - inDex, \ - transferBufFer, \ - completIon, \ - contExt, \ - refereNce ) \ -{ \ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hanDle ); \ - ( uRb )->data_buffer = ( transferBufFer ); \ - ( uRb )->data_length = sizeof(USHORT); \ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt );\ - ( uRb )->reference = ( refereNce );\ - pseTup->bmRequestType = ( 0x80 | recipiEnt );\ - pseTup->bRequest = USB_REQ_GET_STATUS;\ - pseTup->wIndex = ( inDex ); \ - pseTup->wValue = 0;\ - pseTup->wLength = sizeof( USHORT );\ -} - - -#define UsbBuildFeatureRequest(uRb, \ - endp_hanDle,\ - recipiEnt, \ - featureSelecTor, \ - inDex, \ - completIon, \ - contExt, \ - refereNce ) \ - { \ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hanDle ); \ - ( uRb )->data_buffer = NULL;\ - ( uRb )->data_length = ( 0 );\ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt ); \ - ( uRb )->reference = ( refereNce ); \ - pseTup->bmRequestType = recipiEnt; \ - pseTup->bRequest = USB_REQ_SET_FEATURE;\ - pseTup->wValue = ( featureSelecTor );\ - pseTup->wIndex = ( inDex );\ - pseTup->wLength = 0;\ -} - -#define UsbBuildSelectConfigurationRequest(uRb, \ - endp_hanDle,\ - config_Val,\ - completIon, \ - contExt, \ - refereNce ) \ - { \ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hanDle ); \ - ( uRb )->data_buffer = NULL;\ - ( uRb )->data_length = 0;\ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt ); \ - ( uRb )->reference = ( refereNce ); \ - pseTup->bmRequestType = 0;\ - pseTup->bRequest = USB_REQ_SET_CONFIGURATION;\ - pseTup->wValue = ( config_Val );\ - pseTup->wIndex = 0;\ - pseTup->wLength = 0;\ -} - -#define UsbBuildSelectInterfaceRequest(uRb, \ - endp_hanDle,\ - if_Num, \ - alt_Num,\ - completIon, \ - contExt, \ - refereNce ) \ - { \ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hanDle ); \ - ( uRb )->data_buffer = NULL;\ - ( uRb )->data_length = 0;\ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt ); \ - ( uRb )->reference = ( refereNce ); \ - pseTup->bmRequestType = 1;\ - pseTup->bRequest = USB_REQ_SET_INERFACE;\ - pseTup->wValue = ( alt_Num );\ - pseTup->wIndex = ( if_Num );\ - pseTup->wLength = 0;\ -} - - -#define UsbBuildVendorRequest(uRb, \ - endp_hanDle,\ - data_bufFer, \ - data_sIze, \ - request_tYpe, \ - requEst, \ - vaLue, \ - inDex, \ - completIon, \ - contExt, \ - refereNce ) \ - { \ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( endp_hanDle ); \ - ( uRb )->data_buffer = data_bufFer;\ - ( uRb )->data_length = data_sIze;\ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt ); \ - ( uRb )->reference = ( refereNce ); \ - pseTup->bmRequestType = request_tYpe;\ - pseTup->bRequest = requEst;\ - pseTup->wValue = vaLue;\ - pseTup->wIndex = inDex;\ - pseTup->wLength = ( USHORT )data_sIze;\ -} - -#define UsbBuildResetPipeRequest(uRb, \ - dev_hanDle, \ - endp_aDdr, \ - completIon, \ - contExt, \ - refereNce ) \ -{\ - PUSB_CTRL_SETUP_PACKET pseTup = ( PUSB_CTRL_SETUP_PACKET )( uRb )->setup_packet;\ - urb_init( ( uRb ) );\ - ( uRb )->endp_handle = ( dev_hanDle | 0xffff ); \ - ( uRb )->completion = ( completIon );\ - ( uRb )->context = ( contExt ); \ - ( uRb )->reference = ( refereNce ); \ - pseTup->bmRequestType = 0x02;\ - pseTup->bRequest = USB_REQ_CLEAR_FEATURE;\ - pseTup->wIndex = endp_aDdr;\ -} - -// Forward structs declarations -struct _URB; -struct _HCD; -struct _USB_DEV_MANAGER; -struct _USB_DEV; -struct _USB_ENDPOINT; -struct _USB_EVENT; -struct _USB_EVENT_POOL; -struct _USB_DRIVER; - -/* USB constants */ - -#define USB_SPEED_FULL 0x00 -#define USB_SPEED_LOW 0x01 -#define USB_SPEED_HIGH 0x02 - -/* - * Device and/or Interface Class codes - */ -#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 -#define USB_CLASS_DATA 10 -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -/* - * USB types - */ -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -/* - * USB recipients - */ -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -/* - * USB directions - */ -#define USB_DIR_OUT 0 -#define USB_DIR_IN 0x80 - -/* - * Descriptor types - */ -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 - -#define USB_DT_HID (USB_TYPE_CLASS | 0x01) -#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) -#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) -#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) - -/* - * Descriptor sizes per descriptor type - */ -#define USB_DT_DEVICE_SIZE 18 -#define USB_DT_CONFIG_SIZE 9 -#define USB_DT_INTERFACE_SIZE 9 -#define USB_DT_ENDPOINT_SIZE 7 -#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ -#define USB_DT_HUB_NONVAR_SIZE 7 -#define USB_DT_HID_SIZE 9 - -/* - * Endpoints - */ -#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 - -#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 - -/* - * USB Packet IDs (PIDs) - */ -#define USB_PID_UNDEF_0 0xf0 -#define USB_PID_OUT 0xe1 -#define USB_PID_ACK 0xd2 -#define USB_PID_DATA0 0xc3 -#define USB_PID_PING 0xb4 /* USB 2.0 */ -#define USB_PID_SOF 0xa5 -#define USB_PID_NYET 0x96 /* USB 2.0 */ -#define USB_PID_DATA2 0x87 /* USB 2.0 */ -#define USB_PID_SPLIT 0x78 /* USB 2.0 */ -#define USB_PID_IN 0x69 -#define USB_PID_NAK 0x5a -#define USB_PID_DATA1 0x4b -#define USB_PID_PREAMBLE 0x3c /* Token mode */ -#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ -#define USB_PID_SETUP 0x2d -#define USB_PID_STALL 0x1e -#define USB_PID_MDATA 0x0f /* USB 2.0 */ - -/* - * Standard requests - */ -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -/* - * HID requests - */ -#define USB_REQ_GET_REPORT 0x01 -#define USB_REQ_GET_IDLE 0x02 -#define USB_REQ_GET_PROTOCOL 0x03 -#define USB_REQ_SET_REPORT 0x09 -#define USB_REQ_SET_IDLE 0x0A -#define USB_REQ_SET_PROTOCOL 0x0B - -// HUB request -#define HUB_REQ_GET_STATE 0x02 - -// usb2.0 hub -#define HUB_REQ_CLEAR_TT_BUFFER 0x08 - - -typedef LONG USBD_STATUS; - -// -// USBD status codes -// -// Status values are 32 bit values layed out as follows: -// -// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 -// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -// +---+---------------------------+-------------------------------+ -// | S | Status Code | -// +---+---------------------------+-------------------------------+ -// -// where -// -// S - is the state code -// -// 00 - completed with success -// 01 - request is pending -// 10 - completed with error, endpoint not stalled -// 11 - completed with error, endpoint stalled -// -// -// Code - is the status code -// - -// -// Generic test for success on any status value (non-negative numbers -// indicate success). -// - -#define usb_success(Status) ((USBD_STATUS)(Status) >= 0) - -// -// Generic test for pending status value. -// - -#define usb_pending(Status) ((ULONG)(Status) >> 30 == 1) - -// -// Generic test for error on any status value. -// - -#define usb_error(Status) ((USBD_STATUS)(Status) < 0) - -// -// Generic test for stall on any status value. -// - -#define usb_halted(Status) ((ULONG)(Status) >> 30 == 3) - -// -// Macro to check the status code only -// - -#define usb_status(Status) ((ULONG)(Status) & 0x0FFFFFFFL) - - -#define USB_STATUS_SUCCESS ((USBD_STATUS)0x00000000L) -#define USB_STATUS_PENDING ((USBD_STATUS)0x40000000L) -#define USB_STATUS_HALTED ((USBD_STATUS)0xC0000000L) -#define USB_STATUS_ERROR ((USBD_STATUS)0x80000000L) - -// -// HC status codes -// Note: these status codes have both the error and the stall bit set. -// -#define USB_STATUS_CRC ((USBD_STATUS)0xC0000401L) -#define USB_STATUS_BTSTUFF ((USBD_STATUS)0xC0000402L) -#define USB_STATUS_DATA_TOGGLE_MISMATCH ((USBD_STATUS)0xC0000403L) -#define USB_STATUS_STALL_PID ((USBD_STATUS)0xC0000404L) -#define USB_STATUS_DEV_NOT_RESPONDING ((USBD_STATUS)0xC0000405L) -#define USB_STATUS_PID_CHECK_FAILURE ((USBD_STATUS)0xC0000406L) -#define USB_STATUS_UNEXPECTED_PID ((USBD_STATUS)0xC0000407L) -#define USB_STATUS_DATA_OVERRUN ((USBD_STATUS)0xC0000408L) -#define USB_STATUS_DATA_UNDERRUN ((USBD_STATUS)0xC0000409L) -#define USB_STATUS_RESERVED1 ((USBD_STATUS)0xC000040AL) -#define USB_STATUS_RESERVED2 ((USBD_STATUS)0xC000040BL) -#define USB_STATUS_BUFFER_OVERRUN ((USBD_STATUS)0xC000040CL) -#define USB_STATUS_BUFFER_UNDERRUN ((USBD_STATUS)0xC000040DL) -#define USB_STATUS_NOT_ACCESSED ((USBD_STATUS)0xC000040FL) -#define USB_STATUS_FIFO ((USBD_STATUS)0xC0000410L) -#define USB_STATUS_BABBLE_DETECTED ((USBD_STATUS)0xC0000408L) - -// -// returned by HCD if a transfer is submitted to an endpoint that is -// stalled -// -#define USB_STATUS_ENDPOINT_HALTED ((USBD_STATUS)0xC0000430L) - -// -// Software status codes -// Note: the following status codes have only the error bit set -// -#define USB_STATUS_NO_MEMORY ((USBD_STATUS)0x80000100L) -#define USB_STATUS_INVALID_URB_FUNCTION ((USBD_STATUS)0x80000200L) -#define USB_STATUS_INVALID_PARAMETER ((USBD_STATUS)0x80000300L) - -// -// returned if client driver attempts to close an endpoint/interface -// or configuration with outstanding transfers. -// -#define USB_STATUS_ERROR_BUSY ((USBD_STATUS)0x80000400L) -// -// returned by USBD if it cannot complete a URB request, typically this -// will be returned in the URB status field when the Irp is completed -// with a more specific NT error code in the irp.status field. -// -#define USB_STATUS_REQUEST_FAILED ((USBD_STATUS)0x80000500L) - -#define USB_STATUS_INVALID_PIPE_HANDLE ((USBD_STATUS)0x80000600L) - -// returned when there is not enough bandwidth avialable -// to open a requested endpoint -#define USB_STATUS_NO_BANDWIDTH ((USBD_STATUS)0x80000700L) -// -// generic HC error -// -#define USB_STATUS_INTERNAL_HC_ERROR ((USBD_STATUS)0x80000800L) -// -// returned when a short packet terminates the transfer -// ie USBD_SHORT_TRANSFER_OK bit not set -// -#define USB_STATUS_ERROR_SHORT_TRANSFER ((USBD_STATUS)0x80000900L) -// -// returned if the requested start frame is not within -// USBD_ISO_START_FRAME_RANGE of the current USB frame, -// note that the stall bit is set -// -#define USB_STATUS_BAD_START_FRAME ((USBD_STATUS)0xC0000A00L) -// -// returned by HCD if all packets in an iso transfer complete with an error -// -#define USB_STATUS_ISOCH_REQUEST_FAILED ((USBD_STATUS)0xC0000B00L) -// -// returned by USBD if the frame length control for a given -// HC is already taken by anothe driver -// -#define USB_STATUS_FRAME_CONTROL_OWNED ((USBD_STATUS)0xC0000C00L) -// -// returned by USBD if the caller does not own frame length control and -// attempts to release or modify the HC frame length -// -#define USB_STATUS_FRAME_CONTROL_NOT_OWNED ((USBD_STATUS)0xC0000D00L) - -// -// set when a transfers is completed due to an AbortPipe request from -// the client driver -// -// Note: no error or stall bit is set for these status codes -// -#define USB_STATUS_CANCELED ((USBD_STATUS)0x00010000L) - -#define USB_STATUS_CANCELING ((USBD_STATUS)0x00020000L) - -// Device type -- in the "User Defined" range." -#define FILE_HCD_DEV_TYPE 45000 -#define FILE_UHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 1 ) -#define FILE_OHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 2 ) -#define FILE_EHCI_DEV_TYPE ( FILE_HCD_DEV_TYPE + 3 ) -#define FILE_USB_DEV_TYPE ( FILE_HCD_DEV_TYPE + 8 ) - -#define IOCTL_GET_DEV_COUNT CTL_CODE( FILE_HCD_DEV_TYPE, 4093, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer and input_buffer_length is zero, output_buffer is to receive a dword value of the -//dev count, output_buffer_length must be no less than sizeof( unsigned long ). - -#define IOCTL_ENUM_DEVICES CTL_CODE( FILE_HCD_DEV_TYPE, 4094, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer is a dword value to indicate the count of elements in the array -//input_buffer_length is sizeof( unsigned long ), output_buffer is to receive a -//structure ENUM_DEV_ARRAY where dev_count is the elements hold in this array. - -#define IOCTL_GET_DEV_DESC CTL_CODE( FILE_HCD_DEV_TYPE, 4095, METHOD_BUFFERED, FILE_ANY_ACCESS ) -//input_buffer is a structure GET_DEV_DESC_REQ, and the input_buffer_length is -//no less than sizeof( input_buffer ), output_buffer is a buffer to receive the -//requested dev's desc, and output_buffer_length specifies the length of the -//buffer - -#define IOCTL_SUBMIT_URB_RD CTL_CODE( FILE_HCD_DEV_TYPE, 4096, METHOD_IN_DIRECT, FILE_ANY_ACCESS ) -#define IOCTL_SUBMIT_URB_WR CTL_CODE( FILE_HCD_DEV_TYPE, 4097, METHOD_OUT_DIRECT, FILE_ANY_ACCESS ) -// if the major_function is IRP_MJ_DEVICE_CONTROL -// input_buffer is a URB, and input_buffer_length is equal to or greater than -// sizeof( URB ); the output_buffer is a buffer to receive data from or send data -// to device. only the following urb fields can be accessed, others must be zeroed. -// DEV_HANDLE endp_handle; -// UCHAR setup_packet[8]; // for control pipe -// the choosing of IOCTL_SUBMIT_URB_RD or IOCTL_SUBMIT_URB_WR should be determined -// by the current URB, for example, a request string from device will use XXX_RD, -// and a write to the bulk endpoint will use XXX_WR -// if the major_function is IRP_MJ_INTERNAL_DEVICE_CONTROL -// input_buffer is a URB, and input_buffer_length is equal to or greater than -// sizeof( URB ); -// only the following urb fields can be accessed, others must be zeroed. -// DEV_HANDLE endp_handle; -// UCHAR setup_packet[8]; // for control pipe, or zeroed -// PUCHAR data_buffer; // buffer for READ/WRITE -// ULONG data_length; // buffer size in bytes - -#define IOCTL_SUBMIT_URB_NOIO CTL_CODE( FILE_HCD_DEV_TYPE, 4098, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// input_buffer is a URB, and input_buffer_length is equal to or greater than -// sizeof( URB ); the output_buffer is null and no output_buffer_length, -// only the following fields in urb can be accessed, others must be zeroed. -// DEV_HANDLE endp_handle; -// UCHAR setup_packet[8]; //for control pipe -// there is no difference between IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL -#define IOCTL_GET_DEV_HANDLE CTL_CODE( FILE_HCD_DEV_TYPE, 4099, METHOD_BUFFERED, FILE_ANY_ACCESS ) -// input_buffer is null ,and input_buffer_length is zero. -// output_buffer will hold the handle to this dev, output_buffer_length is 4 -// or bigger - -typedef ULONG DEV_HANDLE, ENDP_HANDLE, IF_HANDLE; - -struct URB; -#pragma pack( push, usb_align, 1 ) - -//structures for DeviceIoControl -typedef struct _ENUM_DEV_ELEMENT -{ - DEV_HANDLE dev_handle; - USHORT product_id; - USHORT vendor_id; - UCHAR dev_addr; - -} ENUM_DEV_ELEMENT, *PENUM_DEV_ELEMENT; - -typedef struct _ENUM_DEV_ARRAY -{ - UCHAR dev_count; - ENUM_DEV_ELEMENT dev_arr[ 1 ]; - -} ENUM_DEV_ARRAY, *PENUM_DEV_ARRAY; - -typedef struct _GET_DEV_DESC_REQ -{ - DEV_HANDLE dev_handle; - UCHAR desc_type; - UCHAR desc_idx; - -} GET_DEV_DESC_REQ, *PGET_DEV_DESC_REQ; - -//usb definitions -typedef struct _USB_CTRL_SETUP_PACKET -{ - UCHAR bmRequestType; - UCHAR bRequest; - USHORT wValue; - USHORT wIndex; - USHORT wLength; - -}USB_CTRL_SETUP_PACKET, *PUSB_CTRL_SETUP_PACKET; - -typedef struct _USB_STRING_DESCRIPTOR -{ - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wData[1]; - -} USB_STRING_DESCRIPTOR, *PUSB_STRING_DESCRIPTOR; - -typedef struct _USB_DESC_HEADER -{ - UCHAR bLength; - UCHAR bDescriptorType; - -} USB_DESC_HEADER, *PUSB_DESC_HEADER; - -typedef struct _USB_ENDPOINT_DESC -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bEndpointAddress; - UCHAR bmAttributes; - USHORT wMaxPacketSize; - UCHAR bInterval; - -} USB_ENDPOINT_DESC, *PUSB_ENDPOINT_DESC; - -typedef struct _USB_INTERFACE_DESC -{ - UCHAR bLength; - UCHAR bDescriptorType; - UCHAR bInterfaceNumber; - UCHAR bAlternateSetting; - UCHAR bNumEndpoints; - UCHAR bInterfaceClass; - UCHAR bInterfaceSubClass; - UCHAR bInterfaceProtocol; - UCHAR iInterface; - -} USB_INTERFACE_DESC, *PUSB_INTERFACE_DESC; - -typedef struct _USB_CONFIGURATION_DESC -{ - UCHAR bLength; - UCHAR bDescriptorType; - USHORT wTotalLength; - UCHAR bNumInterfaces; - UCHAR bConfigurationValue; - UCHAR iConfiguration; - UCHAR bmAttributes; - UCHAR MaxPower; - -} USB_CONFIGURATION_DESC, *PUSB_CONFIGURATION_DESC; - -typedef struct _USB_DEVICE_DESC -{ - UCHAR bLength; - UCHAR bDescriptorType; - USHORT bcdUSB; - UCHAR bDeviceClass; - UCHAR bDeviceSubClass; - UCHAR bDeviceProtocol; - UCHAR bMaxPacketSize0; - USHORT idVendor; - USHORT idProduct; - USHORT bcdDevice; - UCHAR iManufacturer; - UCHAR iProduct; - UCHAR iSerialNumber; - UCHAR bNumConfigurations; - -} USB_DEVICE_DESC, *PUSB_DEVICE_DESC; - - -#define URB_FLAG_STATE_MASK 0x0f -#define URB_FLAG_STATE_PENDING 0x00 -#define URB_FLAG_STATE_IN_PROCESS 0x01 -#define URB_FLAG_STATE_FINISHED 0x02 - -// USB2.0 state -#define URB_FLAG_STATE_DOORBELL 0x03 // for async request removal -#define URB_FLAG_STATE_WAIT_FRAME 0x04 // for sync request removal( for cancel only ) -#define URB_FLAG_STATE_ERROR 0x05 - -#define URB_FLAG_IN_SCHEDULE 0x10 -#define URB_FLAG_FORCE_CANCEL 0x20 -#define URB_FLAG_SHORT_PACKET 0x80000000 - -typedef struct _SPLIT_ISO_BUS_TIME -{ - USHORT bus_time; - USHORT start_uframe; - -} SPLIT_ISO_BUS_TIME, *PSPLIT_ISO_BUS_TIME; - -typedef struct _ISO_PACKET_DESC -{ - LONG offset; - LONG length; // expected length - LONG actual_length; - LONG status; - union - { - LONG bus_time; //opaque for client request of split iso, the bus_time is the start_uframe for each transaction - SPLIT_ISO_BUS_TIME params; - }; - -} ISO_PACKET_DESC, *PISO_PACKET_DESC; - -#define CTRL_PARENT_URB_VALID 1 - -typedef void ( *PURBCOMPLETION )( struct _URB *purb, PVOID pcontext); - -typedef struct _CTRL_REQ_STACK -{ - PURBCOMPLETION urb_completion; // the last step of the urb_completion is to call the - // the prevoius stack's callback if has, and the last - // one is purb->completion - PVOID context; - ULONG params[ 3 ]; - -} CTRL_REQ_STACK, *PCTRL_REQ_STACK; - -#pragma pack( pop, usb_align ) - -typedef struct _URB_HS_PIPE_CONTENT -{ - ULONG trans_type : 2; // bit 0-1 - ULONG mult_count : 2; // bit 2-3, used in high speed int and iso requests - ULONG reserved : 1; // bit 1 - ULONG speed_high : 1; // bit 5 - ULONG speed_low : 1; // bit 6 - ULONG trans_dir : 1; // bit 7 - ULONG dev_addr : 7; // bit 8-14 - ULONG endp_addr : 4; // bit 15-18 - ULONG data_toggle : 1; // bit 19 - ULONG max_packet_size : 4; // bit 20-23 log( max_packet_size ) - ULONG interval : 4; // bit 24-27 the same definition in USB2.0, for high or full/low speed - ULONG start_uframe : 3; // bit 28-30 - ULONG reserved1 : 1; // - -} URB_HS_PIPE_CONTENT, *PURB_HS_PIPE_CONTENT; - -typedef struct _URB_HS_CONTEXT_CONTENT -{ - ULONG hub_addr : 7; // high speed hub addr for split transfer - ULONG port_idx : 7; - ULONG reserved : 18; - -} URB_HS_CONTEXT_CONTENT, *PURB_HS_CONTEXT_CONTENT; - -typedef struct _URB -{ - LIST_ENTRY urb_link; - ULONG flags; - DEV_HANDLE endp_handle; - LONG status; - //record info for isr use, similar to td.status - //int pipe has different content in the 8 msb - //the eight bits contain interrupt interval. - //and max packet length is encoded in 3 bits from 23-21 - //that means 2^(x) bytes in the packet. - ULONG pipe; // bit0-1: endp type, bit 6: ls or fs. bit 7: dir - - union - { - UCHAR setup_packet[8]; // for control - LONG params[ 2 ]; // params[ 0 ] is used in iso transfer as max_packet_size - }; - - PUCHAR data_buffer; //user data - LONG data_length; //user data length - - struct _USB_DEV *pdev; - struct _USB_ENDPOINT *pendp; //pipe for current transfer - - PURBCOMPLETION completion; - PVOID context; //parameter of completion - - PVOID urb_ext; //for high speed hcd use - ULONG hs_context; //for high speed hcd use - - PIRP pirp; //irp from client driver - LONG reference; //for caller private use - - LONG td_count; //for any kinds of transfer - LONG rest_bytes; //for split bulk transfer involving more than 1024 tds - LONG bytes_to_transfer; - LONG bytes_transfered; //( bulk transfer )accumulate one split-transfer by xfered bytes of the executed transactions - PLIST_ENTRY last_finished_td; //last inactive td useful for large amount transfer - LIST_ENTRY trasac_list; //list of tds or qhs - - union - { - LONG iso_start_frame; // for high speed endp, this is uframe index, and not used for full/low speed endp, instead, - // iso_packet_desc.param.start_uframe is used. - LONG int_start_frame; // frame( ms ) index for high/full/low speed endp - struct - { - UCHAR ctrl_req_flags; - UCHAR ctrl_stack_count; - UCHAR ctrl_cur_stack; // the receiver uses this by increment the stack pointer first. if the requester - UCHAR ctrl_reserved; // send it down with ctrl_stack_count zero, that means the stack is not initialized, - // and can be initialized by receiver to 1 and only 1. - // If the initializer found the stack size won't meet the number down the drivers, it must - // reallocate one urb with the required stack size. and store the previous urb in - // ctrl_parent_urb - } ctrl_req_context; - }; - - union - { - LONG iso_frame_count; // uframe for high speed and frame for full/low speed - struct _URB* ctrl_parent_urb; - }; - - union - { - ISO_PACKET_DESC iso_packet_desc[ 1 ]; //used to build up trasac_list for iso transfer and claim bandwidth - CTRL_REQ_STACK ctrl_req_stack[ 1 ]; - }; - -} URB, *PURB; - - -NTSTATUS -usb_set_dev_ext( -ULONG dev_ref, -PVOID dev_ext, -LONG size -); - -NTSTATUS -usb_set_if_ext( -ULONG dev_ref, -ULONG if_ref, -PVOID if_ext, -LONG size -); - -PVOID -usb_get_dev_ext( -ULONG dev_ref -); - -PVOID -usb_get_if_ext( -ULONG dev_ref, -ULONG if_ref -); - -NTSTATUS -usb_claim_interface( -ULONG dev_ref, -ULONG if_ref, -struct _USB_DRIVER *usb_drvr -); - -//return reference to the endp -ULONG -usb_get_endp( -ULONG dev_ref, -LONG endp_addr -); - -//return reference to the interface -ULONG -usb_get_interface( -ULONG dev_ref, -LONG if_idx -); - -NTSTATUS -usb_set_configuration( -ULONG dev_ref, -LONG config_value -); - -// each call will return full size of the config desc and -// its if, endp descs. -// return value is the bytes actually returned. -// if the return value is equal to wTotalLength, all the descs of the -// configuration returned. -NTSTATUS -usb_get_config_desc( -ULONG dev_ref, -LONG config_idx, -PCHAR buffer, -PLONG psize -); - -NTSTATUS -usb_submit_urb( -struct _USB_DEV_MANAGER* dev_mgr, -PURB purb -); - -NTSTATUS -usb_cancel_urb( -ULONG dev_ref, -ULONG endp_ref, -PURB purb -); - -void usb_fill_int_urb(PURB urb, - struct _USB_DEV *dev, - ULONG pipe, - PVOID transfer_buffer, - LONG buffer_length, - PURBCOMPLETION complete, - PVOID context, - int interval); - -LONG -usb_calc_bus_time( -LONG low_speed, -LONG input_dir, -LONG isoc, -LONG bytecount -); - -//increment the dev->ref_count to lock the dev -NTSTATUS -usb_query_and_lock_dev( -struct _USB_DEV_MANAGER* dev_mgr, -DEV_HANDLE dev_handle, -struct _USB_DEV** ppdev -); - -//decrement the dev->ref_count -NTSTATUS -usb_unlock_dev( -struct _USB_DEV *dev -); - -NTSTATUS -usb_reset_pipe( -struct _USB_DEV *pdev, -struct _USB_ENDPOINT *pendp, -PURBCOMPLETION client_completion, -PVOID param //parameter for client_completion -); - -VOID -usb_reset_pipe_completion( -PURB purb, -PVOID pcontext -); - -PVOID -usb_alloc_mem( -POOL_TYPE pool_type, -LONG size -); - -VOID -usb_free_mem( -PVOID pbuf -); - -PUSB_CONFIGURATION_DESC -usb_find_config_desc_by_val( -PUCHAR pbuf, -LONG val, -LONG cfg_count -); - -PUSB_CONFIGURATION_DESC -usb_find_config_desc_by_idx( -PUCHAR pbuf, -LONG idx, -LONG cfg_count -); - -BOOLEAN -usb_skip_if_and_altif( -PUCHAR* pdesc_BUF -); - -BOOLEAN -usb_skip_one_config( -PUCHAR* pconfig_desc_BUF -); - -VOID -usb_wait_ms_dpc( -ULONG ms -); - -VOID -usb_wait_us_dpc( -ULONG us -); - -BOOLEAN -usb_query_clicks( -PLARGE_INTEGER clicks -); - -VOID -usb_cal_cpu_freq(VOID); - -NTSTATUS -usb_reset_pipe_ex( -struct _USB_DEV_MANAGER *dev_mgr, -DEV_HANDLE endp_handle, -PURBCOMPLETION reset_completion, -PVOID param -); - -VOID -usb_call_ctrl_completion( -PURB purb -); - -BOOLEAN -is_header_match( -PUCHAR pbuf, -ULONG type -); //used to check descriptor validity -#endif diff --git a/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.h b/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.h deleted file mode 100644 index a504df95490..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.h +++ /dev/null @@ -1,31 +0,0 @@ -//#define NTDDI_VERSION NTDDI_WIN2K -//#define _WIN32_WINNT _WIN32_WINNT_WIN2K - -#include -#include - -// NT4 DDK-compatibility -#ifndef RTL_CONSTANT_STRING -# define RTL_CONSTANT_STRING(s) { sizeof( s ) - sizeof( (s)[0] ), sizeof( s ), s } -#endif - -#ifndef OBJ_KERNEL_HANDLE -# define OBJ_KERNEL_HANDLE 0x00000200L -#endif - -#ifndef FILE_DEVICE_SECURE_OPEN -# define FILE_DEVICE_SECURE_OPEN 0x00000100 -#endif - -#include "debug.h" -#include "usb.h" -#include "hcd.h" -#include "td.h" -#include "irplist.h" -#include "events.h" -#include "devmgr.h" -#include "hub.h" -#include "umss.h" -#include "mouse.h" -#include "keyboard.h" -#include "uhciver.h" diff --git a/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.rc b/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.rc deleted file mode 100644 index 4a1139d5ba2..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/usbdriver.rc +++ /dev/null @@ -1,45 +0,0 @@ -// Resource script for USBISO driver -// Generated by Walt Oney's driver wizard - -#include - -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US - - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,0,1,0 - PRODUCTVERSION 0,0,1,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "This is a beta version of usb driver stack( ehci ), contact me at mypublic99@yahoo.com\0" - VALUE "CompanyName", "Woodhead Software\0" - VALUE "FileDescription", "usbdriver.sys\0" - VALUE "FileVersion", "0, 0, 1, 0\0" - VALUE "InternalName", "usbdriver.sys\0" - VALUE "LegalCopyright", "Copyright © 2002-2004 Woodhead Software\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "usbdriver.sys\0" - VALUE "PrivateBuild", "0.01\0" - VALUE "ProductName", "usb driver stack for windows NT\0" - VALUE "ProductVersion", "0, 0, 1, 0\0" - VALUE "SpecialBuild", "0131.d\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - diff --git a/reactos/drivers/usb/nt4compat/usbdrv/usbdrv.rbuild b/reactos/drivers/usb/nt4compat/usbdrv/usbdrv.rbuild deleted file mode 100644 index 9aad31dadba..00000000000 --- a/reactos/drivers/usb/nt4compat/usbdrv/usbdrv.rbuild +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - . - ntoskrnl - hal - ehci.c - ohci.c - uhci.c - roothub.c - hub.c - td.c - usb.c - umss.c - bulkonly.c - cbi.c - devmgr.c - dmgrdisp.c - compdrv.c - etd.c - gendrv.c - mouse.c - keyboard.c - usbdriver.rc - usbdriver.h -