mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
Timer modifications, turning on debug messages, implementing more functions (but spinlocks are disabled now).
Now it detects attached device(s) and show info in debug messages. svn path=/trunk/; revision=16800
This commit is contained in:
parent
ad3464c9a6
commit
6cc3428516
8 changed files with 314 additions and 139 deletions
|
@ -100,7 +100,7 @@ DECLARE_MUTEX (usb_bus_list_lock); /* exported only for usbfs */
|
|||
EXPORT_SYMBOL_GPL (usb_bus_list_lock);
|
||||
|
||||
/* used when updating hcd data */
|
||||
static spinlock_t hcd_data_lock = SPIN_LOCK_UNLOCKED;
|
||||
static spinlock_t hcd_data_lock;// = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -476,7 +476,7 @@ static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb)
|
|||
hcd->rh_timer.function = rh_report_status;
|
||||
hcd->rh_timer.data = (unsigned long) urb;
|
||||
/* USB 2.0 spec says 256msec; this is close enough */
|
||||
hcd->rh_timer.expires = jiffies + HZ/4;
|
||||
hcd->rh_timer.expires = HZ/4;
|
||||
add_timer (&hcd->rh_timer);
|
||||
urb->hcpriv = hcd; /* nonzero to indicate it's queued */
|
||||
return 0;
|
||||
|
@ -515,7 +515,7 @@ static void rh_report_status (unsigned long ptr)
|
|||
urb->status = 0;
|
||||
urb->hcpriv = 0;
|
||||
} else
|
||||
mod_timer (&hcd->rh_timer, jiffies + HZ/4);
|
||||
mod_timer (&hcd->rh_timer, HZ/4);
|
||||
spin_unlock (&hcd_data_lock);
|
||||
spin_unlock (&urb->lock);
|
||||
|
||||
|
@ -982,7 +982,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
|
|||
|
||||
if (!hcd || !dev)
|
||||
return -ENODEV;
|
||||
// printk("submit_urb %p, # %i, t %i\n",urb,urb->dev->devnum,usb_pipetype(urb->pipe));
|
||||
printk("submit_urb %p, # %i, t %i\n",urb,urb->dev->devnum,usb_pipetype(urb->pipe));
|
||||
/*
|
||||
* FIXME: make urb timeouts be generic, keeping the HCD cores
|
||||
* as simple as possible.
|
||||
|
@ -1053,10 +1053,12 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
|
|||
|
||||
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
|
||||
done:
|
||||
|
||||
if (status) {
|
||||
usb_put_urb (urb);
|
||||
urb_unlink (urb);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#endif
|
||||
|
||||
/* Wakes up khubd */
|
||||
//static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
|
||||
static spinlock_t hub_event_lock;
|
||||
//static DECLARE_MUTEX(usb_address0_sem);
|
||||
|
||||
static LIST_HEAD(hub_event_list); /* List of hubs needing servicing */
|
||||
|
@ -141,13 +141,24 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
|
|||
case -ECONNRESET: /* async unlink */
|
||||
case -ESHUTDOWN: /* hardware going away */
|
||||
return;
|
||||
|
||||
case -EOVERFLOW:
|
||||
if (hub->RestCounter>0) {
|
||||
// we already resetted one time ...
|
||||
hub->error = 0;
|
||||
hub->nerrors = 0;
|
||||
break;
|
||||
}
|
||||
hub->RestCounter++;
|
||||
|
||||
default: /* presumably an error */
|
||||
/* Cause a hub reset after 10 consecutive errors */
|
||||
//printe("hub_irq got ...: error %d URB: %d",hub->error,urb->status);
|
||||
|
||||
dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status);
|
||||
if ((++hub->nerrors < 10) || hub->error)
|
||||
goto resubmit;
|
||||
hub->error = urb->status;
|
||||
|
||||
/* FALL THROUGH */
|
||||
|
||||
/* let khubd handle things */
|
||||
|
@ -155,6 +166,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
hub->nerrors = 0;
|
||||
|
||||
/* Something happened, let khubd figure it out */
|
||||
|
@ -269,17 +281,40 @@ static void hub_power_on(struct usb_hub *hub)
|
|||
{
|
||||
struct usb_device *dev;
|
||||
int i;
|
||||
int DelayPerPort;
|
||||
int DelayAfterPort;
|
||||
|
||||
DelayAfterPort = hub->descriptor->bPwrOn2PwrGood * 2;
|
||||
DelayPerPort = 0;
|
||||
|
||||
switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
|
||||
case 0x00:
|
||||
DelayAfterPort = hub->descriptor->bPwrOn2PwrGood * 2;
|
||||
DelayPerPort = 0;
|
||||
break;
|
||||
case 0x01:
|
||||
DelayAfterPort = hub->descriptor->bPwrOn2PwrGood;
|
||||
DelayPerPort = hub->descriptor->bPwrOn2PwrGood /4;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
//dev_dbg(hub_dev, "unknown reserved power switching mode\n");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Enable power to the ports */
|
||||
dev_dbg(hubdev(interface_to_usbdev(hub->intf)),
|
||||
"enabling power on all ports\n");
|
||||
dev = interface_to_usbdev(hub->intf);
|
||||
|
||||
for (i = 0; i < hub->descriptor->bNbrPorts; i++)
|
||||
for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
|
||||
set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
|
||||
wait_ms(DelayPerPort);
|
||||
}
|
||||
|
||||
/* Wait for power to be enabled */
|
||||
wait_ms(hub->descriptor->bPwrOn2PwrGood * 2);
|
||||
wait_ms(DelayAfterPort);
|
||||
}
|
||||
|
||||
static int hub_hub_status(struct usb_hub *hub,
|
||||
|
@ -435,6 +470,9 @@ static int hub_configure(struct usb_hub *hub,
|
|||
(hub->descriptor->wHubCharacteristics & HUB_CHAR_PORTIND)
|
||||
? "" : "not");
|
||||
|
||||
if (hub->descriptor->bPwrOn2PwrGood<3) hub->descriptor->bPwrOn2PwrGood = 3;
|
||||
if (hub->descriptor->bPwrOn2PwrGood>20) hub->descriptor->bPwrOn2PwrGood = 20;
|
||||
|
||||
dev_dbg(hub_dev, "power on to power good time: %dms\n",
|
||||
hub->descriptor->bPwrOn2PwrGood * 2);
|
||||
dev_dbg(hub_dev, "hub controller current requirement: %dmA\n",
|
||||
|
@ -560,27 +598,31 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|||
if ((desc->desc.bInterfaceSubClass != 0) &&
|
||||
(desc->desc.bInterfaceSubClass != 1)) {
|
||||
descriptor_error:
|
||||
desc->desc.bInterfaceSubClass =0;
|
||||
dev_err (&intf->dev, "bad descriptor, ignoring hub\n");
|
||||
return -EIO;
|
||||
//return -EIO;
|
||||
}
|
||||
|
||||
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
|
||||
if (desc->desc.bNumEndpoints != 1) {
|
||||
goto descriptor_error;
|
||||
desc->desc.bNumEndpoints = 1;
|
||||
//goto descriptor_error;
|
||||
}
|
||||
|
||||
endpoint = &desc->endpoint[0].desc;
|
||||
|
||||
/* Output endpoint? Curiouser and curiouser.. */
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
|
||||
goto descriptor_error;
|
||||
//goto descriptor_error;
|
||||
endpoint->bEndpointAddress |= USB_DIR_IN;
|
||||
}
|
||||
|
||||
/* If it's not an interrupt endpoint, we'd better punt! */
|
||||
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
!= USB_ENDPOINT_XFER_INT) {
|
||||
goto descriptor_error;
|
||||
return -EIO;
|
||||
endpoint->bmAttributes |= USB_ENDPOINT_XFER_INT;
|
||||
//goto descriptor_error;
|
||||
//return -EIO;
|
||||
}
|
||||
|
||||
/* We found a hub */
|
||||
|
@ -594,6 +636,8 @@ descriptor_error:
|
|||
|
||||
memset(hub, 0, sizeof(*hub));
|
||||
|
||||
hub->RestCounter = 0;
|
||||
|
||||
INIT_LIST_HEAD(&hub->event_list);
|
||||
hub->intf = intf;
|
||||
init_MUTEX(&hub->khubd_sem);
|
||||
|
@ -606,12 +650,13 @@ descriptor_error:
|
|||
|
||||
usb_set_intfdata (intf, hub);
|
||||
|
||||
if (hub_configure(hub, endpoint) >= 0) {
|
||||
if (hub_configure(hub, endpoint) >= 0)
|
||||
{
|
||||
strcpy (intf->dev.name, "Hub");
|
||||
return 0;
|
||||
}
|
||||
|
||||
hub_disconnect (intf);
|
||||
//hub_disconnect (intf);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -703,6 +748,9 @@ static int hub_port_status(struct usb_device *dev, int port,
|
|||
struct usb_hub *hub = usb_get_intfdata (dev->actconfig->interface);
|
||||
int ret;
|
||||
|
||||
if (!hub)
|
||||
return -ENODEV;
|
||||
|
||||
ret = get_port_status(dev, port + 1, &hub->status->port);
|
||||
if (ret < 0) {
|
||||
dev_err (hubdev (dev),
|
||||
|
@ -717,9 +765,10 @@ static int hub_port_status(struct usb_device *dev, int port,
|
|||
}
|
||||
|
||||
#define HUB_RESET_TRIES 5
|
||||
#define HUB_PROBE_TRIES 2
|
||||
#define HUB_PROBE_TRIES 5
|
||||
#define HUB_ROOT_RESET_TIME 40
|
||||
#define HUB_SHORT_RESET_TIME 10
|
||||
#define HUB_LONG_RESET_TIME 200
|
||||
#define HUB_LONG_RESET_TIME 70
|
||||
#define HUB_RESET_TIMEOUT 500
|
||||
|
||||
/* return: -1 on error, 0 on success, 1 on disconnect. */
|
||||
|
@ -835,8 +884,8 @@ int hub_port_disable(struct usb_device *hub, int port)
|
|||
*/
|
||||
|
||||
#define HUB_DEBOUNCE_TIMEOUT 400
|
||||
#define HUB_DEBOUNCE_STEP 25
|
||||
#define HUB_DEBOUNCE_STABLE 4
|
||||
#define HUB_DEBOUNCE_STEP 5
|
||||
#define HUB_DEBOUNCE_STABLE 3
|
||||
|
||||
/* return: -1 on error, 0 on success, 1 on disconnect. */
|
||||
static int hub_port_debounce(struct usb_device *hub, int port)
|
||||
|
@ -885,7 +934,11 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
struct usb_device *dev;
|
||||
unsigned int delay = HUB_SHORT_RESET_TIME;
|
||||
int i;
|
||||
|
||||
int DevcoosenAdress = 0;
|
||||
|
||||
//printe("port %d, status %x, change %x,\n",port + 1, portstatus, portchange);
|
||||
|
||||
|
||||
dev_dbg (&hubstate->intf->dev,
|
||||
"port %d, status %x, change %x, %s\n",
|
||||
port + 1, portstatus, portchange, portspeed (portstatus));
|
||||
|
@ -909,10 +962,17 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
dev_err (&hubstate->intf->dev,
|
||||
"connect-debounce failed, port %d disabled\n",
|
||||
port+1);
|
||||
//printe("connect-debounce failed, port %d disabled\n", port+1);
|
||||
hub_port_disable(hub, port);
|
||||
return;
|
||||
}
|
||||
|
||||
/* root hub ports have a slightly longer reset period
|
||||
* (from USB 2.0 spec, section 7.1.7.5)
|
||||
*/
|
||||
if (!hub->parent)
|
||||
delay = HUB_ROOT_RESET_TIME;
|
||||
|
||||
/* Some low speed devices have problems with the quick delay, so */
|
||||
/* be a bit pessimistic with those devices. RHbug #23670 */
|
||||
if (portstatus & USB_PORT_STAT_LOW_SPEED)
|
||||
|
@ -932,7 +992,7 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
break;
|
||||
}
|
||||
|
||||
hub->children[port] = dev;
|
||||
|
||||
dev->state = USB_STATE_POWERED;
|
||||
|
||||
/* Reset the device, and detect its speed */
|
||||
|
@ -942,8 +1002,12 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
}
|
||||
|
||||
/* Find a new address for it */
|
||||
usb_connect(dev);
|
||||
|
||||
if (DevcoosenAdress==0) {
|
||||
usb_choose_address(dev);
|
||||
DevcoosenAdress = dev->devnum;
|
||||
}
|
||||
dev->devnum = DevcoosenAdress ;
|
||||
|
||||
/* Set up TT records, if needed */
|
||||
if (hub->tt) {
|
||||
dev->tt = hub->tt;
|
||||
|
@ -985,8 +1049,10 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
dev->dev.parent = dev->parent->dev.parent->parent;
|
||||
|
||||
/* Run it through the hoops (find a driver, etc) */
|
||||
if (!usb_new_device(dev, &hub->dev))
|
||||
if (!usb_new_device(dev, &hub->dev)) {
|
||||
hub->children[port] = dev;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Free the configuration if there was an error */
|
||||
usb_put_dev(dev);
|
||||
|
@ -995,7 +1061,7 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port,
|
|||
delay = HUB_LONG_RESET_TIME;
|
||||
}
|
||||
|
||||
hub->children[port] = NULL;
|
||||
|
||||
hub_port_disable(hub, port);
|
||||
done:
|
||||
up(&usb_address0_sem);
|
||||
|
@ -1149,34 +1215,39 @@ static int STDCALL hub_thread(void *__hub)
|
|||
|
||||
daemonize("khubd");
|
||||
allow_signal(SIGKILL);
|
||||
|
||||
// Initialize khubd spinlock
|
||||
KeInitializeSpinLock((PKSPIN_LOCK)&hub_event_lock);
|
||||
|
||||
/* Send me a signal to get me die (for debugging) */
|
||||
do {
|
||||
LARGE_INTEGER delay;
|
||||
|
||||
/* The following is just for debug */
|
||||
inc_jiffies(1);
|
||||
do_all_timers();
|
||||
handle_irqs(-1);
|
||||
/* End of debug hack*/
|
||||
|
||||
hub_events();
|
||||
|
||||
/* The following is just for debug */
|
||||
handle_irqs(-1);
|
||||
/* End of debug hack*/
|
||||
|
||||
|
||||
//FIXME: Correct this
|
||||
//wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); // interruptable_sleep_on analog - below
|
||||
//while (!list_empty(&hub_event_list)) {
|
||||
// interruptible_sleep_on(&khubd_wait);
|
||||
//}
|
||||
|
||||
delay.QuadPart = -10000*100; // convert to 100ns units
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1);
|
||||
|
||||
if (current->flags & PF_FREEZE)
|
||||
refrigerator(PF_IOTHREAD);
|
||||
|
||||
} while (!signal_pending(current));
|
||||
|
||||
// dbg("hub_thread exiting");
|
||||
dbg("hub_thread exiting");
|
||||
complete_and_exit(&khubd_exited, 0);
|
||||
}
|
||||
|
||||
|
@ -1361,20 +1432,24 @@ int usb_physical_reset_device(struct usb_device *dev)
|
|||
return 1;
|
||||
}
|
||||
|
||||
dev->actconfig = dev->config;
|
||||
usb_set_maxpacket(dev);
|
||||
usb_set_configuration(dev, dev->config[0].desc.bConfigurationValue);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
kfree(descriptor);
|
||||
|
||||
ret = usb_set_configuration(dev, dev->actconfig->desc.bConfigurationValue);
|
||||
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
|
||||
USB_REQ_SET_CONFIGURATION, 0,
|
||||
dev->actconfig->desc.bConfigurationValue, 0,
|
||||
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
|
||||
if (ret < 0) {
|
||||
err("failed to set dev %s active configuration (error=%d)",
|
||||
dev->devpath, ret);
|
||||
return ret;
|
||||
}
|
||||
dev->state = USB_STATE_CONFIGURED;
|
||||
|
||||
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
|
||||
struct usb_interface *intf = &dev->actconfig->interface[i];
|
||||
|
|
|
@ -40,6 +40,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
|
|||
struct usb_api_data awd;
|
||||
int status;
|
||||
|
||||
printk("usb_start_wait_urb(): urb devnum=%d, timeout=%d, urb->actual_length=%d\n", urb->dev->devnum, timeout, urb->actual_length);
|
||||
|
||||
init_waitqueue_head((PKEVENT)&awd.wqh);
|
||||
awd.done = 0;
|
||||
|
||||
|
@ -48,6 +50,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
|
|||
|
||||
urb->context = &awd;
|
||||
status = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
if (status) {
|
||||
// something went wrong
|
||||
usb_free_urb(urb);
|
||||
|
@ -55,7 +58,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
|
|||
remove_wait_queue(&awd.wqh, &wait);
|
||||
return status;
|
||||
}
|
||||
|
||||
printk("TRACE 3.1, timeout=%d, awd.done=%d\n", timeout, awd.done);
|
||||
while (timeout && !awd.done)
|
||||
{
|
||||
timeout = schedule_timeout(timeout);
|
||||
|
@ -84,6 +87,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
|
|||
*actual_length = urb->actual_length;
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -152,12 +156,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u
|
|||
dr->wIndex = cpu_to_le16p(&index);
|
||||
dr->wLength = cpu_to_le16p(&size);
|
||||
|
||||
//dbg("usb_control_msg");
|
||||
printk("usb_control_msg: devnum=%d, size=%d, timeout=%d\n", dev->devnum, size, timeout);
|
||||
|
||||
ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
|
||||
|
||||
kfree(dr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -201,8 +201,8 @@ int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
|||
struct usb_device *dev;
|
||||
struct usb_operations *op;
|
||||
int is_out;
|
||||
// printk("sub dev %p bus %p num %i op %p sub %p\n",
|
||||
// urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb);
|
||||
printk("sub dev %p bus %p num %i op %p sub %p\n",
|
||||
urb->dev, urb->dev->bus,urb->dev->devnum,urb->dev->bus->op, urb->dev->bus->op->submit_urb);
|
||||
if (!urb || urb->hcpriv || !urb->complete)
|
||||
return -EINVAL;
|
||||
if (!(dev = urb->dev) ||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "hcd.h"
|
||||
#endif
|
||||
|
||||
#define DEBUG
|
||||
|
||||
extern int usb_hub_init(void);
|
||||
extern void usb_hub_cleanup(void);
|
||||
|
@ -95,6 +96,9 @@ int usb_device_probe(struct device *dev)
|
|||
|
||||
if (!driver->probe)
|
||||
return error;
|
||||
/* driver claim() doesn't yet affect dev->driver... */
|
||||
if (intf->driver)
|
||||
return error;
|
||||
|
||||
id = usb_match_id (intf, driver->id_table);
|
||||
if (id) {
|
||||
|
@ -396,6 +400,14 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
|
|||
{
|
||||
struct usb_host_interface *intf;
|
||||
struct usb_device *dev;
|
||||
struct usb_device_id *save_id;
|
||||
int firsttime;
|
||||
|
||||
firsttime = 1;
|
||||
|
||||
save_id = (struct usb_device_id*)id;
|
||||
retry_id:
|
||||
id = (struct usb_device_id*)save_id;
|
||||
|
||||
/* proc_connectinfo in devio.c may call us with id == NULL. */
|
||||
if (id == NULL)
|
||||
|
@ -967,6 +979,35 @@ void STDCALL usb_connect(struct usb_device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_choose_address - pick device address (usbcore-internal)
|
||||
* @dev: newly detected device (in DEFAULT state)
|
||||
*
|
||||
* Picks a device address. It's up to the hub (or root hub) driver
|
||||
* to handle and manage enumeration, starting from the DEFAULT state.
|
||||
* Only hub drivers (but not virtual root hub drivers for host
|
||||
* controllers) should ever call this.
|
||||
*/
|
||||
void usb_choose_address(struct usb_device *dev)
|
||||
{
|
||||
int devnum;
|
||||
// FIXME needs locking for SMP!!
|
||||
/* why? this is called only from the hub thread,
|
||||
* which hopefully doesn't run on multiple CPU's simultaneously 8-)
|
||||
*/
|
||||
|
||||
/* Try to allocate the next devnum beginning at bus->devnum_next. */
|
||||
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, dev->bus->devnum_next);
|
||||
if (devnum >= 128)
|
||||
devnum = find_next_zero_bit(dev->bus->devmap.devicemap, 128, 1);
|
||||
|
||||
dev->bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);
|
||||
|
||||
if (devnum < 128) {
|
||||
set_bit(devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = devnum;
|
||||
}
|
||||
}
|
||||
|
||||
// hub-only!! ... and only exported for reset/reinit path.
|
||||
// otherwise used internally, for usb_new_device()
|
||||
|
@ -1062,10 +1103,10 @@ static void set_device_description (struct usb_device *dev)
|
|||
* controllers) should ever call this.
|
||||
*/
|
||||
#define NEW_DEVICE_RETRYS 2
|
||||
#define SET_ADDRESS_RETRYS 2
|
||||
#define SET_ADDRESS_RETRYS 20
|
||||
int usb_new_device(struct usb_device *dev, struct device *parent)
|
||||
{
|
||||
int err = 0;
|
||||
int err = -EINVAL;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
|
@ -1108,7 +1149,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
i = 8;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
dev->epmaxpacketin [0] = i;
|
||||
dev->epmaxpacketout[0] = i;
|
||||
|
@ -1119,15 +1160,12 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
err = usb_set_address(dev);
|
||||
if (err >= 0)
|
||||
break;
|
||||
wait_ms(200);
|
||||
wait_ms(5);
|
||||
}
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n",
|
||||
dev->devnum, err);
|
||||
dev->state = USB_STATE_DEFAULT;
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return 1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wait_ms(10); /* Let the SET_ADDRESS settle */
|
||||
|
@ -1140,17 +1178,13 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
}
|
||||
|
||||
if (err < 8) {
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "USB device not responding, giving up (error=%d)\n", err);
|
||||
}
|
||||
else {
|
||||
dev_err(&dev->dev, "USB device descriptor short read (expected %i, got %i)\n", 8, err);
|
||||
}
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return 1;
|
||||
dev_err(&dev->dev, "device descriptor read/8, error %d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
if (dev->speed == USB_SPEED_FULL) {
|
||||
//usb_disable_endpoint(dev, 0);
|
||||
usb_endpoint_running(dev, 0, 1);
|
||||
usb_endpoint_running(dev, 0, 0);
|
||||
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
|
||||
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
|
||||
}
|
||||
|
@ -1159,26 +1193,15 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
|
||||
err = usb_get_device_descriptor(dev);
|
||||
if (err < (signed)sizeof(dev->descriptor)) {
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "unable to get device descriptor (error=%d)\n", err);
|
||||
}
|
||||
else {
|
||||
dev_err(&dev->dev, "USB device descriptor short read (expected %Zi, got %i)\n",
|
||||
sizeof(dev->descriptor), err);
|
||||
}
|
||||
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return 1;
|
||||
dev_err(&dev->dev, "device descriptor read/all, error %d\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = usb_get_configuration(dev);
|
||||
if (err < 0) {
|
||||
dev_err(&dev->dev, "unable to get device %d configuration (error=%d)\n",
|
||||
dev->devnum, err);
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return 1;
|
||||
dev_err(&dev->dev, "can't read configurations, error %d\n",
|
||||
err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* we set the default configuration here */
|
||||
|
@ -1186,9 +1209,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
if (err) {
|
||||
dev_err(&dev->dev, "failed to set device %d default configuration (error=%d)\n",
|
||||
dev->devnum, err);
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return 1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* USB device state == configured ... tell the world! */
|
||||
|
@ -1234,7 +1255,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
"usb-%s-%s interface %d",
|
||||
dev->bus->bus_name, dev->devpath,
|
||||
desc->bInterfaceNumber);
|
||||
DPRINT1("usb_new_device: %s\n", interface->dev.name);
|
||||
DPRINT1(".........................usb_new_device: %s\n", interface->dev.name);
|
||||
}
|
||||
dev_dbg (&dev->dev, "%s - registering interface %s\n", __FUNCTION__, interface->dev.bus_id);
|
||||
device_add (&interface->dev);
|
||||
|
@ -1244,6 +1265,11 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
|
|||
usbfs_add_device(dev);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
dev->state = USB_STATE_DEFAULT;
|
||||
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
|
||||
dev->devnum = -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -125,6 +125,27 @@ VOID STDCALL DriverUnload(PDRIVER_OBJECT DriverObject)
|
|||
ohci_hcd_pci_cleanup();
|
||||
}
|
||||
|
||||
void RegisterISR(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status;
|
||||
POHCI_DEVICE_EXTENSION DeviceExtension = (POHCI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* Connect interrupt and enable them */
|
||||
Status = IoConnectInterrupt(
|
||||
&DeviceExtension->InterruptObject, SerialInterruptService,
|
||||
DeviceObject, NULL,
|
||||
Vector, Dirql, Dirql,
|
||||
InterruptMode, ShareInterrupt,
|
||||
Affinity, FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("hci: IoConnectInterrupt() failed with status 0x%08x\n", Status);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
|
@ -154,6 +175,9 @@ InitLinuxWrapper(PDEVICE_OBJECT DeviceObject)
|
|||
// Probe device with real id now
|
||||
ohci_pci_driver.probe(dev, pci_ids);
|
||||
|
||||
// Register interrupt here
|
||||
RegisterISR(DeviceObject);
|
||||
|
||||
DPRINT1("InitLinuxWrapper() done\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -169,6 +193,9 @@ OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
|||
POHCI_DEVICE_EXTENSION DeviceExtension;
|
||||
PCM_RESOURCE_LIST AllocatedResources;
|
||||
|
||||
NTSTATUS Status; // debug
|
||||
LONGLONG delay; // debug
|
||||
|
||||
/*
|
||||
* Get the initialization data we saved in VideoPortInitialize.
|
||||
*/
|
||||
|
@ -236,7 +263,13 @@ OHCD_PnPStartDevice(IN PDEVICE_OBJECT DeviceObject,
|
|||
/*
|
||||
* Init wrapper with this object
|
||||
*/
|
||||
return InitLinuxWrapper(DeviceObject);
|
||||
//return InitLinuxWrapper(DeviceObject);
|
||||
Status = InitLinuxWrapper(DeviceObject);
|
||||
|
||||
delay = -10000000*60*2; // wait 2 minutes
|
||||
KeDelayExecutionThread(KernelMode, FALSE, (LARGE_INTEGER *)&delay); //wait_us(1);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Dispatch PNP
|
||||
|
|
|
@ -34,7 +34,12 @@ typedef short s16;
|
|||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef int spinlock_t;
|
||||
typedef struct
|
||||
{
|
||||
KSPIN_LOCK SpinLock;
|
||||
KIRQL OldIrql;
|
||||
} spinlock_t;
|
||||
|
||||
typedef int atomic_t;
|
||||
#ifndef STANDALONE
|
||||
#ifndef _MODE_T_
|
||||
|
@ -156,7 +161,8 @@ struct pt_regs
|
|||
};
|
||||
struct completion {
|
||||
unsigned int done;
|
||||
wait_queue_head_t wait;
|
||||
KEVENT wait;
|
||||
//wait_queue_head_t wait;
|
||||
};
|
||||
|
||||
// windows lookaside list head
|
||||
|
@ -383,12 +389,19 @@ struct usbdevfs_hub_portinfo
|
|||
#define init_MUTEX(x)
|
||||
|
||||
#define SPIN_LOCK_UNLOCKED 0
|
||||
#define spin_lock_init(a) do {} while(0)
|
||||
#define spin_lock(a) *(int*)a=1
|
||||
#define spin_unlock(a) do {} while(0)
|
||||
|
||||
#define spin_lock_irqsave(a,b) b=0
|
||||
#define spin_unlock_irqrestore(a,b)
|
||||
#define spin_lock_init(a) my_spin_lock_init(a)
|
||||
void my_spin_lock_init(spinlock_t *sl);
|
||||
|
||||
#define spin_lock(a) my_spin_lock(a)
|
||||
void my_spin_lock(spinlock_t *sl);
|
||||
|
||||
#define spin_unlock(a) my_spin_unlock(a)
|
||||
void my_spin_unlock(spinlock_t *sl);
|
||||
|
||||
#define spin_lock_irqsave(a,b) my_spin_lock_irqsave(a,b)
|
||||
void my_spin_lock_irqsave(spinlock_t *sl, int flags);
|
||||
#define spin_unlock_irqrestore(a,b) my_spin_unlock(a)
|
||||
|
||||
#if 0
|
||||
#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
|
||||
|
@ -526,12 +539,15 @@ void my_init_waitqueue_head(PKEVENT a);
|
|||
VOID KeMemoryBarrier(VOID);
|
||||
|
||||
#define mb() KeMemoryBarrier()
|
||||
#define wmb() __asm__ __volatile__ ("": : :"memory")
|
||||
#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
|
||||
#define wmb() do {} while (0)
|
||||
#define rmb() do {} while (0)
|
||||
/*#define wmb() __asm__ __volatile__ ("": : :"memory")
|
||||
#define rmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")*/
|
||||
|
||||
#define in_interrupt() 0
|
||||
|
||||
#define init_completion(x) (x)->done=0
|
||||
#define init_completion(x) my_init_completion(x)
|
||||
void my_init_completion(struct completion *);
|
||||
#define wait_for_completion(x) my_wait_for_completion(x)
|
||||
void my_wait_for_completion(struct completion*);
|
||||
|
||||
|
@ -790,9 +806,10 @@ void my_wake_up(PKEVENT);
|
|||
// cannot be mapped via macro due to collision with urb->complete
|
||||
static void __inline__ complete(struct completion *p)
|
||||
{
|
||||
printk("completing event 0x%08x\n", (ULONG)p);
|
||||
/* Wake up x->wait */
|
||||
p->done++;
|
||||
wake_up((PKEVENT)&p->wait);
|
||||
wake_up((PKEVENT)&p->wait);
|
||||
}
|
||||
|
||||
#define kernel_thread(a,b,c) my_kernel_thread(a,b,c)
|
||||
|
@ -832,7 +849,5 @@ void inc_jiffies(int);
|
|||
void init_wrapper(struct pci_dev *pci_dev);
|
||||
void do_all_timers(void);
|
||||
|
||||
#define __KERNEL_DS 0x18
|
||||
|
||||
int my_pci_write_config_word(struct pci_dev *, int, u16);
|
||||
|
||||
|
|
|
@ -242,56 +242,65 @@ extern unsigned int LAST_USB_IRQ;
|
|||
int my_schedule_timeout(int x)
|
||||
{
|
||||
LONGLONG HH;
|
||||
LONGLONG temp;
|
||||
LONGLONG delay;
|
||||
extern unsigned int LAST_USB_EVENT_TICK;
|
||||
//LONGLONG temp;
|
||||
LARGE_INTEGER delay;
|
||||
//PULONG tmp_debug=NULL;
|
||||
//extern unsigned int LAST_USB_EVENT_TICK;
|
||||
|
||||
//*tmp_debug = 0xFFAAFFAA;
|
||||
|
||||
printk("schedule_timeout: %d ms\n", x);
|
||||
|
||||
//delay.QuadPart = -x*10000; // convert to 100ns units
|
||||
//KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1);
|
||||
|
||||
/*
|
||||
x+=5; // safety
|
||||
x = x*1000; // to us format
|
||||
*/
|
||||
x = 300; // it's enough for most purposes
|
||||
|
||||
while(x>0)
|
||||
{
|
||||
KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008);
|
||||
temp = HH - LAST_USB_EVENT_TICK;
|
||||
//temp = HH - LAST_USB_EVENT_TICK;
|
||||
|
||||
//if (temp>(3579)) { //3579 = 1ms!
|
||||
if (temp>1000) {
|
||||
//if (temp>1000) {
|
||||
do_all_timers();
|
||||
LAST_USB_EVENT_TICK = HH;
|
||||
}
|
||||
|
||||
//if (LAST_USB_IRQ != OHCI_1_INTERRUPT ) {
|
||||
// LAST_USB_IRQ = OHCI_1_INTERRUPT;
|
||||
handle_irqs(-1);
|
||||
// LAST_USB_EVENT_TICK = HH;
|
||||
//}
|
||||
|
||||
handle_irqs(-1);
|
||||
|
||||
if (need_wakeup)
|
||||
break;
|
||||
|
||||
delay = 10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, (LARGE_INTEGER *)&delay); //wait_us(1);
|
||||
delay.QuadPart = -10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1);
|
||||
x-=1;
|
||||
//DPRINT("schedule_timeout(): time left: %d\n", x);
|
||||
}
|
||||
need_wakeup=0;
|
||||
|
||||
printk("schedule DONE!!!!!!\n");
|
||||
|
||||
return x;
|
||||
return 0;//x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wait_for_completion(struct completion *x)
|
||||
{
|
||||
LONGLONG HH;
|
||||
LONGLONG temp;
|
||||
LONGLONG delay;
|
||||
LARGE_INTEGER delay;
|
||||
|
||||
extern unsigned int LAST_USB_EVENT_TICK;
|
||||
|
||||
printk("wait for completion\n");
|
||||
printk("wait for completion11, x=0x%08x\n", (DWORD)x);
|
||||
|
||||
int n=10;
|
||||
n = n*1000; // to us format
|
||||
|
||||
|
||||
while(!x->done && (n>0))
|
||||
{
|
||||
KeQueryTickCount((LARGE_INTEGER *)&HH);//IoInputDword(0x8008);
|
||||
|
@ -299,23 +308,26 @@ void my_wait_for_completion(struct completion *x)
|
|||
|
||||
//if (temp>(3579)) {
|
||||
if (temp>(1000)) {
|
||||
do_all_timers();
|
||||
// do_all_timers();
|
||||
LAST_USB_EVENT_TICK = HH;
|
||||
}
|
||||
|
||||
//if (LAST_USB_IRQ != OHCI_1_INTERRUPT ) {
|
||||
// LAST_USB_IRQ = OHCI_1_INTERRUPT;
|
||||
handle_irqs(-1);
|
||||
//}
|
||||
// handle_irqs(-1);
|
||||
|
||||
delay = 10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, (LARGE_INTEGER *)&delay); //wait_us(1);
|
||||
delay.QuadPart = -10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &delay); //wait_us(1);
|
||||
n--;
|
||||
}
|
||||
printk("wait for completion done %i\n",x->done);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_init_completion(struct completion *x)
|
||||
{
|
||||
x->done=0;
|
||||
KeInitializeEvent(&x->wait, NotificationEvent, FALSE);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_interruptible_sleep_on(PKEVENT evnt)
|
||||
{
|
||||
KeWaitForSingleObject(evnt, Executive, KernelMode, FALSE, NULL);
|
||||
|
@ -364,6 +376,7 @@ int my_request_irq(unsigned int irq,
|
|||
num_irqs++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
@ -609,8 +622,8 @@ struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, si
|
|||
return 0;
|
||||
|
||||
retval = ExAllocatePool(NonPagedPool, sizeof(struct pci_pool)); // Non-paged because could be
|
||||
// pci_pool is rather big struct
|
||||
|
||||
// accesses at IRQL < PASSIVE
|
||||
|
||||
// fill retval structure
|
||||
strncpy (retval->name, name, sizeof retval->name);
|
||||
retval->name[sizeof retval->name - 1] = 0;
|
||||
|
@ -623,7 +636,7 @@ struct pci_pool *my_pci_pool_create(const char * name, struct pci_dev * pdev, si
|
|||
retval->pages_allocated = 0;
|
||||
retval->blocks_allocated = 0;
|
||||
|
||||
DPRINT1("pci_pool_create(): %s/%s size %d, %d/page (%d alloc)\n",
|
||||
DPRINT("pci_pool_create(): %s/%s size %d, %d/page (%d alloc)\n",
|
||||
pdev ? pdev->slot_name : NULL, retval->name, size,
|
||||
retval->blocks_per_page, allocation);
|
||||
|
||||
|
@ -652,10 +665,11 @@ void * my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_
|
|||
{
|
||||
PVOID result;
|
||||
POHCI_DEVICE_EXTENSION devExt = (POHCI_DEVICE_EXTENSION)pool->pdev->dev_ext;
|
||||
//PHYSICAL_ADDRESS logicalAddr;
|
||||
DPRINT1("pci_pool_alloc() called, blocks already allocated=%d\n", pool->blocks_allocated);
|
||||
//size_t current_block_in_page;
|
||||
int page,map,i,block,offset;
|
||||
int page=0, offset;
|
||||
int map, i, block;
|
||||
|
||||
//DPRINT1("pci_pool_alloc() called, blocks already allocated=%d, dma_handle=%p\n", pool->blocks_allocated, dma_handle);
|
||||
//ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
if (pool->pages_allocated == 0)
|
||||
{
|
||||
|
@ -665,7 +679,7 @@ void * my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_
|
|||
PAGE_SIZE, &pool->pages[pool->pages_allocated].dmaAddress, FALSE); //FIXME: Cache-enabled?
|
||||
|
||||
// mark all blocks as free (bit=set)
|
||||
memset(pool->pages[pool->pages_allocated].bitmap, 0xFF, 128*sizeof(long));
|
||||
memset(pool->pages[pool->pages_allocated].bitmap, 0xFF, 128*sizeof(unsigned long));
|
||||
|
||||
/* FIXME: the next line replaces physical address by virtual address:
|
||||
* this change is needed to boot VMWare, but I'm really not sure this
|
||||
|
@ -687,6 +701,7 @@ void * my_pci_pool_alloc(struct pci_pool * pool, int mem_flags, dma_addr_t *dma_
|
|||
|
||||
if ((i + block) < pool->blocks_per_page)
|
||||
{
|
||||
DPRINT("pci_pool_alloc(): Allocating block %p:%d:%d:%d\n", pool, page, map, block);
|
||||
clear_bit(block, &pool->pages[page].bitmap[map]);
|
||||
offset = (BITS_PER_LONG * map) + block;
|
||||
offset *= pool->size;
|
||||
|
@ -705,22 +720,6 @@ ready:
|
|||
result = (char *)pool->pages[page].virtualAddress + offset;
|
||||
pool->blocks_allocated++;
|
||||
|
||||
#if 0
|
||||
// check do we have enough free blocks on the current page
|
||||
if (pool->pages_allocated*pool->blocks_per_page < pool->blocks_allocated+1)
|
||||
{
|
||||
DPRINT1("Panic!! We need one more page to be allocated, and Fireball doesn't want to alloc it!\n");
|
||||
*dma_handle = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Alloc one block now
|
||||
pool->blocks_allocated++;
|
||||
current_block_in_page = pool->blocks_allocated - (pool->blocks_allocated / pool->blocks_per_page) * pool->blocks_per_page;
|
||||
*dma_handle = pool->pages[pool->pages_allocated-1].dmaAddress.QuadPart + pool->size*(current_block_in_page - 1);
|
||||
result = pool->pages[pool->pages_allocated-1].virtualAddress + pool->size*(current_block_in_page - 1);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -764,8 +763,7 @@ void my_pci_pool_free (struct pci_pool * pool, void * vaddr, dma_addr_t dma)
|
|||
set_bit (block, &pool->pages[page].bitmap[map]);
|
||||
|
||||
pool->blocks_allocated--;
|
||||
|
||||
DPRINT1("pci_pool_free(): alloc'd: %d\n", pool->blocks_allocated);
|
||||
DPRINT("pci_pool_free(): alloc'd: %d\n", pool->blocks_allocated);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -882,3 +880,27 @@ void my_pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size
|
|||
{
|
||||
my_dma_unmap_single(&hwdev->dev, dma_addr, size, direction);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* SPINLOCK routines */
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_spin_lock_init(spinlock_t *sl)
|
||||
{
|
||||
KeInitializeSpinLock(&sl->SpinLock);
|
||||
}
|
||||
|
||||
void my_spin_lock(spinlock_t *sl)
|
||||
{
|
||||
//KeAcquireSpinLock(&sl->SpinLock, &sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_unlock(spinlock_t *sl)
|
||||
{
|
||||
//KeReleaseSpinLock(&sl->SpinLock, sl->OldIrql);
|
||||
}
|
||||
|
||||
void my_spin_lock_irqsave(spinlock_t *sl, int flags)
|
||||
{
|
||||
my_spin_lock(sl);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue