[ros-diffs] [fireball] 14587: Initial version of uhci driver import
from Linux 2.5 kernel. Currently compiles and links,
but not usable (most probably will bugcheck when loaded).
fireball at svn.reactos.com
fireball at svn.reactos.com
Mon Apr 11 14:50:32 CEST 2005
Initial version of uhci driver import from Linux 2.5 kernel. Currently
compiles and links, but not usable (most probably will bugcheck when
loaded).
Also a lot of compile warnings exist.
I will update UsbStack wiki page sometime soon to reflect direction of
my work.
Modified: trunk/reactos/drivers/usb/cromwell/Makefile
Modified: trunk/reactos/drivers/usb/cromwell/core/usb.c
Modified: trunk/reactos/drivers/usb/cromwell/core/usbcore.def
Modified: trunk/reactos/drivers/usb/cromwell/linux/linux_wrapper.h
Modified: trunk/reactos/drivers/usb/cromwell/linux/usb.h
Modified: trunk/reactos/drivers/usb/cromwell/sys/linuxwrapper.c
Added: trunk/reactos/drivers/usb/cromwell/uhci/
Added: trunk/reactos/drivers/usb/cromwell/uhci/makefile
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-debug.c
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-hcd.c
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-hcd.h
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-hub.c
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci.def
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci.rc
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci_config.h
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci_main.c
_____
Modified: trunk/reactos/drivers/usb/cromwell/Makefile
--- trunk/reactos/drivers/usb/cromwell/Makefile 2005-04-11 08:41:58 UTC
(rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/Makefile 2005-04-11 12:49:25 UTC
(rev 14587)
@@ -6,7 +6,7 @@
include $(PATH_TO_TOP)/rules.mak
-DRIVERS = core host
+DRIVERS = core host uhci
all: $(DRIVERS)
_____
Modified: trunk/reactos/drivers/usb/cromwell/core/usb.c
--- trunk/reactos/drivers/usb/cromwell/core/usb.c 2005-04-11
08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/core/usb.c 2005-04-11
12:49:25 UTC (rev 14587)
@@ -688,7 +688,7 @@
*
* A pointer to the device with the incremented reference counter is
returned.
*/
-struct usb_device *usb_get_dev (struct usb_device *dev)
+struct usb_device STDCALL *usb_get_dev (struct usb_device *dev)
{
struct device *tmp;
_____
Modified: trunk/reactos/drivers/usb/cromwell/core/usbcore.def
--- trunk/reactos/drivers/usb/cromwell/core/usbcore.def 2005-04-11
08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/core/usbcore.def 2005-04-11
12:49:25 UTC (rev 14587)
@@ -8,6 +8,7 @@
usb_alloc_urb at 8
usb_free_urb at 4
usb_get_urb at 4
+usb_get_dev at 4
usb_submit_urb at 8
usb_unlink_urb at 4
usb_bus_init at 4
_____
Modified: trunk/reactos/drivers/usb/cromwell/linux/linux_wrapper.h
--- trunk/reactos/drivers/usb/cromwell/linux/linux_wrapper.h
2005-04-11 08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/linux/linux_wrapper.h
2005-04-11 12:49:25 UTC (rev 14587)
@@ -443,6 +443,8 @@
#define pci_unregister_driver(a) do {} while(0)
+#define pci_write_config_word(a,b,c) my_pci_write_config_word(a,b,c)
+
#define bus_register(a) do {} while(0)
#define bus_unregister(a) do {} while(0)
_____
Modified: trunk/reactos/drivers/usb/cromwell/linux/usb.h
--- trunk/reactos/drivers/usb/cromwell/linux/usb.h 2005-04-11
08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/linux/usb.h 2005-04-11
12:49:25 UTC (rev 14587)
@@ -272,7 +272,7 @@
#define to_usb_device(d) container_of(d, struct usb_device, dev)
extern struct usb_device STDCALL *usb_alloc_dev(struct usb_device
*parent, struct usb_bus *);
-extern struct usb_device *usb_get_dev(struct usb_device *dev);
+extern struct usb_device STDCALL *usb_get_dev(struct usb_device *dev);
extern void STDCALL usb_put_dev(struct usb_device *dev);
/* mostly for devices emulating SCSI over USB */
_____
Modified: trunk/reactos/drivers/usb/cromwell/sys/linuxwrapper.c
--- trunk/reactos/drivers/usb/cromwell/sys/linuxwrapper.c
2005-04-11 08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/sys/linuxwrapper.c
2005-04-11 12:49:25 UTC (rev 14587)
@@ -290,6 +290,16 @@
return NULL;
}
/*----------------------------------------------------------------------
--*/
+int my_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
+{
+ //dev->bus, dev->devfn, where, val
+ OHCI_DEVICE_EXTENSION *dev_ext = (OHCI_DEVICE_EXTENSION
*)dev->dev_ext;
+
+ //FIXME: Is returning this value correct?
+ //FIXME: Mixing pci_dev and win structs isn't a good thing at
all
+ return HalSetBusDataByOffset(PCIConfiguration, dev->bus->number,
dev_ext->SystemIoSlotNumber, &val, where, sizeof(val));
+}
+/*---------------------------------------------------------------------
---*/
int my_request_irq(unsigned int irq,
int (*handler)(int,void *, struct pt_regs *),
unsigned long mode, const char *desc, void
*data)
_____
Added: trunk/reactos/drivers/usb/cromwell/uhci/makefile
--- trunk/reactos/drivers/usb/cromwell/uhci/makefile 2005-04-11
08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/uhci/makefile 2005-04-11
12:49:25 UTC (rev 14587)
@@ -0,0 +1,16 @@
+PATH_TO_TOP = ../../../..
+
+TARGET_TYPE = export_driver
+
+TARGET_NAME = uhci
+
+TARGET_DDKLIBS = ntoskrnl.a usbcore.a
+
+TARGET_CFLAGS = -Wall -I$(PATH_TO_TOP)/ntoskrnl/include -DDEBUG_MODE
+
+TARGET_OBJECTS = \
+ uhci-hcd.o uhci_main.o ../sys/ros_wrapper.o ../sys/linuxwrapper.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
_____
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-debug.c
--- trunk/reactos/drivers/usb/cromwell/uhci/uhci-debug.c
2005-04-11 08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/uhci/uhci-debug.c
2005-04-11 12:49:25 UTC (rev 14587)
@@ -0,0 +1,616 @@
+/*
+ * UHCI-specific debugging code. Invaluable when something
+ * goes wrong, but don't get in my face.
+ *
+ * Kernel visible pointers are surrounded in []'s and bus
+ * visible pointers are surrounded in ()'s
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2001 Johannes Erdfelt
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#endif
+
+#include "uhci-hcd.h"
+
+/* Handle REALLY large printk's so we don't overflow buffers */
+static inline void lprintk(char *buf)
+{
+ char *p;
+
+ /* Just write one line at a time */
+ while (buf) {
+ p = strchr(buf, '\n');
+ if (p)
+ *p = 0;
+ printk(KERN_DEBUG "%s\n", buf);
+ buf = p;
+ if (buf)
+ buf++;
+ }
+}
+
+static inline int uhci_is_skeleton_qh(struct uhci_hcd *uhci, struct
uhci_qh *qh)
+{
+ int i;
+
+ for (i = 0; i < UHCI_NUM_SKELQH; i++)
+ if (qh == uhci->skelqh[i])
+ return 1;
+
+ return 0;
+}
+
+static int uhci_show_td(struct uhci_td *td, char *buf, int len, int
space)
+{
+ char *out = buf;
+ char *spid;
+ u32 status, token;
+
+ /* Try to make sure there's enough memory */
+ if (len < 160)
+ return 0;
+
+ status = td_status(td);
+ out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td,
le32_to_cpu(td->link));
+ out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
+ ((status >> 27) & 3),
+ (status & TD_CTRL_SPD) ? "SPD " : "",
+ (status & TD_CTRL_LS) ? "LS " : "",
+ (status & TD_CTRL_IOC) ? "IOC " : "",
+ (status & TD_CTRL_ACTIVE) ? "Active " : "",
+ (status & TD_CTRL_STALLED) ? "Stalled " : "",
+ (status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
+ (status & TD_CTRL_BABBLE) ? "Babble " : "",
+ (status & TD_CTRL_NAK) ? "NAK " : "",
+ (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+ (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
+ status & 0x7ff);
+
+ token = td_token(td);
+ switch (uhci_packetid(token)) {
+ case USB_PID_SETUP:
+ spid = "SETUP";
+ break;
+ case USB_PID_OUT:
+ spid = "OUT";
+ break;
+ case USB_PID_IN:
+ spid = "IN";
+ break;
+ default:
+ spid = "?";
+ break;
+ }
+
+ out += sprintf(out, "MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s)
",
+ token >> 21,
+ ((token >> 19) & 1),
+ (token >> 15) & 15,
+ (token >> 8) & 127,
+ (token & 0xff),
+ spid);
+ out += sprintf(out, "(buf=%08x)\n", le32_to_cpu(td->buffer));
+
+ return out - buf;
+}
+
+static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int
space)
+{
+ char *out = buf;
+ struct urb_priv *urbp;
+ struct list_head *head, *tmp;
+ struct uhci_td *td;
+ int i = 0, checked = 0, prevactive = 0;
+
+ /* Try to make sure there's enough memory */
+ if (len < 80 * 6)
+ return 0;
+
+ out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n",
space, "",
+ qh, le32_to_cpu(qh->link),
le32_to_cpu(qh->element));
+
+ if (qh->element & UHCI_PTR_QH)
+ out += sprintf(out, "%*s Element points to QH
(bug?)\n", space, "");
+
+ if (qh->element & UHCI_PTR_DEPTH)
+ out += sprintf(out, "%*s Depth traverse\n", space, "");
+
+ if (qh->element & cpu_to_le32(8))
+ out += sprintf(out, "%*s Bit 3 set (bug?)\n", space,
"");
+
+ if (!(qh->element & ~(UHCI_PTR_QH | UHCI_PTR_DEPTH)))
+ out += sprintf(out, "%*s Element is NULL (bug?)\n",
space, "");
+
+ if (!qh->urbp) {
+ out += sprintf(out, "%*s urbp == NULL\n", space, "");
+ goto out;
+ }
+
+ urbp = qh->urbp;
+
+ head = &urbp->td_list;
+ tmp = head->next;
+
+ td = list_entry(tmp, struct uhci_td, list);
+
+ if (cpu_to_le32(td->dma_handle) != (qh->element &
~UHCI_PTR_BITS))
+ out += sprintf(out, "%*s Element != First TD\n", space,
"");
+
+ while (tmp != head) {
+ struct uhci_td *td = list_entry(tmp, struct uhci_td,
list);
+
+ tmp = tmp->next;
+
+ out += sprintf(out, "%*s%d: ", space + 2, "", i++);
+ out += uhci_show_td(td, out, len - (out - buf), 0);
+
+ if (i > 10 && !checked && prevactive && tmp != head &&
+ debug <= 2) {
+ struct list_head *ntmp = tmp;
+ struct uhci_td *ntd = td;
+ int active = 1, ni = i;
+
+ checked = 1;
+
+ while (ntmp != head && ntmp->next != head &&
active) {
+ ntd = list_entry(ntmp, struct uhci_td,
list);
+
+ ntmp = ntmp->next;
+
+ active = td_status(ntd) &
TD_CTRL_ACTIVE;
+
+ ni++;
+ }
+
+ if (active && ni > i) {
+ out += sprintf(out, "%*s[skipped %d
active TD's]\n", space, "", ni - i);
+ tmp = ntmp;
+ td = ntd;
+ i = ni;
+ }
+ }
+
+ prevactive = td_status(td) & TD_CTRL_ACTIVE;
+ }
+
+ if (list_empty(&urbp->queue_list) || urbp->queued)
+ goto out;
+
+ out += sprintf(out, "%*sQueued QH's:\n", -space, "--");
+
+ head = &urbp->queue_list;
+ tmp = head->next;
+
+ while (tmp != head) {
+ struct urb_priv *nurbp = list_entry(tmp, struct
urb_priv,
+ queue_list);
+ tmp = tmp->next;
+
+ out += uhci_show_qh(nurbp->qh, out, len - (out - buf),
space);
+ }
+
+out:
+ return out - buf;
+}
+
+#define show_frame_num() \
+ if (!shown) { \
+ shown = 1; \
+ out += sprintf(out, "- Frame %d\n", i); \
+ }
+
+#ifdef CONFIG_PROC_FS
+static const char *qh_names[] = {
+ "skel_int128_qh", "skel_int64_qh",
+ "skel_int32_qh", "skel_int16_qh",
+ "skel_int8_qh", "skel_int4_qh",
+ "skel_int2_qh", "skel_int1_qh",
+ "skel_ls_control_qh", "skel_fs_control_qh",
+ "skel_bulk_qh", "skel_term_qh"
+};
+
+#define show_qh_name() \
+ if (!shown) { \
+ shown = 1; \
+ out += sprintf(out, "- %s\n", qh_names[i]); \
+ }
+
+static int uhci_show_sc(int port, unsigned short status, char *buf, int
len)
+{
+ char *out = buf;
+
+ /* Try to make sure there's enough memory */
+ if (len < 160)
+ return 0;
+
+ out += sprintf(out, " stat%d = %04x
%s%s%s%s%s%s%s%s%s%s\n",
+ port,
+ status,
+ (status & USBPORTSC_SUSP) ? " Suspend" : "",
+ (status & USBPORTSC_OCC) ? " OverCurrentChange" :
"",
+ (status & USBPORTSC_OC) ? " OverCurrent" : "",
+ (status & USBPORTSC_PR) ? " Reset" : "",
+ (status & USBPORTSC_LSDA) ? " LowSpeed" : "",
+ (status & USBPORTSC_RD) ? " ResumeDetect" : "",
+ (status & USBPORTSC_PEC) ? " EnableChange" : "",
+ (status & USBPORTSC_PE) ? " Enabled" : "",
+ (status & USBPORTSC_CSC) ? " ConnectChange" : "",
+ (status & USBPORTSC_CCS) ? " Connected" : "");
+
+ return out - buf;
+}
+
+static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len)
+{
+ char *out = buf;
+ unsigned int io_addr = uhci->io_addr;
+ unsigned short usbcmd, usbstat, usbint, usbfrnum;
+ unsigned int flbaseadd;
+ unsigned char sof;
+ unsigned short portsc1, portsc2;
+
+ /* Try to make sure there's enough memory */
+ if (len < 80 * 6)
+ return 0;
+
+ usbcmd = inw(io_addr + 0);
+ usbstat = inw(io_addr + 2);
+ usbint = inw(io_addr + 4);
+ usbfrnum = inw(io_addr + 6);
+ flbaseadd = inl(io_addr + 8);
+ sof = inb(io_addr + 12);
+ portsc1 = inw(io_addr + 16);
+ portsc2 = inw(io_addr + 18);
+
+ out += sprintf(out, " usbcmd = %04x
%s%s%s%s%s%s%s%s\n",
+ usbcmd,
+ (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
+ (usbcmd & USBCMD_CF) ? "CF " : "",
+ (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
+ (usbcmd & USBCMD_FGR) ? "FGR " : "",
+ (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
+ (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
+ (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+ (usbcmd & USBCMD_RS) ? "RS " : "");
+
+ out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n",
+ usbstat,
+ (usbstat & USBSTS_HCH) ? "HCHalted " : "",
+ (usbstat & USBSTS_HCPE) ? "HostControllerProcessError
" : "",
+ (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
+ (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
+ (usbstat & USBSTS_ERROR) ? "USBError " : "",
+ (usbstat & USBSTS_USBINT) ? "USBINT " : "");
+
+ out += sprintf(out, " usbint = %04x\n", usbint);
+ out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >>
10) & 1,
+ 0xfff & (4*(unsigned int)usbfrnum));
+ out += sprintf(out, " flbaseadd = %08x\n", flbaseadd);
+ out += sprintf(out, " sof = %02x\n", sof);
+ out += uhci_show_sc(1, portsc1, out, len - (out - buf));
+ out += uhci_show_sc(2, portsc2, out, len - (out - buf));
+
+ return out - buf;
+}
+
+static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp,
char *buf, int len)
+{
+ struct list_head *tmp;
+ char *out = buf;
+ int count = 0;
+
+ if (len < 200)
+ return 0;
+
+ out += sprintf(out, "urb_priv [%p] ", urbp);
+ out += sprintf(out, "urb [%p] ", urbp->urb);
+ out += sprintf(out, "qh [%p] ", urbp->qh);
+ out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
+ out += sprintf(out, "EP=%x(%s) ",
usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" :
"OUT"));
+
+ switch (usb_pipetype(urbp->urb->pipe)) {
+ case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO "); break;
+ case PIPE_INTERRUPT: out += sprintf(out, "INT "); break;
+ case PIPE_BULK: out += sprintf(out, "BLK "); break;
+ case PIPE_CONTROL: out += sprintf(out, "CTL "); break;
+ }
+
+ out += sprintf(out, "%s", (urbp->fsbr ? "FSBR " : ""));
+ out += sprintf(out, "%s", (urbp->fsbr_timeout ? "FSBR_TO " :
""));
+
+ if (urbp->urb->status != -EINPROGRESS)
+ out += sprintf(out, "Status=%d ", urbp->urb->status);
+ //out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
+ //out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
+
+ count = 0;
+ list_for_each(tmp, &urbp->td_list)
+ count++;
+ out += sprintf(out, "TDs=%d ",count);
+
+ if (urbp->queued)
+ out += sprintf(out, "queued\n");
+ else {
+ count = 0;
+ list_for_each(tmp, &urbp->queue_list)
+ count++;
+ out += sprintf(out, "queued URBs=%d\n", count);
+ }
+
+ return out - buf;
+}
+
+static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
+{
+ char *out = buf;
+ struct list_head *head, *tmp;
+ int count;
+
+ out += sprintf(out, "Main list URBs:");
+ if (list_empty(&uhci->urb_list))
+ out += sprintf(out, " Empty\n");
+ else {
+ out += sprintf(out, "\n");
+ count = 0;
+ head = &uhci->urb_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct urb_priv *urbp = list_entry(tmp, struct
urb_priv, urb_list);
+
+ out += sprintf(out, " %d: ", ++count);
+ out += uhci_show_urbp(uhci, urbp, out, len -
(out - buf));
+ tmp = tmp->next;
+ }
+ }
+
+ out += sprintf(out, "Remove list URBs:");
+ if (list_empty(&uhci->urb_remove_list))
+ out += sprintf(out, " Empty\n");
+ else {
+ out += sprintf(out, "\n");
+ count = 0;
+ head = &uhci->urb_remove_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct urb_priv *urbp = list_entry(tmp, struct
urb_priv, urb_list);
+
+ out += sprintf(out, " %d: ", ++count);
+ out += uhci_show_urbp(uhci, urbp, out, len -
(out - buf));
+ tmp = tmp->next;
+ }
+ }
+
+ out += sprintf(out, "Complete list URBs:");
+ if (list_empty(&uhci->complete_list))
+ out += sprintf(out, " Empty\n");
+ else {
+ out += sprintf(out, "\n");
+ count = 0;
+ head = &uhci->complete_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct urb_priv *urbp = list_entry(tmp, struct
urb_priv, urb_list);
+
+ out += sprintf(out, " %d: ", ++count);
+ out += uhci_show_urbp(uhci, urbp, out, len -
(out - buf));
+ tmp = tmp->next;
+ }
+ }
+
+ return out - buf;
+}
+
+static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int
len)
+{
+ unsigned long flags;
+ char *out = buf;
+ int i, j;
+ struct uhci_qh *qh;
+ struct uhci_td *td;
+ struct list_head *tmp, *head;
+
+ spin_lock_irqsave(&uhci->schedule_lock, flags);
+
+ out += sprintf(out, "HC status\n");
+ out += uhci_show_status(uhci, out, len - (out - buf));
+
+ out += sprintf(out, "Frame List\n");
+ for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+ int shown = 0;
+ td = uhci->fl->frame_cpu[i];
+ if (!td)
+ continue;
+
+ if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+ show_frame_num();
+ out += sprintf(out, " frame list does not
match td->dma_handle!\n");
+ }
+ show_frame_num();
+
+ head = &td->fl_list;
+ tmp = head;
+ do {
+ td = list_entry(tmp, struct uhci_td, fl_list);
+ tmp = tmp->next;
+ out += uhci_show_td(td, out, len - (out - buf),
4);
+ } while (tmp != head);
+ }
+
+ out += sprintf(out, "Skeleton QH's\n");
+
+ for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+ int shown = 0;
+
+ qh = uhci->skelqh[i];
+
+ if (debug > 1) {
+ show_qh_name();
+ out += uhci_show_qh(qh, out, len - (out - buf),
4);
+ }
+
+ /* Last QH is the Terminating QH, it's different */
+ if (i == UHCI_NUM_SKELQH - 1) {
+ if (qh->link != UHCI_PTR_TERM)
+ out += sprintf(out, " bandwidth
reclamation on!\n");
+
+ if (qh->element !=
cpu_to_le32(uhci->term_td->dma_handle))
+ out += sprintf(out, " skel_term_qh
element is not set to term_td!\n");
+
+ continue;
+ }
+
+ j = (i < 7) ? 7 : i+1; /* Next skeleton */
+ if (list_empty(&qh->list)) {
+ if (i < UHCI_NUM_SKELQH - 1) {
+ if (qh->link !=
+
(cpu_to_le32(uhci->skelqh[j]->dma_handle) | UHCI_PTR_QH)) {
+ show_qh_name();
+ out += sprintf(out, "
skeleton QH not linked to next skeleton QH!\n");
+ }
+ }
+
+ continue;
+ }
+
+ show_qh_name();
+
+ head = &qh->list;
+ tmp = head->next;
+
+ while (tmp != head) {
+ qh = list_entry(tmp, struct uhci_qh, list);
+
+ tmp = tmp->next;
+
+ out += uhci_show_qh(qh, out, len - (out - buf),
4);
+ }
+
+ if (i < UHCI_NUM_SKELQH - 1) {
+ if (qh->link !=
+ (cpu_to_le32(uhci->skelqh[j]->dma_handle) |
UHCI_PTR_QH))
+ out += sprintf(out, " last QH not
linked to next skeleton!\n");
+ }
+ }
+
+ if (debug > 2)
+ out += uhci_show_lists(uhci, out, len - (out - buf));
+
+ spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+
+ return out - buf;
+}
+
+#define MAX_OUTPUT (64 * 1024)
+
+static struct proc_dir_entry *uhci_proc_root = NULL;
+
+struct uhci_proc {
+ int size;
+ char *data;
+ struct uhci_hcd *uhci;
+};
+
+static int uhci_proc_open(struct inode *inode, struct file *file)
+{
+ const struct proc_dir_entry *dp = PDE(inode);
+ struct uhci_hcd *uhci = dp->data;
+ struct uhci_proc *up;
+ int ret = -ENOMEM;
+
+ lock_kernel();
+ up = kmalloc(sizeof(*up), GFP_KERNEL);
+ if (!up)
+ goto out;
+
+ up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
+ if (!up->data) {
+ kfree(up);
+ goto out;
+ }
+
+ up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT);
+
+ file->private_data = up;
+
+ ret = 0;
+out:
+ unlock_kernel();
+ return ret;
+}
+
+static loff_t uhci_proc_lseek(struct file *file, loff_t off, int
whence)
+{
+ struct uhci_proc *up;
+ loff_t new = -1;
+
+ lock_kernel();
+ up = file->private_data;
+
+ switch (whence) {
+ case 0:
+ new = off;
+ break;
+ case 1:
+ new = file->f_pos + off;
+ break;
+ }
+ if (new < 0 || new > up->size) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ unlock_kernel();
+ return (file->f_pos = new);
+}
+
+static ssize_t uhci_proc_read(struct file *file, char *buf, size_t
nbytes,
+ loff_t *ppos)
+{
+ struct uhci_proc *up = file->private_data;
+ unsigned int pos;
+ unsigned int size;
+
+ pos = *ppos;
+ size = up->size;
+ if (pos >= size)
+ return 0;
+ if (nbytes >= size)
+ nbytes = size;
+ if (pos + nbytes > size)
+ nbytes = size - pos;
+
+ if (!access_ok(VERIFY_WRITE, buf, nbytes))
+ return -EINVAL;
+
+ if (copy_to_user(buf, up->data + pos, nbytes))
+ return -EFAULT;
+
+ *ppos += nbytes;
+
+ return nbytes;
+}
+
+static int uhci_proc_release(struct inode *inode, struct file *file)
+{
+ struct uhci_proc *up = file->private_data;
+
+ kfree(up->data);
+ kfree(up);
+
+ return 0;
+}
+
+static struct file_operations uhci_proc_operations = {
+ .open = uhci_proc_open,
+ .llseek = uhci_proc_lseek,
+ .read = uhci_proc_read,
+// write: uhci_proc_write,
+ .release = uhci_proc_release,
+};
+#endif
_____
Added: trunk/reactos/drivers/usb/cromwell/uhci/uhci-hcd.c
--- trunk/reactos/drivers/usb/cromwell/uhci/uhci-hcd.c 2005-04-11
08:41:58 UTC (rev 14586)
+++ trunk/reactos/drivers/usb/cromwell/uhci/uhci-hcd.c 2005-04-11
12:49:25 UTC (rev 14587)
@@ -0,0 +1,2617 @@
+/*
+ * Universal Host Controller Interface driver for USB.
+ *
+ * Maintainer: Johannes Erdfelt <johannes at erdfelt.com>
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2002 Johannes Erdfelt, johannes at erdfelt.com
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Georg Acher, acher at in.tum.de
+ * (C) Copyright 1999 Deti Fliegl, deti at fliegl.de
+ * (C) Copyright 1999 Thomas Sailer, sailer at ife.ee.ethz.ch
+ * (C) Copyright 1999 Roman Weissgaerber, weissg at vienna.at
+ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI
interface
+ * support from usb-ohci.c by Adam Richter,
adam at yggdrasil.com).
+ * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ *
+ * Intel documents this fairly well, and as far as I know there
+ * are no royalties or anything like that, but even so there are
+ * people who decided that they want to do the same thing in a
+ * completely different way.
+ *
+ * WARNING! The USB documentation is downright evil. Most of it
+ * is just crap, written by a committee. You're better off ignoring
+ * most of it, the important stuff is:
+ * - the low-level protocol (fairly simple but lots of small details)
+ * - working around the horridness of the rest
+ */
+
+#if 0
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.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/unistd.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#ifdef CONFIG_USB_DEBUG
+#define DEBUG
+#else
+#undef DEBUG
+#endif
+#include <linux/usb.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#endif
+
+#include "uhci_config.h"
+#include "../usb_wrapper.h"
+#include "../core/hcd.h"
+#include "uhci-hcd.h"
+
+#if 0
+#include <linux/pm.h>
+#endif
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v2.1"
+#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt,
Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman
Weissgaerber"
+#define DRIVER_DESC "USB Universal Host Controller Interface driver"
+
+/*
+ * debug = 0, no debugging messages
+ * debug = 1, dump failed URB's except for stalls
+ * debug = 2, dump all failed URB's (including stalls)
+ * show all queues in /proc/driver/uhci/[pci_addr]
+ * debug = 3, show all TD's in URB's when dumping
+ */
+#ifdef DEBUG
+static int debug = 1;
+#else
+static int debug = 0;
+#endif
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debug level");
+static char *errbuf;
+#define ERRBUF_LEN (PAGE_SIZE * 8)
+
+#include "uhci-hub.c"
+#include "uhci-debug.c"
+
+static kmem_cache_t *uhci_up_cachep; /* urb_priv */
+
+static int uhci_get_current_frame_number(struct uhci_hcd *uhci);
+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
+static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb
*urb);
+
+static void hc_state_transitions(struct uhci_hcd *uhci);
+
+/* If a transfer is still active after this much time, turn off FSBR */
+#define IDLE_TIMEOUT (HZ / 20) /* 50 ms */
+#define FSBR_DELAY (HZ / 20) /* 50 ms */
+
+/* When we timeout an idle transfer for FSBR, we'll switch it over to
*/
+/* depth first traversal. We'll do it in groups of this number of TD's
*/
+/* to make sure it doesn't hog all of the bandwidth */
+#define DEPTH_INTERVAL 5
+
+/*
+ * Technically, updating td->status here is a race, but it's not really
a
+ * problem. The worst that can happen is that we set the IOC bit again
+ * generating a spurious interrupt. We could fix this by creating
another
+ * QH and leaving the IOC bit always set, but then we would have to
play
+ * games with the FSBR code to make sure we get the correct order in
all
+ * the cases. I don't think it's worth the effort
+ */
+static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->frame_list_lock, flags);
+ uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC);
+ spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->frame_list_lock, flags);
+ uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+ spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static inline void uhci_add_complete(struct uhci_hcd *uhci, struct urb
*urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->complete_list_lock, flags);
+ list_add_tail(&urbp->complete_list, &uhci->complete_list);
+ spin_unlock_irqrestore(&uhci->complete_list_lock, flags);
+}
+
+static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct
usb_device *dev)
+{
+ dma_addr_t dma_handle;
+ struct uhci_td *td;
+
+ td = pci_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
+ if (!td)
+ return NULL;
+
+ td->dma_handle = dma_handle;
+
+ td->link = UHCI_PTR_TERM;
+ td->buffer = 0;
+
+ td->frame = -1;
+ td->dev = dev;
+
+ INIT_LIST_HEAD(&td->list);
+ INIT_LIST_HEAD(&td->fl_list);
+
+ usb_get_dev(dev);
+
+ return td;
+}
+
+static inline void uhci_fill_td(struct uhci_td *td, __u32 status,
+ __u32 token, __u32 buffer)
+{
+ td->status = cpu_to_le32(status);
+ td->token = cpu_to_le32(token);
+ td->buffer = cpu_to_le32(buffer);
+}
+
+/*
+ * We insert Isochronous URB's directly into the frame list at the
beginning
+ */
+static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct
uhci_td *td, unsigned framenum)
+{
+ unsigned long flags;
+
+ framenum %= UHCI_NUMFRAMES;
+
+ spin_lock_irqsave(&uhci->frame_list_lock, flags);
+
+ td->frame = framenum;
+
+ /* Is there a TD already mapped there? */
+ if (uhci->fl->frame_cpu[framenum]) {
+ struct uhci_td *ftd, *ltd;
+
+ ftd = uhci->fl->frame_cpu[framenum];
+ ltd = list_entry(ftd->fl_list.prev, struct uhci_td,
fl_list);
+
+ list_add_tail(&td->fl_list, &ftd->fl_list);
+
+ td->link = ltd->link;
+ mb();
+ ltd->link = cpu_to_le32(td->dma_handle);
+ } else {
+ td->link = uhci->fl->frame[framenum];
+ mb();
+ uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
+ uhci->fl->frame_cpu[framenum] = td;
+ }
+
+ spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ /* If it's not inserted, don't remove it */
+ spin_lock_irqsave(&uhci->frame_list_lock, flags);
+ if (td->frame == -1 && list_empty(&td->fl_list))
+ goto out;
+
+ if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+ if (list_empty(&td->fl_list)) {
+ uhci->fl->frame[td->frame] = td->link;
+ uhci->fl->frame_cpu[td->frame] = NULL;
+ } else {
+ struct uhci_td *ntd;
+
+ ntd = list_entry(td->fl_list.next, struct
uhci_td, fl_list);
+ uhci->fl->frame[td->frame] =
cpu_to_le32(ntd->dma_handle);
+ uhci->fl->frame_cpu[td->frame] = ntd;
+ }
+ } else {
+ struct uhci_td *ptd;
+
+ ptd = list_entry(td->fl_list.prev, struct uhci_td,
fl_list);
+ ptd->link = td->link;
+ }
+
+ mb();
+ td->link = UHCI_PTR_TERM;
+
+ list_del_init(&td->fl_list);
+ td->frame = -1;
+
+out:
+ spin_unlock_irqrestore(&uhci->frame_list_lock, flags);
+}
+
+/*
+ * Inserts a td into qh list at the top.
+ */
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb,
u32 breadth)
+{
+ struct list_head *tmp, *head;
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td, *ptd;
+
+ if (list_empty(&urbp->td_list))
+ return;
+
+ head = &urbp->td_list;
+ tmp = head->next;
+
+ /* Ordering isn't important here yet since the QH hasn't been */
+ /* inserted into the schedule yet */
[truncated at 1000 lines; 3303 more skipped]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.reactos.org/pipermail/ros-diffs/attachments/20050411/3d6ce5b1/attachment.html
More information about the Ros-diffs
mailing list