[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[MiNT] [PATCH] NetUSBee usb driver



Please Alan commit this patch to add the NetUSBee driver for USB.

Thanks!
Index: sys/usb/src.km/ucd/Makefile
===================================================================
RCS file: /mint/freemint/sys/usb/src.km/ucd/Makefile,v
retrieving revision 1.1
diff -u -8 -p -r1.1 Makefile
--- sys/usb/src.km/ucd/Makefile	29 Apr 2011 11:39:28 -0000	1.1
+++ sys/usb/src.km/ucd/Makefile	22 May 2011 09:12:42 -0000
@@ -1,14 +1,14 @@
 #
 # Makefile for 
 #
 
 SHELL = /bin/sh
-SUBDIRS = ethernat
+SUBDIRS = ethernat netusbee
 
 srcdir = .
 top_srcdir = ../../..
 subdir = ucd
 
 default: all
 
 include $(top_srcdir)/CONFIGVARS
Index: sys/usb/src.km/ucd/netusbee/BINFILES
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/BINFILES
@@ -0,0 +1,4 @@
+# This file gets included by the Makefile in this directory to determine
+# the files that should go only into binary distributions.
+
+BINFILES = netusbee.ucd
Index: sys/usb/src.km/ucd/netusbee/COPYING
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: sys/usb/src.km/ucd/netusbee/EXTRAFILES
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/EXTRAFILES
@@ -0,0 +1,4 @@
+# This file gets included by the Makefile in this directory to determine
+# the files that should go only into source distributions.
+
+SRCFILES += BINFILES EXTRAFILES MISCFILES Makefile SRCFILES
Index: sys/usb/src.km/ucd/netusbee/MISCFILES
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/MISCFILES
@@ -0,0 +1,4 @@
+# This file gets included by the Makefile in this directory to determine
+# the files that should go both into source and binary distributions.
+
+MISCFILES = README
Index: sys/usb/src.km/ucd/netusbee/Makefile
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/Makefile
@@ -0,0 +1,41 @@
+#
+# Makefile for moose
+#
+
+SHELL = /bin/sh
+SUBDIRS = 
+
+srcdir = .
+top_srcdir = ../../../..
+subdir = netusbee
+
+default: all
+
+include $(top_srcdir)/CONFIGVARS
+include $(top_srcdir)/RULES
+include $(top_srcdir)/PHONY
+
+all-here: entry
+
+# default overwrites
+INCLUDES = -I$(top_srcdir)
+DEFINITIONS = -D__KERNEL_MODULE__ -DMODULE_NAME=netusbee $(XDD_DEFINITIONS) -DUSB_SUPPORT
+XDD_DEFINITIONS = 
+
+LD = $(CC) -nostdlib -Wl,--entry -Wl,_init
+LIBS = $(LIBKERN) -lgcc
+CPU = 030
+
+# default definitions
+SGENFILES = netusbee.ucd
+OBJS = $(SSOBJS:.s=.o)
+
+
+entry:
+	$(MAKE) netusbee.ucd
+	
+netusbee.ucd: isp116x-hcd.o $(OBJS) $(LIBKERNTARGET)
+	$(LD) $(CFLAGS) -o $@ $< $(OBJS) $(LIBS)
+
+
+include $(top_srcdir)/DEPENDENCIES
Index: sys/usb/src.km/ucd/netusbee/README
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/README
@@ -0,0 +1 @@
+
Index: sys/usb/src.km/ucd/netusbee/SRCFILES
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/SRCFILES
@@ -0,0 +1,14 @@
+# This file gets included by the Makefile in this directory to determine
+# the files that should go only into source distributions.
+
+HEADER = \
+	isp116x.h \
+	netusbee_int.h
+
+COBJS = \
+	isp116x-hcd.c
+
+SSOBJS = \
+	netusbee_int.S
+
+SRCFILES = $(HEADER) $(COBJS) $(SSOBJS)
Index: sys/usb/src.km/ucd/netusbee/isp116x-hcd.c
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/isp116x-hcd.c
@@ -0,0 +1,1985 @@
+/*
+ * Modified for Atari-NetUSBee by David Gálvez. 2010 - 2011
+ *
+ * ISP116x HCD (Host Controller Driver) for u-boot.
+ *
+ * Copyright (C) 2006-2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2006-2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Derived in part from the SL811 HCD driver "u-boot/drivers/usb/sl811_usb.c"
+ * (original copyright message follows):
+ *
+ *    (C) Copyright 2004
+ *    Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ *    This code is based on linux driver for sl811hs chip, source at
+ *    drivers/usb/host/sl811.c:
+ *
+ *    SL811 Host Controller Interface driver for USB.
+ *
+ *    Copyright (c) 2003/06, Courage Co., Ltd.
+ *
+ *    Based on:
+ *         1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
+ *           Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
+ *           Adam Richter, Gregory P. Smith;
+ *         2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
+ *         3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
+ *
+ *    [[GNU/GPL disclaimer]]
+ *
+ * and in part from AU1x00 OHCI HCD driver "u-boot/cpu/mips/au1x00_usb_ohci.c"
+ * (original copyright message follows):
+ *
+ *    URB OHCI HCD (Host Controller Driver) for USB on the AU1x00.
+ *
+ *    (C) Copyright 2003
+ *    Gary Jennejohn, DENX Software Engineering <garyj@denx.de>
+ *
+ *    [[GNU/GPL disclaimer]]
+ *
+ *    Note: Part of this code has been derived from linux
+ */
+
+#include <stddef.h>
+#include <mint/osbind.h> /* Setexc */
+
+#include "mint/mint.h"
+#include "libkern/libkern.h"
+#include "mint/dcntl.h"
+
+#include "../../config.h"
+#include "../../endian/io.h"
+#include "../../usb.h"
+#include "../ucd_defs.h"
+#include "netusbee_int.h"
+
+#define VER_MAJOR	0
+#define VER_MINOR	1
+#define VER_STATUS	
+
+#define MSG_VERSION	str (VER_MAJOR) "." str (VER_MINOR) str (VER_STATUS) 
+#define MSG_BUILDDATE	__DATE__
+
+#define MSG_BOOT	\
+	"\033p NetUSBee USB controller driver " MSG_VERSION " \033q\r\n"
+
+#define MSG_GREET	\
+	"Ported, mixed and shaken by David Galvez.\r\n" \
+	"Compiled " MSG_BUILDDATE ".\r\n\r\n"
+
+#define MSG_MINT	\
+	"\033pMiNT too old!\033q\r\n"
+
+#define MSG_FAILURE	\
+	"\7\r\nSorry, failed!\r\n\r\n"
+
+/*
+ * ISP116x chips require certain delays between accesses to its
+ * registers. The following timing options exist.
+ *
+ * 1. Configure your memory controller (the best)
+ * 2. Use ndelay (easiest, poorest). For that, enable the following macro.
+ *
+ * Value is in microseconds.
+ */
+#undef ISP116X_HCD_USE_UDELAY
+#ifdef ISP116X_HCD_USE_UDELAY
+# define UDELAY		1
+#endif
+
+/*
+ * On some (slowly?) machines an extra delay after data packing into
+ * controller's FIFOs is required, * otherwise you may get the following
+ * error:
+ *
+ *   uboot> usb start
+ *   (Re)start USB...
+ *   USB:   scanning bus for devices... isp116x: isp116x_submit_job: CTL:TIMEOUT
+ *   isp116x: isp116x_submit_job: ****** FIFO not ready! ******
+ *
+ *         USB device not responding, giving up (status=4)
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         isp116x: isp116x_submit_job: ****** FIFO not empty! ******
+ *         3 USB Device(s) found
+ *                scanning bus for storage devices... 0 Storage Device(s) found
+ *
+ * Value is in milliseconds.
+ */
+#define ISP116X_HCD_USE_EXTRA_DELAY
+#ifdef ISP116X_HCD_USE_EXTRA_DELAY
+# define EXTRA_DELAY	10	/* DEFAULT 2 */
+#endif
+
+/*
+ * Debug section
+ */
+
+#if 0
+# define DEV_DEBUG	1
+#endif
+
+#ifdef DEV_DEBUG
+
+# define FORCE(x)	
+# define ALERT(x)	KERNEL_ALERT x
+# define DEBUG(x)	KERNEL_DEBUG x
+# define TRACE(x)	KERNEL_TRACE x
+# define ASSERT(x)	assert x
+
+#else
+
+# define FORCE(x)	
+# define ALERT(x)	KERNEL_ALERT x
+# define DEBUG(x)	
+# define TRACE(x)	
+# define ASSERT(x)	assert x
+
+#endif
+
+/*
+ * Enable the following defines if you wish enable extra debugging messages.
+ */
+#ifdef DEV_DEBUG
+# define TRACE_EXTRA		/* enable tracing code */
+# define VERBOSE		/* verbose debugging messages */
+#endif
+
+#include "isp116x.h"
+
+#define DRIVER_VERSION	"02 Feb 2011"
+static const char hcd_name[] = "isp116x-hcd";
+
+/****************************************************************************/
+/* BEGIN kernel interface */
+
+struct kentry	*kentry;
+struct ucdinfo	*uinf;
+
+/* END kernel interface */
+/****************************************************************************/
+
+
+struct isp116x isp116x_dev;
+struct isp116x_platform_data isp116x_board;
+static long got_rhsc;		/* root hub status change */
+struct usb_device *devgone;	/* device which was disconnected */
+static long rh_devnum;		/* address of Root Hub endpoint */
+
+/*
+ * interrupt handling - bottom half
+ */
+void _cdecl 	netusbee_int 	(void);
+/*
+ * interrupt handling - top half
+ */
+static void	int_handle_tophalf	(PROC *p, long arg);
+
+/* 
+ *Function prototypes
+ */
+long 		isp116x_check_id	(struct isp116x *);
+static long 	isp116x_reset		(struct isp116x *);
+long		submit_bulk_msg		(struct usb_device *, unsigned long , void *, long);
+long		submit_control_msg	(struct usb_device *, unsigned long, void *,
+					 long, struct devrequest *);
+long		submit_int_msg		(struct usb_device *, unsigned long, void *, long, long);
+
+long _cdecl	init			(struct kentry *, struct ucdinfo *, char **);
+
+/*
+ * USB controller interface
+ */
+
+static long _cdecl	netusbee_open		(struct ucdif *);
+static long _cdecl	netusbee_close		(struct ucdif *);
+static long _cdecl	netusbee_ioctl		(struct ucdif *, short, long);
+
+static char lname[] = "NetUSBee USB controller driver for FreeMiNT\0";
+
+static struct ucdif netusbee_uif = 
+{
+	0,			/* *next */
+	USB_CONTRLL,		/* class */
+	lname,			/* lname */
+	"netusbee",		/* name */
+	0,			/* unit */
+	0,			/* flags */
+	netusbee_open,		/* open */
+	netusbee_close,		/* close */
+	0,			/* resrvd1 */
+	netusbee_ioctl,		/* ioctl */
+	0,			/* resrvd2 */
+//	submit_bulk_msg,
+//	submit_control_msg,
+//	submit_int_msg,
+//	{ NULL },
+};
+
+/* ------------------------------------------------------------------------- */
+
+#define ALIGN(x,a)	(((x)+(a)-1UL)&~((a)-1UL))
+#define min1_t(type,x,y)	\
+	({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+
+/* Galvez: added to avoid shadow warnings */
+#define min2_t(type,x,y)	\
+	({ type __a = (x); type __b = (y); __a < __b ? __a : __b; })
+
+/* ------------------------------------------------------------------------- */
+
+
+/* --- Debugging functions ------------------------------------------------- */
+
+#define isp116x_show_reg(d, r) {				\
+	if ((r) < 0x20)						\
+	{							\
+		DEBUG(("%12s[%02x]: %08lx", #r,			\
+			r, isp116x_read_reg32(d, r)));		\
+	}							\
+	else							\
+	{							\
+		DEBUG(("%12s[%02x]:     %04x", #r,		\
+			r, isp116x_read_reg16(d, r)));		\
+	}							\
+}
+
+#define isp116x_show_regs(d) {					\
+	isp116x_show_reg(d, HCREVISION);			\
+	isp116x_show_reg(d, HCCONTROL);				\
+	isp116x_show_reg(d, HCCMDSTAT);				\
+	isp116x_show_reg(d, HCINTSTAT);				\
+	isp116x_show_reg(d, HCINTENB);				\
+	isp116x_show_reg(d, HCFMINTVL);				\
+	isp116x_show_reg(d, HCFMREM);				\
+	isp116x_show_reg(d, HCFMNUM);				\
+	isp116x_show_reg(d, HCLSTHRESH);			\
+	isp116x_show_reg(d, HCRHDESCA);				\
+	isp116x_show_reg(d, HCRHDESCB);				\
+	isp116x_show_reg(d, HCRHSTATUS);			\
+	isp116x_show_reg(d, HCRHPORT1);				\
+	isp116x_show_reg(d, HCRHPORT2);				\
+	isp116x_show_reg(d, HCHWCFG);				\
+	isp116x_show_reg(d, HCDMACFG);				\
+	isp116x_show_reg(d, HCXFERCTR);				\
+	isp116x_show_reg(d, HCuPINT);				\
+	isp116x_show_reg(d, HCuPINTENB);			\
+	isp116x_show_reg(d, HCCHIPID);				\
+	isp116x_show_reg(d, HCSCRATCH);				\
+	isp116x_show_reg(d, HCITLBUFLEN);			\
+	isp116x_show_reg(d, HCATLBUFLEN);			\
+	isp116x_show_reg(d, HCBUFSTAT);				\
+	isp116x_show_reg(d, HCRDITL0LEN);			\
+	isp116x_show_reg(d, HCRDITL1LEN);			\
+}
+
+
+#if defined(TRACE_EXTRA)
+#if 0
+static long
+isp116x_get_current_frame_number(struct usb_device *usb_dev)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+
+	return isp116x_read_reg32(isp116x, HCFMNUM);
+}
+#endif
+
+static void
+dump_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		     long len, char *str)
+{
+#if defined(VERBOSE)
+	long i;
+	char build_str[64];
+	char buf[(len * 4) + 24 + 6];
+#endif
+	DEBUG(("%s URB:[%4lx] dev:%2ld,ep:%2ld-%c,type:%s,len:%ld stat:0x%lx",
+				str, isp116x_get_current_frame_number(dev), 
+				usb_pipedevice(pipe), usb_pipeendpoint(pipe),
+				usb_pipeout(pipe)  ? 'O' : 'I',
+				usb_pipetype(pipe) < 2 ?
+				(usb_pipeint(pipe) ? "INTR" : "ISOC") :
+				(usb_pipecontrol(pipe) ? "CTRL" : "BULK"),
+				len, dev->status));
+
+#if defined(VERBOSE)
+	sprintf(buf, sizeof(buf),"\0");
+	if (len > 0 && buffer)
+	{
+		sprintf(build_str, sizeof(build_str), __FILE__ ": data(%ld):", len);
+		strcat(buf, build_str);
+		for (i = 0; i < 16 && i < len; i++)
+		{
+			sprintf(build_str, sizeof(build_str), " %02x", ((unsigned char *) buffer)[i]);
+			strcat(buf, build_str);
+		}	
+		sprintf(build_str, sizeof(build_str), "%s\r\n", i < len ? "..." : "");
+		strcat(buf, build_str);
+		DEBUG((buf));
+	}
+#endif
+}
+
+# define PTD_DIR_STR(ptd)  ({char __c;		\
+	switch(PTD_GET_DIR(ptd)){		\
+	case 0:  __c = 's'; break;		\
+	case 1:  __c = 'o'; break;		\
+	default: __c = 'i'; break;		\
+	}; __c;})
+
+/*
+  Dump PTD info. The code documents the format
+  perfectly, right :)
+*/
+static inline void
+dump_ptd(struct ptd *ptd)
+{
+#if defined(VERBOSE)
+	long k;
+	char build_str[64];
+	char buf[64 + 4 * sizeof(struct ptd)];
+#endif
+
+	DEBUG(("PTD(ext) : cc:%x %d%c%d %d,%d,%d t:%x %x%x%x",
+	    PTD_GET_CC(ptd),
+	    PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd),
+	    PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd),
+	    PTD_GET_TOGGLE(ptd),
+	    PTD_GET_ACTIVE(ptd), PTD_GET_SPD(ptd), PTD_GET_LAST(ptd)));
+#if defined(VERBOSE)
+	sprintf(buf, sizeof(buf),"\0");
+	sprintf(build_str, sizeof(build_str), "isp116x: %s: PTD(byte): ", __FUNCTION__);
+	strcat(buf, build_str);
+	for (k = 0; k < sizeof(struct ptd); ++k) /* Galvez: note that bytes in the words are shown swapped */
+	{
+		sprintf(build_str, sizeof(build_str),"%02x ", ((unsigned char *) ptd)[k]);
+		strcat(buf, build_str);
+	}
+	DEBUG((buf));
+#endif
+}
+
+static inline void
+dump_ptd_data(struct ptd *ptd, unsigned char * buffer, long type)
+{
+#if defined(VERBOSE)
+	long k;
+	char build_str[64];
+	char buf[64 + 4 * PTD_GET_LEN(ptd)];
+	
+	sprintf(buf, sizeof(buf),"\0");
+	if (type == 0 /* 0ut data */ )
+	{
+		sprintf(build_str, sizeof(build_str), "isp116x: %s: out data: ", __FUNCTION__);
+		strcat(buf, build_str);
+		for (k = 0; k < PTD_GET_LEN(ptd); ++k)
+		{
+			sprintf(build_str, sizeof(build_str), "%02x ", ((unsigned char *) buffer)[k]);
+			strcat(buf, build_str);
+		}
+		DEBUG((buf));
+	}
+	if (type == 1 /* 1n data */ )
+	{
+		sprintf(build_str, sizeof(build_str), "isp116x: %s: in data: ", __FUNCTION__);
+		strcat(buf, build_str);
+		for (k = 0; k < PTD_GET_COUNT(ptd); ++k)
+		{
+			sprintf(build_str, sizeof(build_str), "%02x ", ((unsigned char *) buffer)[k]);
+			strcat(buf, build_str);
+		}
+		DEBUG((buf));
+	}
+	
+	
+	if (PTD_GET_LAST(ptd))
+	{
+		DEBUG(("--- last PTD ---"));
+	}
+#endif
+}
+
+#else
+
+# define dump_msg(dev, pipe, buffer, len, str)			do { } while (0)
+# define dump_pkt(dev, pipe, buffer, len, setup, str, small)	do {} while (0)
+
+# define dump_ptd(ptd)			do {} while (0)
+# define dump_ptd_data(ptd, buf, type)	do {} while (0)
+
+#endif /* TRACE_EXTRA */
+
+/* --- Virtual Root Hub ---------------------------------------------------- */
+
+/* Device descriptor */
+static unsigned char root_hub_dev_des[] =
+{
+	0x12,			/*  unsigned char  bLength; */
+	0x01,			/*  unsigned char  bDescriptorType; Device */
+	0x10,			/*  unsigned short bcdUSB; v1.1 */
+	0x01,
+	0x09,			/*  unsigned char  bDeviceClass; HUB_CLASSCODE */
+	0x00,			/*  unsigned char  bDeviceSubClass; */
+	0x00,			/*  unsigned char  bDeviceProtocol; */
+	0x08,			/*  unsigned char  bMaxPacketSize0; 8 Bytes */
+	0x00,			/*  unsigned short idVendor; */
+	0x00,
+	0x00,			/*  unsigned short idProduct; */
+	0x00,
+	0x00,			/*  unsigned short bcdDevice; */
+	0x00,
+	0x00,			/*  unsigned char  iManufacturer; */
+	0x01,			/*  unsigned char  iProduct; */
+	0x00,			/*  unsigned char  iSerialNumber; */
+	0x01			/*  unsigned char  bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static unsigned char root_hub_config_des[] =
+{
+	0x09,			/*  unsigned char  bLength; */
+	0x02,			/*  unsigned char  bDescriptorType; Configuration */
+	0x19,			/*  unsigned short wTotalLength; */
+	0x00,
+	0x01,			/*  unsigned char  bNumInterfaces; */
+	0x01,			/*  unsigned char  bConfigurationValue; */
+	0x00,			/*  unsigned char  iConfiguration; */
+	0x40,			/*  unsigned char  bmAttributes;
+				   Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+	0x00,			/*  unsigned char  MaxPower; */
+
+	/* interface */
+	0x09,			/*  unsigned char  if_bLength; */
+	0x04,			/*  unsigned char  if_bDescriptorType; Interface */
+	0x00,			/*  unsigned char  if_bInterfaceNumber; */
+	0x00,			/*  unsigned char  if_bAlternateSetting; */
+	0x01,			/*  unsigned char  if_bNumEndpoints; */
+	0x09,			/*  unsigned char  if_bInterfaceClass; HUB_CLASSCODE */
+	0x00,			/*  unsigned char  if_bInterfaceSubClass; */
+	0x00,			/*  unsigned char  if_bInterfaceProtocol; */
+	0x00,			/*  unsigned char  if_iInterface; */
+
+	/* endpoint */
+	0x07,			/*  unsigned char  ep_bLength; */
+	0x05,			/*  unsigned char  ep_bDescriptorType; Endpoint */
+	0x81,			/*  unsigned char  ep_bEndpointAddress; IN Endpoint 1 */
+	0x03,			/*  unsigned char  ep_bmAttributes; Interrupt */
+	0x00,			/*  unsigned short ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+	0x02,
+	0xff			/*  unsigned char  ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+	0x04,			/*  unsigned char  bLength; */
+	0x03,			/*  unsigned char  bDescriptorType; String-descriptor */
+	0x09,			/*  unsigned char  lang ID */
+	0x04,			/*  unsigned char  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+	0x22,			/*  unsigned char  bLength; */
+	0x03,			/*  unsigned char  bDescriptorType; String-descriptor */
+	'I',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'S',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'P',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'1',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'1',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'6',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'x',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	' ',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'R',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'o',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'o',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	't',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	' ',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'H',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'u',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+	'b',			/*  unsigned char  Unicode */
+	0,			/*  unsigned char  Unicode */
+};
+
+/*
+ * Hub class-specific descriptor is constructed dynamically
+ */
+
+/* --- Virtual root hub management functions ------------------------------- */
+
+static long
+rh_check_port_status(struct isp116x *isp116x)
+{
+	unsigned long temp, ndp, i;
+	long res;
+
+	res = -1;
+	temp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+	ndp = (temp & RH_A_NDP);
+	for (i = 0; i < ndp; i++)
+	{
+		temp = isp116x_read_reg32(isp116x, HCRHPORT1 + i);
+		/* check for a device disconnect */
+		if (((temp & (RH_PS_PESC | RH_PS_CSC)) ==
+		     (RH_PS_PESC | RH_PS_CSC)) && ((temp & RH_PS_CCS) == 0))
+		{
+			res = i;
+			break;
+		}
+	}
+	return res;
+}
+
+/* --- HC management functions --------------------------------------------- */
+
+/* Write len bytes to fifo, pad till 32-bit boundary
+ */
+static void
+write_ptddata_to_fifo(struct isp116x *isp116x, void *buf, long len)
+{
+	unsigned char *dp = (unsigned char *) buf;
+	unsigned short *dp2 = (unsigned short *) buf;
+	unsigned short w;
+	long quot = len % 4;
+	
+/* For NetUSBee, take the raw_write out in write functions, here we don't
+ * like that NetUSBee swap the bytes for us, so we swap them before we send
+ * them, then the bytes will arrive to the USB device with the correct positions
+ */
+ 	if ((unsigned long)dp2 & 1)
+	{
+		/* not aligned */
+		for (; len > 1; len -= 2)
+		{
+			w = *dp++;
+			w |= *dp++ << 8;
+			isp116x_write_data16(isp116x, w);
+		}
+		if (len)
+			isp116x_write_data16(isp116x, (unsigned short) * dp);
+	}
+	else
+	{
+		/* aligned */
+		for (; len > 1; len -= 2)
+			isp116x_write_data16(isp116x, *dp2++);
+		if (len)
+		{
+			isp116x_raw_write_data16(isp116x, 0xff & *((unsigned char *) dp2));
+		}
+	}
+	if (quot == 1 || quot == 2)
+		isp116x_write_data16(isp116x, 0);
+}
+
+/* Read len bytes from fifo and then read till 32-bit boundary
+ */
+static void
+read_ptddata_from_fifo(struct isp116x *isp116x, void *buf, long len)
+{
+	unsigned char *dp = (unsigned char *) buf;
+	unsigned short *dp2 = (unsigned short *) buf;
+	unsigned short w;
+	long quot = len % 4;
+
+/* For NetUSBee, take the raw_read out from read functions, we want to swap the bytes to
+ * read correct values because NetUSBee swapped the bytes by hardware before we read them
+ */
+	if ((unsigned long)dp2 & 1)
+	{
+		/* not aligned */
+		for (; len > 1; len -= 2)
+		{
+			w = isp116x_read_data16(isp116x);
+			*dp++ = w & 0xff;
+			*dp++ = (w >> 8) & 0xff;
+		}
+		if (len)
+			*dp = 0xff & isp116x_read_data16(isp116x);
+	}
+	else
+	{
+		/* aligned */
+		for (; len > 1; len -= 2)
+			*dp2++ = isp116x_read_data16(isp116x);
+		if (len)
+			*(unsigned char *) dp2 = 0xff & isp116x_raw_read_data16(isp116x);
+			
+	}
+	if (quot == 1 || quot == 2)
+		isp116x_read_data16(isp116x);
+}
+
+/* Write PTD's and data for scheduled transfers into the fifo ram.
+ * Fifo must be empty and ready
+ */
+static void
+pack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+		      unsigned long pipe, struct ptd *ptd, long n, void *data,
+		      long len)
+{
+	long buflen = n * sizeof(struct ptd) + len;
+	long i, done;
+
+	DEBUG(("--- pack buffer 0x%08lx - %ld bytes (fifo %ld) ---", data, len, buflen));
+	
+	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+	
+	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+	set_int_lvl7();
+	isp116x_write_addr(isp116x, HCATLPORT | ISP116x_WRITE_OFFSET);
+
+	done = 0;
+	for (i = 0; i < n; i++)
+	{
+		//DEBUG(("i=%ld - done=%ld - len=%d", i, done, PTD_GET_LEN(&ptd[i])));
+
+		/* For NetUSBee, use raw_write to don't swap bytes */
+//		dump_ptd(&ptd[i]);
+		isp116x_raw_write_data16(isp116x, ptd[i].count);
+		isp116x_raw_write_data16(isp116x, ptd[i].mps);
+		isp116x_raw_write_data16(isp116x, ptd[i].len);
+		isp116x_raw_write_data16(isp116x, ptd[i].faddr);
+
+//		dump_ptd_data(&ptd[i], (unsigned char *) data + done, 0);
+
+		/* This part is critical, disamble interrupts */
+//		set_int_lvl7();
+		write_ptddata_to_fifo(isp116x,
+				      (unsigned char *) data + done,
+				      PTD_GET_LEN(&ptd[i]));
+//		set_old_int_lvl();
+
+		done += PTD_GET_LEN(&ptd[i]);
+		set_old_int_lvl();
+	}
+}
+
+/* Read the processed PTD's and data from fifo ram back to URBs' buffers.
+ * Fifo must be full and done
+ */
+static long
+unpack_fifo(struct isp116x *isp116x, struct usb_device *dev,
+		       unsigned long pipe, struct ptd *ptd, long n, void *data,
+		       long len)
+{
+	long buflen = n * sizeof(struct ptd) + len;
+	long i, done, cc, ret;
+
+	isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_AIIEOT);
+	isp116x_write_reg16(isp116x, HCXFERCTR, buflen);
+	set_int_lvl7();
+	isp116x_write_addr(isp116x, HCATLPORT);
+
+	ret = TD_CC_NOERROR;
+	done = 0;
+	for (i = 0; i < n; i++)
+	{		
+		/* For NetUSBee, use raw_read to don't swap bytes */
+		ptd[i].count = isp116x_raw_read_data16(isp116x);
+		ptd[i].mps = isp116x_raw_read_data16(isp116x);
+		ptd[i].len = isp116x_raw_read_data16(isp116x);
+		ptd[i].faddr = isp116x_raw_read_data16(isp116x);
+//		dump_ptd(&ptd[i]);
+		
+		/* when cc is 15 the data has not being touch by the HC
+		 * so we have to read all to empty completly the buffer
+		 */
+		if (PTD_GET_COUNT(ptd) != 0 || PTD_GET_CC(ptd) == 15 
+			|| PTD_GET_CC(ptd) == 5 || PTD_GET_CC(ptd) == 6)
+		{
+			/* This part is critical, disamble interrupts */
+//			set_int_lvl7();
+			read_ptddata_from_fifo(isp116x,
+					       (unsigned char *) data + done,
+					       PTD_GET_LEN(&ptd[i]));
+//			set_old_int_lvl();
+		}
+
+		dump_ptd_data(&ptd[i], (unsigned char *) data + done, 1);
+
+		done += PTD_GET_LEN(&ptd[i]);
+	
+		cc = PTD_GET_CC(&ptd[i]);
+
+		/* Data underrun means basically that we had more buffer space than
+		 * the function had data. It is perfectly normal but upper levels have
+		 * to know how much we actually transferred.
+		 */
+		if (cc == TD_NOTACCESSED ||
+				(cc != TD_CC_NOERROR && (ret == TD_CC_NOERROR || ret == TD_DATAUNDERRUN)))
+			ret = cc;
+	}
+	DEBUG(("--- unpack buffer 0x%08lx - %ld bytes (fifo %ld) count: %d ---", data, len, buflen, PTD_GET_COUNT(ptd)));
+
+	set_old_int_lvl();
+
+	return ret;
+}
+
+/* Interrupt handling
+ */
+static long
+isp116x_interrupt(struct isp116x *isp116x)
+{
+	unsigned short irqstat;
+	unsigned long intstat;
+	long ret = 0;
+
+	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+	irqstat = isp116x_read_reg16(isp116x, HCuPINT);
+	isp116x_write_reg16(isp116x, HCuPINT, irqstat);
+	DEBUG((">>>>>> irqstat %x <<<<<<", irqstat));
+	
+	if (irqstat & HCuPINT_ATL)
+	{
+		DEBUG((">>>>>> HCuPINT_ATL <<<<<<"));
+		udelay(500);
+		ret = 1;
+	}
+
+	if (irqstat & HCuPINT_OPR)
+	{
+		intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
+		isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
+		DEBUG((">>>>>> HCuPINT_OPR %x <<<<<<", intstat));
+
+		if (intstat & HCINT_UE)
+		{
+			ALERT(("unrecoverable error, controller disabled"));
+
+			/* FIXME: be optimistic, hope that bug won't repeat
+			 * often. Make some non-interrupt context restart the
+			 * controller. Count and limit the retries though;
+			 * either hardware or software errors can go forever...
+			 */
+			isp116x_reset(isp116x);
+			ret = -1;
+			return -1;
+		}
+
+		if (intstat & HCINT_RHSC)
+		{
+			got_rhsc = 1;
+			ret = 1;
+			/* When root hub or any of its ports is going
+			   to come out of suspend, it may take more
+			   than 10ms for status bits to stabilize. */
+			mdelay(20);
+		}
+
+		if (intstat & HCINT_SO)
+		{
+			ALERT(("schedule overrun"));
+			ret = -1;
+		}
+
+		irqstat &= ~HCuPINT_OPR;
+	}
+
+	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+	return ret;
+}
+
+/* With one PTD we can transfer almost 1K in one go;
+ * HC does the splitting into endpoint digestible transactions
+ */
+struct ptd ptd[1];
+
+static inline long
+max_transfer_len(struct usb_device *dev, unsigned long pipe)
+{
+	unsigned mpck = (*uinf->usb_maxpacket)(dev, pipe);
+	
+	/* One PTD can transfer 1023 bytes but try to always
+	 * transfer multiples of endpoint buffer size
+	 */
+	return 1023 / mpck * mpck;
+}
+
+
+/* Do an USB transfer
+ */
+static long
+isp116x_submit_job(struct usb_device *dev, unsigned long pipe,
+			      long dir, void *buffer, long len)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+	long type = usb_pipetype(pipe);
+	long epnum = usb_pipeendpoint(pipe);
+	long max = (*uinf->usb_maxpacket)(dev, pipe);
+	long dir_out = usb_pipeout(pipe);
+	long speed_low = usb_pipeslow(pipe);
+	long i, done = 0, stat, timeout, cc;
+
+	/* 500 frames or 0.5s timeout when function is busy and NAKs transactions for a while */
+	long retries = 500;
+	short set_extra_delay = 0;
+
+	DEBUG(("------------------------------------------------"));
+	dump_msg(dev, pipe, buffer, len, "SUBMIT");
+	DEBUG(("------------------------------------------------"));
+	
+	if (len >= 1024)
+	{
+		ALERT(("Too big job"));
+		dev->status = USB_ST_CRC_ERR;
+		return -1;
+	}
+
+	if (isp116x->disabled)
+	{
+		ALERT(("EPIPE"));
+		dev->status = USB_ST_CRC_ERR;
+		return -1;
+	}
+
+	/* device pulled? Shortcut the action. */
+	if (devgone == dev)
+	{
+		ALERT(("ENODEV"));
+		dev->status = USB_ST_CRC_ERR;
+		return USB_ST_CRC_ERR;
+	}
+
+	if (!max)
+	{
+		ALERT(("pipesize for pipe %lx is zero", pipe));
+		dev->status = USB_ST_CRC_ERR;
+		return -1;
+	}
+
+	if (type == PIPE_ISOCHRONOUS)
+	{
+		ALERT(("isochronous transfers not supported"));
+		dev->status = USB_ST_CRC_ERR;
+		return -1;
+	}
+	
+	/* FIFO not empty? */
+	if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL)
+	{
+		DEBUG(("****** FIFO not empty! ******"));
+		dev->status = USB_ST_BUF_ERR;
+		return -1;
+	}
+
+retry:
+	isp116x_write_reg32(isp116x, HCINTSTAT, 0xff);
+	/* Prepare the PTD data */
+	ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK |
+		PTD_TOGGLE(usb_gettoggle(dev, epnum, dir_out));
+	ptd->mps = PTD_MPS(max) | PTD_SPD(speed_low) | PTD_EP(epnum) | PTD_LAST_MSK;
+	ptd->len = PTD_LEN(len) | PTD_DIR(dir);
+	ptd->faddr = PTD_FA(usb_pipedevice(pipe));
+
+	
+retry_same:
+
+	/* FIFO not empty? */
+	if (isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_FULL)
+	{
+		DEBUG(("****** FIFO not empty! 2 ******"));
+		dev->status = USB_ST_BUF_ERR;
+		return -1;
+	}
+
+	/* Pack data into FIFO ram */
+	pack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
+
+# ifdef EXTRA_DELAY
+//	mdelay(EXTRA_DELAY);
+# endif
+	if(set_extra_delay) 
+	{
+		mdelay(10);
+	}
+
+	/* Start the data transfer */
+
+	/* Allow more time for a BULK device to react - some are slow */
+	if (usb_pipebulk(pipe))
+		timeout = 5000; /* Galvez: default = 5000 */
+	else
+		timeout = 100; /* Galvez : netusbee : default = 100 */
+
+	/* Wait for it to complete */
+	for (;;)
+	{
+		/* Check whether the controller is done */
+		stat = isp116x_interrupt(isp116x);
+
+		if (stat < 0)
+		{
+			dev->status = USB_ST_CRC_ERR;
+			break;
+		}
+		if (stat > 0)
+			break;
+
+		/* Check the timeout */
+		if (--timeout)
+			udelay(1);
+		else
+		{
+			DEBUG(("CTL:TIMEOUT "));
+			stat = USB_ST_CRC_ERR;
+			break;
+		}
+	}
+
+	/* We got an Root Hub Status Change interrupt */
+	if (got_rhsc)
+	{
+		isp116x_show_regs(isp116x);
+
+		got_rhsc = 0;
+
+		/* Abuse timeout */
+		timeout = rh_check_port_status(isp116x);
+		if (timeout >= 0)
+		{
+			/*
+			 * FIXME! NOTE! AAAARGH!
+			 * This is potentially dangerous because it assumes
+			 * that only one device is ever plugged in!
+			 */
+			devgone = dev;
+		}
+	}
+
+
+	/* Ok, now we can read transfer status */
+
+	/* FIFO not ready? */
+	if (!(isp116x_read_reg16(isp116x, HCBUFSTAT) & HCBUFSTAT_ATL_DONE))
+	{
+		DEBUG(("****** FIFO not ready! ******"));
+		dev->status = USB_ST_BUF_ERR;
+		return -1;
+	}
+
+	/* Unpack data from FIFO ram */
+	cc = unpack_fifo(isp116x, dev, pipe, ptd, 1, buffer, len);
+
+	i = PTD_GET_COUNT(ptd);
+	done += i;
+	buffer = (char *)buffer + i;
+	len -= i;
+	
+	
+	/* There was some kind of real problem; Prepare the PTD again
+	 * and retry from the failed transaction on
+	 */
+	if (cc && cc != TD_NOTACCESSED && cc != TD_DATAUNDERRUN)
+	{
+		DEBUG(("PROBLEM cc: %ld", cc));
+		if (retries >= 100)
+		{
+			retries -= 100;
+			/* The chip will have toggled the toggle bit for the failed
+			 * transaction too. We have to toggle it back.
+			 */
+			usb_settoggle(dev, epnum, dir_out, !PTD_GET_TOGGLE(ptd));
+			goto retry;
+		}
+	}
+	/* "Normal" errors; TD_NOTACCESSED would mean in effect that the function have NAKed
+	 * the transactions from the first on for the whole frame. It may be busy and we retry
+	 * with the same PTD. PTD_ACTIVE (and not TD_NOTACCESSED) would mean that some of the
+	 * PTD didn't make it because the function was busy or the frame ended before the PTD
+	 * finished. We prepare the rest of the data and try again.
+	 */
+	else if ( cc == TD_NOTACCESSED ||  PTD_GET_ACTIVE(ptd) ||  ( cc != TD_DATAUNDERRUN && PTD_GET_COUNT(ptd) < PTD_GET_LEN(ptd)))
+	{
+		if (retries)
+		{
+			--retries;
+			if (cc == TD_NOTACCESSED && PTD_GET_ACTIVE(ptd) && !PTD_GET_COUNT(ptd))
+			{
+				set_extra_delay = 1;
+				goto retry_same;
+			}
+			DEBUG(("cc == TD_NOTACCESSED || PTD_GET_ACTIVE(ptd) retry"));
+			usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
+			goto retry;
+		}
+	}
+
+	if (cc != TD_CC_NOERROR && cc != TD_DATAUNDERRUN)
+	{
+		DEBUG(("****** completion code error %lx ******", cc));
+		switch (cc)
+		{
+			case TD_CC_BITSTUFFING:
+				dev->status = USB_ST_BIT_ERR;
+				break;
+			case TD_CC_STALL:
+				dev->status = USB_ST_STALLED;
+				break;
+			case TD_BUFFEROVERRUN:
+			case TD_BUFFERUNDERRUN:
+				dev->status = USB_ST_BUF_ERR;
+				break;
+			default:
+				dev->status = USB_ST_CRC_ERR;
+		}
+		return -cc;
+	}
+	else
+		usb_settoggle(dev, epnum, dir_out, PTD_GET_TOGGLE(ptd));
+
+	dump_msg(dev, pipe, buffer, len, "SUBMIT(ret)");
+
+	dev->status = 0;
+
+	return done;
+}
+
+/* Adapted from au1x00_usb_ohci.c
+ */
+static long
+isp116x_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+				 void *buffer, long transfer_len,
+				 struct devrequest *cmd)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+	unsigned long tmp = 0;
+
+	long leni = transfer_len;
+	long len = 0;
+	long stat = 0;
+	unsigned long datab[4];
+	unsigned char *data_buf = (unsigned char *) datab;
+	unsigned short bmRType_bReq;
+	unsigned short wValue;
+	unsigned short wIndex;
+	unsigned short wLength;
+
+	if (usb_pipeint(pipe))
+	{
+		ALERT(("Root-Hub submit IRQ: NOT implemented"));
+		return 0;
+	}
+
+	bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+	wValue = swap_16(cmd->value);
+	wIndex = swap_16(cmd->index);
+	wLength = swap_16(cmd->length);
+
+	DEBUG(("--- HUB ----------------------------------------"));
+	DEBUG(("submit rh urb, req=%x val=0x%x index=0x%x len=%d",
+	    bmRType_bReq, wValue, wIndex, wLength);
+	dump_msg(dev, pipe, buffer, transfer_len, "RH"));
+	DEBUG(("------------------------------------------------"));
+
+	switch (bmRType_bReq)
+	{
+		case RH_GET_STATUS:
+			DEBUG(("RH_GET_STATUS"));
+
+			*(unsigned short *) data_buf = swap_16(1);
+			len = 2;
+			break;
+
+		case RH_GET_STATUS | RH_INTERFACE:
+			DEBUG(("RH_GET_STATUS | RH_INTERFACE"));
+
+			*(unsigned short *) data_buf = swap_16(0);
+			len = 2;
+			break;
+
+		case RH_GET_STATUS | RH_ENDPOINT:
+			DEBUG(("RH_GET_STATUS | RH_ENDPOINT"));
+
+			*(unsigned short *) data_buf = swap_16(0);
+			len = 2;
+			break;
+
+		case RH_GET_STATUS | RH_CLASS:
+			DEBUG(("RH_GET_STATUS | RH_CLASS"));
+
+			tmp = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+			*(unsigned long *) data_buf = swap_32(tmp & ~(RH_HS_CRWE | RH_HS_DRWE));
+			len = 4;
+			break;
+
+		case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+			DEBUG(("RH_GET_STATUS | RH_OTHER | RH_CLASS"));
+
+			tmp = isp116x_read_reg32(isp116x, HCRHPORT1 + wIndex - 1);
+			*(unsigned long *) data_buf = swap_32(tmp);
+			isp116x_show_regs(isp116x);
+			len = 4;
+			break;
+
+		case RH_CLEAR_FEATURE | RH_ENDPOINT:
+			DEBUG(("RH_CLEAR_FEATURE | RH_ENDPOINT"));
+
+			switch (wValue)
+			{
+				case RH_ENDPOINT_STALL:
+				DEBUG(("C_HUB_ENDPOINT_STALL"));
+				len = 0;
+				break;
+			}
+			break;
+
+		case RH_CLEAR_FEATURE | RH_CLASS:
+			DEBUG(("RH_CLEAR_FEATURE | RH_CLASS"));
+
+			switch (wValue)
+			{
+			case RH_C_HUB_LOCAL_POWER:
+				DEBUG(("C_HUB_LOCAL_POWER"));
+				len = 0;
+				break;
+
+			case RH_C_HUB_OVER_CURRENT:
+				DEBUG(("C_HUB_OVER_CURRENT"));
+				isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC);
+				len = 0;
+				break;
+			}
+			break;
+
+		case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+			DEBUG(("RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS"));
+
+			switch (wValue)
+			{
+				case RH_PORT_ENABLE:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+						   		 RH_PS_CCS);
+					len = 0;
+					break;
+
+				case RH_PORT_SUSPEND:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+						   		 RH_PS_POCI);
+					len = 0;
+					break;
+
+				case RH_PORT_POWER:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+						   		RH_PS_LSDA);
+					len = 0;
+					break;
+
+				case RH_C_PORT_CONNECTION:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+							    RH_PS_CSC);
+					len = 0;
+					break;
+
+				case RH_C_PORT_ENABLE:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+					   			RH_PS_PESC);
+					len = 0;
+					break;
+
+				case RH_C_PORT_SUSPEND:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+							    RH_PS_PSSC);
+					len = 0;
+					break;
+
+				case RH_C_PORT_OVER_CURRENT:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+							    RH_PS_POCI);
+					len = 0;
+					break;
+
+				case RH_C_PORT_RESET:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+							    RH_PS_PRSC);
+					len = 0;
+					break;
+
+				default:
+					ALERT(("invalid wValue"));
+					stat = USB_ST_STALLED;
+			}
+
+			isp116x_show_regs(isp116x);
+			break;
+
+		case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+			DEBUG(("RH_SET_FEATURE | RH_OTHER | RH_CLASS"));
+
+			switch (wValue)
+			{
+				case RH_PORT_SUSPEND:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+					   			 RH_PS_PSS);
+					len = 0;
+					break;
+
+				case RH_PORT_RESET:
+					/* Spin until any current reset finishes */
+					while (1)
+					{
+					tmp = isp116x_read_reg32(isp116x,
+						       HCRHPORT1 + wIndex - 1);
+					if (!(tmp & RH_PS_PRS))
+						break;
+					mdelay(1);
+					}
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+					    			RH_PS_PRS);
+					mdelay(10);
+					len = 0;
+					break;
+
+				case RH_PORT_POWER:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+							    RH_PS_PPS);
+					len = 0;
+					break;
+
+				case RH_PORT_ENABLE:
+					isp116x_write_reg32(isp116x, HCRHPORT1 + wIndex - 1,
+					    RH_PS_PES);
+					len = 0;
+					break;
+
+				default:
+					ALERT(("invalid wValue"));
+					stat = USB_ST_STALLED;
+			}
+			isp116x_show_regs(isp116x);
+			break;
+
+		case RH_SET_ADDRESS:
+			DEBUG(("RH_SET_ADDRESS"));
+
+			rh_devnum = wValue;
+			len = 0;
+			break;
+
+		case RH_GET_DESCRIPTOR:
+			DEBUG(("RH_GET_DESCRIPTOR: %x, %d", wValue, wLength));
+
+			switch (wValue)
+			{
+				case (USB_DT_DEVICE << 8):	/* device descriptor */
+					len = min1_t(unsigned long,
+				    			leni, min2_t(unsigned long,
+							sizeof(root_hub_dev_des),
+							wLength));
+				data_buf = root_hub_dev_des;
+				break;
+
+				case (USB_DT_CONFIG << 8):	/* configuration descriptor */
+					len = min1_t(unsigned long,
+				  	 		leni, min2_t(unsigned long,
+							sizeof(root_hub_config_des),
+							wLength));
+					data_buf = root_hub_config_des;
+					break;
+
+				case ((USB_DT_STRING << 8) | 0x00):	/* string 0 descriptors */
+					len = min1_t(unsigned long,
+				    			leni, min2_t(unsigned long,
+							sizeof(root_hub_str_index0),
+							wLength));
+					data_buf = root_hub_str_index0;
+					break;
+
+				case ((USB_DT_STRING << 8) | 0x01):	/* string 1 descriptors */
+					len = min1_t(unsigned long,
+				    			leni, min2_t(unsigned long,
+							sizeof(root_hub_str_index1),
+							wLength));
+					data_buf = root_hub_str_index1;
+					break;
+
+				default:
+					ALERT(("invalid wValue"));
+					stat = USB_ST_STALLED;
+			}
+			break;
+
+		case RH_GET_DESCRIPTOR | RH_CLASS:
+			DEBUG(("RH_GET_DESCRIPTOR | RH_CLASS"));
+
+			tmp = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+			data_buf[0] = 0x09;	/* min length; */
+			data_buf[1] = 0x29;
+			data_buf[2] = tmp & RH_A_NDP;
+			data_buf[3] = 0;
+			if (tmp & RH_A_PSM)	/* per-port power switching? */
+				data_buf[3] |= 0x01;
+			if (tmp & RH_A_NOCP)	/* no overcurrent reporting? */
+				data_buf[3] |= 0x10;
+			else if (tmp & RH_A_OCPM)	/* per-port overcurrent rep? */
+				data_buf[3] |= 0x08;
+
+			/* Corresponds to data_buf[4-7] */
+			datab[1] = 0;
+			data_buf[5] = (tmp & RH_A_POTPGT) >> 24;
+
+			tmp = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+			data_buf[7] = tmp & RH_B_DR;
+			if (data_buf[2] < 7)
+				data_buf[8] = 0xff;
+			else
+			{
+				data_buf[0] += 2;
+				data_buf[8] = (tmp & RH_B_DR) >> 8;
+				data_buf[10] = data_buf[9] = 0xff;
+			}
+
+			len = min1_t(unsigned long, leni,
+			   		 min2_t(unsigned long, data_buf[0], wLength));
+			break;
+
+		case RH_GET_CONFIGURATION:
+			DEBUG(("RH_GET_CONFIGURATION"));
+
+			*(unsigned char *) data_buf = 0x01;
+			len = 1;
+			break;
+
+		case RH_SET_CONFIGURATION:
+			DEBUG(("RH_SET_CONFIGURATION"));
+
+			isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPSC);
+			len = 0;
+			break;
+
+		default:
+			ALERT(("*** *** *** unsupported root hub command *** *** ***"));
+			stat = USB_ST_STALLED;
+	}
+
+	len = min1_t(long, len, leni);
+	if (buffer != data_buf)
+		memcpy(buffer, data_buf, len);
+
+	dev->act_len = len;
+	dev->status = stat;
+	DEBUG(("dev act_len %ld, status %ld", dev->act_len, dev->status));
+
+	dump_msg(dev, pipe, buffer, transfer_len, "RH(ret)");
+
+	return stat;
+}
+
+/* --- Transfer functions -------------------------------------------------- */
+
+long
+submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		   long len, long interval)
+{
+	DEBUG(("dev=0x%lx pipe=%lx buf=0x%lx size=%d int=%d",
+		dev, pipe, buffer, len, interval));
+
+	return -1;
+}
+
+long
+submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		       long len, struct devrequest *setup)
+{
+	long devnum = usb_pipedevice(pipe);
+	long epnum = usb_pipeendpoint(pipe);
+	long max = max_transfer_len(dev, pipe);
+	long dir_in = usb_pipein(pipe);
+	long done, ret;
+	
+	
+	/* Control message is for the HUB? */
+	if (devnum == rh_devnum)
+		return isp116x_submit_rh_msg(dev, pipe, buffer, len, setup);
+
+	/* Ok, no HUB message so send the message to the device */
+
+	/* Setup phase */
+	DEBUG(("--- SETUP PHASE --------------------------------"));
+	usb_settoggle(dev, epnum, 1, 0);
+	
+	
+	ret = isp116x_submit_job(dev, pipe,
+				PTD_DIR_SETUP,
+				 setup, sizeof(struct devrequest));
+	if (ret < 0)
+	{
+		DEBUG(("control setup phase error (ret = %d", ret));
+		return -1;
+	}
+
+	/* Data phase */
+	DEBUG(("--- DATA PHASE ---------------------------------"));
+	done = 0;
+	usb_settoggle(dev, epnum, !dir_in, 1);
+	while (done < len)
+	{
+		ret = isp116x_submit_job(dev, pipe,
+					 dir_in ? PTD_DIR_IN : PTD_DIR_OUT,
+					 (unsigned char *) buffer + done,
+					 max > len - done ? len - done : max);
+		if (ret < 0)
+		{
+			DEBUG(("control data phase error (ret = %d)", ret));
+			return -1;
+		}
+		done += ret;
+
+		if (dir_in && ret < max)	/* short packet */
+			break;
+	}
+
+	/* Status phase */
+	DEBUG(("--- STATUS PHASE -------------------------------"));
+	usb_settoggle(dev, epnum, !dir_in, 1);
+	ret = isp116x_submit_job(dev, pipe,
+				 !dir_in ? PTD_DIR_IN : PTD_DIR_OUT, NULL, 0);
+	if (ret < 0)
+	{
+		DEBUG(("control status phase error (ret = %d", ret));
+		return -1;
+	}
+
+	dev->act_len = done;
+
+	dump_msg(dev, pipe, buffer, len, "DEV(ret)");
+
+	return done;
+}
+
+short flagy = 0;
+
+long
+submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+		    long len)
+{
+	long dir_out = usb_pipeout(pipe);
+	long max = max_transfer_len(dev, pipe);
+	long done, ret;
+	
+	DEBUG(("--- BULK ---------------------------------------"));
+	DEBUG(("dev=%ld pipe=%ld buf=0x%lx size=%d dir_out=%d",
+	      usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out));
+	done = 0;
+	while (done < len)
+	{
+
+		ret = isp116x_submit_job(dev, pipe,
+					 !dir_out ? PTD_DIR_IN : PTD_DIR_OUT,
+					 (unsigned char *) buffer + done,
+					 max > len - done ? len - done : max);
+
+		if (ret < 0)
+		{
+			DEBUG(("error on bulk message (ret = %d)", ret));
+			return -1;
+		}
+
+		done += ret;
+
+		if (!dir_out && ret < max)	/* short packet */
+			break;
+	}
+
+	dev->act_len = done;
+
+	return 0;
+}
+
+
+/* --- Basic functions ----------------------------------------------------- */
+
+
+# if 0
+/* GALVEZ: Test function */
+static long GALVEZ_test_function( struct isp116x *isp116x )
+{
+	short rwc;
+
+	rwc = isp116x_read_reg16(isp116x, HCCONTROL) & HCCONTROL_RWC;
+	if (rwc)
+	{
+		INFO ("remote wake-up supported \n\r");
+	}
+	return 0;
+
+}
+# endif
+
+static long
+isp116x_sw_reset(struct isp116x *isp116x)
+{
+	long retries = 15;
+	long ret = 0;
+
+	isp116x->disabled = 1;
+
+	isp116x_write_reg16(isp116x, HCSWRES, HCSWRES_MAGIC);
+	isp116x_write_reg32(isp116x, HCCMDSTAT, HCCMDSTAT_HCR);
+	
+	while (--retries)
+	{
+		/* It usually resets within 1 ms */
+		/* GALVEZ: not enough for TOS, try 7 ms */
+		mdelay(7);
+		if (!(isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR))
+			break;
+	}
+	
+	if (!retries)
+	{
+		DEBUG(("software reset timeout"));
+		ret = -1;
+	}
+
+# if 0
+	/* GALVEZ: DEBUG SOFTWARE RESET */
+		
+	retries = 5000;
+	
+	while (--retries){
+		if ((isp116x_read_reg32(isp116x, HCCMDSTAT) & HCCMDSTAT_HCR)) {
+			INFO ("HCR: 1 retries: %d\n\r",retries);
+		}
+	}
+# endif /* END DEBUG */
+
+	return ret;
+}
+
+static long
+isp116x_reset(struct isp116x *isp116x)
+{
+	unsigned long t;
+	unsigned short clkrdy = 0;
+	long ret, timeout = 1000;/* ms
+				* Galvez: 15 ms sometimes isn't enough,
+				* for NetUSBee under TOS ??????? increased to 150 ms 
+				*/ 
+
+	ret = isp116x_sw_reset(isp116x);
+
+	if (ret)
+		return ret;
+
+	for (t = 0; t < timeout; t++)
+	{
+		clkrdy = isp116x_read_reg16(isp116x, HCuPINT) & HCuPINT_CLKRDY;
+		if (clkrdy)
+			break;
+		mdelay(4); /* Default 1 ms */
+	}
+	if (!clkrdy)
+	{
+		DEBUG(("clock not ready after %ldms", timeout));
+		/* After sw_reset the clock won't report to be ready, if
+		   H_WAKEUP pin is high. */
+		DEBUG(("please make sure that the H_WAKEUP pin is pulled low!"));
+		ret = -1;
+	}
+	return ret;
+}
+
+static void 
+isp116x_stop(struct isp116x *isp116x)
+{
+	unsigned long val;
+
+	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+	/* Switch off ports' power, some devices don't come up
+	   after next 'start' without this */
+	val = isp116x_read_reg32(isp116x, HCRHDESCA);
+	val &= ~(RH_A_NPS | RH_A_PSM);
+	isp116x_write_reg32(isp116x, HCRHDESCA, val);
+	isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_LPS);
+	
+	isp116x_sw_reset(isp116x);
+}
+
+
+static void
+int_handle_tophalf(PROC *process, long arg)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+
+	if (isp116x->rhport[0] & RH_PS_CSC)
+	{
+		(*uinf->usb_rh_wakeup)();
+	}
+
+	if (isp116x->rhport[1] & RH_PS_CSC)
+	{
+		(*uinf->usb_rh_wakeup)();
+	}
+}
+
+
+void _cdecl netusbee_hub_events(void);
+
+void _cdecl
+netusbee_hub_events(void)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+	unsigned short irqstat;
+	unsigned long intstat;
+
+	/* Shut out all further interrupts */
+	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+	irqstat = isp116x_read_reg16(isp116x, HCuPINT);
+	
+//	set_old_int_lvl();
+	
+	if (irqstat & HCuPINT_OPR)
+	{
+		intstat = isp116x_read_reg32(isp116x, HCINTSTAT);
+		isp116x_write_reg32(isp116x, HCINTSTAT, intstat);
+
+                if (intstat & HCINT_RHSC) 
+		{
+			isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
+			isp116x->rhport[0] = isp116x_read_reg32(isp116x, HCRHPORT1);
+			isp116x->rhport[1] = isp116x_read_reg32(isp116x, HCRHPORT2);
+                        
+			addroottimeout (0L, int_handle_tophalf, 0x1);
+		}
+		isp116x_write_reg16(isp116x, HCuPINT, HCuPINT_OPR);
+         }
+	
+	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+//	set_int_lvl7();
+}
+
+void netusbee_hub_poll_thread(void *);
+void netusbee_hub_poll(PROC *proc, long dummy);
+
+void
+netusbee_hub_poll(PROC *proc, long dummy)
+{
+	wake(WAIT_Q, (long)&netusbee_hub_poll_thread);
+}
+
+void 
+netusbee_hub_poll_thread(void *dummy)
+{
+
+	/* join process group of loader, 
+	 * otherwise doesn't ends when shutingdown
+	 */
+
+	for (;;)
+	{
+		netusbee_hub_events();
+		addtimeout(1000L, netusbee_hub_poll);
+		sleep(WAIT_Q, (long)&netusbee_hub_poll_thread);
+	}
+
+	kthread_exit(0);
+}
+
+
+/*
+ *  Configure the chip. The chip must be successfully reset by now.
+ */
+static long 
+isp116x_start(struct isp116x *isp116x)
+{
+	struct isp116x_platform_data *board = isp116x->board;
+	unsigned long val;
+
+	/* Clear interrupt status and disable all interrupt sources */
+	isp116x_write_reg16(isp116x, HCuPINT, 0xff);
+	isp116x_write_reg16(isp116x, HCuPINTENB, 0);
+
+	isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
+	isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
+
+	/* Hardware configuration */
+	val = HCHWCFG_DBWIDTH(1);
+
+	if (board->int_act_high)
+		val |= HCHWCFG_INT_POL;
+	if (board->int_edge_triggered)
+		val |= HCHWCFG_INT_TRIGGER;
+	if (board->sel15Kres)
+		val |= HCHWCFG_15KRSEL;
+	/* Remote wakeup won't work without working clock */
+	if (board->remote_wakeup_enable)
+		val |= HCHWCFG_CLKNOTSTOP;
+	if (board->oc_enable)
+		val |= HCHWCFG_ANALOG_OC;
+	isp116x_write_reg16(isp116x, HCHWCFG, val);
+
+	/* --- Root hub configuration */
+	val = (25L << 24) & RH_A_POTPGT;
+	/* AN10003_1.pdf recommends RH_A_NPS (no power switching) to
+	   be always set. Yet, instead, we request individual port
+	   power switching. */
+	/* For NetUSBee ports are always powered */
+	val |= RH_A_NPS;
+//	val |= RH_A_PSM;
+	/* Report overcurrent per port */
+//	val |= RH_A_OCPM;
+	/* Overcurrent protection disable */
+	val |= RH_A_NOCP;
+	
+	isp116x_write_reg32(isp116x, HCRHDESCA, val);
+	isp116x->rhdesca = isp116x_read_reg32(isp116x, HCRHDESCA);
+
+	val = RH_B_PPCM;
+	isp116x_write_reg32(isp116x, HCRHDESCB, val);
+	isp116x->rhdescb = isp116x_read_reg32(isp116x, HCRHDESCB);
+
+	val = 0;
+	if (board->remote_wakeup_enable)
+		val |= RH_HS_DRWE;
+	isp116x_write_reg32(isp116x, HCRHSTATUS, val);
+	isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
+
+	isp116x_write_reg32(isp116x, HCFMINTVL, 0x27782edf);
+
+	/* Go operational */
+	val = HCCONTROL_USB_OPER;
+	if (board->remote_wakeup_enable)
+		val |= HCCONTROL_RWE;
+	isp116x_write_reg32(isp116x, HCCONTROL, val);
+
+	/* Disable ports to avoid race in device enumeration */
+	isp116x_write_reg32(isp116x, HCRHPORT1, RH_PS_CCS);
+	isp116x_write_reg32(isp116x, HCRHPORT2, RH_PS_CCS);
+	
+	isp116x->intenb = HCINT_MIE | HCINT_RHSC; /*  HCINT_UE */
+	isp116x_write_reg32(isp116x, HCINTENB, isp116x->intenb);
+//	isp116x->irqenb = HCuPINT_OPR; /* | HCuPINT_ATL;  | HCuPINT_SUSP */
+//	isp116x_write_reg16(isp116x, HCuPINTENB, isp116x->irqenb);
+//	val = isp116x_read_reg16(isp116x, HCHWCFG);
+//	val |= HCHWCFG_INT_ENABLE;
+//	isp116x_write_reg16(isp116x, HCHWCFG, val);
+
+	long r;
+	r = kthread_create(NULL, netusbee_hub_poll_thread, NULL, NULL, "hubpoll");
+	
+	if (r)
+	{
+		/* XXX todo -> exit gracefully */
+		//DEBUG((/*0000000a*/"can't create NetUSBee kernel thread"));
+	}
+
+	isp116x_show_regs(isp116x);
+
+	isp116x->disabled = 0;
+
+	return 0;
+}
+
+/* --- Inteface functions -------------------------------------------------- */
+
+static long _cdecl
+netusbee_open(struct ucdif *u)
+{
+	return E_OK;
+}
+
+static long _cdecl
+netusbee_close(struct ucdif *u)
+{
+	return E_OK;
+}
+
+static long _cdecl
+netusbee_ioctl(struct ucdif *u, short cmd, long arg)
+{
+	long ret = E_OK;
+
+	switch (cmd)
+	{
+		case FS_INFO:
+		{
+			*(long *)arg = (((long)VER_MAJOR << 16) | VER_MINOR);
+			break;
+		}
+		case LOWLEVEL_INIT :
+		{
+			ret = usb_lowlevel_init (0, NULL);
+			break;
+		}
+		case LOWLEVEL_STOP :
+		{
+			ret = usb_lowlevel_stop ();
+			break;
+		}
+		case SUBMIT_CONTROL_MSG :
+		{
+			struct control_msg *ctrl_msg = (struct control_msg *)arg;
+			
+			ret = submit_control_msg (ctrl_msg->dev, ctrl_msg->pipe,
+			 		    ctrl_msg->data, ctrl_msg->size, ctrl_msg->setup);	
+			break;
+		}
+		case SUBMIT_BULK_MSG :
+		{
+			struct bulk_msg *bulk_msg = (struct bulk_msg *)arg;
+
+			ret = submit_bulk_msg (bulk_msg->dev, bulk_msg->pipe,
+				         bulk_msg->data, bulk_msg->len);			
+
+			break;
+		}
+		case SUBMIT_INT_MSG :
+		{
+			struct int_msg *int_msg = (struct int_msg *)arg;
+
+			ret = submit_int_msg(int_msg->dev, int_msg->pipe,
+				       int_msg->buffer, int_msg->transfer_len, 
+				       int_msg->interval);
+
+			break;
+		}
+		default:
+		{
+			return ENOSYS;
+		}
+	}	
+	return ret;
+}
+
+
+
+/* --- Init functions ------------------------------------------------------ */
+
+long
+isp116x_check_id(struct isp116x *isp116x)
+{
+	unsigned short val;
+
+	val = isp116x_read_reg16(isp116x, HCCHIPID);
+	DEBUG(("chip ID: %x", val));
+
+	if ((val & HCCHIPID_MASK) != HCCHIPID_MAGIC)
+	{
+		ALERT(("invalid chip ID %04x", val));
+		return -1;
+	}
+
+	return 0;
+}
+
+
+long 
+usb_lowlevel_init(long dummy1, const struct pci_device_id *dummy2)
+{
+//	unsigned short val;
+
+	struct isp116x *isp116x = &isp116x_dev;
+
+	got_rhsc = rh_devnum = 0;
+
+	/* Init device registers addr */
+	isp116x->addr_reg = (unsigned short *) ISP116X_HCD_ADDR;
+	isp116x->data_reg = (unsigned short *) ISP116X_HCD_DATA;
+
+	/* Setup specific board settings */
+#ifdef ISP116X_HCD_INT_ACT_HIGH
+	isp116x_board.int_act_high = 1;
+#endif
+#ifdef ISP116X_HCD_INT_EDGE_TRIGGERED
+	isp116x_board.int_edge_triggered = 1;
+#endif
+#define ISP116X_HCD_SEL15kRES
+#ifdef ISP116X_HCD_SEL15kRES
+	isp116x_board.sel15Kres = 1;
+#endif
+#define ISP116X_HCD_OC_ENABLE
+#ifdef ISP116X_HCD_OC_ENABLE
+	isp116x_board.oc_enable = 1;
+#endif
+#ifdef ISP116X_HCD_REMOTE_WAKEUP_ENABLE
+	isp116x_board.remote_wakeup_enable = 1;
+#endif
+	isp116x->board = &isp116x_board;
+
+	/* Try to get ISP116x silicon chip ID */
+	if (isp116x_check_id(isp116x) < 0)
+		return (-1);
+		
+	isp116x->disabled = 1;
+	isp116x->sleeping = 0;
+
+	isp116x_reset(isp116x);
+	isp116x_start(isp116x);
+
+	return 0;
+}
+
+long 
+usb_lowlevel_stop(void)
+{
+	struct isp116x *isp116x = &isp116x_dev;
+
+	if (!isp116x->disabled)
+		isp116x_stop(isp116x);
+
+	return 0;
+}
+
+long _cdecl
+init(struct kentry *k, struct ucdinfo *uinfo, char **reason)
+{
+	long ret;
+
+	kentry	= k;
+	uinf	= uinfo;
+
+	if (check_kentry_version())
+		return -1;
+
+	c_conws (MSG_BOOT);
+	c_conws (MSG_GREET);
+	DEBUG (("%s: enter init", __FILE__));
+
+	ret = (*uinf->ucd_register)(&netusbee_uif);
+	if (ret)
+	{
+		DEBUG (("%s: ucd register failed!", __FILE__));
+		return 1;
+	}
+
+	DEBUG (("%s: ucd register ok", __FILE__));
+	return 0;
+}
Index: sys/usb/src.km/ucd/netusbee/isp116x.h
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/isp116x.h
@@ -0,0 +1,560 @@
+/*
+ * Modified for Atari-NetUSBee by David Gálvez. 2010 - 2011
+ *
+ * ISP116x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2005 Olav Kongas <ok@artecdesign.ee>
+ * Portions:
+ * Copyright (C) 2004 Lothar Wassmann
+ * Copyright (C) 2004 Psion Teklogix
+ * Copyright (C) 2004 David Brownell
+ *
+ * This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _NETUSBEE_ISP116X_H
+#define _NETUSBEE_ISP116X_H
+
+/* ------------------------------------------------------------------------- */
+
+/* us of 1ms frame */
+#define  MAX_LOAD_LIMIT		850
+
+/* Full speed: max # of bytes to transfer for a single urb
+   at a time must be < 1024 && must be multiple of 64.
+   832 allows transfering 4kiB within 5 frames. */
+#define MAX_TRANSFER_SIZE_FULLSPEED	832
+
+/* Low speed: there is no reason to schedule in very big
+   chunks; often the requested long transfers are for
+   string descriptors containing short strings. */
+#define MAX_TRANSFER_SIZE_LOWSPEED	64
+
+/* Bytetime (us), a rough indication of how much time it
+   would take to transfer a byte of useful data over USB */
+#define BYTE_TIME_FULLSPEED	1
+#define BYTE_TIME_LOWSPEED	20
+
+/* Buffer sizes */
+#define ISP116x_BUF_SIZE	4096
+#define ISP116x_ITL_BUFSIZE	0
+#define ISP116x_ATL_BUFSIZE	((ISP116x_BUF_SIZE) - 2*(ISP116x_ITL_BUFSIZE))
+
+#define ISP116x_WRITE_OFFSET	0x80
+
+/* --- ISP116x address registers in Netusbee --------------------------------*/
+
+#define ISP116X_HCD_ADDR	0x00FBC000
+#define ISP116X_HCD_DATA	0x00FA0000
+
+/* --- ISP116x registers/bits ---------------------------------------------- */
+
+#define	HCREVISION	0x00
+#define	HCCONTROL	0x01
+#define		HCCONTROL_HCFS	(3UL << 6)	/* host controller
+						   functional state */
+#define		HCCONTROL_USB_RESET	(0UL << 6)
+#define		HCCONTROL_USB_RESUME	(1UL << 6)
+#define		HCCONTROL_USB_OPER	(2UL << 6)
+#define		HCCONTROL_USB_SUSPEND	(3UL << 6)
+#define		HCCONTROL_RWC	(1UL << 9)	/* remote wakeup connected */
+#define		HCCONTROL_RWE	(1UL << 10)	/* remote wakeup enable */
+#define	HCCMDSTAT	0x02
+#define		HCCMDSTAT_HCR	(1UL << 0)	/* host controller reset */
+#define		HCCMDSTAT_SOC	(3UL << 16)	/* scheduling overrun count */
+#define	HCINTSTAT	0x03
+#define		HCINT_SO	(1UL << 0)	/* scheduling overrun */
+#define		HCINT_WDH	(1UL << 1)	/* writeback of done_head */
+#define		HCINT_SF	(1UL << 2)	/* start frame */
+#define		HCINT_RD	(1UL << 3)	/* resume detect */
+#define		HCINT_UE	(1UL << 4)	/* unrecoverable error */
+#define		HCINT_FNO	(1UL << 5)	/* frame number overflow */
+#define		HCINT_RHSC	(1UL << 6)	/* root hub status change */
+#define		HCINT_OC	(1UL << 30)	/* ownership change */
+#define		HCINT_MIE	(1UL << 31)	/* master interrupt enable */
+#define	HCINTENB	0x04
+#define	HCINTDIS	0x05
+#define	HCFMINTVL	0x0d
+#define	HCFMREM		0x0e
+#define	HCFMNUM		0x0f
+#define	HCLSTHRESH	0x11
+#define	HCRHDESCA	0x12
+#define		RH_A_NDP	(0x3UL << 0)	/* #downstream ports */
+#define		RH_A_PSM	(1UL << 8)	/* power switching mode */
+#define		RH_A_NPS	(1UL << 9)	/* no power switching */
+#define		RH_A_DT		(1UL << 10)	/* device type (mbz) */
+#define		RH_A_OCPM	(1UL << 11)	/* overcurrent protection
+						   	mode */
+#define		RH_A_NOCP	(1UL << 12)	/* no overcurrent protection */
+#define		RH_A_POTPGT	(0xffUL << 24)	/* power on -> power good
+						   	time */
+#define	HCRHDESCB	0x13
+#define		RH_B_DR		(0xffffUL << 0)	/* device removable flags */
+#define		RH_B_PPCM	(0xffffUL << 16)	/* port power control mask */
+#define	HCRHSTATUS	0x14
+#define		RH_HS_LPS	(1UL << 0)	/* local power status */
+#define		RH_HS_OCI	(1UL << 1)	/* over current indicator */
+#define		RH_HS_DRWE	(1UL << 15)	/* device remote wakeup
+						   	enable */
+#define		RH_HS_LPSC	(1UL << 16)	/* local power status change */
+#define		RH_HS_OCIC	(1UL << 17)	/* over current indicator
+						   	change */
+#define		RH_HS_CRWE	(1UL << 31)	/* clear remote wakeup
+						   	enable */
+#define	HCRHPORT1	0x15
+#define		RH_PS_CCS	(1UL << 0)	/* current connect status */
+#define		RH_PS_PES	(1UL << 1)	/* port enable status */
+#define		RH_PS_PSS	(1UL << 2)	/* port suspend status */
+#define		RH_PS_POCI	(1UL << 3)	/* port over current
+						   	indicator */
+#define		RH_PS_PRS	(1UL << 4)	/* port reset status */
+#define		RH_PS_PPS	(1UL << 8)	/* port power status */
+#define		RH_PS_LSDA	(1UL << 9)	/* low speed device attached */
+#define		RH_PS_CSC	(1UL << 16)	/* connect status change */
+#define		RH_PS_PESC	(1UL << 17)	/* port enable status change */
+#define		RH_PS_PSSC	(1UL << 18)	/* port suspend status
+						   	change */
+#define		RH_PS_OCIC	(1UL << 19)	/* over current indicator
+						   	change */
+#define		RH_PS_PRSC	(1UL << 20)	/* port reset status change */
+#define		HCRHPORT_CLRMASK	(0x1f << 16)
+#define	HCRHPORT2	0x16
+#define	HCHWCFG		0x20
+#define		HCHWCFG_15KRSEL		(1 << 12)
+#define		HCHWCFG_CLKNOTSTOP	(1 << 11)
+#define		HCHWCFG_ANALOG_OC	(1 << 10)
+#define		HCHWCFG_DACK_MODE	(1 << 8)
+#define		HCHWCFG_EOT_POL		(1 << 7)
+#define		HCHWCFG_DACK_POL	(1 << 6)
+#define		HCHWCFG_DREQ_POL	(1 << 5)
+#define		HCHWCFG_DBWIDTH_MASK	(0x03 << 3)
+#define		HCHWCFG_DBWIDTH(n)	(((n) << 3) & HCHWCFG_DBWIDTH_MASK)
+#define		HCHWCFG_INT_POL		(1 << 2)
+#define		HCHWCFG_INT_TRIGGER	(1 << 1)
+#define		HCHWCFG_INT_ENABLE	(1 << 0)
+#define	HCDMACFG	0x21
+#define		HCDMACFG_BURST_LEN_MASK	(0x03 << 5)
+#define		HCDMACFG_BURST_LEN(n)	(((n) << 5) & HCDMACFG_BURST_LEN_MASK)
+#define		HCDMACFG_BURST_LEN_1	HCDMACFG_BURST_LEN(0)
+#define		HCDMACFG_BURST_LEN_4	HCDMACFG_BURST_LEN(1)
+#define		HCDMACFG_BURST_LEN_8	HCDMACFG_BURST_LEN(2)
+#define		HCDMACFG_DMA_ENABLE	(1 << 4)
+#define		HCDMACFG_BUF_TYPE_MASK	(0x07 << 1)
+#define		HCDMACFG_CTR_SEL	(1 << 2)
+#define		HCDMACFG_ITLATL_SEL	(1 << 1)
+#define		HCDMACFG_DMA_RW_SELECT	(1 << 0)
+#define	HCXFERCTR	0x22
+#define	HCuPINT		0x24
+#define		HCuPINT_SOF		(1 << 0)
+#define		HCuPINT_ATL		(1 << 1)
+#define		HCuPINT_AIIEOT		(1 << 2)
+#define		HCuPINT_OPR		(1 << 4)
+#define		HCuPINT_SUSP		(1 << 5)
+#define		HCuPINT_CLKRDY		(1 << 6)
+#define	HCuPINTENB	0x25
+#define	HCCHIPID	0x27
+#define		HCCHIPID_MASK		0xff00
+#define		HCCHIPID_MAGIC		0x6100
+#define	HCSCRATCH	0x28
+#define	HCSWRES		0x29
+#define		HCSWRES_MAGIC		0x00f6
+#define	HCITLBUFLEN	0x2a
+#define	HCATLBUFLEN	0x2b
+#define	HCBUFSTAT	0x2c
+#define		HCBUFSTAT_ITL0_FULL	(1 << 0)
+#define		HCBUFSTAT_ITL1_FULL	(1 << 1)
+#define		HCBUFSTAT_ATL_FULL	(1 << 2)
+#define		HCBUFSTAT_ITL0_DONE	(1 << 3)
+#define		HCBUFSTAT_ITL1_DONE	(1 << 4)
+#define		HCBUFSTAT_ATL_DONE	(1 << 5)
+#define	HCRDITL0LEN	0x2d
+#define	HCRDITL1LEN	0x2e
+#define	HCITLPORT	0x40
+#define	HCATLPORT	0x41
+
+/* PTD accessor macros. */
+#define PTD_GET_COUNT(p)	(((p)->count & PTD_COUNT_MSK) >> 0)
+#define PTD_COUNT(v)		(((v) << 0) & PTD_COUNT_MSK)
+#define PTD_GET_TOGGLE(p)	(((p)->count & PTD_TOGGLE_MSK) >> 10)
+#define PTD_TOGGLE(v)		(((v) << 10) & PTD_TOGGLE_MSK)
+#define PTD_GET_ACTIVE(p)	(((p)->count & PTD_ACTIVE_MSK) >> 11)
+#define PTD_ACTIVE(v)		(((v) << 11) & PTD_ACTIVE_MSK)
+#define PTD_GET_CC(p)		(((p)->count & PTD_CC_MSK) >> 12)
+#define PTD_CC(v)		(((v) << 12) & PTD_CC_MSK)
+#define PTD_GET_MPS(p)		(((p)->mps & PTD_MPS_MSK) >> 0)
+#define PTD_MPS(v)		(((v) << 0) & PTD_MPS_MSK)
+#define PTD_GET_SPD(p)		(((p)->mps & PTD_SPD_MSK) >> 10)
+#define PTD_SPD(v)		(((v) << 10) & PTD_SPD_MSK)
+#define PTD_GET_LAST(p)		(((p)->mps & PTD_LAST_MSK) >> 11)
+#define PTD_LAST(v)		(((v) << 11) & PTD_LAST_MSK)
+#define PTD_GET_EP(p)		(((p)->mps & PTD_EP_MSK) >> 12)
+#define PTD_EP(v)		(((v) << 12) & PTD_EP_MSK)
+#define PTD_GET_LEN(p)		(((p)->len & PTD_LEN_MSK) >> 0)
+#define PTD_LEN(v)		(((v) << 0) & PTD_LEN_MSK)
+#define PTD_GET_DIR(p)		(((p)->len & PTD_DIR_MSK) >> 10)
+#define PTD_DIR(v)		(((v) << 10) & PTD_DIR_MSK)
+#define PTD_GET_B5_5(p)		(((p)->len & PTD_B5_5_MSK) >> 13)
+#define PTD_B5_5(v)		(((v) << 13) & PTD_B5_5_MSK)
+#define PTD_GET_FA(p)		(((p)->faddr & PTD_FA_MSK) >> 0)
+#define PTD_FA(v)		(((v) << 0) & PTD_FA_MSK)
+#define PTD_GET_FMT(p)		(((p)->faddr & PTD_FMT_MSK) >> 7)
+#define PTD_FMT(v)		(((v) << 7) & PTD_FMT_MSK)
+
+/*  Hardware transfer status codes -- CC from ptd->count */
+#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
+
+/* ------------------------------------------------------------------------- */
+
+#define	LOG2_PERIODIC_SIZE	5	/* arbitrary; this matches OHCI */
+#define	PERIODIC_SIZE		(1 << LOG2_PERIODIC_SIZE)
+
+/* Philips transfer descriptor */
+struct ptd {
+	unsigned short count;
+#define	PTD_COUNT_MSK	(0x3ff << 0)
+#define	PTD_TOGGLE_MSK	(1 << 10)
+#define	PTD_ACTIVE_MSK	(1 << 11)
+#define	PTD_CC_MSK	(0xf << 12)
+	unsigned short mps;
+#define	PTD_MPS_MSK	(0x3ff << 0)
+#define	PTD_SPD_MSK	(1 << 10)
+#define	PTD_LAST_MSK	(1 << 11)
+#define	PTD_EP_MSK	(0xf << 12)
+	unsigned short len;
+#define	PTD_LEN_MSK	(0x3ff << 0)
+#define	PTD_DIR_MSK	(3 << 10)
+#define	PTD_DIR_SETUP	(0)
+#define	PTD_DIR_OUT	(1)
+#define	PTD_DIR_IN	(2)
+#define	PTD_B5_5_MSK	(1 << 13)
+	unsigned short faddr;
+#define	PTD_FA_MSK	(0x7f << 0)
+#define	PTD_FMT_MSK	(1 << 7)
+} __attribute__ ((packed, aligned(2)));
+
+struct isp116x_ep
+{
+	struct usb_device *udev;
+	struct ptd ptd;
+
+	unsigned char maxpacket;
+	unsigned char epnum;
+	unsigned char nextpid;
+
+	unsigned short length;		/* of current packet */
+	unsigned char *data;	/* to databuf */
+
+	unsigned short error_count;
+};
+
+/* URB struct */
+#define N_URB_TD		48
+#define URB_DEL			1
+typedef struct
+{
+	struct isp116x_ep *ed;
+	void *transfer_buffer;	/* (in) associated data buffer */
+	long actual_length;	/* (return) actual transfer length */
+	unsigned long pipe;	/* (in) pipe information */
+#if 0
+	long state;
+#endif
+} urb_priv_t;
+
+struct isp116x_platform_data
+{
+	/* Enable internal resistors on downstream ports */
+	unsigned sel15Kres:1;
+	/* On-chip overcurrent detection */
+	unsigned oc_enable:1;
+	/* Enable wakeup by devices on usb bus (e.g. wakeup
+	   by attachment/detachment or by device activity
+	   such as moving a mouse). When chosen, this option
+	   prevents stopping internal clock, increasing
+	   thereby power consumption in suspended state. */
+	unsigned remote_wakeup_enable:1;
+	/* INT output polarity */
+        unsigned int_act_high:1;
+        /* INT edge or level triggered */
+        unsigned int_edge_triggered:1;
+
+};
+
+struct isp116x
+{
+	unsigned short *addr_reg;
+	unsigned short *data_reg;
+
+	struct isp116x_platform_data *board;
+
+	struct dentry *dentry;
+	unsigned long stat1, stat2, stat4, stat8, stat16;
+
+	unsigned long intenb; /* "OHCI" interrupts */
+	unsigned short irqenb; /* uP interrupts */
+
+	/* Status flags */
+	unsigned disabled:1;
+	unsigned sleeping:1;
+
+	/* Root hub registers */
+	unsigned long rhdesca;
+	unsigned long rhdescb;
+	unsigned long rhstatus;
+	unsigned long rhport[2];
+
+	/* Schedule for the current frame */
+	struct isp116x_ep *atl_active;
+	long atl_buflen;
+	long atl_bufshrt;
+	long atl_last_dir;
+	long atl_finishing;
+};
+
+/* ------------------------------------------------- */
+
+/* Inter-io delay (ns). The chip is picky about access timings; it
+ * expects at least:
+ * 150ns delay between consecutive accesses to DATA_REG,
+ * 300ns delay between access to ADDR_REG and DATA_REG
+ * OE, WE MUST NOT be changed during these intervals
+ */
+#if defined(UDELAY)
+# define	isp116x_delay(h,d)	udelay(d)
+#else
+# define	isp116x_delay(h,d)	do {} while (0)
+#endif
+
+
+unsigned long p;	
+			 
+static inline void isp116x_write_addr(struct isp116x *isp116x, unsigned reg)
+{
+	u16 dumm;
+
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + ((reg & 0x00ff)<<1)); 
+	dumm = __raw_readw(isp116x->data_reg);
+	isp116x->addr_reg = (u16*)ISP116X_HCD_ADDR;
+	dumm = __raw_readw(isp116x->addr_reg);
+	isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_write_data16(struct isp116x *isp116x, unsigned short val)
+{
+	u16 dumm;
+	
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + ((val & 0xff00)>>7)); 
+	dumm = __raw_readw(isp116x->data_reg);
+	isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR - 0x4000) + ((val & 0x00ff)<<1));
+	dumm = __raw_readw(isp116x->addr_reg);
+	isp116x_delay(isp116x, UDELAY);
+}
+
+static inline void isp116x_raw_write_data16(struct isp116x *isp116x, unsigned short val)
+{
+	u16 dumm;
+
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + ((val & 0x00ff)<<1));
+	dumm = __raw_readw(isp116x->data_reg);
+	isp116x->addr_reg =  (u16*)((ISP116X_HCD_ADDR - 0x4000) + ((val & 0xff00)>>7)); 
+	dumm = __raw_readw(isp116x->addr_reg);
+	isp116x_delay(isp116x, UDELAY);
+}
+
+static inline unsigned short isp116x_read_data16(struct isp116x *isp116x)
+{
+	unsigned short val;
+
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + 0x8000);
+	val = readw(isp116x->data_reg );
+	isp116x_delay(isp116x, UDELAY);
+
+	return val;
+}
+
+static inline unsigned short isp116x_raw_read_data16(struct isp116x *isp116x)
+{
+	unsigned short val;
+
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + 0x8000);
+	val = __raw_readw(isp116x->data_reg );
+	isp116x_delay(isp116x, UDELAY);
+
+	return val;
+}
+
+
+static inline void isp116x_write_data32(struct isp116x *isp116x, unsigned long val)
+{
+	writew(val & 0xffff, isp116x->data_reg);
+	isp116x_delay(isp116x, UDELAY);
+	writew(val >> 16, isp116x->data_reg);
+	isp116x_delay(isp116x, UDELAY);
+}
+
+/*
+ * Added for NetUSBee, to write HC registers without swapping them
+ * NetUSBee already swap them by hardware (i suppose.....)
+ */
+static inline void isp116x_raw_write_data32(struct isp116x *isp116x, unsigned long val)
+{
+	u16 dumm;
+
+	isp116x->data_reg =  (u16*)(ISP116X_HCD_DATA + ((val & 0x000000ff)<<1)); 
+	dumm = __raw_readw(isp116x->data_reg);
+	isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR - 0x4000) + ((val & 0x0000ff00)>>7)); 
+	dumm = __raw_readw(isp116x->addr_reg);
+	isp116x_delay(isp116x, UDELAY);
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + ((val & 0x00ff0000)>>15));
+	dumm = __raw_readw(isp116x->data_reg);
+	isp116x->addr_reg = (u16*)((ISP116X_HCD_ADDR - 0x4000) + ((val & 0xff000000)>>23) );
+	dumm = __raw_readw(isp116x->addr_reg);
+	isp116x_delay(isp116x, UDELAY);
+}
+/***********************************************/
+
+static inline unsigned long isp116x_read_data32(struct isp116x *isp116x)
+{
+	unsigned long val;
+
+	val = (unsigned long) readw(isp116x->data_reg);
+	isp116x_delay(isp116x, UDELAY);
+	val |= ((unsigned long) readw(isp116x->data_reg)) << 16;
+	isp116x_delay(isp116x, UDELAY);
+
+	return val;
+}
+
+/*
+ * Added for NetUSBee, to read HC registers without swapping them
+ * NetUSBee already swap them by hardware (i suppose.....)
+ */
+static inline unsigned long isp116x_raw_read_data32(struct isp116x *isp116x)
+{
+	unsigned long val;
+
+	isp116x->data_reg = (u16*)(ISP116X_HCD_DATA + 0x8000);
+	val = (u32) __raw_readw(isp116x->data_reg );
+	isp116x_delay(isp116x, UDELAY);
+	val |= ((u32) __raw_readw(isp116x->data_reg )) << 16;
+	isp116x_delay(isp116x, UDELAY);
+
+	return val;
+}
+/*******************************************************************/
+
+/* Let's keep register access functions out of line. Hint:
+   we wait at least 150 ns at every access.
+*/
+
+/* with NetUSBee use raw_read to avoid swapping bytes*/
+
+static unsigned short isp116x_read_reg16(struct isp116x *isp116x, unsigned reg)
+{
+	isp116x_write_addr(isp116x, reg);
+	return isp116x_raw_read_data16(isp116x);
+}
+
+static unsigned long isp116x_read_reg32(struct isp116x *isp116x, unsigned long reg)
+{
+	isp116x_write_addr(isp116x, reg);
+	return isp116x_raw_read_data32(isp116x);
+}
+
+static void isp116x_write_reg16(struct isp116x *isp116x, unsigned reg,
+				unsigned val)
+{
+	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+	isp116x_raw_write_data16(isp116x, (unsigned short) (val & 0xffff));
+}
+
+/* with NetUSBee used raw_write to avoid swapping bytes by software */
+static void isp116x_write_reg32(struct isp116x *isp116x, unsigned long reg,
+				unsigned long val)
+{
+	isp116x_write_addr(isp116x, reg | ISP116x_WRITE_OFFSET);
+	isp116x_raw_write_data32(isp116x, (unsigned long) val);
+}
+
+/* --- USB HUB constants (not OHCI-specific; see hub.h) -------------------- */
+
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS          0x0500
+#define RH_GET_DESCRIPTOR       0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION    0x0880
+#define RH_SET_CONFIGURATION    0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
+
+#endif /* _NETUSBEE_ISP116X_H */
Index: sys/usb/src.km/ucd/netusbee/netusbee_int.S
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/netusbee_int.S
@@ -0,0 +1,112 @@
+/*
+ * NetUSBee USB driver for FreeMiNT.
+ * Modified for USB by David Galvez. 2010 - 2011
+ *
+ * This file belongs to FreeMiNT. It's not in the original MiNT 1.12
+ * distribution. See the file CHANGES for a detailed log of changes.
+ *
+ * Copyright (c) 2007 Henrik Gilda.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 
+ * Low level and interrupt routines for the NetUSBee driver
+ *
+ * 2005-02-12 Henrik Gilda
+ * 2000-08-02 Frank Naumann
+ * 2000-03-24 Vassilis Papathanassiou
+ *
+ *
+ */
+
+//#define RESMAGIC		0x31415926
+//#define _resvalid		0x426
+//#define _resvector		0x42a
+
+
+//	.globl _netusbee_int
+	.globl _set_old_int_lvl
+	.globl _set_int_lvl5
+	.globl _set_int_lvl6
+	.globl _set_int_lvl7
+	.globl _old_200Hz_int
+	.globl _interrupt_200Hz
+
+	
+
+	.text
+#if 0
+	dc.l	0x58425241		| XBRA
+	dc.l	0x00000000		| (no cookie)
+_old_200Hz_int:
+	ds.l	1
+_interrupt_200Hz:
+	move.w	(sp),oldSR
+	movem.l	a0-a7/d0-d7,-(sp)
+	bsr	_netusbee_int
+	movem.l	(sp)+,a0-a7/d0-d7
+	move.l	_old_200Hz_int(PC),-(sp)	|jump through old handler
+	rts
+
+#endif
+
+oldSR:	ds.w	1
+
+// Sets interrupt level to what was in the SR
+_set_old_int_lvl:
+//	move.w	(sp),oldSR
+	andi.w	#0x0f00,oldSR		//just keep the int lvl
+	move.l	d0,-(sp)
+	move.w	sr,d0
+	andi.w	#0xf0ff,d0
+	or.w	oldSR,d0
+	move.w	d0,sr
+	move.l	(sp)+,d0
+	rts
+
+// Sets interrupt level to 5
+_set_int_lvl5:
+	move.w	d0,-(sp)
+	move.w	sr,d0
+	move.w	d0,oldSR
+	andi.w	#0xf0ff,d0
+	ori.w	#0x0500,d0
+	move.w	d0,sr
+	move.w	(sp)+,d0
+	rts
+
+// Sets interrupt level to 6
+_set_int_lvl6:
+	move.w	d0,-(sp)
+	move.w	sr,d0
+	move.w	d0,oldSR
+	andi.w	#0xf0ff,d0
+	ori.w	#0x0600,d0
+	move.w	d0,sr
+	move.w	(sp)+,d0
+	rts
+
+// Sets interrupt level to 7
+_set_int_lvl7:
+	move.w	d0,-(sp)
+	move.w	sr,d0
+	move.w	d0,oldSR
+	andi.w	#0xf0ff,d0
+	ori.w	#0x0700,d0
+	move.w	d0,sr
+	move.w	(sp)+,d0
+	rts
+
+
Index: sys/usb/src.km/ucd/netusbee/netusbee_int.h
--- /dev/null
+++ sys/usb/src.km/ucd/netusbee/netusbee_int.h
@@ -0,0 +1,40 @@
+/*
+ * NetUSBee USB driver for FreeMiNT.
+ * Modified for USB by David Galvez. 2010 - 2011
+ *
+ * This file belongs to FreeMiNT. It's not in the original MiNT 1.12
+ * distribution. See the file CHANGES for a detailed log of changes.
+ *
+ * Copyright (c) 2007 Henrik Gilda
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _netusbee_int_h
+#define _netusbee_int_h
+
+
+// old handler
+extern void (*old_200Hz_int)(void);
+
+// interrupt wrapper routine
+void interrupt_200Hz(void);
+
+void set_old_int_lvl(void);
+void set_int_lvl5(void);
+void set_int_lvl6(void);
+void set_int_lvl7(void);
+
+#endif // _netusbee_int_h