2006-08-23 22:17:09 +00:00
|
|
|
/**
|
|
|
|
* 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"
|
|
|
|
|
|
|
|
//----------------------------------------------------------
|
|
|
|
|
2006-08-24 12:58:52 +00:00
|
|
|
BOOLEAN
|
2006-08-23 22:17:09 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-08-24 12:58:52 +00:00
|
|
|
BOOLEAN
|
2006-08-23 22:17:09 +00:00
|
|
|
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];
|
2008-12-25 12:27:47 +00:00
|
|
|
pif->pusb_config = pconfig;
|
2006-08-23 22:17:09 +00:00
|
|
|
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
|
2006-08-24 12:58:52 +00:00
|
|
|
BOOLEAN
|
2006-08-23 22:17:09 +00:00
|
|
|
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;
|
2006-08-24 12:58:52 +00:00
|
|
|
USE_BASIC_NON_PENDING_IRQL;
|
2006-08-23 22:17:09 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2006-08-24 12:58:52 +00:00
|
|
|
USE_BASIC_NON_PENDING_IRQL;
|
2006-08-23 22:17:09 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|