mirror of
https://github.com/reactos/reactos.git
synced 2026-07-07 04:44:26 +08:00
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.
svn path=/trunk/; revision=13324
This commit is contained in:
50
reactos/drivers/usb/cromwell/Makefile
Normal file
50
reactos/drivers/usb/cromwell/Makefile
Normal file
@@ -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
|
||||
42
reactos/drivers/usb/cromwell/core/buffer_simple.c
Normal file
42
reactos/drivers/usb/cromwell/core/buffer_simple.c
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
508
reactos/drivers/usb/cromwell/core/config.c
Normal file
508
reactos/drivers/usb/cromwell/core/config.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
365
reactos/drivers/usb/cromwell/core/hcd-pci.c
Normal file
365
reactos/drivers/usb/cromwell/core/hcd-pci.c
Normal file
@@ -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 */
|
||||
|
||||
|
||||
1499
reactos/drivers/usb/cromwell/core/hcd.c
Normal file
1499
reactos/drivers/usb/cromwell/core/hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
430
reactos/drivers/usb/cromwell/core/hcd.h
Normal file
430
reactos/drivers/usb/cromwell/core/hcd.h
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* This file contains declarations of usbcore internals that are mostly
|
||||
* used or exposed by Host Controller Drivers.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* USB Host Controller Driver (usb_hcd) framework
|
||||
*
|
||||
* Since "struct usb_bus" is so thin, you can't share much code in it.
|
||||
* This framework is a layer over that, and should be more sharable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
struct usb_hcd { /* usb_bus.hcpriv points to this */
|
||||
|
||||
/*
|
||||
* housekeeping
|
||||
*/
|
||||
struct usb_bus self; /* hcd is-a bus */
|
||||
|
||||
const char *product_desc; /* product/vendor string */
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
struct timer_list rh_timer; /* drives root hub */
|
||||
struct list_head dev_list; /* devices on this bus */
|
||||
struct work_struct work;
|
||||
|
||||
/*
|
||||
* hardware info/state
|
||||
*/
|
||||
struct hc_driver *driver; /* hw-specific hooks */
|
||||
int irq; /* irq allocated */
|
||||
void *regs; /* device memory/io */
|
||||
struct device *controller; /* handle to hardware */
|
||||
|
||||
/* a few non-PCI controllers exist, mostly for OHCI */
|
||||
struct pci_dev *pdev; /* pci is typical */
|
||||
#ifdef CONFIG_PCI
|
||||
int region; /* pci region for regs */
|
||||
u32 pci_state [16]; /* for PM state save */
|
||||
atomic_t resume_count; /* multiple resumes issue */
|
||||
#endif
|
||||
|
||||
#define HCD_BUFFER_POOLS 4
|
||||
struct pci_pool *pool [HCD_BUFFER_POOLS];
|
||||
|
||||
int state;
|
||||
# define __ACTIVE 0x01
|
||||
# define __SLEEPY 0x02
|
||||
# define __SUSPEND 0x04
|
||||
# define __TRANSIENT 0x80
|
||||
|
||||
# define USB_STATE_HALT 0
|
||||
# define USB_STATE_RUNNING (__ACTIVE)
|
||||
# define USB_STATE_READY (__ACTIVE|__SLEEPY)
|
||||
# define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
||||
# define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
||||
# define USB_STATE_SUSPENDED (__SUSPEND)
|
||||
|
||||
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
|
||||
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
||||
|
||||
/* more shared queuing code would be good; it should support
|
||||
* smarter scheduling, handle transaction translators, etc;
|
||||
* input size of periodic table to an interrupt scheduler.
|
||||
* (ohci 32, uhci 1024, ehci 256/512/1024).
|
||||
*/
|
||||
};
|
||||
|
||||
/* 2.4 does this a bit differently ... */
|
||||
static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
|
||||
{
|
||||
return &hcd->self;
|
||||
}
|
||||
|
||||
|
||||
struct hcd_dev { /* usb_device.hcpriv points to this */
|
||||
struct list_head dev_list; /* on this hcd */
|
||||
struct list_head urb_list; /* pending on this dev */
|
||||
|
||||
/* per-configuration HC/HCD state, such as QH or ED */
|
||||
void *ep[32];
|
||||
};
|
||||
|
||||
// urb.hcpriv is really hardware-specific
|
||||
|
||||
struct hcd_timeout { /* timeouts we allocate */
|
||||
struct list_head timeout_list;
|
||||
struct timer_list timer;
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FIXME usb_operations should vanish or become hc_driver,
|
||||
* when usb_bus and usb_hcd become the same thing.
|
||||
*/
|
||||
|
||||
struct usb_operations {
|
||||
int (*allocate)(struct usb_device *);
|
||||
int (*deallocate)(struct usb_device *);
|
||||
int (*get_frame_number) (struct usb_device *usb_dev);
|
||||
int (*submit_urb) (struct urb *urb, int mem_flags);
|
||||
int (*unlink_urb) (struct urb *urb);
|
||||
|
||||
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
|
||||
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
|
||||
int mem_flags,
|
||||
dma_addr_t *dma);
|
||||
void (*buffer_free)(struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
void (*disable)(struct usb_device *udev, int bEndpointAddress);
|
||||
};
|
||||
|
||||
/* each driver provides one of these, and hardware init support */
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
struct hc_driver {
|
||||
const char *description; /* "ehci-hcd" etc */
|
||||
|
||||
/* irq handler */
|
||||
void (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
|
||||
|
||||
int flags;
|
||||
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
||||
#define HCD_USB11 0x0010 /* USB 1.1 */
|
||||
#define HCD_USB2 0x0020 /* USB 2.0 */
|
||||
|
||||
/* called to init HCD and root hub */
|
||||
int (*start) (struct usb_hcd *hcd);
|
||||
|
||||
/* called after all devices were suspended */
|
||||
int (*suspend) (struct usb_hcd *hcd, u32 state);
|
||||
|
||||
/* called before any devices get resumed */
|
||||
int (*resume) (struct usb_hcd *hcd);
|
||||
|
||||
/* cleanly make HCD stop writing memory and doing I/O */
|
||||
void (*stop) (struct usb_hcd *hcd);
|
||||
|
||||
/* return current frame number */
|
||||
int (*get_frame_number) (struct usb_hcd *hcd);
|
||||
|
||||
/* memory lifecycle */
|
||||
struct usb_hcd *(*hcd_alloc) (void);
|
||||
void (*hcd_free) (struct usb_hcd *hcd);
|
||||
|
||||
/* manage i/o requests, device state */
|
||||
int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
|
||||
int mem_flags);
|
||||
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
||||
void (*endpoint_disable)(struct usb_hcd *hcd,
|
||||
struct hcd_dev *dev, int bEndpointAddress);
|
||||
|
||||
/* root hub support */
|
||||
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
||||
int (*hub_control) (struct usb_hcd *hcd,
|
||||
u16 typeReq, u16 wValue, u16 wIndex,
|
||||
char *buf, u16 wLength);
|
||||
};
|
||||
|
||||
extern void STDCALL usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
|
||||
extern void STDCALL usb_bus_init (struct usb_bus *bus);
|
||||
extern void usb_rh_status_dequeue (struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
struct pci_dev;
|
||||
struct pci_device_id;
|
||||
extern int STDCALL usb_hcd_pci_probe (struct pci_dev *dev,
|
||||
const struct pci_device_id *id);
|
||||
extern void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
// FIXME: see Documentation/power/pci.txt (2.4.6 and later?)
|
||||
// extern int usb_hcd_pci_save_state (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state);
|
||||
extern int usb_hcd_pci_resume (struct pci_dev *dev);
|
||||
// extern int usb_hcd_pci_enable_wake (struct pci_dev *dev, u32 state, int flg);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#endif /* CONFIG_PCI */
|
||||
|
||||
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
|
||||
int hcd_buffer_create (struct usb_hcd *hcd);
|
||||
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);
|
||||
void hcd_buffer_free (struct usb_bus *bus, size_t size,
|
||||
void *addr, dma_addr_t dma);
|
||||
|
||||
/* generic bus glue, needed for host controllers that don't use PCI */
|
||||
extern struct usb_operations usb_hcd_operations;
|
||||
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
|
||||
extern void STDCALL usb_hc_died (struct usb_hcd *hcd);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
|
||||
extern int usb_new_device(struct usb_device *dev, struct device *parent);
|
||||
extern void STDCALL usb_connect(struct usb_device *dev);
|
||||
extern void usb_disconnect(struct usb_device **);
|
||||
|
||||
/* exported to hub driver ONLY to support usb_reset_device () */
|
||||
extern int usb_get_configuration(struct usb_device *dev);
|
||||
extern void usb_set_maxpacket(struct usb_device *dev);
|
||||
extern void usb_destroy_configuration(struct usb_device *dev);
|
||||
extern int usb_set_address(struct usb_device *dev);
|
||||
|
||||
/* use these only before the device's address has been set */
|
||||
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
|
||||
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* HCD Root Hub support
|
||||
*/
|
||||
|
||||
#include "hub.h"
|
||||
|
||||
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
||||
#define DeviceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
#define DeviceOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
||||
|
||||
#define InterfaceRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
#define EndpointRequest \
|
||||
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
||||
|
||||
/* table 9.6 standard features */
|
||||
#define DEVICE_REMOTE_WAKEUP 1
|
||||
#define ENDPOINT_HALT 0
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
|
||||
#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR)
|
||||
#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS)
|
||||
#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS)
|
||||
#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE)
|
||||
#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE)
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Generic bandwidth allocation constants/support
|
||||
*/
|
||||
#define FRAME_TIME_USECS 1000L
|
||||
#define BitTime(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 */
|
||||
|
||||
extern void STDCALL usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int bustime, int isoc);
|
||||
extern void STDCALL usb_release_bandwidth (struct usb_device *dev, struct urb *urb,
|
||||
int isoc);
|
||||
|
||||
/*
|
||||
* Full/low speed bandwidth allocation constants/support.
|
||||
*/
|
||||
#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_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
||||
|
||||
extern int STDCALL usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
|
||||
|
||||
/*
|
||||
* Ceiling microseconds (typical) for that many bytes at high speed
|
||||
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
||||
* to preallocate bandwidth)
|
||||
*/
|
||||
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
||||
#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
#define HS_USECS_ISO(bytes) NS_TO_US ( ((long)(38 * 8 * 2.083)) \
|
||||
+ ((2083UL * (3167 + BitTime (bytes)))/1000) \
|
||||
+ USB2_HOST_DELAY)
|
||||
|
||||
extern long STDCALL usb_calc_bus_time (int speed, int is_input,
|
||||
int isoc, int bytecount);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
extern struct usb_bus STDCALL *usb_alloc_bus (struct usb_operations *);
|
||||
extern void STDCALL usb_free_bus (struct usb_bus *);
|
||||
|
||||
extern void STDCALL usb_register_bus (struct usb_bus *);
|
||||
extern void STDCALL usb_deregister_bus (struct usb_bus *);
|
||||
|
||||
extern int STDCALL usb_register_root_hub (struct usb_device *usb_dev,
|
||||
struct device *parent_dev);
|
||||
|
||||
/* for portability to 2.4, hcds should call this */
|
||||
static inline int hcd_register_root (struct usb_hcd *hcd)
|
||||
{
|
||||
return usb_register_root_hub (
|
||||
hcd_to_bus (hcd)->root_hub, hcd->controller);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* exported only within usbcore */
|
||||
|
||||
extern struct list_head usb_bus_list;
|
||||
extern struct semaphore usb_bus_list_lock;
|
||||
|
||||
extern void usb_bus_get (struct usb_bus *bus);
|
||||
extern void usb_bus_put (struct usb_bus *bus);
|
||||
|
||||
extern int usb_find_interface_driver (struct usb_device *dev,
|
||||
struct usb_interface *interface);
|
||||
|
||||
#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
|
||||
|
||||
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
|
||||
|
||||
/*
|
||||
* USB device fs stuff
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USB_DEVICEFS
|
||||
|
||||
/*
|
||||
* these are expected to be called from the USB core/hub thread
|
||||
* with the kernel lock held
|
||||
*/
|
||||
extern void usbfs_add_bus(struct usb_bus *bus);
|
||||
extern void usbfs_remove_bus(struct usb_bus *bus);
|
||||
extern void usbfs_add_device(struct usb_device *dev);
|
||||
extern void usbfs_remove_device(struct usb_device *dev);
|
||||
extern void usbfs_update_special (void);
|
||||
|
||||
extern int usbfs_init(void);
|
||||
extern void usbfs_cleanup(void);
|
||||
|
||||
#else /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
static inline void usbfs_add_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_remove_bus(struct usb_bus *bus) {}
|
||||
static inline void usbfs_add_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_remove_device(struct usb_device *dev) {}
|
||||
static inline void usbfs_update_special (void) {}
|
||||
|
||||
static inline int usbfs_init(void) { return 0; }
|
||||
static inline void usbfs_cleanup(void) { }
|
||||
|
||||
#endif /* CONFIG_USB_DEVICEFS */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
|
||||
// bleech -- resurfaced in 2.4.11 or 2.4.12
|
||||
#define bitmap DeviceRemovable
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* random stuff */
|
||||
|
||||
#define RUN_CONTEXT (in_irq () ? "in_irq" \
|
||||
: (in_interrupt () ? "in_interrupt" : "can sleep"))
|
||||
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
1383
reactos/drivers/usb/cromwell/core/hub.c
Normal file
1383
reactos/drivers/usb/cromwell/core/hub.c
Normal file
File diff suppressed because it is too large
Load Diff
195
reactos/drivers/usb/cromwell/core/hub.h
Normal file
195
reactos/drivers/usb/cromwell/core/hub.h
Normal file
@@ -0,0 +1,195 @@
|
||||
#ifndef __LINUX_HUB_H
|
||||
#define __LINUX_HUB_H
|
||||
|
||||
/*
|
||||
* Hub protocol and driver data structures.
|
||||
*
|
||||
* Some of these are known to the "virtual root hub" code
|
||||
* in host controller drivers.
|
||||
*/
|
||||
#if 0
|
||||
#include <linux/list.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/compiler.h> /* likely()/unlikely() */
|
||||
#endif
|
||||
/*
|
||||
* Hub request types
|
||||
*/
|
||||
|
||||
#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE)
|
||||
#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER)
|
||||
|
||||
/*
|
||||
* Hub class requests
|
||||
* See USB 2.0 spec Table 11-16
|
||||
*/
|
||||
#define HUB_CLEAR_TT_BUFFER 8
|
||||
#define HUB_RESET_TT 9
|
||||
#define HUB_GET_TT_STATE 10
|
||||
#define HUB_STOP_TT 11
|
||||
|
||||
/*
|
||||
* Hub Class feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#define C_HUB_LOCAL_POWER 0
|
||||
#define C_HUB_OVER_CURRENT 1
|
||||
|
||||
/*
|
||||
* Port feature numbers
|
||||
* See USB 2.0 spec Table 11-17
|
||||
*/
|
||||
#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_HIGHSPEED 10
|
||||
#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
|
||||
#define USB_PORT_FEAT_TEST 21
|
||||
#define USB_PORT_FEAT_INDICATOR 22
|
||||
|
||||
/*
|
||||
* Hub Status and Hub Change results
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
*/
|
||||
struct usb_port_status {
|
||||
__u16 wPortStatus;
|
||||
__u16 wPortChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* wPortStatus bit field
|
||||
* See USB 2.0 spec Table 11-21
|
||||
*/
|
||||
#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
|
||||
/* bits 5 to 7 are reserved */
|
||||
#define USB_PORT_STAT_POWER 0x0100
|
||||
#define USB_PORT_STAT_LOW_SPEED 0x0200
|
||||
#define USB_PORT_STAT_HIGH_SPEED 0x0400
|
||||
#define USB_PORT_STAT_TEST 0x0800
|
||||
#define USB_PORT_STAT_INDICATOR 0x1000
|
||||
/* bits 13 to 15 are reserved */
|
||||
|
||||
/*
|
||||
* wPortChange bit field
|
||||
* See USB 2.0 spec Table 11-22
|
||||
* Bits 0 to 4 shown, bits 5 to 15 are reserved
|
||||
*/
|
||||
#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)
|
||||
* See USB 2.0 spec Table 11-13, offset 3
|
||||
*/
|
||||
#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */
|
||||
#define HUB_CHAR_COMPOUND 0x0004 /* D2 */
|
||||
#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */
|
||||
#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* D7 */
|
||||
|
||||
struct usb_hub_status {
|
||||
__u16 wHubStatus;
|
||||
__u16 wHubChange;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
* See USB 2.0 spec Table 11-19 and Table 11-20
|
||||
* Bits 0 and 1 for wHubStatus and wHubChange
|
||||
* Bits 2 to 15 are reserved for both
|
||||
*/
|
||||
#define HUB_STATUS_LOCAL_POWER 0x0001
|
||||
#define HUB_STATUS_OVERCURRENT 0x0002
|
||||
#define HUB_CHANGE_LOCAL_POWER 0x0001
|
||||
#define HUB_CHANGE_OVERCURRENT 0x0002
|
||||
|
||||
|
||||
/*
|
||||
* Hub descriptor
|
||||
* See USB 2.0 spec Table 11-13
|
||||
*/
|
||||
|
||||
#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
|
||||
#define USB_DT_HUB_NONVAR_SIZE 7
|
||||
|
||||
struct usb_hub_descriptor {
|
||||
__u8 bDescLength;
|
||||
__u8 bDescriptorType;
|
||||
__u8 bNbrPorts;
|
||||
__u16 wHubCharacteristics;
|
||||
__u8 bPwrOn2PwrGood;
|
||||
__u8 bHubContrCurrent;
|
||||
/* add 1 bit for hub status change; round to bytes */
|
||||
__u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
__u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct usb_device;
|
||||
|
||||
/*
|
||||
* As of USB 2.0, full/low speed devices are segregated into trees.
|
||||
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
||||
* The other type grows from high speed hubs when they connect to
|
||||
* full/low speed devices using "Transaction Translators" (TTs).
|
||||
*
|
||||
* TTs should only be known to the hub driver, and high speed bus
|
||||
* drivers (only EHCI for now). They affect periodic scheduling and
|
||||
* sometimes control/bulk error recovery.
|
||||
*/
|
||||
struct usb_tt {
|
||||
struct usb_device *hub; /* upstream highspeed hub */
|
||||
int multi; /* true means one TT per port */
|
||||
|
||||
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
||||
spinlock_t lock;
|
||||
struct list_head clear_list; /* of usb_tt_clear */
|
||||
struct work_struct kevent;
|
||||
};
|
||||
|
||||
struct usb_tt_clear {
|
||||
struct list_head clear_list;
|
||||
unsigned tt;
|
||||
u16 devinfo;
|
||||
};
|
||||
|
||||
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
|
||||
|
||||
struct usb_hub {
|
||||
struct usb_interface *intf; /* the "real" device */
|
||||
struct urb *urb; /* for interrupt polling pipe */
|
||||
|
||||
/* buffer for urb ... 1 bit each for hub and children, rounded up */
|
||||
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
|
||||
dma_addr_t buffer_dma; /* DMA address for buffer */
|
||||
union {
|
||||
struct usb_hub_status hub;
|
||||
struct usb_port_status port;
|
||||
} *status; /* buffer for status reports */
|
||||
|
||||
int error; /* last reported error */
|
||||
int nerrors; /* track consecutive errors */
|
||||
|
||||
struct list_head hub_list; /* all hubs */
|
||||
struct list_head event_list; /* hubs w/data or errs ready */
|
||||
|
||||
struct usb_hub_descriptor *descriptor; /* class descriptor */
|
||||
struct semaphore khubd_sem;
|
||||
struct usb_tt tt; /* Transaction Translator */
|
||||
};
|
||||
|
||||
#endif /* __LINUX_HUB_H */
|
||||
18
reactos/drivers/usb/cromwell/core/makefile
Normal file
18
reactos/drivers/usb/cromwell/core/makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = usbcore
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o \
|
||||
buffer_simple.o usb-debug.o ../sys/ros_wrapper.o \
|
||||
../sys/linuxwrapper.o usbcore.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
6
reactos/drivers/usb/cromwell/core/makefile.crom
Normal file
6
reactos/drivers/usb/cromwell/core/makefile.crom
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
O_TARGET := message.o hcd.o hcd-pci.o hub.o usb.o config.o urb.o buffer_simple.o urb.o usb-debug.o
|
||||
|
||||
#O_TARGET := urb.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
1053
reactos/drivers/usb/cromwell/core/message.c
Normal file
1053
reactos/drivers/usb/cromwell/core/message.c
Normal file
File diff suppressed because it is too large
Load Diff
398
reactos/drivers/usb/cromwell/core/urb.c
Normal file
398
reactos/drivers/usb/cromwell/core/urb.c
Normal file
@@ -0,0 +1,398 @@
|
||||
#include "../usb_wrapper.h"
|
||||
#include "hcd.h"
|
||||
|
||||
/**
|
||||
* usb_init_urb - initializes a urb so that it can be used by a USB driver
|
||||
* @urb: pointer to the urb to initialize
|
||||
*
|
||||
* Initializes a urb so that the USB subsystem can use it properly.
|
||||
*
|
||||
* If a urb is created with a call to usb_alloc_urb() it is not
|
||||
* necessary to call this function. Only use this if you allocate the
|
||||
* space for a struct urb on your own. If you call this function, be
|
||||
* careful when freeing the memory for your urb that it is no longer in
|
||||
* use by the USB core.
|
||||
*
|
||||
* Only use this function if you _really_ understand what you are doing.
|
||||
*/
|
||||
void STDCALL usb_init_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
memset(urb, 0, sizeof(*urb));
|
||||
urb->count = (atomic_t)ATOMIC_INIT(1);
|
||||
spin_lock_init(&urb->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_alloc_urb - creates a new urb for a USB driver to use
|
||||
* @iso_packets: number of iso packets for this urb
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list of
|
||||
* valid options for this.
|
||||
*
|
||||
* Creates an urb for the USB driver to use, initializes a few internal
|
||||
* structures, incrementes the usage counter, and returns a pointer to it.
|
||||
*
|
||||
* If no memory is available, NULL is returned.
|
||||
*
|
||||
* If the driver want to use this urb for interrupt, control, or bulk
|
||||
* endpoints, pass '0' as the number of iso packets.
|
||||
*
|
||||
* The driver must call usb_free_urb() when it is finished with the urb.
|
||||
*/
|
||||
struct urb STDCALL *usb_alloc_urb(int iso_packets, int mem_flags)
|
||||
{
|
||||
struct urb *urb;
|
||||
|
||||
urb = (struct urb *)kmalloc(sizeof(struct urb) +
|
||||
iso_packets * sizeof(struct usb_iso_packet_descriptor),
|
||||
mem_flags);
|
||||
if (!urb) {
|
||||
err("alloc_urb: kmalloc failed");
|
||||
return NULL;
|
||||
}
|
||||
usb_init_urb(urb);
|
||||
return urb;
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_free_urb - frees the memory used by a urb when all users of it are finished
|
||||
* @urb: pointer to the urb to free
|
||||
*
|
||||
* Must be called when a user of a urb is finished with it. When the last user
|
||||
* of the urb calls this function, the memory of the urb is freed.
|
||||
*
|
||||
* Note: The transfer buffer associated with the urb is not freed, that must be
|
||||
* done elsewhere.
|
||||
*/
|
||||
void STDCALL usb_free_urb(struct urb *urb)
|
||||
{
|
||||
if (urb)
|
||||
if (atomic_dec_and_test(&urb->count))
|
||||
{
|
||||
kfree(urb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* usb_get_urb - increments the reference count of the urb
|
||||
* @urb: pointer to the urb to modify
|
||||
*
|
||||
* This must be called whenever a urb is transferred from a device driver to a
|
||||
* host controller driver. This allows proper reference counting to happen
|
||||
* for urbs.
|
||||
*
|
||||
* A pointer to the urb with the incremented reference counter is returned.
|
||||
*/
|
||||
struct urb STDCALL * usb_get_urb(struct urb *urb)
|
||||
{
|
||||
if (urb) {
|
||||
atomic_inc(&urb->count);
|
||||
return urb;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_submit_urb - issue an asynchronous transfer request for an endpoint
|
||||
* @urb: pointer to the urb describing the request
|
||||
* @mem_flags: the type of memory to allocate, see kmalloc() for a list
|
||||
* of valid options for this.
|
||||
*
|
||||
* This submits a transfer request, and transfers control of the URB
|
||||
* describing that request to the USB subsystem. Request completion will
|
||||
* be indicated later, asynchronously, by calling the completion handler.
|
||||
* The three types of completion are success, error, and unlink
|
||||
* (also called "request cancellation").
|
||||
* URBs may be submitted in interrupt context.
|
||||
*
|
||||
* The caller must have correctly initialized the URB before submitting
|
||||
* it. Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
|
||||
* available to ensure that most fields are correctly initialized, for
|
||||
* the particular kind of transfer, although they will not initialize
|
||||
* any transfer flags.
|
||||
*
|
||||
* Successful submissions return 0; otherwise this routine returns a
|
||||
* negative error number. If the submission is successful, the complete()
|
||||
* callback from the urb will be called exactly once, when the USB core and
|
||||
* host controller driver are finished with the urb. When the completion
|
||||
* function is called, control of the URB is returned to the device
|
||||
* driver which issued the request. The completion handler may then
|
||||
* immediately free or reuse that URB.
|
||||
*
|
||||
* For control endpoints, the synchronous usb_control_msg() call is
|
||||
* often used (in non-interrupt context) instead of this call.
|
||||
* That is often used through convenience wrappers, for the requests
|
||||
* that are standardized in the USB 2.0 specification. For bulk
|
||||
* endpoints, a synchronous usb_bulk_msg() call is available.
|
||||
*
|
||||
* Request Queuing:
|
||||
*
|
||||
* URBs may be submitted to endpoints before previous ones complete, to
|
||||
* minimize the impact of interrupt latencies and system overhead on data
|
||||
* throughput. This is required for continuous isochronous data streams,
|
||||
* and may also be required for some kinds of interrupt transfers. Such
|
||||
* queueing also maximizes bandwidth utilization by letting USB controllers
|
||||
* start work on later requests before driver software has finished the
|
||||
* completion processing for earlier requests.
|
||||
*
|
||||
* Bulk and Isochronous URBs may always be queued. At this writing, all
|
||||
* mainstream host controller drivers support queueing for control and
|
||||
* interrupt transfer requests.
|
||||
*
|
||||
* Reserved Bandwidth Transfers:
|
||||
*
|
||||
* Periodic transfers (interrupt or isochronous) are performed repeatedly,
|
||||
* using the interval specified in the urb. Submitting the first urb to
|
||||
* the endpoint reserves the bandwidth necessary to make those transfers.
|
||||
* If the USB subsystem can't allocate sufficient bandwidth to perform
|
||||
* the periodic request, submitting such a periodic request should fail.
|
||||
*
|
||||
* Device drivers must explicitly request that repetition, by ensuring that
|
||||
* some URB is always on the endpoint's queue (except possibly for short
|
||||
* periods during completion callacks). When there is no longer an urb
|
||||
* queued, the endpoint's bandwidth reservation is canceled. This means
|
||||
* drivers can use their completion handlers to ensure they keep bandwidth
|
||||
* they need, by reinitializing and resubmitting the just-completed urb
|
||||
* until the driver longer needs that periodic bandwidth.
|
||||
*
|
||||
* Memory Flags:
|
||||
*
|
||||
* The general rules for how to decide which mem_flags to use
|
||||
* are the same as for kmalloc. There are four
|
||||
* different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
|
||||
* GFP_ATOMIC.
|
||||
*
|
||||
* GFP_NOFS is not ever used, as it has not been implemented yet.
|
||||
*
|
||||
* GFP_ATOMIC is used when
|
||||
* (a) you are inside a completion handler, an interrupt, bottom half,
|
||||
* tasklet or timer, or
|
||||
* (b) you are holding a spinlock or rwlock (does not apply to
|
||||
* semaphores), or
|
||||
* (c) current->state != TASK_RUNNING, this is the case only after
|
||||
* you've changed it.
|
||||
*
|
||||
* GFP_NOIO is used in the block io path and error handling of storage
|
||||
* devices.
|
||||
*
|
||||
* All other situations use GFP_KERNEL.
|
||||
*
|
||||
* Some more specific rules for mem_flags can be inferred, such as
|
||||
* (1) start_xmit, timeout, and receive methods of network drivers must
|
||||
* use GFP_ATOMIC (they are called with a spinlock held);
|
||||
* (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
|
||||
* called with a spinlock held);
|
||||
* (3) If you use a kernel thread with a network driver you must use
|
||||
* GFP_NOIO, unless (b) or (c) apply;
|
||||
* (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
|
||||
* apply or your are in a storage driver's block io path;
|
||||
* (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
|
||||
* (6) changing firmware on a running storage or net device uses
|
||||
* GFP_NOIO, unless b) or c) apply
|
||||
*
|
||||
*/
|
||||
int STDCALL usb_submit_urb(struct urb *urb, int mem_flags)
|
||||
{
|
||||
int pipe, temp, max;
|
||||
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);
|
||||
if (!urb || urb->hcpriv || !urb->complete)
|
||||
return -EINVAL;
|
||||
if (!(dev = urb->dev) ||
|
||||
(dev->state < USB_STATE_DEFAULT) ||
|
||||
(!dev->bus) || (dev->devnum <= 0))
|
||||
return -ENODEV;
|
||||
if (!(op = dev->bus->op) || !op->submit_urb)
|
||||
return -ENODEV;
|
||||
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->actual_length = 0;
|
||||
urb->bandwidth = 0;
|
||||
|
||||
/* Lots of sanity checks, so HCDs can rely on clean data
|
||||
* and don't need to duplicate tests
|
||||
*/
|
||||
pipe = urb->pipe;
|
||||
temp = usb_pipetype (pipe);
|
||||
is_out = usb_pipeout (pipe);
|
||||
|
||||
if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED)
|
||||
return -ENODEV;
|
||||
|
||||
/* (actually HCDs may need to duplicate this, endpoint might yet
|
||||
* stall due to queued bulk/intr transactions that complete after
|
||||
* we check)
|
||||
*/
|
||||
if (usb_endpoint_halted (dev, usb_pipeendpoint (pipe), is_out))
|
||||
return -EPIPE;
|
||||
|
||||
/* FIXME there should be a sharable lock protecting us against
|
||||
* config/altsetting changes and disconnects, kicking in here.
|
||||
* (here == before maxpacket, and eventually endpoint type,
|
||||
* checks get made.)
|
||||
*/
|
||||
|
||||
max = usb_maxpacket (dev, pipe, is_out);
|
||||
if (max <= 0) {
|
||||
dbg ("%s: bogus endpoint %d-%s on usb-%s-%s (bad maxpacket %d)",
|
||||
__FUNCTION__,
|
||||
usb_pipeendpoint (pipe), is_out ? "OUT" : "IN",
|
||||
dev->bus->bus_name, dev->devpath,
|
||||
max);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* periodic transfers limit size per frame/uframe,
|
||||
* but drivers only control those sizes for ISO.
|
||||
* while we're checking, initialize return status.
|
||||
*/
|
||||
if (temp == PIPE_ISOCHRONOUS) {
|
||||
int n, len;
|
||||
|
||||
/* "high bandwidth" mode, 1-3 packets/uframe? */
|
||||
if (dev->speed == USB_SPEED_HIGH) {
|
||||
int mult = 1 + ((max >> 11) & 0x03);
|
||||
max &= 0x03ff;
|
||||
max *= mult;
|
||||
}
|
||||
|
||||
if (urb->number_of_packets <= 0)
|
||||
return -EINVAL;
|
||||
for (n = 0; n < urb->number_of_packets; n++) {
|
||||
len = urb->iso_frame_desc [n].length;
|
||||
if (len < 0 || len > max)
|
||||
return -EMSGSIZE;
|
||||
urb->iso_frame_desc [n].status = -EXDEV;
|
||||
urb->iso_frame_desc [n].actual_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* the I/O buffer must be mapped/unmapped, except when length=0 */
|
||||
if (urb->transfer_buffer_length < 0)
|
||||
return -EMSGSIZE;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* stuff that drivers shouldn't do, but which shouldn't
|
||||
* cause problems in HCDs if they get it wrong.
|
||||
*/
|
||||
{
|
||||
unsigned int orig_flags = urb->transfer_flags;
|
||||
unsigned int allowed;
|
||||
|
||||
/* enforce simple/standard policy */
|
||||
allowed = URB_ASYNC_UNLINK; // affects later unlinks
|
||||
allowed |= URB_NO_DMA_MAP;
|
||||
allowed |= URB_NO_INTERRUPT;
|
||||
switch (temp) {
|
||||
case PIPE_BULK:
|
||||
if (is_out)
|
||||
allowed |= URB_ZERO_PACKET;
|
||||
/* FALLTHROUGH */
|
||||
case PIPE_CONTROL:
|
||||
allowed |= URB_NO_FSBR; /* only affects UHCI */
|
||||
/* FALLTHROUGH */
|
||||
default: /* all non-iso endpoints */
|
||||
if (!is_out)
|
||||
allowed |= URB_SHORT_NOT_OK;
|
||||
break;
|
||||
case PIPE_ISOCHRONOUS:
|
||||
allowed |= URB_ISO_ASAP;
|
||||
break;
|
||||
}
|
||||
urb->transfer_flags &= allowed;
|
||||
|
||||
/* fail if submitter gave bogus flags */
|
||||
if (urb->transfer_flags != orig_flags) {
|
||||
err ("BOGUS urb flags, %x --> %x",
|
||||
orig_flags, urb->transfer_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Force periodic transfer intervals to be legal values that are
|
||||
* a power of two (so HCDs don't need to).
|
||||
*
|
||||
* FIXME want bus->{intr,iso}_sched_horizon values here. Each HC
|
||||
* supports different values... this uses EHCI/UHCI defaults (and
|
||||
* EHCI can use smaller non-default values).
|
||||
*/
|
||||
switch (temp) {
|
||||
case PIPE_ISOCHRONOUS:
|
||||
case PIPE_INTERRUPT:
|
||||
/* too small? */
|
||||
if (urb->interval <= 0)
|
||||
return -EINVAL;
|
||||
/* too big? */
|
||||
switch (dev->speed) {
|
||||
case USB_SPEED_HIGH: /* units are microframes */
|
||||
// NOTE usb handles 2^15
|
||||
if (urb->interval > (1024 * 8))
|
||||
urb->interval = 1024 * 8;
|
||||
temp = 1024 * 8;
|
||||
break;
|
||||
case USB_SPEED_FULL: /* units are frames/msec */
|
||||
case USB_SPEED_LOW:
|
||||
if (temp == PIPE_INTERRUPT) {
|
||||
if (urb->interval > 255)
|
||||
return -EINVAL;
|
||||
// NOTE ohci only handles up to 32
|
||||
temp = 128;
|
||||
} else {
|
||||
if (urb->interval > 1024)
|
||||
urb->interval = 1024;
|
||||
// NOTE usb and ohci handle up to 2^15
|
||||
temp = 1024;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
/* power of two? */
|
||||
while (temp > urb->interval)
|
||||
temp >>= 1;
|
||||
urb->interval = temp;
|
||||
}
|
||||
|
||||
return op->submit_urb (urb, mem_flags);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* usb_unlink_urb - abort/cancel a transfer request for an endpoint
|
||||
* @urb: pointer to urb describing a previously submitted request
|
||||
*
|
||||
* This routine cancels an in-progress request. The requests's
|
||||
* completion handler will be called with a status code indicating
|
||||
* that the request has been canceled, and that control of the URB
|
||||
* has been returned to that device driver.
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
|
||||
* request is synchronous. Success is indicated by returning zero,
|
||||
* at which time the urb will have been unlinked,
|
||||
* and the completion function will see status -ENOENT. Failure is
|
||||
* indicated by any other return value. This mode may not be used
|
||||
* when unlinking an urb from an interrupt context, such as a bottom
|
||||
* half or a completion handler,
|
||||
*
|
||||
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
|
||||
* request is asynchronous. Success is indicated by returning -EINPROGRESS,
|
||||
* at which time the urb will normally not have been unlinked,
|
||||
* and the completion function will see status -ECONNRESET. Failure is
|
||||
* indicated by any other return value.
|
||||
*/
|
||||
int STDCALL usb_unlink_urb(struct urb *urb)
|
||||
{
|
||||
if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
|
||||
return urb->dev->bus->op->unlink_urb(urb);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
206
reactos/drivers/usb/cromwell/core/usb-debug.c
Normal file
206
reactos/drivers/usb/cromwell/core/usb-debug.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* debug.c - USB debug helper routines.
|
||||
*
|
||||
* I just want these out of the way where they aren't in your
|
||||
* face, but so that you can still use them..
|
||||
*/
|
||||
#define CONFIG_USB_DEBUG
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
#define DEBUG
|
||||
#else
|
||||
#undef DEBUG
|
||||
#endif
|
||||
#include <linux/usb.h>
|
||||
#else
|
||||
#include "../usb_wrapper.h"
|
||||
#endif
|
||||
|
||||
static void usb_show_endpoint(struct usb_host_endpoint *endpoint)
|
||||
{
|
||||
usb_show_endpoint_descriptor(&endpoint->desc);
|
||||
}
|
||||
|
||||
static void usb_show_interface(struct usb_host_interface *altsetting)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_interface_descriptor(&altsetting->desc);
|
||||
|
||||
for (i = 0; i < altsetting->desc.bNumEndpoints; i++)
|
||||
usb_show_endpoint(altsetting->endpoint + i);
|
||||
}
|
||||
|
||||
static void usb_show_config(struct usb_host_config *config)
|
||||
{
|
||||
int i, j;
|
||||
struct usb_interface *ifp;
|
||||
|
||||
usb_show_config_descriptor(&config->desc);
|
||||
for (i = 0; i < config->desc.bNumInterfaces; i++) {
|
||||
ifp = config->interface + i;
|
||||
|
||||
if (!ifp)
|
||||
break;
|
||||
|
||||
printk("\n Interface: %d\n", i);
|
||||
for (j = 0; j < ifp->num_altsetting; j++)
|
||||
usb_show_interface(ifp->altsetting + j);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_device(struct usb_device *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
usb_show_device_descriptor(&dev->descriptor);
|
||||
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
|
||||
usb_show_config(dev->config + i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and show the different USB descriptors.
|
||||
*/
|
||||
void usb_show_device_descriptor(struct usb_device_descriptor *desc)
|
||||
{
|
||||
if (!desc)
|
||||
{
|
||||
printk("Invalid USB device descriptor (NULL POINTER)\n");
|
||||
return;
|
||||
}
|
||||
printk(" Length = %2d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_DEVICE_SIZE ? "" : " (!!!)");
|
||||
printk(" DescriptorType = %02x\n", desc->bDescriptorType);
|
||||
|
||||
printk(" USB version = %x.%02x\n",
|
||||
desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
|
||||
printk(" Vendor:Product = %04x:%04x\n",
|
||||
desc->idVendor, desc->idProduct);
|
||||
printk(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
|
||||
printk(" NumConfigurations = %d\n", desc->bNumConfigurations);
|
||||
printk(" Device version = %x.%02x\n",
|
||||
desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
|
||||
|
||||
printk(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
|
||||
switch (desc->bDeviceClass) {
|
||||
case 0:
|
||||
printk(" Per-interface classes\n");
|
||||
break;
|
||||
case USB_CLASS_AUDIO:
|
||||
printk(" Audio device class\n");
|
||||
break;
|
||||
case USB_CLASS_COMM:
|
||||
printk(" Communications class\n");
|
||||
break;
|
||||
case USB_CLASS_HID:
|
||||
printk(" Human Interface Devices class\n");
|
||||
break;
|
||||
case USB_CLASS_PRINTER:
|
||||
printk(" Printer device class\n");
|
||||
break;
|
||||
case USB_CLASS_MASS_STORAGE:
|
||||
printk(" Mass Storage device class\n");
|
||||
break;
|
||||
case USB_CLASS_HUB:
|
||||
printk(" Hub device class\n");
|
||||
break;
|
||||
case USB_CLASS_VENDOR_SPEC:
|
||||
printk(" Vendor class\n");
|
||||
break;
|
||||
default:
|
||||
printk(" Unknown class\n");
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_config_descriptor(struct usb_config_descriptor *desc)
|
||||
{
|
||||
printk("Configuration:\n");
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_CONFIG_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" wTotalLength = %04x\n", desc->wTotalLength);
|
||||
printk(" bNumInterfaces = %02x\n", desc->bNumInterfaces);
|
||||
printk(" bConfigurationValue = %02x\n", desc->bConfigurationValue);
|
||||
printk(" iConfiguration = %02x\n", desc->iConfiguration);
|
||||
printk(" bmAttributes = %02x\n", desc->bmAttributes);
|
||||
printk(" bMaxPower = %4dmA\n", desc->bMaxPower * 2);
|
||||
}
|
||||
|
||||
void usb_show_interface_descriptor(struct usb_interface_descriptor *desc)
|
||||
{
|
||||
printk(" Alternate Setting: %2d\n", desc->bAlternateSetting);
|
||||
printk(" bLength = %4d%s\n", desc->bLength,
|
||||
desc->bLength == USB_DT_INTERFACE_SIZE ? "" : " (!!!)");
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bInterfaceNumber = %02x\n", desc->bInterfaceNumber);
|
||||
printk(" bAlternateSetting = %02x\n", desc->bAlternateSetting);
|
||||
printk(" bNumEndpoints = %02x\n", desc->bNumEndpoints);
|
||||
printk(" bInterface Class:SubClass:Protocol = %02x:%02x:%02x\n",
|
||||
desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol);
|
||||
printk(" iInterface = %02x\n", desc->iInterface);
|
||||
}
|
||||
|
||||
void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
|
||||
{
|
||||
char *LengthCommentString = (desc->bLength ==
|
||||
USB_DT_ENDPOINT_AUDIO_SIZE) ? " (Audio)" : (desc->bLength ==
|
||||
USB_DT_ENDPOINT_SIZE) ? "" : " (!!!)";
|
||||
char *EndpointType[4] = { "Control", "Isochronous", "Bulk", "Interrupt" };
|
||||
|
||||
printk(" Endpoint:\n");
|
||||
printk(" bLength = %4d%s\n",
|
||||
desc->bLength, LengthCommentString);
|
||||
printk(" bDescriptorType = %02x\n", desc->bDescriptorType);
|
||||
printk(" bEndpointAddress = %02x (%s)\n", desc->bEndpointAddress,
|
||||
(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_CONTROL ? "i/o" :
|
||||
(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? "in" : "out");
|
||||
printk(" bmAttributes = %02x (%s)\n", desc->bmAttributes,
|
||||
EndpointType[USB_ENDPOINT_XFERTYPE_MASK & desc->bmAttributes]);
|
||||
printk(" wMaxPacketSize = %04x\n", desc->wMaxPacketSize);
|
||||
printk(" bInterval = %02x\n", desc->bInterval);
|
||||
|
||||
/* Audio extensions to the endpoint descriptor */
|
||||
if (desc->bLength == USB_DT_ENDPOINT_AUDIO_SIZE) {
|
||||
printk(" bRefresh = %02x\n", desc->bRefresh);
|
||||
printk(" bSynchAddress = %02x\n", desc->bSynchAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_show_string(struct usb_device *dev, char *id, int index)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if (!index)
|
||||
return;
|
||||
if (!(buf = kmalloc(256, GFP_KERNEL)))
|
||||
return;
|
||||
if (usb_string(dev, index, buf, 256) > 0)
|
||||
dev_printk(KERN_INFO, &dev->dev, "%s: %s\n", id, buf);
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
void usb_dump_urb (struct urb *urb)
|
||||
{
|
||||
printk ("urb :%p\n", urb);
|
||||
printk ("dev :%p\n", urb->dev);
|
||||
printk ("pipe :%08X\n", urb->pipe);
|
||||
printk ("status :%d\n", urb->status);
|
||||
printk ("transfer_flags :%08X\n", urb->transfer_flags);
|
||||
printk ("transfer_buffer :%p\n", urb->transfer_buffer);
|
||||
printk ("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
|
||||
printk ("actual_length :%d\n", urb->actual_length);
|
||||
printk ("setup_packet :%p\n", urb->setup_packet);
|
||||
printk ("start_frame :%d\n", urb->start_frame);
|
||||
printk ("number_of_packets :%d\n", urb->number_of_packets);
|
||||
printk ("interval :%d\n", urb->interval);
|
||||
printk ("error_count :%d\n", urb->error_count);
|
||||
printk ("context :%p\n", urb->context);
|
||||
printk ("complete :%p\n", urb->complete);
|
||||
}
|
||||
|
||||
1596
reactos/drivers/usb/cromwell/core/usb.c
Normal file
1596
reactos/drivers/usb/cromwell/core/usb.c
Normal file
File diff suppressed because it is too large
Load Diff
5
reactos/drivers/usb/cromwell/core/usb.h
Normal file
5
reactos/drivers/usb/cromwell/core/usb.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Functions local to drivers/usb/core/ */
|
||||
|
||||
extern void usb_create_driverfs_dev_files (struct usb_device *dev);
|
||||
extern void usb_create_driverfs_intf_files (struct usb_interface *intf);
|
||||
|
||||
BIN
reactos/drivers/usb/cromwell/core/usbcore.a
Normal file
BIN
reactos/drivers/usb/cromwell/core/usbcore.a
Normal file
Binary file not shown.
16
reactos/drivers/usb/cromwell/core/usbcore.c
Normal file
16
reactos/drivers/usb/cromwell/core/usbcore.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
ReactOS specific functions for usbcore module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PVOID Context1, IN PVOID Context2)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
BIN
reactos/drivers/usb/cromwell/core/usbcore.coff
Normal file
BIN
reactos/drivers/usb/cromwell/core/usbcore.coff
Normal file
Binary file not shown.
29
reactos/drivers/usb/cromwell/core/usbcore.def
Normal file
29
reactos/drivers/usb/cromwell/core/usbcore.def
Normal file
@@ -0,0 +1,29 @@
|
||||
;
|
||||
; Exports definition file for usbcore.sys
|
||||
;
|
||||
EXPORTS
|
||||
usb_init_urb@4
|
||||
usb_alloc_urb@8
|
||||
usb_free_urb@4
|
||||
usb_get_urb@4
|
||||
usb_submit_urb@8
|
||||
usb_unlink_urb@4
|
||||
usb_bus_init@4
|
||||
usb_alloc_bus@4
|
||||
usb_free_bus@4
|
||||
usb_register_bus@4
|
||||
usb_deregister_bus@4
|
||||
usb_register_root_hub@8
|
||||
usb_calc_bus_time@16
|
||||
usb_check_bandwidth@8
|
||||
usb_claim_bandwidth@16
|
||||
usb_release_bandwidth@12
|
||||
usb_hcd_giveback_urb@12
|
||||
;usb_hcd_irq@12
|
||||
usb_hc_died@4
|
||||
usb_alloc_dev@8
|
||||
usb_connect@4
|
||||
usb_put_dev@4
|
||||
usb_disabled@0
|
||||
usb_hcd_pci_probe@8
|
||||
usb_hcd_pci_remove@4
|
||||
11539
reactos/drivers/usb/cromwell/core/usbcore.map
Normal file
11539
reactos/drivers/usb/cromwell/core/usbcore.map
Normal file
File diff suppressed because it is too large
Load Diff
BIN
reactos/drivers/usb/cromwell/core/usbcore.nostrip.sys
Normal file
BIN
reactos/drivers/usb/cromwell/core/usbcore.nostrip.sys
Normal file
Binary file not shown.
5
reactos/drivers/usb/cromwell/core/usbcore.rc
Normal file
5
reactos/drivers/usb/cromwell/core/usbcore.rc
Normal file
@@ -0,0 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB Core Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "usbcore\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "usbcore.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
BIN
reactos/drivers/usb/cromwell/core/usbcore.sym
Normal file
BIN
reactos/drivers/usb/cromwell/core/usbcore.sym
Normal file
Binary file not shown.
BIN
reactos/drivers/usb/cromwell/core/usbcore.sys
Normal file
BIN
reactos/drivers/usb/cromwell/core/usbcore.sys
Normal file
Binary file not shown.
16
reactos/drivers/usb/cromwell/host/makefile
Normal file
16
reactos/drivers/usb/cromwell/host/makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
PATH_TO_TOP = ../../../..
|
||||
|
||||
TARGET_TYPE = export_driver
|
||||
|
||||
TARGET_NAME = ohci
|
||||
|
||||
TARGET_DDKLIBS = ntoskrnl.a usbcore.a
|
||||
|
||||
TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
ohci-hcd.o ohci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
||||
3
reactos/drivers/usb/cromwell/host/makefile.crom
Normal file
3
reactos/drivers/usb/cromwell/host/makefile.crom
Normal file
@@ -0,0 +1,3 @@
|
||||
O_TARGET := ohci-hcd.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
666
reactos/drivers/usb/cromwell/host/ohci-dbg.c
Normal file
666
reactos/drivers/usb/cromwell/host/ohci-dbg.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define edstring(ed_type) ({ char *temp; \
|
||||
switch (ed_type) { \
|
||||
case PIPE_CONTROL: temp = "ctrl"; break; \
|
||||
case PIPE_BULK: temp = "bulk"; break; \
|
||||
case PIPE_INTERRUPT: temp = "intr"; break; \
|
||||
default: temp = "isoc"; break; \
|
||||
}; temp;})
|
||||
#define pipestring(pipe) edstring(usb_pipetype(pipe))
|
||||
|
||||
/* debug| print the main components of an URB
|
||||
* small: 0) header + data packets 1) just header
|
||||
*/
|
||||
static void __attribute__((unused))
|
||||
urb_print (struct urb * urb, char * str, int small)
|
||||
{
|
||||
unsigned int pipe= urb->pipe;
|
||||
|
||||
if (!urb->dev || !urb->dev->bus) {
|
||||
dbg("%s URB: no dev", str);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef OHCI_VERBOSE_DEBUG
|
||||
if (urb->status != 0)
|
||||
#endif
|
||||
dbg("%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d stat=%d",
|
||||
str,
|
||||
urb,
|
||||
usb_pipedevice (pipe),
|
||||
usb_pipeendpoint (pipe),
|
||||
usb_pipeout (pipe)? "out" : "in",
|
||||
pipestring (pipe),
|
||||
urb->transfer_flags,
|
||||
urb->actual_length,
|
||||
urb->transfer_buffer_length,
|
||||
urb->status);
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
if (!small) {
|
||||
int i, len;
|
||||
|
||||
if (usb_pipecontrol (pipe)) {
|
||||
printk (KERN_DEBUG __FILE__ ": setup(8):");
|
||||
for (i = 0; i < 8 ; i++)
|
||||
printk (" %02x", ((__u8 *) urb->setup_packet) [i]);
|
||||
printk ("\n");
|
||||
}
|
||||
if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) {
|
||||
printk (KERN_DEBUG __FILE__ ": data(%d/%d):",
|
||||
urb->actual_length,
|
||||
urb->transfer_buffer_length);
|
||||
len = usb_pipeout (pipe)?
|
||||
urb->transfer_buffer_length: urb->actual_length;
|
||||
for (i = 0; i < 16 && i < len; i++)
|
||||
printk (" %02x", ((__u8 *) urb->transfer_buffer) [i]);
|
||||
printk ("%s stat:%d\n", i < len? "...": "", urb->status);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ohci_dbg_sw(ohci, next, size, format, arg...) \
|
||||
do { \
|
||||
if (next) { \
|
||||
unsigned s_len; \
|
||||
s_len = snprintf (*next, *size, format, ## arg ); \
|
||||
*size -= s_len; *next += s_len; \
|
||||
} else \
|
||||
ohci_dbg(ohci,format, ## arg ); \
|
||||
} while (0);
|
||||
|
||||
|
||||
static void ohci_dump_intr_mask (
|
||||
struct ohci_hcd *ohci,
|
||||
char *label,
|
||||
u32 mask,
|
||||
char **next,
|
||||
unsigned *size)
|
||||
{
|
||||
ohci_dbg_sw (ohci, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s\n",
|
||||
label,
|
||||
mask,
|
||||
(mask & OHCI_INTR_MIE) ? " MIE" : "",
|
||||
(mask & OHCI_INTR_OC) ? " OC" : "",
|
||||
(mask & OHCI_INTR_RHSC) ? " RHSC" : "",
|
||||
(mask & OHCI_INTR_FNO) ? " FNO" : "",
|
||||
(mask & OHCI_INTR_UE) ? " UE" : "",
|
||||
(mask & OHCI_INTR_RD) ? " RD" : "",
|
||||
(mask & OHCI_INTR_SF) ? " SF" : "",
|
||||
(mask & OHCI_INTR_WDH) ? " WDH" : "",
|
||||
(mask & OHCI_INTR_SO) ? " SO" : ""
|
||||
);
|
||||
}
|
||||
|
||||
static void maybe_print_eds (
|
||||
struct ohci_hcd *ohci,
|
||||
char *label,
|
||||
u32 value,
|
||||
char **next,
|
||||
unsigned *size)
|
||||
{
|
||||
if (value)
|
||||
ohci_dbg_sw (ohci, next, size, "%s %08x\n", label, value);
|
||||
}
|
||||
|
||||
static char *hcfs2string (int state)
|
||||
{
|
||||
switch (state) {
|
||||
case OHCI_USB_RESET: return "reset";
|
||||
case OHCI_USB_RESUME: return "resume";
|
||||
case OHCI_USB_OPER: return "operational";
|
||||
case OHCI_USB_SUSPEND: return "suspend";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
// dump control and status registers
|
||||
static void
|
||||
ohci_dump_status (struct ohci_hcd *controller, char **next, unsigned *size)
|
||||
{
|
||||
struct ohci_regs *regs = controller->regs;
|
||||
u32 temp;
|
||||
|
||||
temp = readl (®s->revision) & 0xff;
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"OHCI %d.%d, %s legacy support registers\n",
|
||||
0x03 & (temp >> 4), (temp & 0x0f),
|
||||
(temp & 0x10) ? "with" : "NO");
|
||||
|
||||
temp = readl (®s->control);
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"control 0x%03x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n",
|
||||
temp,
|
||||
(temp & OHCI_CTRL_RWE) ? " RWE" : "",
|
||||
(temp & OHCI_CTRL_RWC) ? " RWC" : "",
|
||||
(temp & OHCI_CTRL_IR) ? " IR" : "",
|
||||
hcfs2string (temp & OHCI_CTRL_HCFS),
|
||||
(temp & OHCI_CTRL_BLE) ? " BLE" : "",
|
||||
(temp & OHCI_CTRL_CLE) ? " CLE" : "",
|
||||
(temp & OHCI_CTRL_IE) ? " IE" : "",
|
||||
(temp & OHCI_CTRL_PLE) ? " PLE" : "",
|
||||
temp & OHCI_CTRL_CBSR
|
||||
);
|
||||
|
||||
temp = readl (®s->cmdstatus);
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"cmdstatus 0x%05x SOC=%d%s%s%s%s\n", temp,
|
||||
(temp & OHCI_SOC) >> 16,
|
||||
(temp & OHCI_OCR) ? " OCR" : "",
|
||||
(temp & OHCI_BLF) ? " BLF" : "",
|
||||
(temp & OHCI_CLF) ? " CLF" : "",
|
||||
(temp & OHCI_HCR) ? " HCR" : ""
|
||||
);
|
||||
|
||||
ohci_dump_intr_mask (controller, "intrstatus",
|
||||
readl (®s->intrstatus), next, size);
|
||||
ohci_dump_intr_mask (controller, "intrenable",
|
||||
readl (®s->intrenable), next, size);
|
||||
// intrdisable always same as intrenable
|
||||
|
||||
maybe_print_eds (controller, "ed_periodcurrent",
|
||||
readl (®s->ed_periodcurrent), next, size);
|
||||
|
||||
maybe_print_eds (controller, "ed_controlhead",
|
||||
readl (®s->ed_controlhead), next, size);
|
||||
maybe_print_eds (controller, "ed_controlcurrent",
|
||||
readl (®s->ed_controlcurrent), next, size);
|
||||
|
||||
maybe_print_eds (controller, "ed_bulkhead",
|
||||
readl (®s->ed_bulkhead), next, size);
|
||||
maybe_print_eds (controller, "ed_bulkcurrent",
|
||||
readl (®s->ed_bulkcurrent), next, size);
|
||||
|
||||
maybe_print_eds (controller, "donehead",
|
||||
readl (®s->donehead), next, size);
|
||||
}
|
||||
|
||||
#define dbg_port_sw(hc,num,value,next,size) \
|
||||
ohci_dbg_sw (hc, next, size, \
|
||||
"roothub.portstatus [%d] " \
|
||||
"0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
|
||||
num, temp, \
|
||||
(temp & RH_PS_PRSC) ? " PRSC" : "", \
|
||||
(temp & RH_PS_OCIC) ? " OCIC" : "", \
|
||||
(temp & RH_PS_PSSC) ? " PSSC" : "", \
|
||||
(temp & RH_PS_PESC) ? " PESC" : "", \
|
||||
(temp & RH_PS_CSC) ? " CSC" : "", \
|
||||
\
|
||||
(temp & RH_PS_LSDA) ? " LSDA" : "", \
|
||||
(temp & RH_PS_PPS) ? " PPS" : "", \
|
||||
(temp & RH_PS_PRS) ? " PRS" : "", \
|
||||
(temp & RH_PS_POCI) ? " POCI" : "", \
|
||||
(temp & RH_PS_PSS) ? " PSS" : "", \
|
||||
\
|
||||
(temp & RH_PS_PES) ? " PES" : "", \
|
||||
(temp & RH_PS_CCS) ? " CCS" : "" \
|
||||
);
|
||||
|
||||
|
||||
static void
|
||||
ohci_dump_roothub (
|
||||
struct ohci_hcd *controller,
|
||||
int verbose,
|
||||
char **next,
|
||||
unsigned *size)
|
||||
{
|
||||
u32 temp, ndp, i;
|
||||
|
||||
temp = roothub_a (controller);
|
||||
if (temp == ~(u32)0)
|
||||
return;
|
||||
ndp = (temp & RH_A_NDP);
|
||||
|
||||
if (verbose) {
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"roothub.a %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", temp,
|
||||
((temp & RH_A_POTPGT) >> 24) & 0xff,
|
||||
(temp & RH_A_NOCP) ? " NOCP" : "",
|
||||
(temp & RH_A_OCPM) ? " OCPM" : "",
|
||||
(temp & RH_A_DT) ? " DT" : "",
|
||||
(temp & RH_A_NPS) ? " NPS" : "",
|
||||
(temp & RH_A_PSM) ? " PSM" : "",
|
||||
ndp
|
||||
);
|
||||
temp = roothub_b (controller);
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"roothub.b %08x PPCM=%04x DR=%04x\n",
|
||||
temp,
|
||||
(temp & RH_B_PPCM) >> 16,
|
||||
(temp & RH_B_DR)
|
||||
);
|
||||
temp = roothub_status (controller);
|
||||
ohci_dbg_sw (controller, next, size,
|
||||
"roothub.status %08x%s%s%s%s%s%s\n",
|
||||
temp,
|
||||
(temp & RH_HS_CRWE) ? " CRWE" : "",
|
||||
(temp & RH_HS_OCIC) ? " OCIC" : "",
|
||||
(temp & RH_HS_LPSC) ? " LPSC" : "",
|
||||
(temp & RH_HS_DRWE) ? " DRWE" : "",
|
||||
(temp & RH_HS_OCI) ? " OCI" : "",
|
||||
(temp & RH_HS_LPS) ? " LPS" : ""
|
||||
);
|
||||
}
|
||||
|
||||
for (i = 0; i < ndp; i++) {
|
||||
temp = roothub_portstatus (controller, i);
|
||||
dbg_port_sw (controller, i, temp, next, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void ohci_dump (struct ohci_hcd *controller, int verbose)
|
||||
{
|
||||
ohci_dbg (controller, "OHCI controller state\n");
|
||||
|
||||
// dumps some of the state we know about
|
||||
ohci_dump_status (controller, NULL, 0);
|
||||
if (controller->hcca)
|
||||
ohci_dbg (controller,
|
||||
"hcca frame #%04x\n", controller->hcca->frame_no);
|
||||
ohci_dump_roothub (controller, 1, NULL, 0);
|
||||
}
|
||||
|
||||
static const char data0 [] = "DATA0";
|
||||
static const char data1 [] = "DATA1";
|
||||
|
||||
static void ohci_dump_td (struct ohci_hcd *ohci, char *label, struct td *td)
|
||||
{
|
||||
u32 tmp = le32_to_cpup (&td->hwINFO);
|
||||
|
||||
ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x",
|
||||
label, td,
|
||||
(tmp & TD_DONE) ? " (DONE)" : "",
|
||||
td->urb, td->index,
|
||||
le32_to_cpup (&td->hwNextTD));
|
||||
if ((tmp & TD_ISO) == 0) {
|
||||
const char *toggle, *pid;
|
||||
u32 cbp, be;
|
||||
|
||||
switch (tmp & TD_T) {
|
||||
case TD_T_DATA0: toggle = data0; break;
|
||||
case TD_T_DATA1: toggle = data1; break;
|
||||
case TD_T_TOGGLE: toggle = "(CARRY)"; break;
|
||||
default: toggle = "(?)"; break;
|
||||
}
|
||||
switch (tmp & TD_DP) {
|
||||
case TD_DP_SETUP: pid = "SETUP"; break;
|
||||
case TD_DP_IN: pid = "IN"; break;
|
||||
case TD_DP_OUT: pid = "OUT"; break;
|
||||
default: pid = "(bad pid)"; break;
|
||||
}
|
||||
ohci_dbg (ohci, " info %08x CC=%x %s DI=%d %s %s", tmp,
|
||||
TD_CC_GET(tmp), /* EC, */ toggle,
|
||||
(tmp & TD_DI) >> 21, pid,
|
||||
(tmp & TD_R) ? "R" : "");
|
||||
cbp = le32_to_cpup (&td->hwCBP);
|
||||
be = le32_to_cpup (&td->hwBE);
|
||||
ohci_dbg (ohci, " cbp %08x be %08x (len %d)", cbp, be,
|
||||
cbp ? (be + 1 - cbp) : 0);
|
||||
} else {
|
||||
unsigned i;
|
||||
ohci_dbg (ohci, " info %08x CC=%x FC=%d DI=%d SF=%04x", tmp,
|
||||
TD_CC_GET(tmp),
|
||||
(tmp >> 24) & 0x07,
|
||||
(tmp & TD_DI) >> 21,
|
||||
tmp & 0x0000ffff);
|
||||
ohci_dbg (ohci, " bp0 %08x be %08x",
|
||||
le32_to_cpup (&td->hwCBP) & ~0x0fff,
|
||||
le32_to_cpup (&td->hwBE));
|
||||
for (i = 0; i < MAXPSW; i++) {
|
||||
u16 psw = le16_to_cpup (&td->hwPSW [i]);
|
||||
int cc = (psw >> 12) & 0x0f;
|
||||
ohci_dbg (ohci, " psw [%d] = %2x, CC=%x %s=%d", i,
|
||||
psw, cc,
|
||||
(cc >= 0x0e) ? "OFFSET" : "SIZE",
|
||||
psw & 0x0fff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* caller MUST own hcd spinlock if verbose is set! */
|
||||
static void __attribute__((unused))
|
||||
ohci_dump_ed (struct ohci_hcd *ohci, char *label, struct ed *ed, int verbose)
|
||||
{
|
||||
u32 tmp = ed->hwINFO;
|
||||
char *type = "";
|
||||
|
||||
ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x",
|
||||
label,
|
||||
ed, ed->state, edstring (ed->type),
|
||||
le32_to_cpup (&ed->hwNextED));
|
||||
switch (tmp & (ED_IN|ED_OUT)) {
|
||||
case ED_OUT: type = "-OUT"; break;
|
||||
case ED_IN: type = "-IN"; break;
|
||||
/* else from TDs ... control */
|
||||
}
|
||||
ohci_dbg (ohci,
|
||||
" info %08x MAX=%d%s%s%s%s EP=%d%s DEV=%d", le32_to_cpu (tmp),
|
||||
0x03ff & (le32_to_cpu (tmp) >> 16),
|
||||
(tmp & ED_DEQUEUE) ? " DQ" : "",
|
||||
(tmp & ED_ISO) ? " ISO" : "",
|
||||
(tmp & ED_SKIP) ? " SKIP" : "",
|
||||
(tmp & ED_LOWSPEED) ? " LOW" : "",
|
||||
0x000f & (le32_to_cpu (tmp) >> 7),
|
||||
type,
|
||||
0x007f & le32_to_cpu (tmp));
|
||||
ohci_dbg (ohci, " tds: head %08x %s%s tail %08x%s",
|
||||
tmp = le32_to_cpup (&ed->hwHeadP),
|
||||
(ed->hwHeadP & ED_C) ? data1 : data0,
|
||||
(ed->hwHeadP & ED_H) ? " HALT" : "",
|
||||
le32_to_cpup (&ed->hwTailP),
|
||||
verbose ? "" : " (not listing)");
|
||||
if (verbose) {
|
||||
struct list_head *tmp;
|
||||
|
||||
/* use ed->td_list because HC concurrently modifies
|
||||
* hwNextTD as it accumulates ed_donelist.
|
||||
*/
|
||||
list_for_each (tmp, &ed->td_list) {
|
||||
struct td *td;
|
||||
td = list_entry (tmp, struct td, td_list);
|
||||
ohci_dump_td (ohci, " ->", td);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void ohci_dump (struct ohci_hcd *controller, int verbose) {}
|
||||
|
||||
#undef OHCI_VERBOSE_DEBUG
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef STUB_DEBUG_FILES
|
||||
|
||||
static inline void create_debug_files (struct ohci_hcd *bus) { }
|
||||
static inline void remove_debug_files (struct ohci_hcd *bus) { }
|
||||
|
||||
#else
|
||||
|
||||
static inline struct ohci_hcd *dev_to_ohci (struct device *dev)
|
||||
{
|
||||
struct usb_hcd *hcd = dev_get_drvdata (dev);
|
||||
|
||||
return hcd_to_ohci (hcd);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_list (struct ohci_hcd *ohci, char *buf, size_t count, struct ed *ed)
|
||||
{
|
||||
unsigned temp, size = count;
|
||||
|
||||
if (!ed)
|
||||
return 0;
|
||||
|
||||
/* print first --> last */
|
||||
while (ed->ed_prev)
|
||||
ed = ed->ed_prev;
|
||||
|
||||
/* dump a snapshot of the bulk or control schedule */
|
||||
while (ed) {
|
||||
u32 info = ed->hwINFO;
|
||||
u32 scratch = cpu_to_le32p (&ed->hwINFO);
|
||||
struct list_head *entry;
|
||||
struct td *td;
|
||||
|
||||
temp = snprintf (buf, size,
|
||||
"ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
|
||||
ed,
|
||||
(info & ED_LOWSPEED) ? 'l' : 'f',
|
||||
scratch & 0x7f,
|
||||
(scratch >> 7) & 0xf,
|
||||
(info & ED_IN) ? "in" : "out",
|
||||
0x03ff & (scratch >> 16),
|
||||
scratch,
|
||||
(info & ED_SKIP) ? " s" : "",
|
||||
(ed->hwHeadP & ED_H) ? " H" : "",
|
||||
(ed->hwHeadP & ED_C) ? data1 : data0);
|
||||
size -= temp;
|
||||
buf += temp;
|
||||
|
||||
list_for_each (entry, &ed->td_list) {
|
||||
u32 cbp, be;
|
||||
|
||||
td = list_entry (entry, struct td, td_list);
|
||||
scratch = cpu_to_le32p (&td->hwINFO);
|
||||
cbp = le32_to_cpup (&td->hwCBP);
|
||||
be = le32_to_cpup (&td->hwBE);
|
||||
temp = snprintf (buf, size,
|
||||
"\n\ttd %p %s %d cc=%x urb %p (%08x)",
|
||||
td,
|
||||
({ char *pid;
|
||||
switch (scratch & TD_DP) {
|
||||
case TD_DP_SETUP: pid = "setup"; break;
|
||||
case TD_DP_IN: pid = "in"; break;
|
||||
case TD_DP_OUT: pid = "out"; break;
|
||||
default: pid = "(?)"; break;
|
||||
} pid;}),
|
||||
cbp ? (be + 1 - cbp) : 0,
|
||||
TD_CC_GET (scratch), td->urb, scratch);
|
||||
size -= temp;
|
||||
buf += temp;
|
||||
}
|
||||
|
||||
temp = snprintf (buf, size, "\n");
|
||||
size -= temp;
|
||||
buf += temp;
|
||||
|
||||
ed = ed->ed_next;
|
||||
}
|
||||
return count - size;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_async (struct device *dev, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
size_t temp;
|
||||
unsigned long flags;
|
||||
|
||||
ohci = dev_to_ohci(dev);
|
||||
|
||||
/* display control and bulk lists together, for simplicity */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
temp = show_list (ohci, buf, PAGE_SIZE, ohci->ed_controltail);
|
||||
temp += show_list (ohci, buf + temp, PAGE_SIZE - temp, ohci->ed_bulktail);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
return temp;
|
||||
}
|
||||
static DEVICE_ATTR (async, S_IRUGO, show_async, NULL);
|
||||
|
||||
|
||||
#define DBG_SCHED_LIMIT 64
|
||||
|
||||
static ssize_t
|
||||
show_periodic (struct device *dev, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
struct ed **seen, *ed;
|
||||
unsigned long flags;
|
||||
unsigned temp, size, seen_count;
|
||||
char *next;
|
||||
unsigned i;
|
||||
|
||||
if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, SLAB_ATOMIC)))
|
||||
return 0;
|
||||
seen_count = 0;
|
||||
|
||||
ohci = dev_to_ohci(dev);
|
||||
next = buf;
|
||||
size = PAGE_SIZE;
|
||||
|
||||
temp = snprintf (next, size, "size = %d\n", NUM_INTS);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
/* dump a snapshot of the periodic schedule (and load) */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
for (i = 0; i < NUM_INTS; i++) {
|
||||
if (!(ed = ohci->periodic [i]))
|
||||
continue;
|
||||
|
||||
temp = snprintf (next, size, "%2d [%3d]:", i, ohci->load [i]);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
do {
|
||||
temp = snprintf (next, size, " ed%d/%p",
|
||||
ed->interval, ed);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
for (temp = 0; temp < seen_count; temp++) {
|
||||
if (seen [temp] == ed)
|
||||
break;
|
||||
}
|
||||
|
||||
/* show more info the first time around */
|
||||
if (temp == seen_count) {
|
||||
u32 info = ed->hwINFO;
|
||||
u32 scratch = cpu_to_le32p (&ed->hwINFO);
|
||||
|
||||
temp = snprintf (next, size,
|
||||
" (%cs dev%d%s ep%d%s"
|
||||
" max %d %08x%s%s)",
|
||||
(info & ED_LOWSPEED) ? 'l' : 'f',
|
||||
scratch & 0x7f,
|
||||
(info & ED_ISO) ? " iso" : "",
|
||||
(scratch >> 7) & 0xf,
|
||||
(info & ED_IN) ? "in" : "out",
|
||||
0x03ff & (scratch >> 16),
|
||||
scratch,
|
||||
(info & ED_SKIP) ? " s" : "",
|
||||
(ed->hwHeadP & ED_H) ? " H" : "");
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
// FIXME some TD info too
|
||||
|
||||
if (seen_count < DBG_SCHED_LIMIT)
|
||||
seen [seen_count++] = ed;
|
||||
|
||||
ed = ed->ed_next;
|
||||
|
||||
} else {
|
||||
/* we've seen it and what's after */
|
||||
temp = 0;
|
||||
ed = 0;
|
||||
}
|
||||
|
||||
} while (ed);
|
||||
|
||||
temp = snprintf (next, size, "\n");
|
||||
size -= temp;
|
||||
next += temp;
|
||||
}
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
kfree (seen);
|
||||
|
||||
return PAGE_SIZE - size;
|
||||
}
|
||||
static DEVICE_ATTR (periodic, S_IRUGO, show_periodic, NULL);
|
||||
|
||||
|
||||
#undef DBG_SCHED_LIMIT
|
||||
|
||||
static ssize_t
|
||||
show_registers (struct device *dev, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
struct ohci_regs *regs;
|
||||
unsigned long flags;
|
||||
unsigned temp, size;
|
||||
char *next;
|
||||
u32 rdata;
|
||||
|
||||
ohci = dev_to_ohci(dev);
|
||||
regs = ohci->regs;
|
||||
next = buf;
|
||||
size = PAGE_SIZE;
|
||||
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
|
||||
/* dump driver info, then registers in spec order */
|
||||
|
||||
ohci_dbg_sw (ohci, &next, &size,
|
||||
"%s version " DRIVER_VERSION "\n", hcd_name);
|
||||
|
||||
ohci_dump_status(ohci, &next, &size);
|
||||
|
||||
/* hcca */
|
||||
if (ohci->hcca)
|
||||
ohci_dbg_sw (ohci, &next, &size,
|
||||
"hcca frame 0x%04x\n", ohci->hcca->frame_no);
|
||||
|
||||
/* other registers mostly affect frame timings */
|
||||
rdata = readl (®s->fminterval);
|
||||
temp = snprintf (next, size,
|
||||
"fmintvl 0x%08x %sFSMPS=0x%04x FI=0x%04x\n",
|
||||
rdata, (rdata >> 31) ? " FIT" : "",
|
||||
(rdata >> 16) & 0xefff, rdata & 0xffff);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
rdata = readl (®s->fmremaining);
|
||||
temp = snprintf (next, size, "fmremaining 0x%08x %sFR=0x%04x\n",
|
||||
rdata, (rdata >> 31) ? " FRT" : "",
|
||||
rdata & 0x3fff);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
rdata = readl (®s->periodicstart);
|
||||
temp = snprintf (next, size, "periodicstart 0x%04x\n",
|
||||
rdata & 0x3fff);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
rdata = readl (®s->lsthresh);
|
||||
temp = snprintf (next, size, "lsthresh 0x%04x\n",
|
||||
rdata & 0x3fff);
|
||||
size -= temp;
|
||||
next += temp;
|
||||
|
||||
/* roothub */
|
||||
ohci_dump_roothub (ohci, 1, &next, &size);
|
||||
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
return PAGE_SIZE - size;
|
||||
}
|
||||
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
|
||||
|
||||
|
||||
static inline void create_debug_files (struct ohci_hcd *bus)
|
||||
{
|
||||
device_create_file (bus->hcd.controller, &dev_attr_async);
|
||||
device_create_file (bus->hcd.controller, &dev_attr_periodic);
|
||||
device_create_file (bus->hcd.controller, &dev_attr_registers);
|
||||
ohci_dbg (bus, "created debug files\n");
|
||||
}
|
||||
|
||||
static inline void remove_debug_files (struct ohci_hcd *bus)
|
||||
{
|
||||
device_remove_file (bus->hcd.controller, &dev_attr_async);
|
||||
device_remove_file (bus->hcd.controller, &dev_attr_periodic);
|
||||
device_remove_file (bus->hcd.controller, &dev_attr_registers);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
703
reactos/drivers/usb/cromwell/host/ohci-hcd.c
Normal file
703
reactos/drivers/usb/cromwell/host/ohci-hcd.c
Normal file
@@ -0,0 +1,703 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* [ Initialisation is based on Linus' ]
|
||||
* [ uhci code and gregs ohci fragments ]
|
||||
* [ (C) Copyright 1999 Linus Torvalds ]
|
||||
* [ (C) Copyright 1999 Gregory P. Smith]
|
||||
*
|
||||
*
|
||||
* OHCI is the main "non-Intel/VIA" standard for USB 1.1 host controller
|
||||
* interfaces (though some non-x86 Intel chips use it). It supports
|
||||
* smarter hardware than UHCI. A download link for the spec available
|
||||
* through the http://www.usb.org website.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 2003/02/24 show registers in sysfs (Kevin Brosius)
|
||||
*
|
||||
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
|
||||
* bandwidth accounting; if debugging, show schedules in driverfs
|
||||
* 2002/07/19 fixes to management of ED and schedule state.
|
||||
* 2002/06/09 SA-1111 support (Christopher Hoover)
|
||||
* 2002/06/01 remember frame when HC won't see EDs any more; use that info
|
||||
* to fix urb unlink races caused by interrupt latency assumptions;
|
||||
* minor ED field and function naming updates
|
||||
* 2002/01/18 package as a patch for 2.5.3; this should match the
|
||||
* 2.4.17 kernel modulo some bugs being fixed.
|
||||
*
|
||||
* 2001/10/18 merge pmac cleanup (Benjamin Herrenschmidt) and bugfixes
|
||||
* from post-2.4.5 patches.
|
||||
* 2001/09/20 URB_ZERO_PACKET support; hcca_dma portability, OPTi warning
|
||||
* 2001/09/07 match PCI PM changes, errnos from Linus' tree
|
||||
* 2001/05/05 fork 2.4.5 version into "hcd" framework, cleanup, simplify;
|
||||
* pbook pci quirks gone (please fix pbook pci sw!) (db)
|
||||
*
|
||||
* 2001/04/08 Identify version on module load (gb)
|
||||
* 2001/03/24 td/ed hashing to remove bus_to_virt (Steve Longerbeam);
|
||||
pci_map_single (db)
|
||||
* 2001/03/21 td and dev/ed allocation uses new pci_pool API (db)
|
||||
* 2001/03/07 hcca allocation uses pci_alloc_consistent (Steve Longerbeam)
|
||||
*
|
||||
* 2000/09/26 fixed races in removing the private portion of the urb
|
||||
* 2000/09/07 disable bulk and control lists when unlinking the last
|
||||
* endpoint descriptor in order to avoid unrecoverable errors on
|
||||
* the Lucent chips. (rwc@sgi)
|
||||
* 2000/08/29 use bandwidth claiming hooks (thanks Randy!), fix some
|
||||
* urb unlink probs, indentation fixes
|
||||
* 2000/08/11 various oops fixes mostly affecting iso and cleanup from
|
||||
* device unplugs.
|
||||
* 2000/06/28 use PCI hotplug framework, for better power management
|
||||
* and for Cardbus support (David Brownell)
|
||||
* 2000/earlier: fixes for NEC/Lucent chips; suspend/resume handling
|
||||
* when the controller loses power; handle UE; cleanup; ...
|
||||
*
|
||||
* v5.2 1999/12/07 URB 3rd preview,
|
||||
* v5.1 1999/11/30 URB 2nd preview, cpia, (usb-scsi)
|
||||
* v5.0 1999/11/22 URB Technical preview, Paul Mackerras powerbook susp/resume
|
||||
* i386: HUB, Keyboard, Mouse, Printer
|
||||
*
|
||||
* v4.3 1999/10/27 multiple HCs, bulk_request
|
||||
* v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
|
||||
* v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
|
||||
* v4.0 1999/08/18
|
||||
* v3.0 1999/06/25
|
||||
* v2.1 1999/05/09 code clean up
|
||||
* v2.0 1999/05/04
|
||||
* v1.0 1999/04/27 initial release
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include <linux/config.h>
|
||||
|
||||
#ifdef CONFIG_USB_DEBUG
|
||||
# define DEBUG
|
||||
#else
|
||||
# undef DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h> /* for in_interrupt () */
|
||||
#include <linux/usb.h>
|
||||
#include "../core/hcd.h"
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <asm/byteorder.h>
|
||||
#else
|
||||
#include "ohci_config.h"
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#include "../core/hcd.h"
|
||||
|
||||
//#define OHCI_VERBOSE_DEBUG
|
||||
#endif
|
||||
|
||||
/*
|
||||
* TO DO:
|
||||
*
|
||||
* - "disabled" and "sleeping" should be in hcd->state
|
||||
* - lots more testing!!
|
||||
*/
|
||||
|
||||
#define DRIVER_VERSION "2003 Feb 24"
|
||||
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
|
||||
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
// #define OHCI_VERBOSE_DEBUG /* not always helpful */
|
||||
|
||||
/* For initializing controller (mask in an HCFS mode too) */
|
||||
#define OHCI_CONTROL_INIT \
|
||||
(OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE
|
||||
|
||||
#define OHCI_UNLINK_TIMEOUT (HZ / 10)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static const char hcd_name [] = "ohci-hcd";
|
||||
|
||||
#include "ohci.h"
|
||||
|
||||
static inline void disable (struct ohci_hcd *ohci)
|
||||
{
|
||||
ohci->disabled = 1;
|
||||
ohci->hcd.state = USB_STATE_HALT;
|
||||
}
|
||||
|
||||
#include "ohci-hub.c"
|
||||
#include "ohci-dbg.c"
|
||||
#include "ohci-mem.c"
|
||||
#include "ohci-q.c"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* queue up an urb for anything except the root hub
|
||||
*/
|
||||
static int ohci_urb_enqueue (
|
||||
struct usb_hcd *hcd,
|
||||
struct urb *urb,
|
||||
int mem_flags
|
||||
) {
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
struct ed *ed;
|
||||
urb_priv_t *urb_priv;
|
||||
unsigned int pipe = urb->pipe;
|
||||
int i, size = 0;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
urb_print (urb, "SUB", usb_pipein (pipe));
|
||||
#endif
|
||||
|
||||
/* every endpoint has a ed, locate and maybe (re)initialize it */
|
||||
if (! (ed = ed_get (ohci, urb->dev, pipe, urb->interval)))
|
||||
return -ENOMEM;
|
||||
|
||||
/* for the private part of the URB we need the number of TDs (size) */
|
||||
switch (ed->type) {
|
||||
case PIPE_CONTROL:
|
||||
/* td_submit_urb() doesn't yet handle these */
|
||||
if (urb->transfer_buffer_length > 4096)
|
||||
return -EMSGSIZE;
|
||||
|
||||
/* 1 TD for setup, 1 for ACK, plus ... */
|
||||
size = 2;
|
||||
/* FALLTHROUGH */
|
||||
// case PIPE_INTERRUPT:
|
||||
// case PIPE_BULK:
|
||||
default:
|
||||
/* one TD for every 4096 Bytes (can be upto 8K) */
|
||||
size += urb->transfer_buffer_length / 4096;
|
||||
/* ... and for any remaining bytes ... */
|
||||
if ((urb->transfer_buffer_length % 4096) != 0)
|
||||
size++;
|
||||
/* ... and maybe a zero length packet to wrap it up */
|
||||
if (size == 0)
|
||||
size++;
|
||||
else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0
|
||||
&& (urb->transfer_buffer_length
|
||||
% usb_maxpacket (urb->dev, pipe,
|
||||
usb_pipeout (pipe))) == 0)
|
||||
size++;
|
||||
break;
|
||||
case PIPE_ISOCHRONOUS: /* number of packets from URB */
|
||||
size = urb->number_of_packets;
|
||||
break;
|
||||
}
|
||||
|
||||
/* allocate the private part of the URB */
|
||||
urb_priv = kmalloc (sizeof (urb_priv_t) + size * sizeof (struct td *),
|
||||
mem_flags);
|
||||
if (!urb_priv)
|
||||
return -ENOMEM;
|
||||
memset (urb_priv, 0, sizeof (urb_priv_t) + size * sizeof (struct td *));
|
||||
|
||||
/* fill the private part of the URB */
|
||||
urb_priv->length = size;
|
||||
urb_priv->ed = ed;
|
||||
|
||||
/* allocate the TDs (deferring hash chain updates) */
|
||||
for (i = 0; i < size; i++) {
|
||||
urb_priv->td [i] = td_alloc (ohci, mem_flags);
|
||||
if (!urb_priv->td [i]) {
|
||||
urb_priv->length = i;
|
||||
urb_free_priv (ohci, urb_priv);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
|
||||
/* don't submit to a dead HC */
|
||||
if (ohci->disabled || ohci->sleeping) {
|
||||
retval = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* schedule the ed if needed */
|
||||
if (ed->state == ED_IDLE) {
|
||||
retval = ed_schedule (ohci, ed);
|
||||
if (retval < 0)
|
||||
goto fail;
|
||||
if (ed->type == PIPE_ISOCHRONOUS) {
|
||||
u16 frame = le16_to_cpu (ohci->hcca->frame_no);
|
||||
|
||||
/* delay a few frames before the first TD */
|
||||
frame += max_t (u16, 8, ed->interval);
|
||||
frame &= ~(ed->interval - 1);
|
||||
frame |= ed->branch;
|
||||
urb->start_frame = frame;
|
||||
|
||||
/* yes, only URB_ISO_ASAP is supported, and
|
||||
* urb->start_frame is never used as input.
|
||||
*/
|
||||
}
|
||||
} else if (ed->type == PIPE_ISOCHRONOUS)
|
||||
urb->start_frame = ed->last_iso + ed->interval;
|
||||
|
||||
/* fill the TDs and link them to the ed; and
|
||||
* enable that part of the schedule, if needed
|
||||
* and update count of queued periodic urbs
|
||||
*/
|
||||
urb->hcpriv = urb_priv;
|
||||
td_submit_urb (ohci, urb);
|
||||
|
||||
fail:
|
||||
if (retval)
|
||||
urb_free_priv (ohci, urb_priv);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* decouple the URB from the HC queues (TDs, urb_priv); it's
|
||||
* already marked using urb->status. reporting is always done
|
||||
* asynchronously, and we might be dealing with an urb that's
|
||||
* partially transferred, or an ED with other urbs being unlinked.
|
||||
*/
|
||||
static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
urb_print (urb, "UNLINK", 1);
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
if (!ohci->disabled) {
|
||||
urb_priv_t *urb_priv;
|
||||
|
||||
/* Unless an IRQ completed the unlink while it was being
|
||||
* handed to us, flag it for unlink and giveback, and force
|
||||
* some upcoming INTR_SF to call finish_unlinks()
|
||||
*/
|
||||
urb_priv = urb->hcpriv;
|
||||
if (urb_priv) {
|
||||
urb_priv->state = URB_DEL;
|
||||
if (urb_priv->ed->state == ED_OPER)
|
||||
start_urb_unlink (ohci, urb_priv->ed);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* with HC dead, we won't respect hc queue pointers
|
||||
* any more ... just clean up every urb's memory.
|
||||
*/
|
||||
if (urb->hcpriv) {
|
||||
spin_unlock (&ohci->lock);
|
||||
finish_urb (ohci, urb, NULL);
|
||||
spin_lock (&ohci->lock);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* frees config/altsetting state for endpoints,
|
||||
* including ED memory, dummy TD, and bulk/intr data toggle
|
||||
*/
|
||||
|
||||
static void
|
||||
ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int epnum = ep & USB_ENDPOINT_NUMBER_MASK;
|
||||
unsigned long flags;
|
||||
struct ed *ed;
|
||||
|
||||
/* ASSERT: any requests/urbs are being unlinked */
|
||||
/* ASSERT: nobody can be submitting urbs for this any more */
|
||||
|
||||
epnum <<= 1;
|
||||
if (epnum != 0 && !(ep & USB_DIR_IN))
|
||||
epnum |= 1;
|
||||
|
||||
rescan:
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ed = dev->ep [epnum];
|
||||
if (!ed)
|
||||
goto done;
|
||||
|
||||
if (!HCD_IS_RUNNING (ohci->hcd.state) || ohci->disabled)
|
||||
ed->state = ED_IDLE;
|
||||
switch (ed->state) {
|
||||
case ED_UNLINK: /* wait for hw to finish? */
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
set_current_state (TASK_UNINTERRUPTIBLE);
|
||||
schedule_timeout (1);
|
||||
goto rescan;
|
||||
case ED_IDLE: /* fully unlinked */
|
||||
if (list_empty (&ed->td_list)) {
|
||||
td_free (ohci, ed->dummy);
|
||||
ed_free (ohci, ed);
|
||||
break;
|
||||
}
|
||||
/* else FALL THROUGH */
|
||||
default:
|
||||
/* caller was supposed to have unlinked any requests;
|
||||
* that's not our job. can't recover; must leak ed.
|
||||
*/
|
||||
ohci_err (ohci, "ed %p (#%d) state %d%s\n",
|
||||
ed, epnum, ed->state,
|
||||
list_empty (&ed->td_list) ? "" : "(has tds)");
|
||||
td_free (ohci, ed->dummy);
|
||||
break;
|
||||
}
|
||||
dev->ep [epnum] = 0;
|
||||
done:
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
static int ohci_get_frame (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
|
||||
return le16_to_cpu (ohci->hcca->frame_no);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*
|
||||
* HC functions
|
||||
*-------------------------------------------------------------------------*/
|
||||
|
||||
/* reset the HC and BUS */
|
||||
|
||||
static int hc_reset (struct ohci_hcd *ohci)
|
||||
{
|
||||
u32 temp;
|
||||
u32 ints;
|
||||
u32 control;
|
||||
|
||||
/* Disable HC interrupts */
|
||||
writel (OHCI_INTR_MIE, &ohci->regs->intrdisable);
|
||||
// acknowledge all pending interrupts
|
||||
ints = readl(&ohci->regs->intrstatus);
|
||||
writel (ints, &ohci->regs->intrstatus);
|
||||
|
||||
if (readl (&ohci->regs->control) & OHCI_CTRL_IR) {
|
||||
// takeover without negotiation - there is noone to negotiate with
|
||||
control = readl (&ohci->regs->control) & ~OHCI_CTRL_IR;
|
||||
writel (control, &ohci->regs->control);
|
||||
}
|
||||
|
||||
ohci_dbg (ohci, "USB HC reset_hc %s: ctrl = 0x%x ;\n",
|
||||
hcd_to_bus (&ohci->hcd)->bus_name,
|
||||
readl (&ohci->regs->control));
|
||||
|
||||
/* Reset USB (needed by some controllers); RemoteWakeupConnected
|
||||
* saved if boot firmware (BIOS/SMM/...) told us it's connected
|
||||
*/
|
||||
ohci->hc_control = readl (&ohci->regs->control);
|
||||
ohci->hc_control &= OHCI_CTRL_RWC; /* hcfs 0 = RESET */
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
// flush those pci writes
|
||||
(void) readl (&ohci->regs->control);
|
||||
wait_ms (50);
|
||||
|
||||
/* HC Reset requires max 10 us delay */
|
||||
writel (OHCI_HCR, &ohci->regs->cmdstatus);
|
||||
temp = 30; /* ... allow extra time */
|
||||
while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) {
|
||||
if (--temp == 0) {
|
||||
ohci_err (ohci, "USB HC reset timed out!\n");
|
||||
return -1;
|
||||
}
|
||||
udelay (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.
|
||||
*/
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
// flush those pci writes
|
||||
(void) readl (&ohci->regs->control);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define FI 0x2edf /* 12000 bits per frame (-1) */
|
||||
#define LSTHRESH 0x628 /* lowspeed bit threshold */
|
||||
|
||||
/* Start an OHCI controller, set the BUS operational
|
||||
* enable interrupts
|
||||
* connect the virtual root hub
|
||||
*/
|
||||
static int hc_start (struct ohci_hcd *ohci)
|
||||
{
|
||||
u32 mask, tmp;
|
||||
struct usb_device *udev;
|
||||
struct usb_bus *bus;
|
||||
|
||||
spin_lock_init (&ohci->lock);
|
||||
ohci->disabled = 1;
|
||||
ohci->sleeping = 0;
|
||||
|
||||
/* Tell the controller where the control and bulk lists are
|
||||
* The lists are empty now. */
|
||||
writel (0, &ohci->regs->ed_controlhead);
|
||||
writel (0, &ohci->regs->ed_bulkhead);
|
||||
|
||||
/* a reset clears this */
|
||||
writel ((u32) ohci->hcca_dma, &ohci->regs->hcca);
|
||||
// usbprintk("HCCA: %p \n",ohci->regs->hcca);
|
||||
|
||||
/* force default fmInterval (we won't adjust it); init thresholds
|
||||
* for last FS and LS packets, reserve 90% for periodic.
|
||||
*/
|
||||
writel ((((6 * (FI - 210)) / 7) << 16) | FI, &ohci->regs->fminterval);
|
||||
writel (((9 * FI) / 10) & 0x3fff, &ohci->regs->periodicstart);
|
||||
writel (LSTHRESH, &ohci->regs->lsthresh);
|
||||
|
||||
/* some OHCI implementations are finicky about how they init.
|
||||
* bogus values here mean not even enumeration could work.
|
||||
*/
|
||||
if ((readl (&ohci->regs->fminterval) & 0x3fff0000) == 0
|
||||
|| !readl (&ohci->regs->periodicstart)) {
|
||||
ohci_err (ohci, "init err\n");
|
||||
return -EOVERFLOW;
|
||||
}
|
||||
|
||||
/* start controller operations */
|
||||
ohci->hc_control &= OHCI_CTRL_RWC;
|
||||
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
|
||||
ohci->disabled = 0;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
|
||||
/* Choose the interrupts we care about now, others later on demand */
|
||||
mask = OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_WDH;
|
||||
writel (mask, &ohci->regs->intrstatus);
|
||||
writel (mask, &ohci->regs->intrenable);
|
||||
|
||||
/* handle root hub init quirks ... */
|
||||
tmp = roothub_a (ohci);
|
||||
tmp &= ~(RH_A_PSM | RH_A_OCPM);
|
||||
if (ohci->flags & OHCI_QUIRK_SUPERIO) {
|
||||
/* NSC 87560 and maybe others */
|
||||
tmp |= RH_A_NOCP;
|
||||
tmp &= ~(RH_A_POTPGT | RH_A_NPS);
|
||||
} else {
|
||||
/* hub power always on; required for AMD-756 and some
|
||||
* Mac platforms, use this mode everywhere by default
|
||||
*/
|
||||
tmp |= RH_A_NPS;
|
||||
}
|
||||
writel (tmp, &ohci->regs->roothub.a);
|
||||
writel (RH_HS_LPSC, &ohci->regs->roothub.status);
|
||||
writel (0, &ohci->regs->roothub.b);
|
||||
// flush those pci writes
|
||||
(void) readl (&ohci->regs->control);
|
||||
|
||||
// POTPGT delay is bits 24-31, in 2 ms units.
|
||||
mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
|
||||
|
||||
/* connect the virtual root hub */
|
||||
bus = hcd_to_bus (&ohci->hcd);
|
||||
bus->root_hub = udev = usb_alloc_dev (NULL, bus);
|
||||
ohci->hcd.state = USB_STATE_READY;
|
||||
if (!udev) {
|
||||
disable (ohci);
|
||||
ohci->hc_control &= ~OHCI_CTRL_HCFS;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
ohci_err(ohci,"out of mem");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
usb_connect (udev);
|
||||
udev->speed = USB_SPEED_FULL;
|
||||
if (hcd_register_root (&ohci->hcd) != 0) {
|
||||
usb_put_dev (udev);
|
||||
bus->root_hub = NULL;
|
||||
disable (ohci);
|
||||
ohci->hc_control &= ~OHCI_CTRL_HCFS;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
return -ENODEV;
|
||||
}
|
||||
create_debug_files (ohci);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* an interrupt happens */
|
||||
|
||||
static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
struct ohci_regs *regs = ohci->regs;
|
||||
int ints;
|
||||
|
||||
/* we can eliminate a (slow) readl() if _only_ WDH caused this irq */
|
||||
if ((ohci->hcca->done_head != 0)
|
||||
&& ! (le32_to_cpup (&ohci->hcca->done_head) & 0x01)) {
|
||||
ints = OHCI_INTR_WDH;
|
||||
|
||||
/* cardbus/... hardware gone before remove() */
|
||||
} else if ((ints = readl (®s->intrstatus)) == ~(u32)0) {
|
||||
disable (ohci);
|
||||
ohci_dbg (ohci, "device removed!\n");
|
||||
return;
|
||||
|
||||
/* interrupt for some other device? */
|
||||
} else if ((ints &= readl (®s->intrenable)) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ints & OHCI_INTR_UE) {
|
||||
disable (ohci);
|
||||
ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
|
||||
// e.g. due to PCI Master/Target Abort
|
||||
|
||||
ohci_dump (ohci, 1);
|
||||
hc_reset (ohci);
|
||||
}
|
||||
|
||||
if (ints & OHCI_INTR_WDH) {
|
||||
writel (OHCI_INTR_WDH, ®s->intrdisable);
|
||||
dl_done_list (ohci, dl_reverse_done_list (ohci), ptregs);
|
||||
writel (OHCI_INTR_WDH, ®s->intrenable);
|
||||
}
|
||||
|
||||
/* could track INTR_SO to reduce available PCI/... bandwidth */
|
||||
|
||||
/* handle any pending URB/ED unlinks, leaving INTR_SF enabled
|
||||
* when there's still unlinking to be done (next frame).
|
||||
*/
|
||||
spin_lock (&ohci->lock);
|
||||
if (ohci->ed_rm_list)
|
||||
finish_unlinks (ohci, le16_to_cpu (ohci->hcca->frame_no),
|
||||
ptregs);
|
||||
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list)
|
||||
writel (OHCI_INTR_SF, ®s->intrdisable);
|
||||
spin_unlock (&ohci->lock);
|
||||
|
||||
writel (ints, ®s->intrstatus);
|
||||
writel (OHCI_INTR_MIE, ®s->intrenable);
|
||||
// flush those pci writes
|
||||
(void) readl (&ohci->regs->control);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void ohci_stop (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
struct ohci_regs *regs = ohci->regs;
|
||||
int ints;
|
||||
|
||||
ohci_dbg (ohci, "stop %s controller%s\n",
|
||||
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
|
||||
ohci->disabled ? " (disabled)" : ""
|
||||
);
|
||||
ohci_dump (ohci, 1);
|
||||
|
||||
if (!ohci->disabled)
|
||||
hc_reset (ohci);
|
||||
|
||||
// Disable all interrupts
|
||||
writel (OHCI_INTR_MIE, ®s->intrdisable);
|
||||
// acknowledge all pending interrupts
|
||||
ints = readl(®s->intrstatus);
|
||||
writel (ints, ®s->intrstatus);
|
||||
// flush register writes
|
||||
(void) readl (&ohci->regs->control);
|
||||
|
||||
remove_debug_files (ohci);
|
||||
ohci_mem_cleanup (ohci);
|
||||
if (ohci->hcca) {
|
||||
pci_free_consistent (ohci->hcd.pdev, sizeof *ohci->hcca,
|
||||
ohci->hcca, ohci->hcca_dma);
|
||||
ohci->hcca = NULL;
|
||||
ohci->hcca_dma = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
// FIXME: this restart logic should be generic,
|
||||
// and handle full hcd state cleanup
|
||||
|
||||
/* controller died; cleanup debris, then restart */
|
||||
/* must not be called from interrupt context */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int hc_restart (struct ohci_hcd *ohci)
|
||||
{
|
||||
int temp;
|
||||
int i;
|
||||
|
||||
ohci->disabled = 1;
|
||||
ohci->sleeping = 0;
|
||||
if (hcd_to_bus (&ohci->hcd)->root_hub)
|
||||
usb_disconnect (&hcd_to_bus (&ohci->hcd)->root_hub);
|
||||
|
||||
/* empty the interrupt branches */
|
||||
for (i = 0; i < NUM_INTS; i++) ohci->load [i] = 0;
|
||||
for (i = 0; i < NUM_INTS; i++) ohci->hcca->int_table [i] = 0;
|
||||
|
||||
/* no EDs to remove */
|
||||
ohci->ed_rm_list = NULL;
|
||||
|
||||
/* empty control and bulk lists */
|
||||
ohci->ed_controltail = NULL;
|
||||
ohci->ed_bulktail = NULL;
|
||||
|
||||
if ((temp = hc_reset (ohci)) < 0 || (temp = hc_start (ohci)) < 0) {
|
||||
ohci_err (ohci, "can't restart, %d\n", temp);
|
||||
return temp;
|
||||
} else
|
||||
ohci_dbg (ohci, "restart complete\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define DRIVER_INFO DRIVER_VERSION " " DRIVER_DESC
|
||||
|
||||
MODULE_AUTHOR (DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION (DRIVER_INFO);
|
||||
MODULE_LICENSE ("GPL");
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
#include "ohci-pci.c"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SA1111
|
||||
#include "ohci-sa1111.c"
|
||||
#endif
|
||||
|
||||
#if !(defined(CONFIG_PCI) || defined(CONFIG_SA1111))
|
||||
#error "missing bus glue for ohci-hcd"
|
||||
#endif
|
||||
271
reactos/drivers/usb/cromwell/host/ohci-hub.c
Normal file
271
reactos/drivers/usb/cromwell/host/ohci-hub.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under GPL
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* OHCI Root Hub ... the nonsharable stuff
|
||||
*
|
||||
* Registers don't need cpu_to_le32, that happens transparently
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
#define read_roothub(hc, register, mask) ({ \
|
||||
u32 temp = readl (&hc->regs->roothub.register); \
|
||||
if (temp == -1) \
|
||||
disable (hc); \
|
||||
else if (hc->flags & OHCI_QUIRK_AMD756) \
|
||||
while (temp & mask) \
|
||||
temp = readl (&hc->regs->roothub.register); \
|
||||
temp; })
|
||||
|
||||
static u32 roothub_a (struct ohci_hcd *hc)
|
||||
{ return read_roothub (hc, a, 0xfc0fe000); }
|
||||
static inline u32 roothub_b (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.b); }
|
||||
static inline u32 roothub_status (struct ohci_hcd *hc)
|
||||
{ return readl (&hc->regs->roothub.status); }
|
||||
static u32 roothub_portstatus (struct ohci_hcd *hc, int i)
|
||||
{ return read_roothub (hc, portstatus [i], 0xffe0fce0); }
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#define dbg_port(hc,label,num,value) \
|
||||
ohci_dbg (hc, \
|
||||
"%s roothub.portstatus [%d] " \
|
||||
"= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \
|
||||
label, num, temp, \
|
||||
(temp & RH_PS_PRSC) ? " PRSC" : "", \
|
||||
(temp & RH_PS_OCIC) ? " OCIC" : "", \
|
||||
(temp & RH_PS_PSSC) ? " PSSC" : "", \
|
||||
(temp & RH_PS_PESC) ? " PESC" : "", \
|
||||
(temp & RH_PS_CSC) ? " CSC" : "", \
|
||||
\
|
||||
(temp & RH_PS_LSDA) ? " LSDA" : "", \
|
||||
(temp & RH_PS_PPS) ? " PPS" : "", \
|
||||
(temp & RH_PS_PRS) ? " PRS" : "", \
|
||||
(temp & RH_PS_POCI) ? " POCI" : "", \
|
||||
(temp & RH_PS_PSS) ? " PSS" : "", \
|
||||
\
|
||||
(temp & RH_PS_PES) ? " PES" : "", \
|
||||
(temp & RH_PS_CCS) ? " CCS" : "" \
|
||||
);
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* build "status change" packet (one or two bytes) from HC registers */
|
||||
|
||||
static int
|
||||
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports, i, changed = 0, length = 1;
|
||||
|
||||
ports = roothub_a (ohci) & RH_A_NDP;
|
||||
if (ports > MAX_ROOT_PORTS) {
|
||||
if (ohci->disabled)
|
||||
return -ESHUTDOWN;
|
||||
ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
|
||||
ports, readl (&ohci->regs->roothub.a) & RH_A_NDP);
|
||||
/* retry later; "should not happen" */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* init status */
|
||||
if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
|
||||
buf [0] = changed = 1;
|
||||
else
|
||||
buf [0] = 0;
|
||||
if (ports > 7) {
|
||||
buf [1] = 0;
|
||||
length++;
|
||||
}
|
||||
|
||||
/* look at each port */
|
||||
for (i = 0; i < ports; i++) {
|
||||
u32 status = roothub_portstatus (ohci, i);
|
||||
|
||||
status &= RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
|
||||
| RH_PS_OCIC | RH_PS_PRSC;
|
||||
if (status) {
|
||||
changed = 1;
|
||||
if (i < 7)
|
||||
buf [0] |= 1 << (i + 1);
|
||||
else
|
||||
buf [1] |= 1 << (i - 7);
|
||||
}
|
||||
}
|
||||
return changed ? length : 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
ohci_hub_descriptor (
|
||||
struct ohci_hcd *ohci,
|
||||
struct usb_hub_descriptor *desc
|
||||
) {
|
||||
u32 rh = roothub_a (ohci);
|
||||
int ports = rh & RH_A_NDP;
|
||||
u16 temp;
|
||||
|
||||
desc->bDescriptorType = 0x29;
|
||||
desc->bPwrOn2PwrGood = (rh & RH_A_POTPGT) >> 24;
|
||||
desc->bHubContrCurrent = 0;
|
||||
|
||||
desc->bNbrPorts = ports;
|
||||
temp = 1 + (ports / 8);
|
||||
desc->bDescLength = 7 + 2 * temp;
|
||||
|
||||
temp = 0;
|
||||
if (rh & RH_A_PSM) /* per-port power switching? */
|
||||
temp |= 0x0001;
|
||||
if (rh & RH_A_NOCP) /* no overcurrent reporting? */
|
||||
temp |= 0x0010;
|
||||
else if (rh & RH_A_OCPM) /* per-port overcurrent reporting? */
|
||||
temp |= 0x0008;
|
||||
desc->wHubCharacteristics = cpu_to_le16 (temp);
|
||||
|
||||
/* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */
|
||||
rh = roothub_b (ohci);
|
||||
desc->bitmap [0] = rh & RH_B_DR;
|
||||
if (ports > 7) {
|
||||
desc->bitmap [1] = (rh & RH_B_DR) >> 8;
|
||||
desc->bitmap [2] = desc->bitmap [3] = 0xff;
|
||||
} else
|
||||
desc->bitmap [1] = 0xff;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_hub_control (
|
||||
struct usb_hcd *hcd,
|
||||
u16 typeReq,
|
||||
u16 wValue,
|
||||
u16 wIndex,
|
||||
char *buf,
|
||||
u16 wLength
|
||||
) {
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ports = hcd_to_bus (hcd)->root_hub->maxchild;
|
||||
u32 temp;
|
||||
int retval = 0;
|
||||
|
||||
switch (typeReq) {
|
||||
case ClearHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
writel (RH_HS_OCIC, &ohci->regs->roothub.status);
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case ClearPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_ENABLE:
|
||||
temp = RH_PS_CCS;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
temp = RH_PS_PESC;
|
||||
break;
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
temp = RH_PS_POCI;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_SUSPEND:
|
||||
temp = RH_PS_PSSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
temp = RH_PS_LSDA;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
temp = RH_PS_CSC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_OVER_CURRENT:
|
||||
temp = RH_PS_OCIC;
|
||||
break;
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
temp = RH_PS_PRSC;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
writel (temp, &ohci->regs->roothub.portstatus [wIndex]);
|
||||
// readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case GetHubDescriptor:
|
||||
ohci_hub_descriptor (ohci, (struct usb_hub_descriptor *) buf);
|
||||
break;
|
||||
case GetHubStatus:
|
||||
temp = roothub_status (ohci) & ~(RH_HS_CRWE | RH_HS_DRWE);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
break;
|
||||
case GetPortStatus:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
temp = roothub_portstatus (ohci, wIndex);
|
||||
*(u32 *) buf = cpu_to_le32 (temp);
|
||||
|
||||
#ifndef OHCI_VERBOSE_DEBUG
|
||||
if (*(u16*)(buf+2)) /* only if wPortChange is interesting */
|
||||
#endif
|
||||
dbg_port (ohci, "GetStatus", wIndex + 1, temp);
|
||||
break;
|
||||
case SetHubFeature:
|
||||
switch (wValue) {
|
||||
case C_HUB_OVER_CURRENT:
|
||||
// FIXME: this can be cleared, yes?
|
||||
case C_HUB_LOCAL_POWER:
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
switch (wValue) {
|
||||
case USB_PORT_FEAT_SUSPEND:
|
||||
writel (RH_PS_PSS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_POWER:
|
||||
writel (RH_PS_PPS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
case USB_PORT_FEAT_RESET:
|
||||
temp = readl (&ohci->regs->roothub.portstatus [wIndex]);
|
||||
if (temp & RH_PS_CCS)
|
||||
writel (RH_PS_PRS,
|
||||
&ohci->regs->roothub.portstatus [wIndex]);
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error:
|
||||
/* "protocol stall" on error */
|
||||
retval = -EPIPE;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
146
reactos/drivers/usb/cromwell/host/ohci-mem.c
Normal file
146
reactos/drivers/usb/cromwell/host/ohci-mem.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* There's basically three types of memory:
|
||||
* - data used only by the HCD ... kmalloc is fine
|
||||
* - async and periodic schedules, shared by HC and HCD ... these
|
||||
* need to use pci_pool or pci_alloc_consistent
|
||||
* - driver buffers, read/written by HC ... the hcd glue or the
|
||||
* device driver provides us with dma addresses
|
||||
*
|
||||
* There's also PCI "register" data, which is memory mapped.
|
||||
* No memory seen by this driver is pagable.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static struct usb_hcd *ohci_hcd_alloc (void)
|
||||
{
|
||||
struct ohci_hcd *ohci;
|
||||
|
||||
ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
|
||||
if (ohci != 0) {
|
||||
memset (ohci, 0, sizeof (struct ohci_hcd));
|
||||
return &ohci->hcd;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_hcd_free (struct usb_hcd *hcd)
|
||||
{
|
||||
kfree (hcd_to_ohci (hcd));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_mem_init (struct ohci_hcd *ohci)
|
||||
{
|
||||
ohci->td_cache = pci_pool_create ("ohci_td", ohci->hcd.pdev,
|
||||
sizeof (struct td),
|
||||
32 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->td_cache)
|
||||
return -ENOMEM;
|
||||
ohci->ed_cache = pci_pool_create ("ohci_ed", ohci->hcd.pdev,
|
||||
sizeof (struct ed),
|
||||
16 /* byte alignment */,
|
||||
0 /* no page-crossing issues */);
|
||||
if (!ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ohci_mem_cleanup (struct ohci_hcd *ohci)
|
||||
{
|
||||
if (ohci->td_cache) {
|
||||
pci_pool_destroy (ohci->td_cache);
|
||||
ohci->td_cache = 0;
|
||||
}
|
||||
if (ohci->ed_cache) {
|
||||
pci_pool_destroy (ohci->ed_cache);
|
||||
ohci->ed_cache = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* ohci "done list" processing needs this mapping */
|
||||
static inline struct td *
|
||||
dma_to_td (struct ohci_hcd *hc, dma_addr_t td_dma)
|
||||
{
|
||||
struct td *td;
|
||||
|
||||
td_dma &= TD_MASK;
|
||||
td = hc->td_hash [TD_HASH_FUNC(td_dma)];
|
||||
while (td && td->td_dma != td_dma)
|
||||
td = td->td_hash;
|
||||
return td;
|
||||
}
|
||||
|
||||
/* TDs ... */
|
||||
static struct td *
|
||||
td_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct td *td;
|
||||
|
||||
td = pci_pool_alloc (hc->td_cache, mem_flags, &dma);
|
||||
if (td) {
|
||||
/* in case hc fetches it, make it look dead */
|
||||
memset (td, 0, sizeof *td);
|
||||
td->hwNextTD = cpu_to_le32 (dma);
|
||||
td->td_dma = dma;
|
||||
/* hashed in td_fill */
|
||||
}
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
td_free (struct ohci_hcd *hc, struct td *td)
|
||||
{
|
||||
struct td **prev = &hc->td_hash [TD_HASH_FUNC (td->td_dma)];
|
||||
|
||||
while (*prev && *prev != td)
|
||||
prev = &(*prev)->td_hash;
|
||||
if (*prev)
|
||||
*prev = td->td_hash;
|
||||
else if ((td->hwINFO & TD_DONE) != 0)
|
||||
ohci_dbg (hc, "no hash for td %p\n", td);
|
||||
pci_pool_free (hc->td_cache, td, td->td_dma);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* EDs ... */
|
||||
static struct ed *
|
||||
ed_alloc (struct ohci_hcd *hc, int mem_flags)
|
||||
{
|
||||
dma_addr_t dma;
|
||||
struct ed *ed;
|
||||
|
||||
ed = pci_pool_alloc (hc->ed_cache, mem_flags, &dma);
|
||||
if (ed) {
|
||||
memset (ed, 0, sizeof (*ed));
|
||||
INIT_LIST_HEAD (&ed->td_list);
|
||||
ed->dma = dma;
|
||||
}
|
||||
return ed;
|
||||
}
|
||||
|
||||
static void
|
||||
ed_free (struct ohci_hcd *hc, struct ed *ed)
|
||||
{
|
||||
pci_pool_free (hc->ed_cache, ed, ed->dma);
|
||||
}
|
||||
|
||||
405
reactos/drivers/usb/cromwell/host/ohci-pci.c
Normal file
405
reactos/drivers/usb/cromwell/host/ohci-pci.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* [ Initialisation is based on Linus' ]
|
||||
* [ uhci code and gregs ohci fragments ]
|
||||
* [ (C) Copyright 1999 Linus Torvalds ]
|
||||
* [ (C) Copyright 1999 Gregory P. Smith]
|
||||
*
|
||||
* PCI Bus Glue
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/pmac_feature.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/prom.h>
|
||||
#ifndef CONFIG_PM
|
||||
# define CONFIG_PM
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
#error "This file is PCI bus glue. CONFIG_PCI must be defined."
|
||||
#endif
|
||||
|
||||
#include "../linux/pci_ids.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int __devinit
|
||||
ohci_pci_start (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int ret;
|
||||
|
||||
if (hcd->pdev) {
|
||||
ohci->hcca = pci_alloc_consistent (hcd->pdev,
|
||||
sizeof *ohci->hcca, &ohci->hcca_dma);
|
||||
if (!ohci->hcca)
|
||||
return -ENOMEM;
|
||||
|
||||
/* AMD 756, for most chips (early revs), corrupts register
|
||||
* values on read ... so enable the vendor workaround.
|
||||
*/
|
||||
if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD
|
||||
&& hcd->pdev->device == 0x740c) {
|
||||
ohci->flags = OHCI_QUIRK_AMD756;
|
||||
ohci_info (ohci, "AMD756 erratum 4 workaround\n");
|
||||
}
|
||||
|
||||
/* FIXME for some of the early AMD 760 southbridges, OHCI
|
||||
* won't work at all. blacklist them.
|
||||
*/
|
||||
|
||||
/* Apple's OHCI driver has a lot of bizarre workarounds
|
||||
* for this chip. Evidently control and bulk lists
|
||||
* can get confused. (B&W G3 models, and ...)
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI
|
||||
&& hcd->pdev->device == 0xc861) {
|
||||
ohci_info (ohci,
|
||||
"WARNING: OPTi workarounds unavailable\n");
|
||||
}
|
||||
|
||||
/* Check for NSC87560. We have to look at the bridge (fn1) to
|
||||
* identify the USB (fn2). This quirk might apply to more or
|
||||
* even all NSC stuff.
|
||||
*/
|
||||
else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) {
|
||||
struct pci_dev *b, *hc;
|
||||
|
||||
hc = hcd->pdev;
|
||||
b = pci_find_slot (hc->bus->number,
|
||||
PCI_DEVFN (PCI_SLOT (hc->devfn), 1));
|
||||
if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
|
||||
&& b->vendor == PCI_VENDOR_ID_NS) {
|
||||
ohci->flags |= OHCI_QUIRK_SUPERIO;
|
||||
ohci_info (ohci, "Using NSC SuperIO setup\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
memset (ohci->hcca, 0, sizeof (struct ohci_hcca));
|
||||
if ((ret = ohci_mem_init (ohci)) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return ret;
|
||||
}
|
||||
ohci->regs = hcd->regs;
|
||||
|
||||
if (hc_reset (ohci) < 0) {
|
||||
ohci_stop (hcd);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (hc_start (ohci) < 0) {
|
||||
ohci_err (ohci, "can't start\n");
|
||||
ohci_stop (hcd);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ohci_dump (ohci, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
unsigned long flags;
|
||||
u16 cmd;
|
||||
|
||||
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) {
|
||||
ohci_dbg (ohci, "can't suspend (state is %s)\n",
|
||||
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* act as if usb suspend can always be used */
|
||||
ohci_dbg (ohci, "suspend to %d\n", state);
|
||||
ohci->sleeping = 1;
|
||||
|
||||
/* First stop processing */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->hc_control &=
|
||||
~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE);
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
(void) readl (&ohci->regs->intrstatus);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
/* Wait a frame or two */
|
||||
mdelay (1);
|
||||
if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF)
|
||||
mdelay (1);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
disable_irq (hcd->pdev->irq);
|
||||
/* else, 2.4 assumes shared irqs -- don't disable */
|
||||
#endif
|
||||
|
||||
/* Enable remote wakeup */
|
||||
writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD,
|
||||
&ohci->regs->intrenable);
|
||||
|
||||
/* Suspend chip and let things settle down a bit */
|
||||
ohci->hc_control = OHCI_USB_SUSPEND;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (500); /* No schedule here ! */
|
||||
|
||||
switch (readl (&ohci->regs->control) & OHCI_CTRL_HCFS) {
|
||||
case OHCI_USB_RESET:
|
||||
ohci_dbg (ohci, "suspend->reset ?\n");
|
||||
break;
|
||||
case OHCI_USB_RESUME:
|
||||
ohci_dbg (ohci, "suspend->resume ?\n");
|
||||
break;
|
||||
case OHCI_USB_OPER:
|
||||
ohci_dbg (ohci, "suspend->operational ?\n");
|
||||
break;
|
||||
case OHCI_USB_SUSPEND:
|
||||
ohci_dbg (ohci, "suspended\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* In some rare situations, Apple's OHCI have happily trashed
|
||||
* memory during sleep. We disable its bus master bit during
|
||||
* suspend
|
||||
*/
|
||||
pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd);
|
||||
cmd &= ~PCI_COMMAND_MASTER;
|
||||
pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd);
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Disable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ohci_pci_resume (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int temp;
|
||||
int retval = 0;
|
||||
unsigned long flags;
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
{
|
||||
struct device_node *of_node;
|
||||
|
||||
/* Re-enable USB PAD & cell clock */
|
||||
of_node = pci_device_to_OF_node (hcd->pdev);
|
||||
if (of_node)
|
||||
pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1);
|
||||
}
|
||||
#endif
|
||||
/* did we suspend, or were we powered off? */
|
||||
ohci->hc_control = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* the registers may look crazy here */
|
||||
ohci_dump_status (ohci, 0, 0);
|
||||
#endif
|
||||
|
||||
/* Re-enable bus mastering */
|
||||
pci_set_master (ohci->hcd.pdev);
|
||||
|
||||
switch (temp) {
|
||||
|
||||
case OHCI_USB_RESET: // lost power
|
||||
ohci_info (ohci, "USB restart\n");
|
||||
retval = hc_restart (ohci);
|
||||
break;
|
||||
|
||||
case OHCI_USB_SUSPEND: // host wakeup
|
||||
case OHCI_USB_RESUME: // remote wakeup
|
||||
ohci_info (ohci, "USB continue from %s wakeup\n",
|
||||
(temp == OHCI_USB_SUSPEND)
|
||||
? "host" : "remote");
|
||||
ohci->hc_control = OHCI_USB_RESUME;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (20); /* no schedule here ! */
|
||||
/* Some controllers (lucent) need a longer delay here */
|
||||
mdelay (15);
|
||||
|
||||
temp = readl (&ohci->regs->control);
|
||||
temp = ohci->hc_control & OHCI_CTRL_HCFS;
|
||||
if (temp != OHCI_USB_RESUME) {
|
||||
ohci_err (ohci, "controller won't resume\n");
|
||||
ohci->disabled = 1;
|
||||
retval = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Some chips likes being resumed first */
|
||||
writel (OHCI_USB_OPER, &ohci->regs->control);
|
||||
(void) readl (&ohci->regs->control);
|
||||
mdelay (3);
|
||||
|
||||
/* Then re-enable operations */
|
||||
spin_lock_irqsave (&ohci->lock, flags);
|
||||
ohci->disabled = 0;
|
||||
ohci->sleeping = 0;
|
||||
ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER;
|
||||
if (!ohci->ed_rm_list) {
|
||||
if (ohci->ed_controltail)
|
||||
ohci->hc_control |= OHCI_CTRL_CLE;
|
||||
if (ohci->ed_bulktail)
|
||||
ohci->hc_control |= OHCI_CTRL_BLE;
|
||||
}
|
||||
hcd->state = USB_STATE_READY;
|
||||
writel (ohci->hc_control, &ohci->regs->control);
|
||||
|
||||
/* trigger a start-frame interrupt (why?) */
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrstatus);
|
||||
writel (OHCI_INTR_SF, &ohci->regs->intrenable);
|
||||
|
||||
/* Check for a pending done list */
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrdisable);
|
||||
(void) readl (&ohci->regs->intrdisable);
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
||||
#ifdef CONFIG_PMAC_PBOOK
|
||||
if (_machine == _MACH_Pmac)
|
||||
enable_irq (hcd->pdev->irq);
|
||||
#endif
|
||||
if (ohci->hcca->done_head)
|
||||
dl_done_list (ohci, dl_reverse_done_list (ohci), NULL);
|
||||
writel (OHCI_INTR_WDH, &ohci->regs->intrenable);
|
||||
|
||||
/* assume there are TDs on the bulk and control lists */
|
||||
writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus);
|
||||
|
||||
// ohci_dump_status (ohci);
|
||||
ohci_dbg (ohci, "sleeping = %d, disabled = %d\n",
|
||||
ohci->sleeping, ohci->disabled);
|
||||
break;
|
||||
|
||||
default:
|
||||
ohci_warn (ohci, "odd PCI resume\n");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static const struct hc_driver ohci_pci_hc_driver = {
|
||||
.description = hcd_name,
|
||||
|
||||
/*
|
||||
* generic hardware linkage
|
||||
*/
|
||||
.irq = ohci_irq,
|
||||
.flags = HCD_MEMORY | HCD_USB11,
|
||||
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.start = ohci_pci_start,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ohci_pci_suspend,
|
||||
.resume = ohci_pci_resume,
|
||||
#endif
|
||||
.stop = ohci_stop,
|
||||
|
||||
/*
|
||||
* memory lifecycle (except per-request)
|
||||
*/
|
||||
.hcd_alloc = ohci_hcd_alloc,
|
||||
.hcd_free = ohci_hcd_free,
|
||||
|
||||
/*
|
||||
* managing i/o requests and associated device resources
|
||||
*/
|
||||
.urb_enqueue = ohci_urb_enqueue,
|
||||
.urb_dequeue = ohci_urb_dequeue,
|
||||
.endpoint_disable = ohci_endpoint_disable,
|
||||
|
||||
/*
|
||||
* scheduling support
|
||||
*/
|
||||
.get_frame_number = ohci_get_frame,
|
||||
|
||||
/*
|
||||
* root hub support
|
||||
*/
|
||||
.hub_status_data = ohci_hub_status_data,
|
||||
.hub_control = ohci_hub_control,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static const struct pci_device_id __devinitdata pci_ids [] = { {
|
||||
|
||||
/* handle any USB OHCI controller */
|
||||
.class = (PCI_CLASS_SERIAL_USB << 8) | 0x10,
|
||||
.class_mask = ~0,
|
||||
.driver_data = (unsigned long) &ohci_pci_hc_driver,
|
||||
|
||||
/* no matter who makes it */
|
||||
.vendor = PCI_ANY_ID,
|
||||
.device = PCI_ANY_ID,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
|
||||
}, { /* end: all zeroes */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE (pci, pci_ids);
|
||||
|
||||
/* pci driver glue; this is a "new style" PCI driver module */
|
||||
static struct pci_driver ohci_pci_driver = {
|
||||
.name = (char *) hcd_name,
|
||||
.id_table = pci_ids,
|
||||
|
||||
.probe = usb_hcd_pci_probe,
|
||||
.remove = usb_hcd_pci_remove,
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = usb_hcd_pci_suspend,
|
||||
.resume = usb_hcd_pci_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
static int __init ohci_hcd_pci_init (void)
|
||||
{
|
||||
printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
|
||||
sizeof (struct ed), sizeof (struct td));
|
||||
return pci_module_init (&ohci_pci_driver);
|
||||
}
|
||||
module_init (ohci_hcd_pci_init);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void __exit ohci_hcd_pci_cleanup (void)
|
||||
{
|
||||
pci_unregister_driver (&ohci_pci_driver);
|
||||
}
|
||||
module_exit (ohci_hcd_pci_cleanup);
|
||||
1014
reactos/drivers/usb/cromwell/host/ohci-q.c
Normal file
1014
reactos/drivers/usb/cromwell/host/ohci-q.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
reactos/drivers/usb/cromwell/host/ohci.a
Normal file
BIN
reactos/drivers/usb/cromwell/host/ohci.a
Normal file
Binary file not shown.
BIN
reactos/drivers/usb/cromwell/host/ohci.coff
Normal file
BIN
reactos/drivers/usb/cromwell/host/ohci.coff
Normal file
Binary file not shown.
2
reactos/drivers/usb/cromwell/host/ohci.def
Normal file
2
reactos/drivers/usb/cromwell/host/ohci.def
Normal file
@@ -0,0 +1,2 @@
|
||||
LIBRARY ohci.sys
|
||||
EXPORTS
|
||||
406
reactos/drivers/usb/cromwell/host/ohci.h
Normal file
406
reactos/drivers/usb/cromwell/host/ohci.h
Normal file
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* OHCI HCD (Host Controller Driver) for USB.
|
||||
*
|
||||
* (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
|
||||
* (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
|
||||
*
|
||||
* This file is licenced under the GPL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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".
|
||||
*/
|
||||
struct ed {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 hwINFO; /* endpoint config bitmap */
|
||||
/* info bits defined by hcd */
|
||||
#define ED_DEQUEUE __constant_cpu_to_le32(1 << 27)
|
||||
/* info bits defined by the hardware */
|
||||
#define ED_ISO __constant_cpu_to_le32(1 << 15)
|
||||
#define ED_SKIP __constant_cpu_to_le32(1 << 14)
|
||||
#define ED_LOWSPEED __constant_cpu_to_le32(1 << 13)
|
||||
#define ED_OUT __constant_cpu_to_le32(0x01 << 11)
|
||||
#define ED_IN __constant_cpu_to_le32(0x02 << 11)
|
||||
__u32 hwTailP; /* tail of TD list */
|
||||
__u32 hwHeadP; /* head of TD list (hc r/w) */
|
||||
#define ED_C __constant_cpu_to_le32(0x02) /* toggle carry */
|
||||
#define ED_H __constant_cpu_to_le32(0x01) /* halted */
|
||||
__u32 hwNextED; /* next ED in list */
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
dma_addr_t dma; /* addr of ED */
|
||||
struct td *dummy; /* next TD to activate */
|
||||
|
||||
/* host's view of schedule */
|
||||
struct ed *ed_next; /* on schedule or rm_list */
|
||||
struct 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) --> ...
|
||||
* some special cases : OPER --> IDLE ...
|
||||
*/
|
||||
u8 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 */
|
||||
|
||||
u8 type; /* PIPE_{BULK,...} */
|
||||
|
||||
/* periodic scheduling params (for intr and iso) */
|
||||
u8 branch;
|
||||
u16 interval;
|
||||
u16 load;
|
||||
u16 last_iso; /* iso only */
|
||||
|
||||
/* HC may see EDs on rm_list until next frame (frame_no == tick) */
|
||||
u16 tick;
|
||||
} __attribute__ ((aligned(16)));
|
||||
|
||||
#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)
|
||||
*/
|
||||
struct td {
|
||||
/* first fields are hardware-specified, le32 */
|
||||
__u32 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) */
|
||||
|
||||
__u32 hwCBP; /* Current Buffer Pointer (or 0) */
|
||||
__u32 hwNextTD; /* Next TD Pointer */
|
||||
__u32 hwBE; /* Memory Buffer End Pointer */
|
||||
|
||||
/* PSW is only for ISO */
|
||||
#define MAXPSW 1 /* hardware allows 8 */
|
||||
__u16 hwPSW [MAXPSW];
|
||||
|
||||
/* rest are purely for the driver's use */
|
||||
__u8 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 */
|
||||
} __attribute__ ((aligned(32))); /* c/b/i need 16; only iso needs 32 */
|
||||
|
||||
#define TD_MASK ((u32)~0x1f) /* strip hw status in low addr bits */
|
||||
|
||||
/*
|
||||
* Hardware transfer status codes -- CC from td->hwINFO or td->hwPSW
|
||||
*/
|
||||
#define TD_CC_NOERROR 0x00
|
||||
#define TD_CC_CRC 0x01
|
||||
#define TD_CC_BITSTUFFING 0x02
|
||||
#define TD_CC_DATATOGGLEM 0x03
|
||||
#define TD_CC_STALL 0x04
|
||||
#define TD_DEVNOTRESP 0x05
|
||||
#define TD_PIDCHECKFAIL 0x06
|
||||
#define TD_UNEXPECTEDPID 0x07
|
||||
#define TD_DATAOVERRUN 0x08
|
||||
#define TD_DATAUNDERRUN 0x09
|
||||
/* 0x0A, 0x0B reserved for hardware */
|
||||
#define TD_BUFFEROVERRUN 0x0C
|
||||
#define TD_BUFFERUNDERRUN 0x0D
|
||||
/* 0x0E, 0x0F reserved for HCD */
|
||||
#define TD_NOTACCESSED 0x0F
|
||||
|
||||
|
||||
/* map OHCI TD status codes (CC) to errno values */
|
||||
static const int cc_to_error [16] = {
|
||||
/* No Error */ 0,
|
||||
/* CRC Error */ -EILSEQ,
|
||||
/* Bit Stuff */ -EPROTO,
|
||||
/* Data Togg */ -EILSEQ,
|
||||
/* Stall */ -EPIPE,
|
||||
/* DevNotResp */ -ETIMEDOUT,
|
||||
/* PIDCheck */ -EPROTO,
|
||||
/* UnExpPID */ -EPROTO,
|
||||
/* DataOver */ -EOVERFLOW,
|
||||
/* DataUnder */ -EREMOTEIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* (for hw) */ -EIO,
|
||||
/* BufferOver */ -ECOMM,
|
||||
/* BuffUnder */ -ENOSR,
|
||||
/* (for HCD) */ -EALREADY,
|
||||
/* (for HCD) */ -EALREADY
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
struct ohci_hcca {
|
||||
#define NUM_INTS 32
|
||||
__u32 int_table [NUM_INTS]; /* periodic schedule */
|
||||
__u16 frame_no; /* current frame number */
|
||||
__u16 pad1; /* set to 0 on each frame_no change */
|
||||
__u32 done_head; /* info returned for an interrupt */
|
||||
u8 reserved_for_hc [116];
|
||||
u8 what [4]; /* spec only identifies 252 bytes :) */
|
||||
} __attribute__ ((aligned(256)));
|
||||
|
||||
|
||||
/*
|
||||
* This is the structure of the OHCI controller's memory mapped I/O region.
|
||||
* You must use readl() and writel() (in <asm/io.h>) to access these fields!!
|
||||
* Layout is in section 7 (and appendix B) of the spec.
|
||||
*/
|
||||
struct ohci_regs {
|
||||
/* control and status registers (section 7.1) */
|
||||
__u32 revision;
|
||||
__u32 control;
|
||||
__u32 cmdstatus;
|
||||
__u32 intrstatus;
|
||||
__u32 intrenable;
|
||||
__u32 intrdisable;
|
||||
|
||||
/* memory pointers (section 7.2) */
|
||||
__u32 hcca;
|
||||
__u32 ed_periodcurrent;
|
||||
__u32 ed_controlhead;
|
||||
__u32 ed_controlcurrent;
|
||||
__u32 ed_bulkhead;
|
||||
__u32 ed_bulkcurrent;
|
||||
__u32 donehead;
|
||||
|
||||
/* frame counters (section 7.3) */
|
||||
__u32 fminterval;
|
||||
__u32 fmremaining;
|
||||
__u32 fmnumber;
|
||||
__u32 periodicstart;
|
||||
__u32 lsthresh;
|
||||
|
||||
/* Root hub ports (section 7.4) */
|
||||
struct ohci_roothub_regs {
|
||||
__u32 a;
|
||||
__u32 b;
|
||||
__u32 status;
|
||||
#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports (RH_A_NDP) */
|
||||
__u32 portstatus [MAX_ROOT_PORTS];
|
||||
} roothub;
|
||||
|
||||
/* and optional "legacy support" registers (appendix B) at 0x0100 */
|
||||
|
||||
} __attribute__ ((aligned(32)));
|
||||
|
||||
|
||||
/* 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 */
|
||||
|
||||
|
||||
/* hcd-private per-urb state */
|
||||
typedef struct urb_priv {
|
||||
struct ed *ed;
|
||||
__u16 length; // # tds in this request
|
||||
__u16 td_cnt; // tds already serviced
|
||||
int state;
|
||||
struct td *td [0]; // all TDs in this request
|
||||
|
||||
} urb_priv_t;
|
||||
|
||||
#define URB_DEL 1
|
||||
|
||||
#define TD_HASH_SIZE 64 /* power'o'two */
|
||||
// sizeof (struct td) ~= 64 == 2^6 ...
|
||||
#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE)
|
||||
|
||||
|
||||
/*
|
||||
* This is the full ohci controller description
|
||||
*
|
||||
* Note how the "proper" USB information is just
|
||||
* a subset of what the full implementation needs. (Linus)
|
||||
*/
|
||||
|
||||
struct ohci_hcd {
|
||||
spinlock_t lock;
|
||||
|
||||
/*
|
||||
* I/O memory used to communicate with the HC (dma-consistent)
|
||||
*/
|
||||
struct ohci_regs *regs;
|
||||
|
||||
/*
|
||||
* main memory used to communicate with the HC (dma-consistent).
|
||||
* hcd adds to schedule for a live hc any time, but removals finish
|
||||
* only at the start of the next frame.
|
||||
*/
|
||||
struct ohci_hcca *hcca;
|
||||
dma_addr_t hcca_dma;
|
||||
|
||||
struct ed *ed_rm_list; /* to be removed */
|
||||
|
||||
struct ed *ed_bulktail; /* last in bulk list */
|
||||
struct ed *ed_controltail; /* last in ctrl list */
|
||||
struct ed *periodic [NUM_INTS]; /* shadow int_table */
|
||||
|
||||
/*
|
||||
* memory management for queue data structures
|
||||
*/
|
||||
struct pci_pool *td_cache;
|
||||
struct pci_pool *ed_cache;
|
||||
struct td *td_hash [TD_HASH_SIZE];
|
||||
|
||||
/*
|
||||
* driver state
|
||||
*/
|
||||
int disabled; /* e.g. got a UE, we're hung */
|
||||
int sleeping;
|
||||
int load [NUM_INTS];
|
||||
u32 hc_control; /* copy of hc control reg */
|
||||
|
||||
unsigned long flags; /* for HC bugs */
|
||||
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
|
||||
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
|
||||
// there are also chip quirks/bugs in init logic
|
||||
|
||||
/*
|
||||
* framework state
|
||||
*/
|
||||
struct usb_hcd hcd;
|
||||
};
|
||||
|
||||
#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef DEBUG
|
||||
#define STUB_DEBUG_FILES
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define ohci_dbg(ohci, fmt, args...) \
|
||||
dev_dbg ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_err(ohci, fmt, args...) \
|
||||
dev_err ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_info(ohci, fmt, args...) \
|
||||
dev_info ((ohci)->hcd.controller , fmt , ## args )
|
||||
#define ohci_warn(ohci, fmt, args...) \
|
||||
dev_warn ((ohci)->hcd.controller , fmt , ## args )
|
||||
|
||||
#ifdef OHCI_VERBOSE_DEBUG
|
||||
# define ohci_vdbg ohci_dbg
|
||||
#else
|
||||
# define ohci_vdbg(ohci, fmt, args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
4524
reactos/drivers/usb/cromwell/host/ohci.map
Normal file
4524
reactos/drivers/usb/cromwell/host/ohci.map
Normal file
File diff suppressed because it is too large
Load Diff
BIN
reactos/drivers/usb/cromwell/host/ohci.nostrip.sys
Normal file
BIN
reactos/drivers/usb/cromwell/host/ohci.nostrip.sys
Normal file
Binary file not shown.
5
reactos/drivers/usb/cromwell/host/ohci.rc
Normal file
5
reactos/drivers/usb/cromwell/host/ohci.rc
Normal file
@@ -0,0 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "USB OHCI Device Driver\0"
|
||||
#define REACTOS_STR_INTERNAL_NAME "ohci\0"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "ohci.sys\0"
|
||||
#include <reactos/version.rc>
|
||||
BIN
reactos/drivers/usb/cromwell/host/ohci.sym
Normal file
BIN
reactos/drivers/usb/cromwell/host/ohci.sym
Normal file
Binary file not shown.
BIN
reactos/drivers/usb/cromwell/host/ohci.sys
Normal file
BIN
reactos/drivers/usb/cromwell/host/ohci.sys
Normal file
Binary file not shown.
5
reactos/drivers/usb/cromwell/host/ohci_config.h
Normal file
5
reactos/drivers/usb/cromwell/host/ohci_config.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/*
|
||||
* Configs for OHCI
|
||||
*/
|
||||
|
||||
#define CONFIG_PCI
|
||||
16
reactos/drivers/usb/cromwell/host/ohci_main.c
Normal file
16
reactos/drivers/usb/cromwell/host/ohci_main.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
ReactOS specific functions for ohci module
|
||||
by Aleksey Bragin (aleksey@reactos.com)
|
||||
*/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
|
||||
/*
|
||||
* Standard DriverEntry method.
|
||||
*/
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PVOID Context1, IN PVOID Context2)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
384
reactos/drivers/usb/cromwell/linux/asm/bitops.h
Normal file
384
reactos/drivers/usb/cromwell/linux/asm/bitops.h
Normal file
@@ -0,0 +1,384 @@
|
||||
#ifndef _I386_BITOPS_H
|
||||
#define _I386_BITOPS_H
|
||||
|
||||
/*
|
||||
* Copyright 1992, Linus Torvalds.
|
||||
*/
|
||||
|
||||
//#include <linux/config.h>
|
||||
|
||||
/*
|
||||
* These have to be done with inline assembly: that way the bit-setting
|
||||
* is guaranteed to be atomic. All bit operations return 0 if the bit
|
||||
* was cleared before the operation and != 0 if it was not.
|
||||
*
|
||||
* bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define LOCK_PREFIX "lock ; "
|
||||
#else
|
||||
#define LOCK_PREFIX ""
|
||||
#endif
|
||||
|
||||
#define ADDR (*(volatile long *) addr)
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is atomic and may not be reordered. See __set_bit()
|
||||
* if you do not require the atomic guarantees.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* __set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike set_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__(
|
||||
"btsl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* clear_bit() is atomic and may not be reordered. However, it does
|
||||
* not contain a memory barrier, so if it is used for locking purposes,
|
||||
* you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
|
||||
* in order to ensure changes are visible on other processors.
|
||||
*/
|
||||
static __inline__ void clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
#define smp_mb__before_clear_bit() barrier()
|
||||
#define smp_mb__after_clear_bit() barrier()
|
||||
|
||||
/**
|
||||
* __change_bit - Toggle a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* Unlike change_bit(), this function is non-atomic and may be reordered.
|
||||
* If it's called on the same region of memory simultaneously, the effect
|
||||
* may be that only one operation succeeds.
|
||||
*/
|
||||
static __inline__ void __change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__(
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* change_bit() is atomic and may not be reordered.
|
||||
* Note that @nr may be almost arbitrarily large; this function is not
|
||||
* restricted to acting on a single-word quantity.
|
||||
*/
|
||||
static __inline__ void change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %1,%0"
|
||||
:"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btsl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* __test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is non-atomic and can be reordered.
|
||||
* If two examples of this operation race, one can appear to succeed
|
||||
* but actually fail. You must protect multiple accesses with a lock.
|
||||
*/
|
||||
static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__(
|
||||
"btrl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/* WARNING: non atomic and it can be reordered! */
|
||||
static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its new value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static __inline__ int test_and_change_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__( LOCK_PREFIX
|
||||
"btcl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit),"=m" (ADDR)
|
||||
:"Ir" (nr) : "memory");
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static int test_bit(int nr, const volatile void * addr);
|
||||
#endif
|
||||
|
||||
static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (oldbit)
|
||||
:"m" (ADDR),"Ir" (nr));
|
||||
return oldbit;
|
||||
}
|
||||
|
||||
#define test_bit(nr,addr) \
|
||||
(__builtin_constant_p(nr) ? \
|
||||
constant_test_bit((nr),(addr)) : \
|
||||
variable_test_bit((nr),(addr)))
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit-number of the first zero bit, not the number of the byte
|
||||
* containing a bit.
|
||||
*/
|
||||
static __inline__ int find_first_zero_bit(void * addr, unsigned size)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
int res;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
/* This looks at memory. Mark it volatile to tell gcc not to move it around */
|
||||
__asm__ __volatile__(
|
||||
"movl $-1,%%eax\n\t"
|
||||
"xorl %%edx,%%edx\n\t"
|
||||
"repe; scasl\n\t"
|
||||
"je 1f\n\t"
|
||||
"xorl -4(%%edi),%%eax\n\t"
|
||||
"subl $4,%%edi\n\t"
|
||||
"bsfl %%eax,%%edx\n"
|
||||
"1:\tsubl %%ebx,%%edi\n\t"
|
||||
"shll $3,%%edi\n\t"
|
||||
"addl %%edi,%%edx"
|
||||
:"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the first zero bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The maximum size to search
|
||||
*/
|
||||
static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
|
||||
{
|
||||
unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
|
||||
int set = 0, bit = offset & 31, res;
|
||||
|
||||
if (bit) {
|
||||
/*
|
||||
* Look for zero in first byte
|
||||
*/
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jne 1f\n\t"
|
||||
"movl $32, %0\n"
|
||||
"1:"
|
||||
: "=r" (set)
|
||||
: "r" (~(*p >> bit)));
|
||||
if (set < (32 - bit))
|
||||
return set + offset;
|
||||
set = 32 - bit;
|
||||
p++;
|
||||
}
|
||||
/*
|
||||
* No zero yet, search remaining full bytes for a zero
|
||||
*/
|
||||
res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
|
||||
return (offset + set + res);
|
||||
}
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static __inline__ unsigned long ffz(unsigned long word)
|
||||
{
|
||||
__asm__("bsfl %1,%0"
|
||||
:"=r" (word)
|
||||
:"r" (~word));
|
||||
return word;
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/**
|
||||
* ffs - find first bit set
|
||||
* @x: the word to search
|
||||
*
|
||||
* This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
static __inline__ int ffs(int x)
|
||||
{
|
||||
int r;
|
||||
|
||||
__asm__("bsfl %1,%0\n\t"
|
||||
"jnz 1f\n\t"
|
||||
"movl $-1,%0\n"
|
||||
"1:" : "=r" (r) : "rm" (x));
|
||||
return r+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* hweightN - returns the hamming weight of a N-bit word
|
||||
* @x: the word to weigh
|
||||
*
|
||||
* The Hamming Weight of a number is the total number of bits set in it.
|
||||
*/
|
||||
|
||||
#define hweight32(x) generic_hweight32(x)
|
||||
#define hweight16(x) generic_hweight16(x)
|
||||
#define hweight8(x) generic_hweight8(x)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define ext2_set_bit __test_and_set_bit
|
||||
#define ext2_clear_bit __test_and_clear_bit
|
||||
#define ext2_test_bit test_bit
|
||||
#define ext2_find_first_zero_bit find_first_zero_bit
|
||||
#define ext2_find_next_zero_bit find_next_zero_bit
|
||||
|
||||
/* Bitmap functions for the minix filesystem. */
|
||||
#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
|
||||
#define minix_set_bit(nr,addr) __set_bit(nr,addr)
|
||||
#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
|
||||
#define minix_test_bit(nr,addr) test_bit(nr,addr)
|
||||
#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _I386_BITOPS_H */
|
||||
72
reactos/drivers/usb/cromwell/linux/bitops.h
Normal file
72
reactos/drivers/usb/cromwell/linux/bitops.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#define _LINUX_BITOPS_H
|
||||
|
||||
|
||||
/*
|
||||
* ffs: find first bit set. This is defined the same way as
|
||||
* the libc and compiler builtin ffs routines, therefore
|
||||
* differs in spirit from the above ffz (man ffs).
|
||||
*/
|
||||
|
||||
static inline int generic_ffs(int x)
|
||||
{
|
||||
int r = 1;
|
||||
|
||||
if (!x)
|
||||
return 0;
|
||||
if (!(x & 0xffff)) {
|
||||
x >>= 16;
|
||||
r += 16;
|
||||
}
|
||||
if (!(x & 0xff)) {
|
||||
x >>= 8;
|
||||
r += 8;
|
||||
}
|
||||
if (!(x & 0xf)) {
|
||||
x >>= 4;
|
||||
r += 4;
|
||||
}
|
||||
if (!(x & 3)) {
|
||||
x >>= 2;
|
||||
r += 2;
|
||||
}
|
||||
if (!(x & 1)) {
|
||||
x >>= 1;
|
||||
r += 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* hweightN: returns the hamming weight (i.e. the number
|
||||
* of bits set) of a N-bit word
|
||||
*/
|
||||
|
||||
static inline unsigned int generic_hweight32(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
|
||||
res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
|
||||
res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
|
||||
res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
|
||||
return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight16(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
|
||||
res = (res & 0x3333) + ((res >> 2) & 0x3333);
|
||||
res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
|
||||
return (res & 0x00FF) + ((res >> 8) & 0x00FF);
|
||||
}
|
||||
|
||||
static inline unsigned int generic_hweight8(unsigned int w)
|
||||
{
|
||||
unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
|
||||
res = (res & 0x33) + ((res >> 2) & 0x33);
|
||||
return (res & 0x0F) + ((res >> 4) & 0x0F);
|
||||
}
|
||||
|
||||
#include "asm/bitops.h"
|
||||
|
||||
|
||||
#endif
|
||||
337
reactos/drivers/usb/cromwell/linux/boot.h
Normal file
337
reactos/drivers/usb/cromwell/linux/boot.h
Normal file
@@ -0,0 +1,337 @@
|
||||
#ifndef _Boot_H_
|
||||
#define _Boot_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/***************************************************************************
|
||||
Includes used by XBox boot code
|
||||
***************************************************************************/
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/////////////////////////////////
|
||||
// configuration
|
||||
|
||||
#include "consts.h"
|
||||
#include "stdint.h"
|
||||
#include "cromwell_types.h"
|
||||
|
||||
|
||||
unsigned int cromwell_config;
|
||||
unsigned int cromwell_retryload;
|
||||
unsigned int cromwell_loadbank;
|
||||
unsigned int cromwell_Biostype;
|
||||
|
||||
unsigned int xbox_ram;
|
||||
|
||||
#define XROMWELL 0
|
||||
#define CROMWELL 1
|
||||
|
||||
#define ICON_WIDTH 64
|
||||
#define ICON_HEIGHT 64
|
||||
/*
|
||||
static double min (double a, double b)
|
||||
{
|
||||
if (a < b) return a; else return b;
|
||||
}
|
||||
|
||||
static inline double max (double a, double b)
|
||||
{
|
||||
if (a > b) return a; else return b;
|
||||
}
|
||||
*/
|
||||
//#include "iso_fs.h"
|
||||
//#include "BootVideo.h"
|
||||
|
||||
//#define ASSERT(exp) { if(!(exp)) { bprintf("Assert failed file " __FILE__ " line %d\n", __LINE__); } }
|
||||
|
||||
#if 0
|
||||
extern volatile CURRENT_VIDEO_MODE_DETAILS vmode;
|
||||
unsigned int video_encoder;
|
||||
|
||||
volatile u32 VIDEO_CURSOR_POSX;
|
||||
volatile u32 VIDEO_CURSOR_POSY;
|
||||
volatile u32 VIDEO_ATTR;
|
||||
volatile u32 VIDEO_LUMASCALING;
|
||||
volatile u32 VIDEO_RSCALING;
|
||||
volatile u32 VIDEO_BSCALING;
|
||||
volatile u32 BIOS_TICK_COUNT;
|
||||
volatile u32 VIDEO_VSYNC_POSITION;
|
||||
volatile u32 VIDEO_VSYNC_DIR;
|
||||
volatile u32 DVD_TRAY_STATE;
|
||||
|
||||
u8 VIDEO_AV_MODE ;
|
||||
|
||||
#define DVD_CLOSED 0
|
||||
#define DVD_CLOSING 1
|
||||
#define DVD_OPEN 2
|
||||
#define DVD_OPENING 3
|
||||
|
||||
/////////////////////////////////
|
||||
// Superfunky i386 internal structures
|
||||
|
||||
typedef struct gdt_t {
|
||||
unsigned short m_wSize __attribute__ ((packed));
|
||||
unsigned long m_dwBase32 __attribute__ ((packed));
|
||||
unsigned short m_wDummy __attribute__ ((packed));
|
||||
} ts_descriptor_pointer;
|
||||
|
||||
typedef struct { // inside an 8-byte protected mode interrupt vector
|
||||
u16 m_wHandlerHighAddressLow16;
|
||||
u16 m_wSelector;
|
||||
u16 m_wType;
|
||||
u16 m_wHandlerLinearAddressHigh16;
|
||||
} ts_pm_interrupt;
|
||||
|
||||
typedef enum {
|
||||
EDT_UNKNOWN= 0,
|
||||
EDT_XBOXFS
|
||||
} enumDriveType;
|
||||
|
||||
typedef struct tsHarddiskInfo { // this is the retained knowledge about an IDE device after init
|
||||
unsigned short m_fwPortBase;
|
||||
unsigned short m_wCountHeads;
|
||||
unsigned short m_wCountCylinders;
|
||||
unsigned short m_wCountSectorsPerTrack;
|
||||
unsigned long m_dwCountSectorsTotal; /* total */
|
||||
unsigned char m_bLbaMode; /* am i lba (0x40) or chs (0x00) */
|
||||
unsigned char m_szIdentityModelNumber[40];
|
||||
unsigned char term_space_1[2];
|
||||
unsigned char m_szSerial[20];
|
||||
unsigned char term_space_2[2];
|
||||
char m_szFirmware[8];
|
||||
unsigned char term_space_3[2];
|
||||
unsigned char m_fDriveExists;
|
||||
unsigned char m_fAtapi; // true if a CDROM, etc
|
||||
enumDriveType m_enumDriveType;
|
||||
unsigned char m_bCableConductors; // valid for device 0 if present
|
||||
unsigned short m_wAtaRevisionSupported;
|
||||
unsigned char s_length;
|
||||
unsigned char m_length;
|
||||
unsigned char m_fHasMbr;
|
||||
unsigned short m_securitySettings; //This contains the contents of the ATA security regs
|
||||
} tsHarddiskInfo;
|
||||
|
||||
/////////////////////////////////
|
||||
// LED-flashing codes
|
||||
// or these together as argument to I2cSetFrontpanelLed
|
||||
|
||||
enum {
|
||||
I2C_LED_RED0 = 0x80,
|
||||
I2C_LED_RED1 = 0x40,
|
||||
I2C_LED_RED2 = 0x20,
|
||||
I2C_LED_RED3 = 0x10,
|
||||
I2C_LED_GREEN0 = 0x08,
|
||||
I2C_LED_GREEN1 = 0x04,
|
||||
I2C_LED_GREEN2 = 0x02,
|
||||
I2C_LED_GREEN3 = 0x01
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
/* BIOS-wide error codes all have b31 set */
|
||||
|
||||
enum {
|
||||
ERR_SUCCESS = 0, // completed without error
|
||||
|
||||
ERR_I2C_ERROR_TIMEOUT = 0x80000001, // I2C action failed because it did not complete in a reasonable time
|
||||
ERR_I2C_ERROR_BUS = 0x80000002, // I2C action failed due to non retryable bus error
|
||||
|
||||
ERR_BOOT_PIC_ALG_BROKEN = 0x80000101 // PIC algorithm did not pass its self-test
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
// some Boot API prototypes
|
||||
|
||||
//////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
/* ---------------------------- IO primitives -----------------------------------------------------------
|
||||
*/
|
||||
|
||||
static __inline void IoOutputByte(u16 wAds, u8 bValue) {
|
||||
// __asm__ (" out %%al,%%dx" : : "edx" (dwAds), "al" (bValue) );
|
||||
__asm__ __volatile__ ("outb %b0,%w1": :"a" (bValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputWord(u16 wAds, u16 wValue) {
|
||||
// __asm__ (" out %%ax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outw %0,%w1": :"a" (wValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
static __inline void IoOutputDword(u16 wAds, u32 dwValue) {
|
||||
// __asm__ (" out %%eax,%%dx " : : "edx" (dwAds), "ax" (wValue) );
|
||||
__asm__ __volatile__ ("outl %0,%w1": :"a" (dwValue), "Nd" (wAds));
|
||||
}
|
||||
|
||||
|
||||
static __inline u8 IoInputByte(u16 wAds) {
|
||||
unsigned char _v;
|
||||
|
||||
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u16 IoInputWord(u16 wAds) {
|
||||
u16 _v;
|
||||
|
||||
__asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
static __inline u32 IoInputDword(u16 wAds) {
|
||||
u32 _v;
|
||||
|
||||
__asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (wAds));
|
||||
return _v;
|
||||
}
|
||||
|
||||
#define rdmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("rdmsr" \
|
||||
: "=a" (val1), "=d" (val2) \
|
||||
: "c" (msr))
|
||||
|
||||
#define wrmsr(msr,val1,val2) \
|
||||
__asm__ __volatile__("wrmsr" \
|
||||
: /* no outputs */ \
|
||||
: "c" (msr), "a" (val1), "d" (val2))
|
||||
|
||||
|
||||
void BootPciInterruptEnable(void);
|
||||
|
||||
// boot process
|
||||
int BootPerformPicChallengeResponseAction(void);
|
||||
// LED control (see associated enum above)
|
||||
int I2cSetFrontpanelLed(u8 b);
|
||||
|
||||
#define bprintf(...)
|
||||
|
||||
#if PRINT_TRACE
|
||||
#define TRACE bprintf(__FILE__ " :%d\n\r",__LINE__);
|
||||
#else
|
||||
#define TRACE
|
||||
#endif
|
||||
|
||||
typedef struct _LIST_ENTRY {
|
||||
struct _LIST_ENTRY *m_plistentryNext;
|
||||
struct _LIST_ENTRY *m_plistentryPrevious;
|
||||
} LIST_ENTRY;
|
||||
|
||||
void ListEntryInsertAfterCurrent(LIST_ENTRY *plistentryCurrent, LIST_ENTRY *plistentryNew);
|
||||
void ListEntryRemove(LIST_ENTRY *plistentryCurrent);
|
||||
|
||||
////////// BootPerformXCodeActions.c
|
||||
|
||||
int BootPerformXCodeActions(void);
|
||||
|
||||
#include "BootEEPROM.h"
|
||||
#include "BootParser.h"
|
||||
|
||||
////////// BootStartBios.c
|
||||
|
||||
void StartBios(CONFIGENTRY *config,int nActivePartition, int nFATXPresent,int bootfrom);
|
||||
int BootMenu(CONFIGENTRY *config,int nDrive,int nActivePartition, int nFATXPresent);
|
||||
|
||||
////////// BootResetActions.c
|
||||
void ClearIDT (void);
|
||||
void BootResetAction(void);
|
||||
void BootCpuCache(bool fEnable) ;
|
||||
int printk(const char *szFormat, ...);
|
||||
void BiosCmosWrite(u8 bAds, u8 bData);
|
||||
u8 BiosCmosRead(u8 bAds);
|
||||
|
||||
|
||||
///////// BootPciPeripheralInitialization.c
|
||||
void BootPciPeripheralInitialization(void);
|
||||
void BootAGPBUSInitialization(void);
|
||||
void BootDetectMemorySize(void);
|
||||
extern void ReadPCIByte(unsigned int bus, unsigned int dev, unsigned intfunc, unsigned int reg_off, unsigned char *pbyteval);
|
||||
extern void WritePCIByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char byteval);
|
||||
extern void ReadPCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int *pdwordval);
|
||||
extern void WritePCIDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned int dwordval);
|
||||
extern void ReadPCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
extern void WritePCIBlock(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, unsigned char *buf, unsigned int nbytes);
|
||||
|
||||
void PciWriteByte (unsigned int bus, unsigned int dev, unsigned int func,
|
||||
unsigned int reg_off, unsigned char byteval);
|
||||
u8 PciReadByte(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
u32 PciWriteDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off, u32 dw);
|
||||
u32 PciReadDword(unsigned int bus, unsigned int dev, unsigned int func, unsigned int reg_off);
|
||||
|
||||
///////// BootPerformPicChallengeResponseAction.c
|
||||
|
||||
int I2CTransmitWord(u8 bPicAddressI2cFormat, u16 wDataToWrite);
|
||||
int I2CTransmitByteGetReturn(u8 bPicAddressI2cFormat, u8 bDataToWrite);
|
||||
bool I2CGetTemperature(int *, int *);
|
||||
void I2CModifyBits(u8 bAds, u8 bReg, u8 bData, u8 bMask);
|
||||
|
||||
///////// BootIde.c
|
||||
|
||||
extern tsHarddiskInfo tsaHarddiskInfo[]; // static struct stores data about attached drives
|
||||
int BootIdeInit(void);
|
||||
int BootIdeReadSector(int nDriveIndex, void * pbBuffer, unsigned int block, int byte_offset, int n_bytes);
|
||||
int BootIdeBootSectorHddOrElTorito(int nDriveIndex, u8 * pbaResult);
|
||||
int BootIdeAtapiAdditionalSenseCode(int nDrive, u8 * pba, int nLengthMaxReturn);
|
||||
int BootIdeSetTransferMode(int nIndexDrive, int nMode);
|
||||
int BootIdeWaitNotBusy(unsigned uIoBase);
|
||||
bool BootIdeAtapiReportFriendlyError(int nDriveIndex, char * szErrorReturn, int nMaxLengthError);
|
||||
void BootIdeAtapiPrintkFriendlyError(int nDriveIndex);
|
||||
|
||||
///////// BootUSB.c
|
||||
|
||||
void BootStopUSB(void);
|
||||
void BootStartUSB(void);
|
||||
void USBGetEvents(void);
|
||||
|
||||
#include "xpad.h"
|
||||
|
||||
extern struct xpad_data XPAD_current[4];
|
||||
extern struct xpad_data XPAD_last[4];
|
||||
|
||||
extern void wait_ms(u32 ticks);
|
||||
extern void wait_us(u32 ticks);
|
||||
extern void wait_smalldelay(void);
|
||||
|
||||
|
||||
void * memcpy(void *dest, const void *src, size_t size);
|
||||
void * memset(void *dest, int data, size_t size);
|
||||
int memcmp(const void *buffer1, const void *buffer2, size_t num);
|
||||
int _strncmp(const char *sz1, const char *sz2, int nMax);
|
||||
char * strcpy(char *sz, const char *szc);
|
||||
char * _strncpy (char * dest, const char * src, size_t n);
|
||||
void chrreplace(char *string, char search, char ch);
|
||||
|
||||
#define printf printk
|
||||
#define sleep wait_ms
|
||||
int tolower(int ch);
|
||||
int isspace (int c);
|
||||
|
||||
void MemoryManagementInitialization(void * pvStartAddress, u32 dwTotalMemoryAllocLength);
|
||||
void * malloc(size_t size);
|
||||
void free(void *);
|
||||
|
||||
extern volatile int nCountI2cinterrupts, nCountUnusedInterrupts, nCountUnusedInterruptsPic2, nCountInterruptsSmc, nCountInterruptsIde;
|
||||
extern volatile bool fSeenPowerdown;
|
||||
typedef enum {
|
||||
ETS_OPEN_OR_OPENING=0,
|
||||
ETS_CLOSING,
|
||||
ETS_CLOSED
|
||||
} TRAY_STATE;
|
||||
extern volatile TRAY_STATE traystate;
|
||||
|
||||
|
||||
extern void BootInterruptsWriteIdt(void);
|
||||
#endif
|
||||
int copy_swap_trim(unsigned char *dst, unsigned char *src, int len);
|
||||
void HMAC_SHA1( unsigned char *result,
|
||||
unsigned char *key, int key_length,
|
||||
unsigned char *text1, int text1_length,
|
||||
unsigned char *text2, int text2_length );
|
||||
|
||||
char *strrchr0(char *string, char ch);
|
||||
|
||||
#endif // _Boot_H_
|
||||
70
reactos/drivers/usb/cromwell/linux/consts.h
Normal file
70
reactos/drivers/usb/cromwell/linux/consts.h
Normal file
@@ -0,0 +1,70 @@
|
||||
#ifndef _Consts_H_
|
||||
#define _Consts_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* includes for startup code in a form usable by the .S files
|
||||
*
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#define PCI_CFG_ADDR 0x0CF8
|
||||
#define PCI_CFG_DATA 0x0CFC
|
||||
|
||||
|
||||
#define I2C_IO_BASE 0xc000
|
||||
|
||||
#define BUS_0 0
|
||||
#define BUS_1 1
|
||||
|
||||
#define DEV_0 0
|
||||
#define DEV_1 1
|
||||
#define DEV_2 2
|
||||
#define DEV_3 3
|
||||
#define DEV_4 4
|
||||
#define DEV_5 5
|
||||
#define DEV_6 6
|
||||
#define DEV_7 7
|
||||
#define DEV_8 8
|
||||
#define DEV_9 9
|
||||
#define DEV_a 0xa
|
||||
#define DEV_b 0xb
|
||||
#define DEV_c 0xc
|
||||
#define DEV_d 0xd
|
||||
#define DEV_e 0xe
|
||||
#define DEV_f 0xf
|
||||
#define DEV_10 0x10
|
||||
#define DEV_11 0x11
|
||||
#define DEV_12 0x12
|
||||
#define DEV_13 0x13
|
||||
#define DEV_14 0x14
|
||||
#define DEV_15 0x15
|
||||
#define DEV_16 0x16
|
||||
#define DEV_17 0x17
|
||||
#define DEV_18 0x18
|
||||
#define DEV_19 0x19
|
||||
#define DEV_1a 0x1a
|
||||
#define DEV_1b 0x1b
|
||||
#define DEV_1c 0x1c
|
||||
#define DEV_1d 0x1d
|
||||
#define DEV_1e 0x1e
|
||||
#define DEV_1f 0x1f
|
||||
|
||||
#define FUNC_0 0
|
||||
/*
|
||||
#define boot_post_macro(value) \
|
||||
movb $(value), %al ;\
|
||||
outb %al, $0x80
|
||||
*/
|
||||
|
||||
#endif // _Consts_H_
|
||||
|
||||
|
||||
27
reactos/drivers/usb/cromwell/linux/cromwell_types.h
Normal file
27
reactos/drivers/usb/cromwell/linux/cromwell_types.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef cromwell_types_h
|
||||
#define cromwell_types_h
|
||||
|
||||
/////////////////////////////////
|
||||
// some typedefs to make for easy sizing
|
||||
|
||||
//typedef unsigned long ULONG;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned char u8;
|
||||
#ifndef bool_already_defined_
|
||||
typedef int bool;
|
||||
#endif
|
||||
typedef unsigned long RGBA; // LSB=R -> MSB = A
|
||||
//typedef long long __int64;
|
||||
|
||||
#define guint int
|
||||
#define guint8 unsigned char
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef cromwell_types_h */
|
||||
132
reactos/drivers/usb/cromwell/linux/errno.h
Normal file
132
reactos/drivers/usb/cromwell/linux/errno.h
Normal file
@@ -0,0 +1,132 @@
|
||||
#ifndef _I386_ERRNO_H
|
||||
#define _I386_ERRNO_H
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define EWOULDBLOCK EAGAIN /* Operation would block */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
|
||||
#define EDEADLOCK EDEADLK
|
||||
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
|
||||
#endif
|
||||
762
reactos/drivers/usb/cromwell/linux/linux_wrapper.h
Normal file
762
reactos/drivers/usb/cromwell/linux/linux_wrapper.h
Normal file
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* linux-wrapper.h
|
||||
*
|
||||
* Hard coded Linux kernel replacements for x86
|
||||
*
|
||||
* (c) 2003 Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Emulation of:
|
||||
* typedefs
|
||||
* structs
|
||||
* macros
|
||||
*
|
||||
* All structs and prototypes are based on kernel source 2.5.72
|
||||
*
|
||||
* #include <standard-GPL-header.h>
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Typedefs */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#include "cromwell_types.h"
|
||||
|
||||
typedef unsigned int __u32;
|
||||
//typedef __u32 u32;
|
||||
typedef unsigned short __u16;
|
||||
//typedef __u16 u16;
|
||||
typedef unsigned char __u8;
|
||||
//typedef __u8 u8;
|
||||
|
||||
typedef short s16;
|
||||
|
||||
typedef u32 dma_addr_t;
|
||||
|
||||
typedef int spinlock_t;
|
||||
typedef int atomic_t;
|
||||
#ifndef STANDALONE
|
||||
typedef int mode_t;
|
||||
typedef int pid_t;
|
||||
typedef int ssize_t;
|
||||
|
||||
#endif
|
||||
typedef int irqreturn_t;
|
||||
typedef unsigned long kernel_ulong_t;
|
||||
|
||||
typedef int wait_queue_head_t;
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Stuff from xbox/linux environment */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#ifndef STANDALONE
|
||||
#ifdef MODULE
|
||||
typedef int size_t;
|
||||
#define NULL ((void*)0)
|
||||
extern void * memset(void *,int,unsigned int);
|
||||
extern void * memcpy(void *,const void *,unsigned int);
|
||||
#if 0
|
||||
extern char * strcpy(char *,const char *);
|
||||
#else
|
||||
static inline char * strcpy(char * dest,const char *src)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
__asm__ __volatile__(
|
||||
"1:\tlodsb\n\t"
|
||||
"stosb\n\t"
|
||||
"testb %%al,%%al\n\t"
|
||||
"jne 1b"
|
||||
: "=&S" (d0), "=&D" (d1), "=&a" (d2)
|
||||
:"0" (src),"1" (dest) : "memory");
|
||||
return dest;
|
||||
}
|
||||
#endif
|
||||
extern size_t strlen(const char *);
|
||||
|
||||
extern int memcmp(const void *,const void *,unsigned int);
|
||||
|
||||
#else
|
||||
#include "boot.h"
|
||||
#include "config.h"
|
||||
#endif
|
||||
#else
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "consts.h"
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* General structs */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
struct timer_list {
|
||||
void (*function)(unsigned long);
|
||||
unsigned long data;
|
||||
int expires;
|
||||
struct list_head timer_list;
|
||||
};
|
||||
|
||||
struct work_struct {
|
||||
void (*func)(void *);
|
||||
};
|
||||
struct device {
|
||||
char name[128];
|
||||
struct bus_type *bus;
|
||||
int dma_mask;
|
||||
char bus_id[16];
|
||||
struct device_driver* driver;
|
||||
void *driver_data;
|
||||
struct device *parent;
|
||||
struct list_head driver_list;
|
||||
void (*release)(struct device * dev);
|
||||
};
|
||||
struct class_device{int a;};
|
||||
struct semaphore{int a;};
|
||||
|
||||
struct device_driver{
|
||||
char *name;
|
||||
struct bus_type *bus;
|
||||
int (*probe) (struct device * dev);
|
||||
int (*remove) (struct device * dev);
|
||||
struct list_head devices;
|
||||
};
|
||||
|
||||
struct bus_type {
|
||||
char * name;
|
||||
int (*match)(struct device * dev, struct device_driver * drv);
|
||||
struct device * (*add) (struct device * parent, char * bus_id);
|
||||
int (*hotplug) (struct device *dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size);
|
||||
};
|
||||
|
||||
struct dummy_process
|
||||
{
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct pt_regs
|
||||
{
|
||||
int a;
|
||||
};
|
||||
struct completion {
|
||||
unsigned int done;
|
||||
wait_queue_head_t wait;
|
||||
};
|
||||
|
||||
/* from mod_devicetable.h */
|
||||
|
||||
struct usb_device_id {
|
||||
/* which fields to match against? */
|
||||
__u16 match_flags;
|
||||
|
||||
/* Used for product specific matches; range is inclusive */
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u16 bcdDevice_lo;
|
||||
__u16 bcdDevice_hi;
|
||||
|
||||
/* Used for device class matches */
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
|
||||
/* Used for interface class matches */
|
||||
__u8 bInterfaceClass;
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
|
||||
/* not matched against */
|
||||
kernel_ulong_t driver_info;
|
||||
};
|
||||
|
||||
/* Some useful macros to use to create struct usb_device_id */
|
||||
#define USB_DEVICE_ID_MATCH_VENDOR 0x0001
|
||||
#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002
|
||||
#define USB_DEVICE_ID_MATCH_DEV_LO 0x0004
|
||||
#define USB_DEVICE_ID_MATCH_DEV_HI 0x0008
|
||||
#define USB_DEVICE_ID_MATCH_DEV_CLASS 0x0010
|
||||
#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS 0x0020
|
||||
#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL 0x0040
|
||||
#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080
|
||||
#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100
|
||||
#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* imported functions from top-level */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
//void zxprintf(char* fmt, ...);
|
||||
//void zxsprintf(char *buffer, char* fmt, ...);
|
||||
//int zxsnprintf(char *buffer, size_t s, char* fmt, ...);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* PCI structs (taken from linux/pci.h et al., but slightly modified) */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
struct pci_dev {
|
||||
int vendor;
|
||||
int device;
|
||||
struct pci_bus *bus;
|
||||
int irq;
|
||||
char *slot_name;
|
||||
struct device dev;
|
||||
int base[4];
|
||||
int flags[4];
|
||||
void * data;
|
||||
};
|
||||
|
||||
struct pci_bus {
|
||||
unsigned char number;
|
||||
};
|
||||
|
||||
struct pci_device_id {
|
||||
__u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
|
||||
__u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
|
||||
__u32 class, class_mask; /* (class,subclass,prog-if) triplet */
|
||||
kernel_ulong_t driver_data; /* Data private to the driver */
|
||||
};
|
||||
|
||||
struct pci_driver {
|
||||
struct list_head node;
|
||||
char *name;
|
||||
const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */
|
||||
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */
|
||||
void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */
|
||||
int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */
|
||||
int (*suspend) (struct pci_dev *dev, u32 state); /* Device suspended */
|
||||
int (*resume) (struct pci_dev *dev); /* Device woken up */
|
||||
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */
|
||||
};
|
||||
|
||||
struct scatterlist
|
||||
{
|
||||
int page;
|
||||
int offset;
|
||||
int length;
|
||||
};
|
||||
|
||||
struct usbdevfs_hub_portinfo
|
||||
{
|
||||
int nports;
|
||||
int port[8];
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* constant defines */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define TASK_UNINTERRUPTIBLE 0
|
||||
#define HZ 100 /* Don't rely on that... */
|
||||
#define KERN_DEBUG "DBG: "
|
||||
#define KERN_ERR "ERR: "
|
||||
#define KERN_WARNING "WRN: "
|
||||
#define KERN_INFO "INF: "
|
||||
#define GFP_KERNEL 0
|
||||
#define GFP_ATOMIC 0
|
||||
#define GFP_NOIO 0
|
||||
#define SLAB_ATOMIC 0
|
||||
#define PCI_ANY_ID (~0)
|
||||
#define SIGKILL 9
|
||||
#define THIS_MODULE 0
|
||||
//#define PAGE_SIZE 4096
|
||||
|
||||
|
||||
#define CLONE_FS 0
|
||||
#define CLONE_FILES 0
|
||||
#define CLONE_SIGHAND 0
|
||||
#define PF_FREEZE 0
|
||||
#define PF_IOTHREAD 0
|
||||
|
||||
|
||||
#define USBDEVFS_HUB_PORTINFO 1234
|
||||
#define SA_SHIRQ 0
|
||||
|
||||
#undef PCI_COMMAND
|
||||
#define PCI_COMMAND 0
|
||||
#undef PCI_COMMAND_MASTER
|
||||
#define PCI_COMMAND_MASTER 0
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Module/export macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define MODULE_AUTHOR(a)
|
||||
#define MODULE_DESCRIPTION(a)
|
||||
#define MODULE_LICENSE(a)
|
||||
#define MODULE_DEVICE_TABLE(type,name) void* module_table_##name=&name
|
||||
|
||||
#define __devinit
|
||||
#define __exit
|
||||
#define __init
|
||||
#define __devinitdata
|
||||
#define module_init(x) static void module_init_##x(void){ x();}
|
||||
#define module_exit(x) void module_exit_##x(void){ x();}
|
||||
#define EXPORT_SYMBOL_GPL(x)
|
||||
#define EXPORT_SYMBOL(x)
|
||||
|
||||
#define __setup(x,y) int setup_##y=(int)y
|
||||
#define subsys_initcall(x) void subsys_##x(void){x();}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Access macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define dev_get_drvdata(a) (a)->driver_data
|
||||
#define dev_set_drvdata(a,b) (a)->driver_data=(b)
|
||||
|
||||
#define __io_virt(x) ((void *)(x))
|
||||
#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
|
||||
#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#define prefetch(x) 1
|
||||
|
||||
/* The kernel macro for list_for_each_entry makes nonsense (have no clue
|
||||
* why, this is just the same definition...) */
|
||||
|
||||
#undef list_for_each_entry
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member), \
|
||||
prefetch(pos->member.next))
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* function wrapper macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define kmalloc(x,y) ExAllocatePool(PagedPool,x)
|
||||
#define kfree(x) ExFreePool(x)
|
||||
|
||||
//#define sprintf(a,b,format, arg...) zxsprintf((a),(b),format, ## arg)
|
||||
//#define snprintf(a,b,format, arg...) zxsnprintf((a),(b),format, ##arg)
|
||||
//#define printk(format, arg...) zxprintf(format, ## arg)
|
||||
#define snprintf(a,b,format, arg...) _snprintf((a),(b),format, ##arg)
|
||||
#define printk(format, arg...) DPRINT1(format, ## arg)
|
||||
#define BUG(...) do {} while(0)
|
||||
|
||||
/* Locks & friends */
|
||||
|
||||
#define DECLARE_MUTEX(x) struct semaphore x
|
||||
#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)
|
||||
|
||||
#if 0
|
||||
#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
|
||||
#define local_irq_restore(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc")
|
||||
#else
|
||||
#define local_irq_save(x) do {} while(0)
|
||||
#define local_irq_restore(x) do {} while(0)
|
||||
#endif
|
||||
|
||||
#define atomic_inc(x) *(x)+=1
|
||||
#define atomic_dec(x) *(x)-=1
|
||||
#define atomic_dec_and_test(x) (*(x)-=1,(*(x))==0)
|
||||
#define atomic_set(x,a) *(x)=a
|
||||
#define atomic_read(x) *(x)
|
||||
#define ATOMIC_INIT(x) (x)
|
||||
|
||||
#define down(x) do {} while(0)
|
||||
#define up(x) do {} while(0)
|
||||
#define down_trylock(a) 0
|
||||
|
||||
#define down_read(a) do {} while(0)
|
||||
#define up_read(a) do {} while(0)
|
||||
|
||||
#define DECLARE_WAIT_QUEUE_HEAD(x) int x
|
||||
|
||||
#define DECLARE_COMPLETION(x) struct completion x
|
||||
|
||||
/* driver */
|
||||
|
||||
#define driver_unregister(a) do {} while(0)
|
||||
#define put_device(a) do {} while(0)
|
||||
|
||||
|
||||
/* PCI */
|
||||
#define pci_pool_create(a,b,c,d,e) (void*)1
|
||||
|
||||
#define pci_pool_alloc(a,b,c) my_pci_pool_alloc(a,b,c)
|
||||
|
||||
static void __inline__ *my_pci_pool_alloc(void* pool, size_t size,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
void* a;
|
||||
a=kmalloc(size,0); //FIXME
|
||||
#ifdef MODULE
|
||||
*dma_handle=((u32)a)&0xfffffff;
|
||||
#else
|
||||
*dma_handle=(u32)a;
|
||||
#endif
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
#define pci_pool_free(a,b,c) kfree(b)
|
||||
#define pci_alloc_consistent(a,b,c) my_pci_alloc_consistent(a,b,c)
|
||||
|
||||
static void __inline__ *my_pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
|
||||
dma_addr_t *dma_handle)
|
||||
{
|
||||
void* a;
|
||||
|
||||
a=kmalloc(size+256,0); //FIXME
|
||||
a=(void*)(((int)a+255)&~255); // 256 alignment
|
||||
*dma_handle=((u32)a)&0xfffffff;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
#define pci_free_consistent(a,b,c,d) kfree(c)
|
||||
#define pci_pool_destroy(a) do {} while(0)
|
||||
|
||||
#define pci_module_init(x) my_pci_module_init(x)
|
||||
int my_pci_module_init(struct pci_driver *x);
|
||||
|
||||
#define pci_unregister_driver(a) do {} while(0)
|
||||
|
||||
#define bus_register(a) do {} while(0)
|
||||
#define bus_unregister(a) do {} while(0)
|
||||
|
||||
#define dma_map_single(a,b,c,d) ((u32)(b)&0xfffffff)
|
||||
#define dma_unmap_single(a,b,c,d) do {} while(0)
|
||||
#define pci_unmap_single(a,b,c,d) do {} while(0)
|
||||
#define dma_sync_single(a,b,c,d) do {} while(0)
|
||||
#define dma_sync_sg(a,b,c,d) do {} while(0)
|
||||
#define dma_map_sg(a,b,c,d) 0
|
||||
#define dma_unmap_sg(a,b,c,d) do {} while(0)
|
||||
|
||||
#define usb_create_driverfs_dev_files(a) do {} while(0)
|
||||
#define usb_create_driverfs_intf_files(a) do {} while(0)
|
||||
#define sg_dma_address(x) ((u32)((x)->page*4096 + (x)->offset))
|
||||
#define sg_dma_len(x) ((x)->length)
|
||||
|
||||
#define page_address(x) ((void*)(x/4096))
|
||||
|
||||
#define DMA_TO_DEVICE 0
|
||||
#define DMA_FROM_DEVICE 0
|
||||
#define PCI_DMA_TODEVICE
|
||||
#define PCI_DMA_FROMDEVICE
|
||||
#define PCI_DMA_TODEVICE
|
||||
|
||||
#define PCI_ROM_RESOURCE 0
|
||||
#define IORESOURCE_IO 1
|
||||
|
||||
#define DECLARE_WAITQUEUE(a,b) wait_queue_head_t a=0
|
||||
#define init_waitqueue_head(a) do {} while(0)
|
||||
#define add_wait_queue(a,b) do {} while(0)
|
||||
#define remove_wait_queue(a,b) 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 wait_for_completion(x) my_wait_for_completion(x)
|
||||
void my_wait_for_completion(struct completion*);
|
||||
|
||||
#define IRQ_NONE 0
|
||||
#define IRQ_HANDLED 1
|
||||
|
||||
#define INIT_WORK(a,b,c) (a)->func=b
|
||||
|
||||
#define set_current_state(a) do {} while(0)
|
||||
|
||||
#define might_sleep() do {} while(0)
|
||||
#define daemonize(a) do {} while(0)
|
||||
#define allow_signal(a) do {} while(0)
|
||||
#define wait_event_interruptible(x,y) do {} while(0)
|
||||
#define flush_scheduled_work() do {} while(0)
|
||||
#define refrigerator(x) do {} while(0)
|
||||
#define signal_pending(x) 1 // fall through threads
|
||||
#define complete_and_exit(a,b) return 0
|
||||
|
||||
#define kill_proc(a,b,c) 0
|
||||
#define yield() do {} while(0)
|
||||
#define cpu_relax() do {} while(0)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Kernel macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define LINUX_VERSION_CODE 0x020572
|
||||
#define UTS_SYSNAME "XBOX"
|
||||
#define UTS_RELEASE "----"
|
||||
|
||||
/* from linux/kernel.h */
|
||||
#define max_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
|
||||
|
||||
#define min_t(type,x,y) \
|
||||
({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
/* from linux/stddef.h */
|
||||
|
||||
#undef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Conversion macros */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define __constant_cpu_to_le32(x) (x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_le32p(x) (*(__u32*)(x))
|
||||
#define le32_to_cpup(x) (*(__u32*)(x))
|
||||
#define le32_to_cpu(x) ((u32)x)
|
||||
#define le16_to_cpus(x) do {} while (0)
|
||||
#define le16_to_cpup(x) (*(__u16*)(x))
|
||||
#define cpu_to_le16p(x) (*(__u16*)(x))
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Debug output */
|
||||
/*------------------------------------------------------------------------*/
|
||||
#ifdef DEBUG_MODE
|
||||
#define dev_printk(lvl,x,f,arg...) printk(f, ## arg)
|
||||
#define dev_dbg(x,f,arg...) do {} while (0) //printk(f, ## arg)
|
||||
#define dev_info(x,f,arg...) printk(f,## arg)
|
||||
#define dev_warn(x,f,arg...) printk(f,## arg)
|
||||
#define dev_err(x,f,arg...) printk(f,## arg)
|
||||
#define pr_debug(x,f,arg...) printk(f,## arg)
|
||||
#define usbprintk printk
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MODE
|
||||
#define dev_printk(lvl,x,f,arg...) do {} while (0)
|
||||
#define dev_dbg(x,f,arg...) do {} while (0) //printk(f, ## arg)
|
||||
#define dev_info(x,f,arg...) do {} while (0)
|
||||
#define dev_warn(x,f,arg...) do {} while (0)
|
||||
#define dev_err(x,f,arg...) do {} while (0)
|
||||
#define pr_debug(x,f,arg...) do {} while (0)
|
||||
#define usbprintk
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define PCI_DEVFN(a,b) 0
|
||||
#define PCI_SLOT(a) 0
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Stuff from kernel */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#include "errno.h"
|
||||
#include "bitops.h"
|
||||
//#include "linux/pci_ids.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* global variables */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define jiffies my_jiffies
|
||||
extern int my_jiffies;
|
||||
#define current my_current
|
||||
extern struct dummy_process *my_current;
|
||||
|
||||
extern struct list_head interrupt_list;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Function prototypes */
|
||||
/*------------------------------------------------------------------------*/
|
||||
void STDCALL usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
#define my_wait_ms(x) wait_ms(x)
|
||||
|
||||
#define my_udelay(x) wait_ms(x)
|
||||
#define udelay(x) my_udelay(x)
|
||||
|
||||
#define my_mdelay(x) wait_ms(1+x/1000);
|
||||
#define mdelay(x) my_mdelay(x);
|
||||
|
||||
#define pci_find_slot(a,b) my_pci_find_slot(a,b)
|
||||
struct pci_dev *my_pci_find_slot(int a,int b);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Timer management */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define MAX_TIMERS 20
|
||||
extern struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
|
||||
static void __inline__ init_timer(struct timer_list* t)
|
||||
{
|
||||
INIT_LIST_HEAD(&t->timer_list);
|
||||
t->function=NULL;
|
||||
t->expires=0;
|
||||
}
|
||||
|
||||
static void __inline__ add_timer(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==0)
|
||||
{
|
||||
main_timer_list[n]=t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void __inline__ del_timer(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==t)
|
||||
{
|
||||
main_timer_list[n]=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
static void __inline__ del_timer_sync(struct timer_list* t)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
if (main_timer_list[n]==t)
|
||||
{
|
||||
main_timer_list[n]=0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
static void __inline__ mod_timer(struct timer_list* t, int ex)
|
||||
{
|
||||
del_timer(t);
|
||||
t->expires=ex;
|
||||
add_timer(t);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device driver and process related stuff */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
static int __inline__ usb_major_init(void){return 0;}
|
||||
static void __inline__ usb_major_cleanup(void){}
|
||||
static void __inline__ schedule_work(void* p){}
|
||||
|
||||
#define device_initialize(x) my_device_initialize(x)
|
||||
void my_device_initialize(struct device *dev);
|
||||
|
||||
#define get_device(x) my_get_device(x)
|
||||
struct device *my_get_device(struct device *dev);
|
||||
|
||||
#define device_add(x) my_device_add(x)
|
||||
int my_device_add(struct device *dev);
|
||||
|
||||
#define driver_register(x) my_driver_register(x)
|
||||
int my_driver_register(struct device_driver *driver);
|
||||
|
||||
#define device_unregister(a) my_device_unregister(a)
|
||||
int my_device_unregister(struct device *dev);
|
||||
|
||||
#define DEVICE_ATTR(a,b,c,d) int xxx_##a
|
||||
#define device_create_file(a,b) do {} while(0)
|
||||
#define device_remove_file(a,b) do {} while(0)
|
||||
|
||||
#define schedule_timeout(x) my_schedule_timeout(x)
|
||||
int my_schedule_timeout(int x);
|
||||
|
||||
#define wake_up(x) my_wake_up(x)
|
||||
void my_wake_up(void*);
|
||||
|
||||
// cannot be mapped via macro due to collision with urb->complete
|
||||
static void __inline__ complete(struct completion *p)
|
||||
{
|
||||
/* Wake up x->wait */
|
||||
p->done++;
|
||||
wake_up(&p->wait);
|
||||
}
|
||||
|
||||
#define kernel_thread(a,b,c) my_kernel_thread(a,b,c)
|
||||
int my_kernel_thread(int (*handler)(void*), void* parm, int flags);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* PCI, simple and inlined... */
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int __inline__ pci_enable_device(struct pci_dev *dev) {return 0;}
|
||||
|
||||
static unsigned long __inline__ pci_resource_start (struct pci_dev *dev, int x)
|
||||
{
|
||||
return dev->base[x];
|
||||
}
|
||||
|
||||
static unsigned long __inline__ pci_resource_len (struct pci_dev *dev, int x){return 0;}
|
||||
|
||||
static int __inline__ request_mem_region(unsigned long addr, unsigned long len, const char * d){return 1;}
|
||||
|
||||
static void __inline__ *ioremap_nocache(unsigned long addr, unsigned long len)
|
||||
{
|
||||
return (void*)addr;
|
||||
}
|
||||
|
||||
static int __inline__ release_mem_region(unsigned long addr, unsigned long len){return 0;}
|
||||
|
||||
static int __inline__ pci_resource_flags(struct pci_dev *dev, int x)
|
||||
{
|
||||
return dev->flags[x];
|
||||
}
|
||||
|
||||
static int __inline__ request_region(unsigned long addr, unsigned long len, const char * d){return 0;}
|
||||
|
||||
static int __inline__ pci_set_master(struct pci_dev *dev){return 0;}
|
||||
|
||||
static int __inline__ iounmap(void* p){return 0;}
|
||||
|
||||
static int __inline__ release_region(unsigned long addr, unsigned long len){return 0;}
|
||||
|
||||
static int __inline__ pci_set_drvdata(struct pci_dev *dev, void* d)
|
||||
{
|
||||
dev->data=(void*)d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __inline__ *pci_get_drvdata(struct pci_dev *dev)
|
||||
{
|
||||
return dev->data;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* IRQ handling */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
#define request_irq(a,b,c,d,e) my_request_irq(a,b,c,d,e)
|
||||
int my_request_irq(unsigned int irq,
|
||||
int (*handler)(int, void *, struct pt_regs *),
|
||||
unsigned long mode, const char *desc, void *data);
|
||||
|
||||
#define free_irq(a,b) my_free_irq(a,b)
|
||||
int free_irq(int irq, void* p);
|
||||
|
||||
|
||||
|
||||
struct my_irqs {
|
||||
int (*handler)(int, void *, struct pt_regs *);
|
||||
int irq;
|
||||
void* data;
|
||||
};
|
||||
|
||||
#define MAX_IRQS 8
|
||||
|
||||
// Exported to top level
|
||||
|
||||
void handle_irqs(int irq);
|
||||
void inc_jiffies(int);
|
||||
void init_wrapper(void);
|
||||
void do_all_timers(void);
|
||||
|
||||
#define __KERNEL_DS 0x18
|
||||
|
||||
|
||||
224
reactos/drivers/usb/cromwell/linux/list.h
Normal file
224
reactos/drivers/usb/cromwell/linux/list.h
Normal file
@@ -0,0 +1,224 @@
|
||||
#ifndef _BOOT_LIST_H
|
||||
#define _BOOT_LIST_H
|
||||
|
||||
/*
|
||||
* Simple doubly linked list implementation.
|
||||
*
|
||||
* Some of the internal functions ("__xxx") are useful when
|
||||
* manipulating whole lists rather than single entries, as
|
||||
* sometimes we already know the next/prev entries and we can
|
||||
* generate better code by using them directly rather than
|
||||
* using the generic single-entry routines.
|
||||
*/
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next, *prev;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||
|
||||
#define LIST_HEAD(name) \
|
||||
struct list_head name = LIST_HEAD_INIT(name)
|
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \
|
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_add(struct list_head *new,
|
||||
struct list_head *prev,
|
||||
struct list_head *next)
|
||||
{
|
||||
next->prev = new;
|
||||
new->next = next;
|
||||
new->prev = prev;
|
||||
prev->next = new;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it after
|
||||
*
|
||||
* Insert a new entry after the specified head.
|
||||
* This is good for implementing stacks.
|
||||
*/
|
||||
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head, head->next);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_add_tail - add a new entry
|
||||
* @new: new entry to be added
|
||||
* @head: list head to add it before
|
||||
*
|
||||
* Insert a new entry before the specified head.
|
||||
* This is useful for implementing queues.
|
||||
*/
|
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||
{
|
||||
__list_add(new, head->prev, head);
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries
|
||||
* point to each other.
|
||||
*
|
||||
* This is only for internal list manipulation where we know
|
||||
* the prev/next entries already!
|
||||
*/
|
||||
static inline void __list_del(struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
next->prev = prev;
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del - deletes entry from list.
|
||||
* @entry: the element to delete from the list.
|
||||
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
|
||||
*/
|
||||
static inline void list_del(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
entry->next = (void *) 0;
|
||||
entry->prev = (void *) 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_del_init - deletes entry from list and reinitialize it.
|
||||
* @entry: the element to delete from the list.
|
||||
*/
|
||||
static inline void list_del_init(struct list_head *entry)
|
||||
{
|
||||
__list_del(entry->prev, entry->next);
|
||||
INIT_LIST_HEAD(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move - delete from one list and add as another's head
|
||||
* @list: the entry to move
|
||||
* @head: the head that will precede our entry
|
||||
*/
|
||||
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_move_tail - delete from one list and add as another's tail
|
||||
* @list: the entry to move
|
||||
* @head: the head that will follow our entry
|
||||
*/
|
||||
static inline void list_move_tail(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
__list_del(list->prev, list->next);
|
||||
list_add_tail(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_empty - tests whether a list is empty
|
||||
* @head: the list to test.
|
||||
*/
|
||||
static inline int list_empty(struct list_head *head)
|
||||
{
|
||||
return head->next == head;
|
||||
}
|
||||
|
||||
static inline void __list_splice(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
struct list_head *first = list->next;
|
||||
struct list_head *last = list->prev;
|
||||
struct list_head *at = head->next;
|
||||
|
||||
first->prev = head;
|
||||
head->next = first;
|
||||
|
||||
last->next = at;
|
||||
at->prev = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice - join two lists
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*/
|
||||
static inline void list_splice(struct list_head *list, struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list))
|
||||
__list_splice(list, head);
|
||||
}
|
||||
|
||||
/**
|
||||
* list_splice_init - join two lists and reinitialise the emptied list.
|
||||
* @list: the new list to add.
|
||||
* @head: the place to add it in the first list.
|
||||
*
|
||||
* The list at @list is reinitialised
|
||||
*/
|
||||
static inline void list_splice_init(struct list_head *list,
|
||||
struct list_head *head)
|
||||
{
|
||||
if (!list_empty(list)) {
|
||||
__list_splice(list, head);
|
||||
INIT_LIST_HEAD(list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* list_entry - get the struct for this entry
|
||||
* @ptr: the &struct list_head pointer.
|
||||
* @type: the type of the struct this is embedded in.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
|
||||
|
||||
/**
|
||||
* list_for_each - iterate over a list
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); \
|
||||
pos = pos->next)
|
||||
/**
|
||||
* list_for_each_prev - iterate over a list backwards
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_prev(pos, head) \
|
||||
for (pos = (head)->prev; pos != (head); \
|
||||
pos = pos->prev)
|
||||
|
||||
/**
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry
|
||||
* @pos: the &struct list_head to use as a loop counter.
|
||||
* @n: another &struct list_head to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
*/
|
||||
#define list_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next)
|
||||
|
||||
/**
|
||||
* list_for_each_entry - iterate over list of given type
|
||||
* @pos: the type * to use as a loop counter.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the list_struct within the struct.
|
||||
*/
|
||||
#define list_for_each_entry(pos, head, member) \
|
||||
for (pos = list_entry((head)->next, typeof(*pos), member) \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||
|
||||
#endif
|
||||
11
reactos/drivers/usb/cromwell/linux/pci_ids.h
Normal file
11
reactos/drivers/usb/cromwell/linux/pci_ids.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef PCI_IDS__H
|
||||
#define PCI_IDS__H
|
||||
|
||||
#define PCI_VENDOR_ID_NS 0x100b
|
||||
#define PCI_DEVICE_ID_NS_87560_LIO 0x000e
|
||||
#define PCI_VENDOR_ID_AMD 0x1022
|
||||
#define PCI_VENDOR_ID_OPTI 0x1045
|
||||
|
||||
#define PCI_CLASS_SERIAL_USB (PCI_CLASS_SERIAL_BUS_CTLR << 8 + PCI_SUBCLASS_SB_USB)
|
||||
|
||||
#endif
|
||||
1032
reactos/drivers/usb/cromwell/linux/usb.h
Normal file
1032
reactos/drivers/usb/cromwell/linux/usb.h
Normal file
File diff suppressed because it is too large
Load Diff
315
reactos/drivers/usb/cromwell/linux/usb_ch9.h
Normal file
315
reactos/drivers/usb/cromwell/linux/usb_ch9.h
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* This file holds USB constants and structures that are needed for USB
|
||||
* device APIs. These are used by the USB device model, which is defined
|
||||
* in chapter 9 of the USB 2.0 specification. Linux has several APIs in C
|
||||
* that need these:
|
||||
*
|
||||
* - the master/host side Linux-USB kernel driver API;
|
||||
* - the "usbfs" user space API; and
|
||||
* - (eventually) a Linux "gadget" slave/device side driver API.
|
||||
*
|
||||
* USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
|
||||
* act either as a USB master/host or as a USB slave/device. That means
|
||||
* the master and slave side APIs will benefit from working well together.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_CH9_H
|
||||
#define __LINUX_USB_CH9_H
|
||||
#if 0
|
||||
#include <asm/types.h> /* __u8 etc */
|
||||
#endif
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* CONTROL REQUEST SUPPORT */
|
||||
|
||||
/*
|
||||
* USB directions
|
||||
*
|
||||
* This bit flag is used in endpoint descriptors' bEndpointAddress field.
|
||||
* It's also one of three fields in control requests bRequestType.
|
||||
*/
|
||||
#define USB_DIR_OUT 0 /* to device */
|
||||
#define USB_DIR_IN 0x80 /* to host */
|
||||
|
||||
/*
|
||||
* USB types, the second of three bRequestType fields
|
||||
*/
|
||||
#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, the third of three bRequestType fields
|
||||
*/
|
||||
#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
|
||||
|
||||
/*
|
||||
* Standard requests, for the bRequest field of a SETUP packet.
|
||||
*
|
||||
* These are qualified by the bRequestType field, so that for example
|
||||
* TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
|
||||
* by a GET_STATUS request.
|
||||
*/
|
||||
#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
|
||||
|
||||
|
||||
/**
|
||||
* struct usb_ctrlrequest - SETUP data for a USB device control request
|
||||
* @bRequestType: matches the USB bmRequestType field
|
||||
* @bRequest: matches the USB bRequest field
|
||||
* @wValue: matches the USB wValue field (le16 byte order)
|
||||
* @wIndex: matches the USB wIndex field (le16 byte order)
|
||||
* @wLength: matches the USB wLength field (le16 byte order)
|
||||
*
|
||||
* This structure is used to send control requests to a USB device. It matches
|
||||
* the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the
|
||||
* USB spec for a fuller description of the different fields, and what they are
|
||||
* used for.
|
||||
*
|
||||
* Note that the driver for any interface can issue control requests.
|
||||
* For most devices, interfaces don't coordinate with each other, so
|
||||
* such requests may be made at any time.
|
||||
*/
|
||||
struct usb_ctrlrequest {
|
||||
__u8 bRequestType;
|
||||
__u8 bRequest;
|
||||
__u16 wValue;
|
||||
__u16 wIndex;
|
||||
__u16 wLength;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
|
||||
* (rarely) accepted by SET_DESCRIPTOR.
|
||||
*
|
||||
* Note that all multi-byte values here are encoded in little endian
|
||||
* byte order "on the wire". But when exposed through Linux-USB APIs,
|
||||
* they've been converted to cpu byte order.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Descriptor types ... USB 2.0 spec table 9.5
|
||||
*/
|
||||
#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_DEVICE_QUALIFIER 0x06
|
||||
#define USB_DT_OTHER_SPEED_CONFIG 0x07
|
||||
#define USB_DT_INTERFACE_POWER 0x08
|
||||
|
||||
/* All standard descriptors have these 2 fields at the beginning */
|
||||
struct usb_descriptor_header {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_DEVICE: Device descriptor */
|
||||
struct usb_device_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u16 idVendor;
|
||||
__u16 idProduct;
|
||||
__u16 bcdDevice;
|
||||
__u8 iManufacturer;
|
||||
__u8 iProduct;
|
||||
__u8 iSerialNumber;
|
||||
__u8 bNumConfigurations;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_DEVICE_SIZE 18
|
||||
|
||||
|
||||
/*
|
||||
* Device and/or Interface Class codes
|
||||
* as found in bDeviceClass or bInterfaceClass
|
||||
* and defined by www.usb.org documents
|
||||
*/
|
||||
#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_STILL_IMAGE 6
|
||||
#define USB_CLASS_PRINTER 7
|
||||
#define USB_CLASS_MASS_STORAGE 8
|
||||
#define USB_CLASS_HUB 9
|
||||
#define USB_CLASS_CDC_DATA 0x0a
|
||||
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
|
||||
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
|
||||
#define USB_CLASS_APP_SPEC 0xfe
|
||||
#define USB_CLASS_VENDOR_SPEC 0xff
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_CONFIG: Configuration descriptor information.
|
||||
*
|
||||
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
|
||||
* descriptor type is different. Highspeed-capable devices can look
|
||||
* different depending on what speed they're currently running. Only
|
||||
* devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
|
||||
* descriptors.
|
||||
*/
|
||||
struct usb_config_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wTotalLength;
|
||||
__u8 bNumInterfaces;
|
||||
__u8 bConfigurationValue;
|
||||
__u8 iConfiguration;
|
||||
__u8 bmAttributes;
|
||||
__u8 bMaxPower;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_CONFIG_SIZE 9
|
||||
|
||||
/* from config descriptor bmAttributes */
|
||||
#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */
|
||||
#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */
|
||||
#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_STRING: String descriptor */
|
||||
struct usb_string_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 wData[1]; /* UTF-16LE encoded */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* note that "string" zero is special, it holds language codes that
|
||||
* the device supports, not Unicode characters.
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_INTERFACE: Interface descriptor */
|
||||
struct usb_interface_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bInterfaceNumber;
|
||||
__u8 bAlternateSetting;
|
||||
__u8 bNumEndpoints;
|
||||
__u8 bInterfaceClass;
|
||||
__u8 bInterfaceSubClass;
|
||||
__u8 bInterfaceProtocol;
|
||||
__u8 iInterface;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_INTERFACE_SIZE 9
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB_DT_ENDPOINT: Endpoint descriptor */
|
||||
struct usb_endpoint_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u8 bEndpointAddress;
|
||||
__u8 bmAttributes;
|
||||
__u16 wMaxPacketSize;
|
||||
__u8 bInterval;
|
||||
|
||||
// NOTE: these two are _only_ in audio endpoints.
|
||||
// use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof.
|
||||
__u8 bRefresh;
|
||||
__u8 bSynchAddress;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define USB_DT_ENDPOINT_SIZE 7
|
||||
#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
|
||||
|
||||
|
||||
/*
|
||||
* 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_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
|
||||
struct usb_qualifier_descriptor {
|
||||
__u8 bLength;
|
||||
__u8 bDescriptorType;
|
||||
|
||||
__u16 bcdUSB;
|
||||
__u8 bDeviceClass;
|
||||
__u8 bDeviceSubClass;
|
||||
__u8 bDeviceProtocol;
|
||||
__u8 bMaxPacketSize0;
|
||||
__u8 bNumConfigurations;
|
||||
__u8 bRESERVED;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* USB 2.0 defines three speeds, here's how Linux identifies them */
|
||||
|
||||
enum usb_device_speed {
|
||||
USB_SPEED_UNKNOWN = 0, /* enumerating */
|
||||
USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */
|
||||
USB_SPEED_HIGH /* usb 2.0 */
|
||||
};
|
||||
|
||||
enum usb_device_state {
|
||||
/* NOTATTACHED isn't in the USB spec, and this state acts
|
||||
* the same as ATTACHED ... but it's clearer this way.
|
||||
*/
|
||||
USB_STATE_NOTATTACHED = 0,
|
||||
|
||||
/* the chapter 9 device states */
|
||||
USB_STATE_ATTACHED,
|
||||
USB_STATE_POWERED,
|
||||
USB_STATE_DEFAULT, /* limited function */
|
||||
USB_STATE_ADDRESS,
|
||||
USB_STATE_CONFIGURED, /* most functions */
|
||||
|
||||
USB_STATE_SUSPENDED
|
||||
|
||||
/* NOTE: there are actually four different SUSPENDED
|
||||
* states, returning to POWERED, DEFAULT, ADDRESS, or
|
||||
* CONFIGURED respectively when SOF tokens flow again.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /* __LINUX_USB_CH9_H */
|
||||
90
reactos/drivers/usb/cromwell/sys/BootUSB.c
Normal file
90
reactos/drivers/usb/cromwell/sys/BootUSB.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* USB support for XBOX, based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
void subsys_usb_init(void);
|
||||
void module_exit_usb_exit(void);
|
||||
|
||||
extern struct pci_device_id *module_table_pci_ids;
|
||||
|
||||
// straigth call...
|
||||
int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id);
|
||||
void usb_hcd_pci_remove (struct pci_dev *dev);
|
||||
|
||||
void XPADInit(void);
|
||||
void XPADRemove(void);
|
||||
void XRemoteInit(void);
|
||||
void XRemoteRemove(void);
|
||||
|
||||
extern int (*thread_handler)(void*);
|
||||
int (*hub_thread_handler)(void*);
|
||||
|
||||
extern int nousb;
|
||||
extern int xpad_num;
|
||||
|
||||
struct pci_dev xx_ohci_dev={
|
||||
.vendor = 0,
|
||||
.device = 0,
|
||||
.bus = NULL,
|
||||
.irq = 1, // currently not used...
|
||||
.slot_name = "OHCI",
|
||||
.dev = {.name = "PCI",.dma_mask=1},
|
||||
.base = {0xfed00000},
|
||||
.flags = {}
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStartUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
nousb=0;
|
||||
|
||||
init_wrapper();
|
||||
subsys_usb_init();
|
||||
hub_thread_handler=thread_handler;
|
||||
usb_hcd_pci_probe(&xx_ohci_dev, module_table_pci_ids);
|
||||
XPADInit();
|
||||
|
||||
XRemoteInit();
|
||||
|
||||
UsbKeyBoardInit();
|
||||
|
||||
for(n=0;n<30;n++) {
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void USBGetEvents(void)
|
||||
{
|
||||
inc_jiffies(1);
|
||||
do_all_timers();
|
||||
hub_thread_handler(NULL);
|
||||
handle_irqs(-1);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void BootStopUSB(void)
|
||||
{
|
||||
int n;
|
||||
|
||||
XPADRemove();
|
||||
XRemoteRemove();
|
||||
UsbKeyBoardRemove();
|
||||
|
||||
for(n=0;n<100;n++)
|
||||
{
|
||||
USBGetEvents();
|
||||
wait_ms(1);
|
||||
}
|
||||
|
||||
module_exit_usb_exit();
|
||||
usb_hcd_pci_remove(&xx_ohci_dev);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
4
reactos/drivers/usb/cromwell/sys/Makefile
Normal file
4
reactos/drivers/usb/cromwell/sys/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
O_TARGET := usbwrapper.o BootUSB.o linuxwrapper.o xpad.o xremote.o usbkey.o risefall.o
|
||||
|
||||
include $(TOPDIR)/Rules.make
|
||||
271
reactos/drivers/usb/cromwell/sys/linuxwrapper.c
Normal file
271
reactos/drivers/usb/cromwell/sys/linuxwrapper.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* USB support based on Linux kernel source
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Concept:
|
||||
*
|
||||
* 1) Forget all device interrupts, scheduling, semaphores, threads etc.
|
||||
* 1a) Forget all DMA and PCI helper functions
|
||||
* 2) Forget usbdevfs, procfs and ioctls
|
||||
* 3) Emulate OHCI interrupts and root hub timer by polling
|
||||
* 4) Emulate hub kernel thread by polling
|
||||
* 5) Emulate synchronous USB-messages (usb_*_msg) with busy waiting
|
||||
*
|
||||
* To be done:
|
||||
* 6) Remove code bloat
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
/* internal state */
|
||||
|
||||
static struct pci_dev *pci_probe_dev;
|
||||
extern int (*thread_handler)(void*);
|
||||
extern void* thread_parm;
|
||||
|
||||
struct my_irqs reg_irqs[MAX_IRQS];
|
||||
int num_irqs;
|
||||
int need_wakeup;
|
||||
|
||||
int my_jiffies;
|
||||
|
||||
struct timer_list *main_timer_list[MAX_TIMERS];
|
||||
struct dummy_process act_cur={0};
|
||||
struct dummy_process *my_current;
|
||||
|
||||
int (*thread_handler)(void*);
|
||||
void* thread_parm;
|
||||
|
||||
#define MAX_DRVS 8
|
||||
static struct device_driver *m_drivers[MAX_DRVS];
|
||||
static int drvs_num;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/*
|
||||
* Helper functions for top-level system
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
void init_wrapper(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
main_timer_list[n]=NULL;
|
||||
}
|
||||
|
||||
my_jiffies=0;
|
||||
num_irqs=0;
|
||||
my_current=&act_cur;
|
||||
pci_probe_dev=NULL;
|
||||
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
reg_irqs[n].handler=NULL;
|
||||
reg_irqs[n].irq=-1;
|
||||
}
|
||||
drvs_num=0;
|
||||
need_wakeup=0;
|
||||
for(n=0;n<MAX_DRVS;n++)
|
||||
m_drivers[n]=NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void handle_irqs(int irq)
|
||||
{
|
||||
int n;
|
||||
// printk("handle irqs\n");
|
||||
for(n=0;n<MAX_IRQS;n++)
|
||||
{
|
||||
if (reg_irqs[n].handler && (irq==reg_irqs[n].irq || irq==-1))
|
||||
reg_irqs[n].handler(reg_irqs[n].irq,reg_irqs[n].data,NULL);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void inc_jiffies(int n)
|
||||
{
|
||||
my_jiffies+=n;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void do_all_timers(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<MAX_TIMERS;n++)
|
||||
{
|
||||
if (main_timer_list[n] &&
|
||||
main_timer_list[n]->function && main_timer_list[n]->expires)
|
||||
{
|
||||
void (*function)(unsigned long)=main_timer_list[n]->function;
|
||||
unsigned long data=main_timer_list[n]->data;
|
||||
main_timer_list[n]->expires=0;
|
||||
|
||||
main_timer_list[n]=NULL; // remove timer
|
||||
// printk("do timer %i fn %p\n",n,function);
|
||||
|
||||
function(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Purpose: Remember thread procedure and data in global var
|
||||
int my_kernel_thread(int (*handler)(void*), void* parm, int flags)
|
||||
{
|
||||
thread_handler=handler;
|
||||
thread_parm=parm;
|
||||
return 42; // PID :-)
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device management
|
||||
* As simple as possible, but as complete as necessary ...
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* calls probe function for hotplug (which does device matching), this is the
|
||||
only link between usbcore and the registered device drivers! */
|
||||
int my_device_add(struct device *dev)
|
||||
{
|
||||
int n,found=0;
|
||||
// printk("drv_num %i %p %p\n",drvs_num,m_drivers[0]->probe,m_drivers[1]->probe);
|
||||
if (dev->driver)
|
||||
{
|
||||
if (dev->driver->probe)
|
||||
return dev->driver->probe(dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(n=0;n<drvs_num;n++)
|
||||
{
|
||||
if (m_drivers[n]->probe)
|
||||
{
|
||||
dev->driver=m_drivers[n];
|
||||
// printk("probe%i %p ",n,m_drivers[n]->probe);
|
||||
if (m_drivers[n]->probe(dev) == 0)
|
||||
{
|
||||
// return 0;
|
||||
found=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) return 0;
|
||||
}
|
||||
dev->driver=NULL;
|
||||
return -ENODEV;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_driver_register(struct device_driver *driver)
|
||||
{
|
||||
|
||||
if (drvs_num<MAX_DRVS)
|
||||
{
|
||||
// printk("driver_register %i: %p %p",drvs_num,driver,driver->probe);
|
||||
m_drivers[drvs_num++]=driver;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_device_unregister(struct device *dev)
|
||||
{
|
||||
if (dev->driver && dev->driver->remove)
|
||||
dev->driver->remove(dev);
|
||||
return 0;
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct device *my_get_device(struct device *dev)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_device_initialize(struct device *dev)
|
||||
{
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wake_up(void* p)
|
||||
{
|
||||
need_wakeup=1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* wait until woken up (only one wait allowed!) */
|
||||
int my_schedule_timeout(int x)
|
||||
{
|
||||
int wait=1;
|
||||
x+=10; // safety
|
||||
// printk("schedule_timeout %i\n",x);
|
||||
while(x>0)
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
if (need_wakeup)
|
||||
break;
|
||||
wait_ms(wait);
|
||||
inc_jiffies(wait);
|
||||
x-=wait;
|
||||
}
|
||||
need_wakeup=0;
|
||||
// printk("schedule DONE!!!!!!\n");
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void my_wait_for_completion(struct completion *x)
|
||||
{
|
||||
int n=100;
|
||||
// printk("wait for completion\n");
|
||||
while(!x->done && (n>0))
|
||||
{
|
||||
do_all_timers();
|
||||
#ifndef HAVE_IRQS
|
||||
handle_irqs(-1);
|
||||
|
||||
#endif
|
||||
wait_ms(10);
|
||||
n--;
|
||||
}
|
||||
// printk("wait for completion done %i\n",x->done);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Helper for pci_module_init
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_pci_module_init(struct pci_driver *x)
|
||||
{
|
||||
struct pci_dev *dev=pci_probe_dev;
|
||||
const struct pci_device_id *id=NULL;
|
||||
if (!pci_probe_dev)
|
||||
{
|
||||
printk(KERN_ERR "PCI device not set!\n");
|
||||
return 0;
|
||||
}
|
||||
x->probe(dev, id);
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
struct pci_dev *my_pci_find_slot(int a,int b)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_request_irq(unsigned int irq,
|
||||
int (*handler)(int,void *, struct pt_regs *),
|
||||
unsigned long mode, const char *desc, void *data)
|
||||
{
|
||||
if (num_irqs<MAX_IRQS)
|
||||
{
|
||||
reg_irqs[num_irqs].handler=handler;
|
||||
reg_irqs[num_irqs].irq=irq;
|
||||
reg_irqs[num_irqs].data=data;
|
||||
num_irqs++;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int my_free_irq(int irq, void* p)
|
||||
{
|
||||
/* No free... */
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
138
reactos/drivers/usb/cromwell/sys/risefall.c
Normal file
138
reactos/drivers/usb/cromwell/sys/risefall.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
#include "xremote.h"
|
||||
|
||||
// This is for the Xpad
|
||||
extern unsigned char xpad_button_history[7];
|
||||
|
||||
// This is for the Keyboard
|
||||
extern unsigned int current_keyboard_key;
|
||||
|
||||
int risefall_xpad_BUTTON(unsigned char selected_Button) {
|
||||
|
||||
int xpad_id;
|
||||
int match;
|
||||
extern int xpad_num;
|
||||
|
||||
// USB keyboard section
|
||||
|
||||
match=0;
|
||||
if (current_keyboard_key!=0) {
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A :
|
||||
if (current_keyboard_key == 0x28) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_B :
|
||||
if (current_keyboard_key == 0x29) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
if (current_keyboard_key == 0x52) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
if (current_keyboard_key == 0x51) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
if (current_keyboard_key == 0x50) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
if (current_keyboard_key == 0x4f) match=1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_keyboard_key=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox IR remote section
|
||||
|
||||
match=0;
|
||||
if (!remotekeyIsRepeat) {
|
||||
/* We only grab the key event when the button is first pressed.
|
||||
* If it's being held down, we ignore the multiple events this
|
||||
* generates */
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_KEY_A:
|
||||
if (current_remote_key == RC_KEY_SELECT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_UP:
|
||||
if (current_remote_key == RC_KEY_UP) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN:
|
||||
if (current_remote_key == RC_KEY_DOWN) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT:
|
||||
if (current_remote_key == RC_KEY_LEFT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT:
|
||||
if (current_remote_key == RC_KEY_RIGHT) match=1;
|
||||
break;
|
||||
case TRIGGER_XPAD_KEY_BACK:
|
||||
if (current_remote_key == RC_KEY_BACK) match=1;
|
||||
break;
|
||||
}
|
||||
if (match) {
|
||||
//A match occurred, so the event has now been processed
|
||||
//Clear it, and return success
|
||||
current_remote_key=0;
|
||||
remotekeyIsRepeat=0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Xbox controller section
|
||||
if (selected_Button < 6) {
|
||||
|
||||
unsigned char Button;
|
||||
|
||||
Button = XPAD_current[0].keys[selected_Button];
|
||||
|
||||
if ((Button>0x30)&&(xpad_button_history[selected_Button]==0)) {
|
||||
// Button Rising Edge
|
||||
xpad_button_history[selected_Button] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((Button==0x00)&&(xpad_button_history[selected_Button]==1)) {
|
||||
// Button Falling Edge
|
||||
xpad_button_history[selected_Button] = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((selected_Button > 5) & (selected_Button < 10) ) {
|
||||
|
||||
unsigned char Buttonmask;
|
||||
|
||||
switch (selected_Button) {
|
||||
case TRIGGER_XPAD_PAD_UP :
|
||||
Buttonmask = XPAD_PAD_UP;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_DOWN :
|
||||
Buttonmask = XPAD_PAD_DOWN;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_LEFT :
|
||||
Buttonmask = XPAD_PAD_LEFT;
|
||||
break;
|
||||
case TRIGGER_XPAD_PAD_RIGHT :
|
||||
Buttonmask = XPAD_PAD_RIGHT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Rising Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) != 0) & ((xpad_button_history[6]&Buttonmask) == 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return 1;
|
||||
}
|
||||
// Falling Edge
|
||||
if (((XPAD_current[0].pad&Buttonmask) == 0) & ((xpad_button_history[6]&Buttonmask) != 0)) {
|
||||
xpad_button_history[6] ^= Buttonmask; // Flip the Bit
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
10
reactos/drivers/usb/cromwell/sys/ros_wrapper.c
Normal file
10
reactos/drivers/usb/cromwell/sys/ros_wrapper.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
void wait_ms(int mils)
|
||||
{
|
||||
LARGE_INTEGER Interval;
|
||||
|
||||
Interval.QuadPart = -mils*10;
|
||||
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
|
||||
}
|
||||
123
reactos/drivers/usb/cromwell/sys/usbkey.c
Normal file
123
reactos/drivers/usb/cromwell/sys/usbkey.c
Normal file
@@ -0,0 +1,123 @@
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
#define keyboarddebug 0
|
||||
|
||||
#if keyboarddebug
|
||||
extern int printe(const char *szFormat, ...);
|
||||
int ycoffset = 0;
|
||||
#endif
|
||||
|
||||
unsigned int current_keyboard_key;
|
||||
|
||||
struct usb_kbd_info {
|
||||
struct urb *urb;
|
||||
unsigned char kbd_pkt[8];
|
||||
unsigned char old[8];
|
||||
|
||||
/*
|
||||
struct input_dev dev;
|
||||
struct usb_device *usbdev;
|
||||
struct urb irq, led;
|
||||
struct usb_ctrlrequest dr;
|
||||
unsigned char leds, newleds;
|
||||
char name[128];
|
||||
int open;
|
||||
*/
|
||||
};
|
||||
|
||||
static void usb_kbd_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct usb_kbd_info *kbd = urb->context;
|
||||
int i;
|
||||
|
||||
if (urb->status) return;
|
||||
|
||||
memcpy(kbd->kbd_pkt, urb->transfer_buffer, 8);
|
||||
|
||||
current_keyboard_key = kbd->kbd_pkt[2];
|
||||
|
||||
|
||||
#if keyboarddebug
|
||||
ycoffset += 15;
|
||||
ycoffset = ycoffset % 600;
|
||||
VIDEO_CURSOR_POSX=20;
|
||||
VIDEO_CURSOR_POSY=ycoffset;
|
||||
printe(" -%02x %02x %02x %02x %02x %02x\n",kbd->kbd_pkt[0],kbd->kbd_pkt[1],kbd->kbd_pkt[2],kbd->kbd_pkt[3],kbd->kbd_pkt[4],kbd->kbd_pkt[5]);
|
||||
#endif
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
|
||||
static int usb_kbd_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct usb_kbd_info *usbk;
|
||||
|
||||
int i, pipe, maxp;
|
||||
char *buf;
|
||||
|
||||
usbk=(struct usb_kbd_info *)kmalloc(sizeof(struct usb_kbd_info),0);
|
||||
if (!usbk) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
usbk->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
usbk->kbd_pkt, 8, usb_kbd_irq,
|
||||
usbk, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,usbk);
|
||||
#if keyboarddebug
|
||||
printe("USB Keyboard Connected\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void usb_kbd_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct usb_kbd_info *usbk = usb_get_intfdata (intf);
|
||||
usbprintk("Keyboard disconnected\n ");
|
||||
usb_unlink_urb(usbk->urb);
|
||||
usb_free_urb(usbk->urb);
|
||||
kfree(usbk);
|
||||
}
|
||||
|
||||
static struct usb_device_id usb_kbd_id_table [] = {
|
||||
{ USB_INTERFACE_INFO(3, 1, 1) },
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver usb_kbd_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "keyboard",
|
||||
.probe = usb_kbd_probe,
|
||||
.disconnect = usb_kbd_disconnect,
|
||||
.id_table = usb_kbd_id_table,
|
||||
};
|
||||
|
||||
void UsbKeyBoardInit(void)
|
||||
{
|
||||
|
||||
//current_remote_key=0;
|
||||
//sbprintk("Keyboard probe %p ",xremote_probe);
|
||||
if (usb_register(&usb_kbd_driver) < 0) {
|
||||
#if keyboarddebug
|
||||
printe("Unable to register Keyboard driver");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UsbKeyBoardRemove(void) {
|
||||
usb_deregister(&usb_kbd_driver);
|
||||
}
|
||||
65
reactos/drivers/usb/cromwell/sys/usbwrapper.c
Normal file
65
reactos/drivers/usb/cromwell/sys/usbwrapper.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Interface calls to BIOS
|
||||
*
|
||||
* 2003-06-21 Georg Acher (georg@acher.org)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "boot.h"
|
||||
#include <stdarg.h>
|
||||
#include "video.h"
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
// Output window for USB messages
|
||||
int usb_curs_x=0;
|
||||
int usb_curs_y=0;
|
||||
|
||||
void zxprintf(char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buffer[1024];
|
||||
int tmp_x, tmp_y;
|
||||
tmp_x=VIDEO_CURSOR_POSX;
|
||||
tmp_y=VIDEO_CURSOR_POSY;
|
||||
|
||||
VIDEO_CURSOR_POSX=usb_curs_x;
|
||||
VIDEO_CURSOR_POSY=usb_curs_y;
|
||||
|
||||
if ((VIDEO_CURSOR_POSY==0) || (VIDEO_CURSOR_POSY > (vmode.height -16)))
|
||||
{
|
||||
BootVideoClearScreen(&jpegBackdrop, 3*vmode.height/4,
|
||||
vmode.height);
|
||||
VIDEO_CURSOR_POSY=3*vmode.height/4;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsprintf(buffer,fmt,ap);
|
||||
//printk(buffer);
|
||||
va_end(ap);
|
||||
|
||||
usb_curs_x=VIDEO_CURSOR_POSX;
|
||||
usb_curs_y=VIDEO_CURSOR_POSY;
|
||||
VIDEO_CURSOR_POSX=tmp_x;
|
||||
VIDEO_CURSOR_POSY=tmp_y;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsnprintf(char *buffer, size_t s, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int zxsprintf(char *buffer, char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int x;
|
||||
va_start(ap, fmt);
|
||||
x=vsprintf(buffer,fmt,ap);
|
||||
va_end(ap);
|
||||
return x;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
183
reactos/drivers/usb/cromwell/sys/xpad.c
Normal file
183
reactos/drivers/usb/cromwell/sys/xpad.c
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Simple XPAD driver for XBOX
|
||||
*
|
||||
* (c) 2003-07-04, Georg Acher (georg@acher.org)
|
||||
*
|
||||
* Inspired by linux/drivers/usb/input/xpad.c
|
||||
* by Marko Friedemann <mfr@bmx-chemnitz.de>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
#include "config.h"
|
||||
|
||||
// history for the Rising - falling events
|
||||
unsigned char xpad_button_history[7];
|
||||
|
||||
/* Stores time and XPAD state */
|
||||
struct xpad_data XPAD_current[4];
|
||||
struct xpad_data XPAD_last[4];
|
||||
|
||||
struct xpad_info
|
||||
{
|
||||
struct urb *urb;
|
||||
int num;
|
||||
unsigned char data[32];
|
||||
};
|
||||
|
||||
int xpad_num=0;
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xpad_info *xpi = urb->context;
|
||||
unsigned char* data= urb->transfer_buffer;
|
||||
|
||||
// struct xpad_data *xp=&XPAD_current[xpi->num];
|
||||
// struct xpad_data *xpo=&XPAD_last[xpi->num];
|
||||
|
||||
/* This hack means the xpad event always gets posted to the
|
||||
* first xpad - avoids problems iterating over multiple xpads
|
||||
* as the xpi->num entries are not reused when xpads are
|
||||
* connected, then removed */
|
||||
|
||||
struct xpad_data *xp=&XPAD_current[0];
|
||||
struct xpad_data *xpo=&XPAD_last[0];
|
||||
|
||||
if (xpi->num<0 || xpi->num>3)
|
||||
return;
|
||||
|
||||
memcpy(xpo,xp,sizeof(struct xpad_data));
|
||||
|
||||
xp->stick_left_x=(short) (((short)data[13] << 8) | data[12]);
|
||||
xp->stick_left_y=(short) (((short)data[15] << 8) | data[14]);
|
||||
xp->stick_right_x=(short) (((short)data[17] << 8) | data[16]);
|
||||
xp->stick_right_y=(short) (((short)data[19] << 8) | data[18]);
|
||||
xp->trig_left= data[10];
|
||||
xp->trig_right= data[11];
|
||||
xp->pad = data[2]&0xf;
|
||||
xp->state = (data[2]>>4)&0xf;
|
||||
xp->keys[0] = data[4]; // a
|
||||
xp->keys[1] = data[5]; // b
|
||||
xp->keys[2] = data[6]; // x
|
||||
xp->keys[3] = data[7]; // y
|
||||
xp->keys[4] = data[8]; // black
|
||||
xp->keys[5] = data[9]; // white
|
||||
xp->timestamp=jiffies; // FIXME: A more uniform flowing time would be better...
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xpad_info *xpi;
|
||||
|
||||
xpi=kmalloc(sizeof(struct xpad_info),GFP_KERNEL);
|
||||
if (!xpi) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xpi->urb=urb;
|
||||
xpi->num=xpad_num;
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xpi->data, 32, xpad_irq,
|
||||
xpi, 32);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
|
||||
usb_set_intfdata(intf,xpi);
|
||||
usbprintk("XPAD #%i connected\n",xpad_num);
|
||||
#ifdef XPAD_VIBRA_STARTUP
|
||||
{
|
||||
// Brum Brum
|
||||
char data1[6]={0,6,0,120,0,120};
|
||||
char data2[6]={0,6,0,0,0,0};
|
||||
int dummy;
|
||||
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data1, 6, &dummy, 500);
|
||||
wait_ms(500);
|
||||
usb_bulk_msg(udev, usb_sndbulkpipe(udev,2),
|
||||
data2, 6, &dummy, 500);
|
||||
}
|
||||
#endif
|
||||
xpad_num++;
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void xpad_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xpad_info *xpi=usb_get_intfdata (intf);
|
||||
usb_unlink_urb(xpi->urb);
|
||||
usb_free_urb(xpi->urb);
|
||||
kfree(xpi);
|
||||
xpad_num--;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static struct usb_device_id xpad_ids [] = {
|
||||
{ USB_DEVICE(0x044f, 0x0f07) },//Thrustmaster, Inc. Controller
|
||||
{ USB_DEVICE(0x045e, 0x0202) },//Microsoft Xbox Controller
|
||||
{ USB_DEVICE(0x045e, 0x0285) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x045e, 0x0289) },//Microsoft Xbox Controller S
|
||||
{ USB_DEVICE(0x046d, 0xca88) },//Logitech Compact Controller for Xbox
|
||||
{ USB_DEVICE(0x05fd, 0x1007) },//???Mad Catz Controller???
|
||||
{ USB_DEVICE(0x05fd, 0x107a) },//InterAct PowerPad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4516) },//Mad Catz Control Pad
|
||||
{ USB_DEVICE(0x0738, 0x4522) },//Mad Catz LumiCON
|
||||
{ USB_DEVICE(0x0738, 0x4526) },//Mad Catz Control Pad Pro
|
||||
{ USB_DEVICE(0x0738, 0x4536) },//Mad Catz MicroCON
|
||||
{ USB_DEVICE(0x0738, 0x4556) },//Mad Catz Lynx Wireless Controller
|
||||
{ USB_DEVICE(0x0c12, 0x9902) },//HAMA VibraX - *FAULTY HARDWARE*
|
||||
{ USB_DEVICE(0x0e4c, 0x1097) },//Radica Gamester Controller
|
||||
{ USB_DEVICE(0x0e4c, 0x2390) },//Radica Games Jtech Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0003) },//Logic3 Freebird wireless Controller
|
||||
{ USB_DEVICE(0x0e6f, 0x0005) },//Eclipse wireless Controlle
|
||||
{ USB_DEVICE(0x0f30, 0x0202) },//Joytech Advanced Controller
|
||||
{ USB_DEVICE(0xffff, 0xffff) },//Chinese-made Xbox Controller
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
||||
static struct usb_driver xpad_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XPAD",
|
||||
.probe = xpad_probe,
|
||||
.disconnect = xpad_disconnect,
|
||||
.id_table = xpad_ids,
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADInit(void)
|
||||
{
|
||||
int n;
|
||||
for(n=0;n<4;n++)
|
||||
{
|
||||
memset(&XPAD_current[n], 0, sizeof(struct xpad_data));
|
||||
memset(&XPAD_last[n], 0, sizeof(struct xpad_data));
|
||||
}
|
||||
memset(&xpad_button_history, 0, sizeof(xpad_button_history));
|
||||
|
||||
usbprintk("XPAD probe %p ",xpad_probe);
|
||||
if (usb_register(&xpad_driver) < 0) {
|
||||
err("Unable to register XPAD driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void XPADRemove(void) {
|
||||
usb_deregister(&xpad_driver);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
142
reactos/drivers/usb/cromwell/sys/xremote.c
Normal file
142
reactos/drivers/usb/cromwell/sys/xremote.c
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: xremote.c,v 1.5 2004/11/22 19:10:57 davidmpye Exp $
|
||||
*
|
||||
* Copyright (c) 2002 Steven Toth <steve@toth.demon.co.uk>
|
||||
*
|
||||
* XBOX DVD dongle infrared device driver for the input driver suite.
|
||||
*
|
||||
* This work was derived from the usbkbd.c kernel module.
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 2002_08_31 - 0.1 - Initial release
|
||||
* 2002_09_02 - 0.2 - Added IOCTL support enabling user space administration
|
||||
* of the translation matrix.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../usb_wrapper.h"
|
||||
|
||||
|
||||
u16 current_remote_key;
|
||||
u8 remotekeyIsRepeat;
|
||||
|
||||
struct xremote_info
|
||||
{
|
||||
struct urb *urb;
|
||||
unsigned char irpkt[8];
|
||||
};
|
||||
|
||||
/* USB callback completion handler
|
||||
* Code in transfer_buffer is received as six unsigned chars
|
||||
* Example PLAY=00 06 ea 0a 40 00
|
||||
* The command is located in byte[2], the rest are ignored.
|
||||
* Key position is byte[4] bit0 (7-0 format) 0=down, 1=up
|
||||
* All other bits are unknown / now required.
|
||||
*/
|
||||
|
||||
static void xremote_irq(struct urb *urb, struct pt_regs *regs)
|
||||
{
|
||||
struct xremote_info *xri = urb->context;
|
||||
|
||||
if (urb->status) return;
|
||||
if (urb->actual_length < 6) return;
|
||||
|
||||
/* Messy/unnecessary, fix this */
|
||||
memcpy(xri->irpkt, urb->transfer_buffer, 6);
|
||||
|
||||
/* Set the key action based in the sent action */
|
||||
current_remote_key = ((xri->irpkt[2] & 0xff)<<8) | (xri->irpkt[3] & 0xff);
|
||||
|
||||
if (((xri->irpkt[4] & 0xff) + ((xri->irpkt[5] & 0xff ) << 8))>0x41) {
|
||||
remotekeyIsRepeat=0;
|
||||
}
|
||||
else remotekeyIsRepeat=1;
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
}
|
||||
|
||||
static int xremote_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct urb *urb;
|
||||
struct usb_device *udev = interface_to_usbdev (intf);
|
||||
struct usb_endpoint_descriptor *ep_irq_in;
|
||||
struct usb_endpoint_descriptor *ep_irq_out;
|
||||
struct xremote_info *xri;
|
||||
|
||||
xri=(struct xremote_info *)kmalloc(sizeof(struct xremote_info),0);
|
||||
if (!xri) return -1;
|
||||
|
||||
urb=usb_alloc_urb(0,0);
|
||||
if (!urb) return -1;
|
||||
|
||||
xri->urb=urb;
|
||||
|
||||
ep_irq_in = &intf->altsetting[0].endpoint[0].desc;
|
||||
usb_fill_int_urb(urb, udev,
|
||||
usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
|
||||
xri->irpkt, 8, xremote_irq,
|
||||
xri, 8);
|
||||
|
||||
usb_submit_urb(urb,GFP_ATOMIC);
|
||||
usb_set_intfdata(intf,xri);
|
||||
|
||||
usbprintk("DVD Remote connected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xremote_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct xremote_info *xri = usb_get_intfdata (intf);
|
||||
usbprintk("DVD Remote disconnected\n ");
|
||||
usb_unlink_urb(xri->urb);
|
||||
usb_free_urb(xri->urb);
|
||||
kfree(xri);
|
||||
}
|
||||
|
||||
static struct usb_device_id xremote_id_table [] = {
|
||||
{ USB_DEVICE(0x040b, 0x6521) }, /* Gamester Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x045e, 0x0284) }, /* Microsoft Xbox DVD Movie Playback Kit IR */
|
||||
{ USB_DEVICE(0x0000, 0x0000) }, // nothing detected - FAIL
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static struct usb_driver xremote_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "XRemote",
|
||||
.probe = xremote_probe,
|
||||
.disconnect = xremote_disconnect,
|
||||
.id_table = xremote_id_table,
|
||||
};
|
||||
|
||||
void XRemoteInit(void)
|
||||
{
|
||||
|
||||
current_remote_key=0;
|
||||
usbprintk("XRemote probe %p ",xremote_probe);
|
||||
if (usb_register(&xremote_driver) < 0) {
|
||||
err("Unable to register XRemote driver");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XRemoteRemove(void) {
|
||||
usb_deregister(&xremote_driver);
|
||||
}
|
||||
14
reactos/drivers/usb/cromwell/usb_wrapper.h
Normal file
14
reactos/drivers/usb/cromwell/usb_wrapper.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//#include <stdlib.h>
|
||||
//#include <ntos/types.h>
|
||||
//#include <ddk/extypes.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <debug.h>
|
||||
|
||||
void wait_ms(int mils);
|
||||
|
||||
#include "linux/linux_wrapper.h"
|
||||
#define __KERNEL__
|
||||
#undef CONFIG_PCI
|
||||
#define CONFIG_PCI
|
||||
|
||||
#include "linux/usb.h"
|
||||
Reference in New Issue
Block a user