This is the initial version of USB port+hub+hostcontroller drivers from a special version of Linux USB Stack. More info will be placed at ROS-Wiki. Added: trunk/reactos/drivers/usb/cromwell/ Added: trunk/reactos/drivers/usb/cromwell/Makefile Added: trunk/reactos/drivers/usb/cromwell/core/ Added: trunk/reactos/drivers/usb/cromwell/core/buffer_simple.c Added: trunk/reactos/drivers/usb/cromwell/core/config.c Added: trunk/reactos/drivers/usb/cromwell/core/hcd-pci.c Added: trunk/reactos/drivers/usb/cromwell/core/hcd.c Added: trunk/reactos/drivers/usb/cromwell/core/hcd.h Added: trunk/reactos/drivers/usb/cromwell/core/hub.c Added: trunk/reactos/drivers/usb/cromwell/core/hub.h Added: trunk/reactos/drivers/usb/cromwell/core/makefile Added: trunk/reactos/drivers/usb/cromwell/core/makefile.crom Added: trunk/reactos/drivers/usb/cromwell/core/message.c Added: trunk/reactos/drivers/usb/cromwell/core/urb.c Added: trunk/reactos/drivers/usb/cromwell/core/usb-debug.c Added: trunk/reactos/drivers/usb/cromwell/core/usb.c Added: trunk/reactos/drivers/usb/cromwell/core/usb.h Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.a Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.c Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.coff Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.def Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.map Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.nostrip.sys Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.rc Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.sym Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.sys Added: trunk/reactos/drivers/usb/cromwell/host/ Added: trunk/reactos/drivers/usb/cromwell/host/makefile Added: trunk/reactos/drivers/usb/cromwell/host/makefile.crom Added: trunk/reactos/drivers/usb/cromwell/host/ohci-dbg.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci-hcd.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci-hub.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci-mem.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci-pci.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci-q.c Added: trunk/reactos/drivers/usb/cromwell/host/ohci.a Added: trunk/reactos/drivers/usb/cromwell/host/ohci.coff Added: trunk/reactos/drivers/usb/cromwell/host/ohci.def Added: trunk/reactos/drivers/usb/cromwell/host/ohci.h Added: trunk/reactos/drivers/usb/cromwell/host/ohci.map Added: trunk/reactos/drivers/usb/cromwell/host/ohci.nostrip.sys Added: trunk/reactos/drivers/usb/cromwell/host/ohci.rc Added: trunk/reactos/drivers/usb/cromwell/host/ohci.sym Added: trunk/reactos/drivers/usb/cromwell/host/ohci.sys Added: trunk/reactos/drivers/usb/cromwell/host/ohci_config.h Added: trunk/reactos/drivers/usb/cromwell/host/ohci_main.c Added: trunk/reactos/drivers/usb/cromwell/linux/ Added: trunk/reactos/drivers/usb/cromwell/linux/asm/ Added: trunk/reactos/drivers/usb/cromwell/linux/asm/bitops.h Added: trunk/reactos/drivers/usb/cromwell/linux/bitops.h Added: trunk/reactos/drivers/usb/cromwell/linux/boot.h Added: trunk/reactos/drivers/usb/cromwell/linux/consts.h Added: trunk/reactos/drivers/usb/cromwell/linux/cromwell_types.h Added: trunk/reactos/drivers/usb/cromwell/linux/errno.h Added: trunk/reactos/drivers/usb/cromwell/linux/linux_wrapper.h Added: trunk/reactos/drivers/usb/cromwell/linux/list.h Added: trunk/reactos/drivers/usb/cromwell/linux/pci_ids.h Added: trunk/reactos/drivers/usb/cromwell/linux/usb.h Added: trunk/reactos/drivers/usb/cromwell/linux/usb_ch9.h Added: trunk/reactos/drivers/usb/cromwell/sys/ Added: trunk/reactos/drivers/usb/cromwell/sys/BootUSB.c Added: trunk/reactos/drivers/usb/cromwell/sys/Makefile Added: trunk/reactos/drivers/usb/cromwell/sys/linuxwrapper.c Added: trunk/reactos/drivers/usb/cromwell/sys/risefall.c Added: trunk/reactos/drivers/usb/cromwell/sys/ros_wrapper.c Added: trunk/reactos/drivers/usb/cromwell/sys/usbkey.c Added: trunk/reactos/drivers/usb/cromwell/sys/usbwrapper.c Added: trunk/reactos/drivers/usb/cromwell/sys/xpad.c Added: trunk/reactos/drivers/usb/cromwell/sys/xremote.c Added: trunk/reactos/drivers/usb/cromwell/usb_wrapper.h _____
Added: trunk/reactos/drivers/usb/cromwell/Makefile --- trunk/reactos/drivers/usb/cromwell/Makefile 2005-01-26 22:05:12 UTC (rev 13323) +++ trunk/reactos/drivers/usb/cromwell/Makefile 2005-01-26 22:34:39 UTC (rev 13324) @@ -0,0 +1,50 @@
+# +# ReactOS USB-Cromwell Drivers +# + +PATH_TO_TOP = ../../.. + +include $(PATH_TO_TOP)/rules.mak + +DRIVERS = core host + +all: $(DRIVERS) + +depends: + +implib: $(DRIVERS:%=%_implib) + +clean: $(DRIVERS:%=%_clean) + +install: $(DRIVERS:%=%_install) + +bootcd: $(DRIVERS:%=%_bootcd) + +.PHONY: all depends implib clean install bootcd + + +# +# USB DRIVERS +# +$(DRIVERS): %: + $(MAKE) -C $* + +$(DRIVERS:%=%_implib): %_implib: + $(MAKE) -C $* implib + +$(DRIVERS:%=%_clean): %_clean: + $(MAKE) -C $* clean + +$(DRIVERS:%=%_install): %_install: + $(MAKE) -C $* install + +$(DRIVERS:%=%_bootcd): %_bootcd: + $(MAKE) -C $* bootcd + +.PHONY: $(DRIVERS) $(DRIVERS:%=%_implib) $(DRIVERS:%=%_clean) $(DRIVERS:%=%_install) $(DRIVERS:%=%_bootcd) + + +etags: + find . -name "*.[ch]" -print | etags --language=c - + +# EOF _____
Added: trunk/reactos/drivers/usb/cromwell/core/buffer_simple.c --- trunk/reactos/drivers/usb/cromwell/core/buffer_simple.c 2005-01-26 22:05:12 UTC (rev 13323) +++ trunk/reactos/drivers/usb/cromwell/core/buffer_simple.c 2005-01-26 22:34:39 UTC (rev 13324) @@ -0,0 +1,42 @@
+/* + * buffer_simple.c -- replacement for usb/core/buffer.c + * + * (c) Georg Acher, georg@acher.org + * + */ + +#include "../usb_wrapper.h" +#define __KERNEL__ +#define CONFIG_PCI +#include "hcd.h" + +/*--------------------------------------------------------------------- ---*/ +int hcd_buffer_create (struct usb_hcd *hcd) +{ + return 0; +} +/*--------------------------------------------------------------------- ---*/ +void hcd_buffer_destroy (struct usb_hcd *hcd) +{ +} +/*--------------------------------------------------------------------- ---*/ +void *hcd_buffer_alloc ( + struct usb_bus *bus, + size_t size, + int mem_flags, + dma_addr_t *dma +) +{ + return kmalloc(size,0); +} +/*--------------------------------------------------------------------- ---*/ +void hcd_buffer_free ( + struct usb_bus *bus, + size_t size, + void *addr, + dma_addr_t dma +) +{ + kfree(addr); +} + _____
Added: trunk/reactos/drivers/usb/cromwell/core/config.c --- trunk/reactos/drivers/usb/cromwell/core/config.c 2005-01-26 22:05:12 UTC (rev 13323) +++ trunk/reactos/drivers/usb/cromwell/core/config.c 2005-01-26 22:34:39 UTC (rev 13324) @@ -0,0 +1,508 @@
+#if 0 +#include <linux/usb.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <asm/byteorder.h> +#else +#include "../usb_wrapper.h" +#endif + +#define USB_MAXALTSETTING 128 /* Hard limit */ +#define USB_MAXENDPOINTS 30 /* Hard limit */ + +/* these maximums are arbitrary */ +#define USB_MAXCONFIG 8 +#define USB_ALTSETTINGALLOC 4 +#define USB_MAXINTERFACES 32 + +static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char *buffer, int size) +{ + struct usb_descriptor_header *header; + unsigned char *begin; + int parsed = 0, len, numskipped; + + header = (struct usb_descriptor_header *)buffer; + + /* Everything should be fine being passed into here, but we sanity */ + /* check JIC */ + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + if (header->bDescriptorType != USB_DT_ENDPOINT) { + warn("unexpected descriptor 0x%X, expecting endpoint, 0x%X", + header->bDescriptorType, USB_DT_ENDPOINT); + return parsed; + } + + if (header->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) + memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_AUDIO_SIZE); + else + memcpy(&endpoint->desc, buffer, USB_DT_ENDPOINT_SIZE); + + le16_to_cpus(&endpoint->desc.wMaxPacketSize); + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + + /* Skip over the rest of the Class Specific or Vendor Specific */ + /* descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", + header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + parsed += header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for drivers */ + /* to later parse */ + len = (int)(buffer - begin); + if (!len) { + endpoint->extra = NULL; + endpoint->extralen = 0; + return parsed; + } + + endpoint->extra = kmalloc(len, GFP_KERNEL); + + if (!endpoint->extra) { + err("couldn't allocate memory for endpoint extra descriptors"); + endpoint->extralen = 0; + return parsed; + } + + memcpy(endpoint->extra, begin, len); + endpoint->extralen = len; + + return parsed; +} + +static int usb_parse_interface(struct usb_interface *interface, unsigned char *buffer, int size) +{ + int i, len, numskipped, retval, parsed = 0; + struct usb_descriptor_header *header; + struct usb_host_interface *ifp; + unsigned char *begin; + + interface->act_altsetting = 0; + interface->num_altsetting = 0; + interface->max_altsetting = USB_ALTSETTINGALLOC; + device_initialize(&interface->dev); + + interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting, + GFP_KERNEL); + + if (!interface->altsetting) { + err("couldn't kmalloc interface->altsetting"); + return -1; + } + + while (size > 0) { + struct usb_interface_descriptor *d; + + if (interface->num_altsetting >= interface->max_altsetting) { + struct usb_host_interface *ptr; + int oldmas; + + oldmas = interface->max_altsetting; + interface->max_altsetting += USB_ALTSETTINGALLOC; + if (interface->max_altsetting > USB_MAXALTSETTING) { + warn("too many alternate settings (incr %d max %d)\n", + USB_ALTSETTINGALLOC, USB_MAXALTSETTING); + return -1; + } + + ptr = kmalloc(sizeof(*ptr) * interface->max_altsetting, GFP_KERNEL); + if (ptr == NULL) { + err("couldn't kmalloc interface->altsetting"); + return -1; + } + memcpy(ptr, interface->altsetting, sizeof(*interface->altsetting) * oldmas); + kfree(interface->altsetting); + interface->altsetting = ptr; + } + + ifp = interface->altsetting + interface->num_altsetting; + ifp->endpoint = NULL; + ifp->extra = NULL; + ifp->extralen = 0; + interface->num_altsetting++; + + memcpy(ifp, buffer, USB_DT_INTERFACE_SIZE); + + /* Skip over the interface */ + buffer += ifp->desc.bLength; + parsed += ifp->desc.bLength; + size -= ifp->desc.bLength; + + begin = buffer; + numskipped = 0; + + /* Skip over any interface, class or vendor descriptors */ + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength < 2) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + numskipped++; + + buffer += header->bLength; + parsed += header->bLength; + size -= header->bLength; + } + + if (numskipped) + dbg("skipped %d class/vendor specific interface descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + ifp->extra = kmalloc(len, GFP_KERNEL); + + if (!ifp->extra) { + err("couldn't allocate memory for interface extra descriptors"); + ifp->extralen = 0; + return -1; + } + memcpy(ifp->extra, begin, len); + ifp->extralen = len; + } + + /* Did we hit an unexpected descriptor? */ + header = (struct usb_descriptor_header *)buffer; + if ((size >= sizeof(struct usb_descriptor_header)) && + ((header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE))) + return parsed; + + if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) { + warn("too many endpoints"); + return -1; + } + + ifp->endpoint = (struct usb_host_endpoint *) + kmalloc(ifp->desc.bNumEndpoints * + sizeof(struct usb_host_endpoint), GFP_KERNEL); + if (!ifp->endpoint) { + err("out of memory"); + return -1; + } + + memset(ifp->endpoint, 0, ifp->desc.bNumEndpoints * + sizeof(struct usb_host_endpoint)); + + for (i = 0; i < ifp->desc.bNumEndpoints; i++) { + header = (struct usb_descriptor_header *)buffer; + + if (header->bLength > size) { + err("ran out of descriptors parsing"); + return -1; + } + + retval = usb_parse_endpoint(ifp->endpoint + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + parsed += retval; + size -= retval; + } + + /* We check to see if it's an alternate to this one */ + d = (struct usb_interface_descriptor *)buffer; + if (size < USB_DT_INTERFACE_SIZE + || d->bDescriptorType != USB_DT_INTERFACE + || !d->bAlternateSetting) + return parsed; + } + + return parsed; +} + +int usb_parse_configuration(struct usb_host_config *config, char *buffer) +{ + int i, retval, size; + struct usb_descriptor_header *header; + + memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); + le16_to_cpus(&config->desc.wTotalLength); + size = config->desc.wTotalLength; + + if (config->desc.bNumInterfaces > USB_MAXINTERFACES) { + warn("too many interfaces"); + return -1; + } + + config->interface = (struct usb_interface *) + kmalloc(config->desc.bNumInterfaces * + sizeof(struct usb_interface), GFP_KERNEL); + dbg("kmalloc IF %p, numif %i", config->interface, config->desc.bNumInterfaces); + if (!config->interface) { + err("out of memory"); + return -1; + } + + memset(config->interface, 0, + config->desc.bNumInterfaces * sizeof(struct usb_interface)); + + buffer += config->desc.bLength; + size -= config->desc.bLength; + + config->extra = NULL; + config->extralen = 0; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + int numskipped, len; + char *begin; + + /* Skip over the rest of the Class Specific or Vendor */ + /* Specific descriptors */ + begin = buffer; + numskipped = 0; + while (size >= sizeof(struct usb_descriptor_header)) { + header = (struct usb_descriptor_header *)buffer; + + if ((header->bLength > size) || (header->bLength < 2)) { + err("invalid descriptor length of %d", header->bLength); + return -1; + } + + /* If we find another "proper" descriptor then we're done */ + if ((header->bDescriptorType == USB_DT_ENDPOINT) || + (header->bDescriptorType == USB_DT_INTERFACE) || + (header->bDescriptorType == USB_DT_CONFIG) || + (header->bDescriptorType == USB_DT_DEVICE)) + break; + + dbg("skipping descriptor 0x%X", header->bDescriptorType); + numskipped++; + + buffer += header->bLength; + size -= header->bLength; + } + if (numskipped) + dbg("skipped %d class/vendor specific endpoint descriptors", numskipped); + + /* Copy any unknown descriptors into a storage area for */ + /* drivers to later parse */ + len = (int)(buffer - begin); + if (len) { + if (config->extralen) { + warn("extra config descriptor"); + } else { + config->extra = kmalloc(len, GFP_KERNEL); + if (!config->extra) { + err("couldn't allocate memory for config extra descriptors"); + config->extralen = 0; + return -1; + } + + memcpy(config->extra, begin, len); + config->extralen = len; + } + } + + retval = usb_parse_interface(config->interface + i, buffer, size); + if (retval < 0) + return retval; + + buffer += retval; + size -= retval; + } + + return size; +} + +// hub-only!! ... and only exported for reset/reinit path. +// otherwise used internally on disconnect/destroy path +void usb_destroy_configuration(struct usb_device *dev) +{ + int c, i, j, k; + + if (!dev->config) + return; + + if (dev->rawdescriptors) { + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + kfree(dev->rawdescriptors[i]); + + kfree(dev->rawdescriptors); + } + + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + struct usb_host_config *cf = &dev->config[c]; + + if (!cf->interface) + break; + + for (i = 0; i < cf->desc.bNumInterfaces; i++) { + struct usb_interface *ifp = + &cf->interface[i]; + + if (!ifp->altsetting) + break; + + for (j = 0; j < ifp->num_altsetting; j++) { + struct usb_host_interface *as = + &ifp->altsetting[j]; + + if(as->extra) { + kfree(as->extra); + } + + if (!as->endpoint) + break; + + for(k = 0; k < as->desc.bNumEndpoints; k++) { + if(as->endpoint[k].extra) { + kfree(as->endpoint[k].extra); + } + } + kfree(as->endpoint); + } + + kfree(ifp->altsetting); + } + kfree(cf->interface); + } + kfree(dev->config); +} + + +// hub-only!! ... and only in reset path, or usb_new_device() +// (used by real hubs and virtual root hubs) +int usb_get_configuration(struct usb_device *dev) +{ + int result; + unsigned int cfgno, length; + unsigned char *buffer; + unsigned char *bigbuffer; + struct usb_config_descriptor *desc; + + if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { + warn("too many configurations"); + return -EINVAL; + } + + if (dev->descriptor.bNumConfigurations < 1) { + warn("not enough configurations"); + return -EINVAL; + } + + dev->config = (struct usb_host_config *) + kmalloc(dev->descriptor.bNumConfigurations * + sizeof(struct usb_host_config), GFP_KERNEL); + if (!dev->config) { + err("out of memory"); + return -ENOMEM; + } + memset(dev->config, 0, dev->descriptor.bNumConfigurations * + sizeof(struct usb_host_config)); + + dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * + dev->descriptor.bNumConfigurations, GFP_KERNEL); + if (!dev->rawdescriptors) { + err("out of memory"); + return -ENOMEM; + } + + buffer = kmalloc(8, GFP_KERNEL); + if (!buffer) { + err("unable to allocate memory for configuration descriptors"); + return -ENOMEM; + } + desc = (struct usb_config_descriptor *)buffer; + + for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { + /* We grab the first 8 bytes so we know how long the whole */ + /* configuration is */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); + if (result < 8) { + if (result < 0) + err("unable to get descriptor"); + else { + err("config descriptor too short (expected %i, got %i)", 8, result); + result = -EINVAL; + } + goto err; + } + + /* Get the full buffer */ + length = le16_to_cpu(desc->wTotalLength); + + bigbuffer = kmalloc(length, GFP_KERNEL); + if (!bigbuffer) { + err("unable to allocate memory for configuration descriptors"); + result = -ENOMEM; + goto err; + } + + /* Now that we know the length, get the whole thing */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); + if (result < 0) { + err("couldn't get all of config descriptors"); + kfree(bigbuffer); + goto err; + } + + if (result < length) { + err("config descriptor too short (expected %i, got %i)", length, result); + result = -EINVAL; + kfree(bigbuffer); + goto err; + } + + dev->rawdescriptors[cfgno] = bigbuffer; + + result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); + if (result > 0) + dbg("descriptor data left"); + else if (result < 0) { + result = -EINVAL; + goto err; + } + } + + kfree(buffer); + return 0; +err: + kfree(buffer); + dev->descriptor.bNumConfigurations = cfgno; + return result; +} + _____
Added: trunk/reactos/drivers/usb/cromwell/core/hcd-pci.c --- trunk/reactos/drivers/usb/cromwell/core/hcd-pci.c 2005-01-26 22:05:12 UTC (rev 13323) +++ trunk/reactos/drivers/usb/cromwell/core/hcd-pci.c 2005-01-26 22:34:39 UTC (rev 13324) @@ -0,0 +1,365 @@
+/* + * (C) Copyright David Brownell 2000-2002 + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if 0 +#include <linux/config.h> + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <linux/usb.h> +#include "hcd.h" +#else +#define DEBUG +#include "../usb_wrapper.h" +#include "hcd.h" +#endif + + +/* PCI-based HCs are normal, but custom bus glue should be ok */ + + +/*--------------------------------------------------------------------- ----*/ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_hcd_pci_probe - initialize PCI-based HCDs + * @dev: USB Host Controller being probed + * @id: pci hotplug id connecting controller to HCD framework + * Context: !in_interrupt() + * + * Allocates basic PCI resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + * Store this function in the HCD's struct pci_driver as probe(). + */ +int STDCALL usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) +{ + struct hc_driver *driver; + unsigned long resource, len; + void *base; + struct usb_hcd *hcd; + int retval, region; + char buf [8]; + //char *bufp = buf; + + if (usb_disabled()) + return -ENODEV; + + if (!id || !(driver = (struct hc_driver *) id->driver_data)) + return -EINVAL; + + if (pci_enable_device (dev) < 0) + return -ENODEV; + + if (!dev->irq) { + err ("Found HC with no IRQ. Check BIOS/PCI %s setup!", + dev->slot_name); + return -ENODEV; + } + + if (driver->flags & HCD_MEMORY) { // EHCI, OHCI + region = 0; + resource = pci_resource_start (dev, 0); + len = pci_resource_len (dev, 0); + if (!request_mem_region (resource, len, driver->description)) { + dbg ("controller already in use"); + return -EBUSY; + } + base = ioremap_nocache (resource, len); + if (base == NULL) { + dbg ("error mapping memory"); + retval = -EFAULT; +clean_1: + release_mem_region (resource, len); + err ("init %s fail, %d", dev->slot_name, retval); + return retval; + } + + } else { // UHCI + resource = len = 0; + for (region = 0; region < PCI_ROM_RESOURCE; region++) { + if (!(pci_resource_flags (dev, region) & IORESOURCE_IO)) + continue; + + resource = pci_resource_start (dev, region); + len = pci_resource_len (dev, region); + if (request_region (resource, len, + driver->description)) + break; + } + if (region == PCI_ROM_RESOURCE) { + dbg ("no i/o regions available"); + return -EBUSY; + } + base = (void *) resource; + } + + // driver->start(), later on, will transfer device from + // control by SMM/BIOS to control by Linux (if needed) + + pci_set_master (dev); + + hcd = driver->hcd_alloc (); + if (hcd == NULL){ + dbg ("hcd alloc fail"); + retval = -ENOMEM; +clean_2: + if (driver->flags & HCD_MEMORY) { + iounmap (base); + goto clean_1; + } else { + release_region (resource, len); + err ("init %s fail, %d", dev->slot_name, retval); + return retval; + } + } + pci_set_drvdata (dev, hcd); + hcd->driver = driver; + hcd->description = driver->description; + hcd->pdev = dev; + hcd->self.bus_name = dev->slot_name; + hcd->product_desc = dev->dev.name; + hcd->self.controller = &dev->dev; + hcd->controller = hcd->self.controller; + + if ((retval = hcd_buffer_create (hcd)) != 0) { +clean_3: + driver->hcd_free (hcd); + goto clean_2; + } + + dev_info (hcd->controller, "%s\n", hcd->product_desc); + +#ifndef __sparc__ + sprintf (buf, "%d", dev->irq); +#else + bufp = __irq_itoa(dev->irq); +#endif + if (request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ, hcd->description, hcd) + != 0) { + dev_err (hcd->controller, + "request interrupt %s failed\n", bufp); + retval = -EBUSY; + goto clean_3; + } + hcd->irq = dev->irq; + + hcd->regs = base; + hcd->region = region; + dev_info (hcd->controller, "irq %s, %s %p\n", bufp, + (driver->flags & HCD_MEMORY) ? "pci mem" : "io base", + base); + + usb_bus_init (&hcd->self); + hcd->self.op = &usb_hcd_operations; + hcd->self.hcpriv = (void *) hcd; + + INIT_LIST_HEAD (&hcd->dev_list); + + usb_register_bus (&hcd->self); + + if ((retval = driver->start (hcd)) < 0) + usb_hcd_pci_remove (dev); + + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_probe); + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_hcd_pci_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + * Store this function in the HCD's struct pci_driver as remove(). + */ +void STDCALL usb_hcd_pci_remove (struct pci_dev *dev) +{ + struct usb_hcd *hcd; + struct usb_device *hub; + + hcd = pci_get_drvdata(dev); + if (!hcd) + return; + dev_info (hcd->controller, "remove, state %x\n", hcd->state); + + if (in_interrupt ()) + BUG (); + + hub = hcd->self.root_hub; + hcd->state = USB_STATE_QUIESCING; + + dev_dbg (hcd->controller, "roothub graceful disconnect\n"); + usb_disconnect (&hub); + + hcd->driver->stop (hcd); + hcd_buffer_destroy (hcd); + hcd->state = USB_STATE_HALT; + pci_set_drvdata (dev, 0); + + free_irq (hcd->irq, hcd); + if (hcd->driver->flags & HCD_MEMORY) { + iounmap (hcd->regs); + release_mem_region (pci_resource_start (dev, 0), + pci_resource_len (dev, 0)); + } else { + release_region (pci_resource_start (dev, hcd->region), + pci_resource_len (dev, hcd->region)); + } + + usb_deregister_bus (&hcd->self); + if (atomic_read (&hcd->self.refcnt) != 1) { + dev_warn (hcd->controller, + "dangling refs (%d) to bus %d!\n", + atomic_read (&hcd->self.refcnt) - 1, + hcd->self.busnum); + } + hcd->driver->hcd_free (hcd); +} +EXPORT_SYMBOL (usb_hcd_pci_remove); + + +#ifdef CONFIG_PM + +/* + * Some "sleep" power levels imply updating struct usb_driver + * to include a callback asking hcds to do their bit by checking + * if all the drivers can suspend. Gets involved with remote wakeup. + * + * If there are pending urbs, then HCs will need to access memory, + * causing extra power drain. New sleep()/wakeup() PM calls might + * be needed, beyond PCI suspend()/resume(). The root hub timer + * still be accessing memory though ... + * + * FIXME: USB should have some power budgeting support working with + * all kinds of hubs. + * + * FIXME: This assumes only D0->D3 suspend and D3->D0 resume. + * D1 and D2 states should do something, yes? + * + * FIXME: Should provide generic enable_wake(), calling pci_enable_wake() + * for all supported states, so that USB remote wakeup can work for any + * devices that support it (and are connected via powered hubs). + * + * FIXME: resume doesn't seem to work right any more... + */ + + +// 2.4 kernels have issued concurrent resumes (w/APM) +// we defend against that error; PCI doesn't yet. + +/** + * usb_hcd_pci_suspend - power management suspend of a PCI-based HCD + * @dev: USB Host Controller being suspended + * + * Store this function in the HCD's struct pci_driver as suspend(). + */ +int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state) +{ + struct usb_hcd *hcd; + int retval; + + hcd = pci_get_drvdata(dev); + dev_info (hcd->controller, "suspend to state %d\n", state); + + pci_save_state (dev, hcd->pci_state); + + // FIXME for all connected devices, leaf-to-root: + // driver->suspend() + // proposed "new 2.5 driver model" will automate that + + /* driver may want to disable DMA etc */ + retval = hcd->driver->suspend (hcd, state); + hcd->state = USB_STATE_SUSPENDED; + + pci_set_power_state (dev, state); + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_suspend); + +/** + * usb_hcd_pci_resume - power management resume of a PCI-based HCD + * @dev: USB Host Controller being resumed + * + * Store this function in the HCD's struct pci_driver as resume(). + */ +int usb_hcd_pci_resume (struct pci_dev *dev) +{ + struct usb_hcd *hcd; + int retval; + + hcd = pci_get_drvdata(dev); + dev_info (hcd->controller, "resume\n"); + + /* guard against multiple resumes (APM bug?) */ + atomic_inc (&hcd->resume_count); + if (atomic_read (&hcd->resume_count) != 1) { + dev_err (hcd->controller, "concurrent PCI resumes\n"); + retval = 0; + goto done; + } + + retval = -EBUSY; + if (hcd->state != USB_STATE_SUSPENDED) { + dev_dbg (hcd->controller, "can't resume, not suspended!\n"); + goto done; + } + hcd->state = USB_STATE_RESUMING; + + pci_set_power_state (dev, 0); + pci_restore_state (dev, hcd->pci_state); + + retval = hcd->driver->resume (hcd); + if (!HCD_IS_RUNNING (hcd->state)) { + dev_dbg (hcd->controller, "resume fail, retval %d\n", retval); + usb_hc_died (hcd); +// FIXME: recover, reset etc. + } else { + // FIXME for all connected devices, root-to-leaf: + // driver->resume (); + // proposed "new 2.5 driver model" will automate that + } + +done: + atomic_dec (&hcd->resume_count); + return retval; +} +EXPORT_SYMBOL (usb_hcd_pci_resume); + +#endif /* CONFIG_PM */ + + _____
Added: trunk/reactos/drivers/usb/cromwell/core/hcd.c --- trunk/reactos/drivers/usb/cromwell/core/hcd.c 2005-01-26 22:05:12 UTC (rev 13323) +++ trunk/reactos/drivers/usb/cromwell/core/hcd.c 2005-01-26 22:34:39 UTC (rev 13324) @@ -0,0 +1,1499 @@
+/* + * (C) Copyright Linus Torvalds 1999 + * (C) Copyright Johannes Erdfelt 1999-2001 + * (C) Copyright Andreas Gal 1999 + * (C) Copyright Gregory P. Smith 1999 + * (C) Copyright Deti Fliegl 1999 + * (C) Copyright Randy Dunlap 2000 + * (C) Copyright David Brownell 2000-2002 + * + * This program is free software; you can redistribute it and/or modify it [truncated at 1000 lines; 31273 more skipped]
fireball@svn.reactos.com wrote:
This is the initial version of USB port+hub+hostcontroller drivers from a special version of Linux USB Stack. More info will be placed at ROS-Wiki.
Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.a Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.coff Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.map Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.nostrip.sys Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.sym Added: trunk/reactos/drivers/usb/cromwell/core/usbcore.sys Added: trunk/reactos/drivers/usb/cromwell/host/ohci.a Added: trunk/reactos/drivers/usb/cromwell/host/ohci.coff Added: trunk/reactos/drivers/usb/cromwell/host/ohci.map Added: trunk/reactos/drivers/usb/cromwell/host/ohci.nostrip.sys Added: trunk/reactos/drivers/usb/cromwell/host/ohci.sym Added: trunk/reactos/drivers/usb/cromwell/host/ohci.sys
It's not a good idea to add the generated files to SVN...