MFH r187125-187188
This commit is contained in:
commit
1bdc6a93e7
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 13, 2005
|
||||
.Dd January 13, 2009
|
||||
.Dt KENV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -67,8 +67,28 @@ If the
|
||||
.Fl q
|
||||
option is set, warnings normally printed as a result of being unable to
|
||||
perform the requested operation will be suppressed.
|
||||
.Pp
|
||||
Variables can be added to the kernel environment using the
|
||||
.Xr /boot/loader.conf
|
||||
file, or also statically compiled into the kernel using the statement
|
||||
.Pp
|
||||
.Dl Ic env Ar filename
|
||||
.Pp
|
||||
in the kernel config file.
|
||||
The file can contain lines of the form
|
||||
.Pp
|
||||
.Dl name = "value" # this is a comment
|
||||
.Pp
|
||||
where whitespace around name and '=', and
|
||||
everything after a '#' character, are ignored. Almost any printable
|
||||
character except '=' is acceptable as part of a name. Quotes
|
||||
are optional and necessary only if the value contains
|
||||
whitespace.
|
||||
.Pp
|
||||
.Sh SEE ALSO
|
||||
.Xr kenv 2 ,
|
||||
.Xr config 5 ,
|
||||
.Xr loader.conf 5 ,
|
||||
.Xr loader 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
13
bin/ln/ln.1
13
bin/ln/ln.1
@ -38,7 +38,7 @@
|
||||
.Sh NAME
|
||||
.Nm ln ,
|
||||
.Nm link
|
||||
.Nd make links
|
||||
.Nd link files
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl s Op Fl F
|
||||
@ -57,8 +57,13 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility creates a new directory entry (linked file) which has the
|
||||
same modes as the original file.
|
||||
utility creates a new directory entry (linked file) for the file name
|
||||
specified by
|
||||
.Ar target_file .
|
||||
The
|
||||
.Ar target_file
|
||||
will be created with the same file modes as the
|
||||
.Ar source_file .
|
||||
It is useful for maintaining multiple copies of a file in many places
|
||||
at once without using up storage for the
|
||||
.Dq copies ;
|
||||
@ -148,7 +153,7 @@ links.
|
||||
A hard link to a file is indistinguishable from the original directory entry;
|
||||
any changes to a file are effectively independent of the name used to reference
|
||||
the file.
|
||||
Hard links may not normally refer to directories and may not span file systems.
|
||||
Directories may not be hardlinked, and hard links may not span file systems.
|
||||
.Pp
|
||||
A symbolic link contains the name of the file to
|
||||
which it is linked.
|
||||
|
@ -466,7 +466,10 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
|
||||
* seek backwards to extract it, so issue a warning. */
|
||||
if (file->offset < iso9660->current_position) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Ignoring out-of-order file");
|
||||
"Ignoring out-of-order file @%x (%s) %jd < %jd",
|
||||
file,
|
||||
iso9660->pathname.s,
|
||||
file->offset, iso9660->current_position);
|
||||
iso9660->entry_bytes_remaining = 0;
|
||||
iso9660->entry_sparse_offset = 0;
|
||||
release_file(iso9660, file);
|
||||
@ -607,7 +610,7 @@ parse_file_info(struct iso9660 *iso9660, struct file_info *parent,
|
||||
file->parent = parent;
|
||||
if (parent != NULL)
|
||||
parent->refcount++;
|
||||
file->offset = toi(isodirrec + DR_extent_offset, DR_extent_size)
|
||||
file->offset = (uint64_t)toi(isodirrec + DR_extent_offset, DR_extent_size)
|
||||
* iso9660->logical_block_size;
|
||||
file->size = toi(isodirrec + DR_size_offset, DR_size_size);
|
||||
file->mtime = isodate7(isodirrec + DR_date_offset);
|
||||
|
@ -108,4 +108,4 @@ The
|
||||
and
|
||||
.Fn flsll
|
||||
functions appeared in
|
||||
.Fx 8.0 .
|
||||
.Fx 7.1 .
|
||||
|
@ -486,6 +486,8 @@ libusb20_dev_close(struct libusb20_device *pdev)
|
||||
|
||||
pdev->is_opened = 0;
|
||||
|
||||
pdev->claimed_interfaces = 0;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
|
||||
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
|
||||
|
||||
#ifdef INLINE_REM_PIO2
|
||||
extern inline
|
||||
extern __gnu89_inline
|
||||
#endif
|
||||
int
|
||||
__ieee754_rem_pio2(double x, double *y)
|
||||
|
@ -41,7 +41,7 @@ pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
|
||||
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
|
||||
|
||||
#ifdef INLINE_REM_PIO2F
|
||||
extern inline
|
||||
extern __gnu89_inline
|
||||
#endif
|
||||
int
|
||||
__ieee754_rem_pio2f(float x, double *y)
|
||||
|
@ -31,7 +31,7 @@ C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
|
||||
C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
|
||||
|
||||
#ifdef INLINE_KERNEL_COSDF
|
||||
extern inline
|
||||
extern __gnu89_inline
|
||||
#endif
|
||||
float
|
||||
__kernel_cosdf(double x)
|
||||
|
@ -30,7 +30,7 @@ S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
|
||||
S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
|
||||
|
||||
#ifdef INLINE_KERNEL_SINDF
|
||||
extern inline
|
||||
extern __gnu89_inline
|
||||
#endif
|
||||
float
|
||||
__kernel_sindf(double x)
|
||||
|
@ -33,7 +33,7 @@ T[] = {
|
||||
};
|
||||
|
||||
#ifdef INLINE_KERNEL_TANDF
|
||||
extern inline
|
||||
extern __gnu89_inline
|
||||
#endif
|
||||
float
|
||||
__kernel_tandf(double x, int iy)
|
||||
|
@ -70,6 +70,7 @@ int debug, fstab_style, verbose;
|
||||
|
||||
struct cpa {
|
||||
char **a;
|
||||
ssize_t sz;
|
||||
int c;
|
||||
};
|
||||
|
||||
@ -503,11 +504,9 @@ hasopt(const char *mntopts, const char *option)
|
||||
static void
|
||||
append_arg(struct cpa *sa, char *arg)
|
||||
{
|
||||
static int a_sz;
|
||||
|
||||
if (sa->c + 1 == a_sz) {
|
||||
a_sz = a_sz == 0 ? 8 : a_sz * 2;
|
||||
sa->a = realloc(sa->a, sizeof(sa->a) * a_sz);
|
||||
if (sa->c + 1 == sa->sz) {
|
||||
sa->sz = sa->sz == 0 ? 8 : sa->sz * 2;
|
||||
sa->a = realloc(sa->a, sizeof(sa->a) * sa->sz);
|
||||
if (sa->a == NULL)
|
||||
errx(1, "realloc failed");
|
||||
}
|
||||
@ -518,11 +517,10 @@ int
|
||||
mountfs(const char *vfstype, const char *spec, const char *name, int flags,
|
||||
const char *options, const char *mntopts)
|
||||
{
|
||||
struct cpa mnt_argv;
|
||||
struct statfs sf;
|
||||
int i, ret;
|
||||
char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX];
|
||||
static int mnt_argv_inited;
|
||||
static struct cpa mnt_argv;
|
||||
|
||||
/* resolve the mountpoint with realpath(3) */
|
||||
(void)checkpath(name, mntpath);
|
||||
@ -557,10 +555,6 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags,
|
||||
/* Construct the name of the appropriate mount command */
|
||||
(void)snprintf(execname, sizeof(execname), "mount_%s", vfstype);
|
||||
|
||||
if (!mnt_argv_inited) {
|
||||
mnt_argv_inited++;
|
||||
mnt_argv.a = NULL;
|
||||
}
|
||||
mnt_argv.c = -1;
|
||||
append_arg(&mnt_argv, execname);
|
||||
mangle(optbuf, &mnt_argv);
|
||||
|
@ -12,8 +12,8 @@ everything beneath that directory will be left alone.
|
||||
|
||||
You can copy "refuse" to your sup directory and add or remove
|
||||
whatever you like. The example supfiles in this directory set
|
||||
CVSup's base directory to "/usr". The sup directory is in the base
|
||||
directory; i.e., it is "/usr/sup". If you have changed your base
|
||||
CVSup's base directory to "/var/db". The sup directory is in the base
|
||||
directory; i.e., it is "/var/db/sup". If you have changed your base
|
||||
directory, your sup directory is /path/to/base/sup.
|
||||
|
||||
This file used to contain /usr/src/etc/sendmail/freebsd.mc in case
|
||||
@ -62,4 +62,4 @@ depend on files in completely different parts.
|
||||
|
||||
For more information about refuse files see cvsup(1), which is
|
||||
installed by the "cvsup" and "cvsup-bin" ports. See also the CVSup
|
||||
FAQ at <http://www.polstra.com/projects/freeware/CVSup/>.
|
||||
FAQ at <http://www.cvsup.org/faq.html>.
|
||||
|
@ -1,8 +1,8 @@
|
||||
#
|
||||
# GENERIC -- Generic kernel configuration file for FreeBSD/amd64
|
||||
#
|
||||
# For more information on this file, please read the handbook section on
|
||||
# Kernel Configuration Files:
|
||||
# For more information on this file, please read the config(5) manual page,
|
||||
# and/or the handbook section on Kernel Configuration Files:
|
||||
#
|
||||
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
|
||||
#
|
||||
@ -24,6 +24,12 @@ ident GENERIC
|
||||
# To statically compile in device wiring instead of /boot/device.hints
|
||||
#hints "GENERIC.hints" # Default places to look for devices.
|
||||
|
||||
# Use the following to compile in values accessible to the kernel
|
||||
# through getenv() (or kenv(1) in userland). The format of the file
|
||||
# is 'variable=value', see kenv(1)
|
||||
#
|
||||
# env "GENERIC.env"
|
||||
|
||||
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
|
||||
|
||||
options SCHED_ULE # ULE scheduler
|
||||
|
@ -108,3 +108,7 @@ device usb2_input_ms
|
||||
|
||||
# USB sound and MIDI device support
|
||||
#device usb2_sound
|
||||
|
||||
# USB scanner support
|
||||
device usb2_image
|
||||
device usb2_scanner
|
||||
|
@ -820,7 +820,7 @@ only forth also support-functions definitions
|
||||
\ Interface to loading conf files
|
||||
|
||||
: load_conf ( addr len -- )
|
||||
." ----- Trying conf " 2dup type cr
|
||||
\ ." ----- Trying conf " 2dup type cr \ debugging
|
||||
0 to end_of_file?
|
||||
reset_line_reading
|
||||
O_RDONLY fopen fd !
|
||||
@ -912,7 +912,7 @@ string current_file_name_ref \ used to print the file name
|
||||
\ loader_conf_files processing support functions
|
||||
|
||||
: get_conf_files ( -- addr len ) \ put addr/len on stack, reset var
|
||||
." -- starting on <" conf_files strtype ." >" cr
|
||||
\ ." -- starting on <" conf_files strtype ." >" cr \ debugging
|
||||
conf_files strget 0 0 conf_files strset
|
||||
;
|
||||
|
||||
@ -939,8 +939,7 @@ string current_file_name_ref \ used to print the file name
|
||||
pos char+ to pos
|
||||
repeat
|
||||
addr len pos addr r@ + pos r> -
|
||||
2dup
|
||||
." get_file_name has " type cr
|
||||
\ 2dup ." get_file_name has " type cr \ debugging
|
||||
;
|
||||
|
||||
: get_next_file ( addr len ptr -- addr len ptr' addr' len' | 0 )
|
||||
|
@ -1609,6 +1609,7 @@ dev/usb2/wlan/usb2_wlan.c optional usb2_core usb2_wlan
|
||||
#
|
||||
# USB2 serial and parallel port drivers
|
||||
#
|
||||
dev/usb2/serial/u3g2.c optional usb2_core usb2_serial usb2_serial_3g
|
||||
dev/usb2/serial/uark2.c optional usb2_core usb2_serial usb2_serial_ark
|
||||
dev/usb2/serial/ubsa2.c optional usb2_core usb2_serial usb2_serial_bsa
|
||||
dev/usb2/serial/ubser2.c optional usb2_core usb2_serial usb2_serial_bser
|
||||
|
@ -84,7 +84,6 @@ powerpc/booke/interrupt.c optional e500
|
||||
powerpc/booke/locore.S optional e500 no-obj
|
||||
powerpc/booke/machdep.c optional e500
|
||||
powerpc/booke/pmap.c optional e500
|
||||
powerpc/booke/support.S optional e500
|
||||
powerpc/booke/swtch.S optional e500
|
||||
powerpc/booke/trap.c optional e500
|
||||
powerpc/booke/uio_machdep.c optional e500
|
||||
|
@ -14,7 +14,7 @@
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* $Id: ar5212_rfgain.c,v 1.2 2008/11/19 21:23:01 sam Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include "opt_ah.h"
|
||||
|
||||
@ -280,7 +280,8 @@ ar5212GetRfgain(struct ath_hal *ah)
|
||||
GAIN_VALUES *gv = &ahp->ah_gainValues;
|
||||
uint32_t rddata, probeType;
|
||||
|
||||
if (!gv->active)
|
||||
/* NB: beware of touching the BB when PHY is powered down */
|
||||
if (!gv->active || !ahp->ah_phyPowerOn)
|
||||
return HAL_RFGAIN_INACTIVE;
|
||||
|
||||
if (ahp->ah_rfgainState == HAL_RFGAIN_READ_REQUESTED) {
|
||||
|
@ -106,6 +106,8 @@ static struct bce_type bce_devs[] = {
|
||||
"HP NC370T Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3106,
|
||||
"HP NC370i Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, HP_VENDORID, 0x3070,
|
||||
"HP NC380T PCI Express Dual Port Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5706 1000Base-T" },
|
||||
|
||||
@ -116,18 +118,38 @@ static struct bce_type bce_devs[] = {
|
||||
"Broadcom NetXtreme II BCM5706 1000Base-SX" },
|
||||
|
||||
/* BCM5708C controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7037,
|
||||
"HP NC373T PCI Express Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, HP_VENDORID, 0x7038,
|
||||
"HP NC373i Integrated Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5708 1000Base-T" },
|
||||
|
||||
/* BCM5708S controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x1706,
|
||||
"HP NC373m Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x7038,
|
||||
"HP NC373i PCI Express Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x703b,
|
||||
"HP NC373i Integrated Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, HP_VENDORID, 0x703d,
|
||||
"HP NC373F PCI Express Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708S, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5708 1000Base-SX" },
|
||||
|
||||
/* BCM5709C controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7055,
|
||||
"HP NC382i Integrated Quad Port PCI Express Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, HP_VENDORID, 0x7059,
|
||||
"HP NC382T PCI Express Dual Port Multifunction Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5709 1000Base-T" },
|
||||
|
||||
/* BCM5709S controllers and OEM boards. */
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x171d,
|
||||
"HP NC382m Dual Port 1GbE Multifunction BL-c Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, HP_VENDORID, 0x7056,
|
||||
"HP NC382i Integrated Quad Port PCI Express Gigabit Server Adapter" },
|
||||
{ BRCM_VENDORID, BRCM_DEVICEID_BCM5709S, PCI_ANY_ID, PCI_ANY_ID,
|
||||
"Broadcom NetXtreme II BCM5709 1000Base-SX" },
|
||||
|
||||
|
@ -83,7 +83,7 @@
|
||||
|
||||
#include "mixer_if.h"
|
||||
|
||||
#define HDA_DRV_TEST_REV "20090110_0123"
|
||||
#define HDA_DRV_TEST_REV "20090113_0124"
|
||||
|
||||
SND_DECLARE_FILE("$FreeBSD$");
|
||||
|
||||
@ -6110,6 +6110,29 @@ hdac_audio_prepare_pin_ctrl(struct hdac_devinfo *devinfo)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hdac_audio_ctl_commit(struct hdac_devinfo *devinfo)
|
||||
{
|
||||
struct hdac_audio_ctl *ctl;
|
||||
int i, z;
|
||||
|
||||
i = 0;
|
||||
while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
|
||||
if (ctl->enable == 0 || ctl->ossmask != 0) {
|
||||
/* Mute disabled and mixer controllable controls.
|
||||
* Last will be initialized by mixer_init().
|
||||
* This expected to reduce click on startup. */
|
||||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0);
|
||||
continue;
|
||||
}
|
||||
/* Init fixed controls to 0dB amplification. */
|
||||
z = ctl->offset;
|
||||
if (z > ctl->step)
|
||||
z = ctl->step;
|
||||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hdac_audio_commit(struct hdac_devinfo *devinfo)
|
||||
{
|
||||
@ -6126,11 +6149,41 @@ hdac_audio_commit(struct hdac_devinfo *devinfo)
|
||||
hdac_command(sc, HDA_CMD_12BIT(cad, devinfo->nid,
|
||||
0x7e7, 0), cad);
|
||||
|
||||
/* Commit controls. */
|
||||
hdac_audio_ctl_commit(devinfo);
|
||||
|
||||
/* Commit selectors, pins and EAPD. */
|
||||
for (i = 0; i < devinfo->nodecnt; i++) {
|
||||
w = &devinfo->widget[i];
|
||||
if (w == NULL)
|
||||
continue;
|
||||
if (w->selconn == -1)
|
||||
w->selconn = 0;
|
||||
if (w->nconns > 0)
|
||||
hdac_widget_connection_select(w, w->selconn);
|
||||
if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||||
hdac_command(sc,
|
||||
HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
|
||||
w->wclass.pin.ctrl), cad);
|
||||
}
|
||||
if (w->param.eapdbtl != HDAC_INVALID) {
|
||||
uint32_t val;
|
||||
|
||||
val = w->param.eapdbtl;
|
||||
if (devinfo->function.audio.quirks &
|
||||
HDA_QUIRK_EAPDINV)
|
||||
val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
|
||||
hdac_command(sc,
|
||||
HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid,
|
||||
val), cad);
|
||||
}
|
||||
}
|
||||
|
||||
/* Commit GPIOs. */
|
||||
gdata = 0;
|
||||
gmask = 0;
|
||||
gdir = 0;
|
||||
commitgpio = 0;
|
||||
|
||||
numgpio = HDA_PARAM_GPIO_COUNT_NUM_GPIO(
|
||||
devinfo->function.audio.gpio);
|
||||
|
||||
@ -6185,54 +6238,6 @@ hdac_audio_commit(struct hdac_devinfo *devinfo)
|
||||
HDA_CMD_SET_GPIO_DATA(cad, devinfo->nid,
|
||||
gdata), cad);
|
||||
}
|
||||
|
||||
for (i = 0; i < devinfo->nodecnt; i++) {
|
||||
w = &devinfo->widget[i];
|
||||
if (w == NULL)
|
||||
continue;
|
||||
if (w->selconn == -1)
|
||||
w->selconn = 0;
|
||||
if (w->nconns > 0)
|
||||
hdac_widget_connection_select(w, w->selconn);
|
||||
if (w->type == HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX) {
|
||||
hdac_command(sc,
|
||||
HDA_CMD_SET_PIN_WIDGET_CTRL(cad, w->nid,
|
||||
w->wclass.pin.ctrl), cad);
|
||||
}
|
||||
if (w->param.eapdbtl != HDAC_INVALID) {
|
||||
uint32_t val;
|
||||
|
||||
val = w->param.eapdbtl;
|
||||
if (devinfo->function.audio.quirks &
|
||||
HDA_QUIRK_EAPDINV)
|
||||
val ^= HDA_CMD_SET_EAPD_BTL_ENABLE_EAPD;
|
||||
hdac_command(sc,
|
||||
HDA_CMD_SET_EAPD_BTL_ENABLE(cad, w->nid,
|
||||
val), cad);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hdac_audio_ctl_commit(struct hdac_devinfo *devinfo)
|
||||
{
|
||||
struct hdac_audio_ctl *ctl;
|
||||
int i, z;
|
||||
|
||||
i = 0;
|
||||
while ((ctl = hdac_audio_ctl_each(devinfo, &i)) != NULL) {
|
||||
if (ctl->enable == 0) {
|
||||
/* Mute disabled controls. */
|
||||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_ALL, 0, 0);
|
||||
continue;
|
||||
}
|
||||
/* Init controls to 0dB amplification. */
|
||||
z = ctl->offset;
|
||||
if (z > ctl->step)
|
||||
z = ctl->step;
|
||||
hdac_audio_ctl_amp_set(ctl, HDA_AMP_MUTE_NONE, z, z);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -7476,10 +7481,6 @@ hdac_attach2(void *arg)
|
||||
device_printf(sc->dev, "AFG commit...\n");
|
||||
);
|
||||
hdac_audio_commit(devinfo);
|
||||
HDA_BOOTHVERBOSE(
|
||||
device_printf(sc->dev, "Ctls commit...\n");
|
||||
);
|
||||
hdac_audio_ctl_commit(devinfo);
|
||||
HDA_BOOTHVERBOSE(
|
||||
device_printf(sc->dev, "HP switch init...\n");
|
||||
);
|
||||
@ -7729,10 +7730,6 @@ hdac_resume(device_t dev)
|
||||
device_printf(dev, "AFG commit...\n");
|
||||
);
|
||||
hdac_audio_commit(devinfo);
|
||||
HDA_BOOTHVERBOSE(
|
||||
device_printf(dev, "Ctls commit...\n");
|
||||
);
|
||||
hdac_audio_ctl_commit(devinfo);
|
||||
HDA_BOOTHVERBOSE(
|
||||
device_printf(dev, "HP switch init...\n");
|
||||
);
|
||||
|
@ -151,6 +151,7 @@ vendor PLANTRONICS 0x047f Plantronics
|
||||
vendor KYOCERA 0x0482 Kyocera Wireless Corp.
|
||||
vendor STMICRO 0x0483 STMicroelectronics
|
||||
vendor FOXCONN 0x0489 Foxconn
|
||||
vendor MEIZU 0x0492 Meizu Electronics
|
||||
vendor YAMAHA 0x0499 YAMAHA
|
||||
vendor COMPAQ 0x049f Compaq
|
||||
vendor HITACHI 0x04a4 Hitachi
|
||||
@ -1657,6 +1658,9 @@ product MCT DU_H3SP_USB232 0x0200 D-Link DU-H3SP USB BAY Hub
|
||||
product MCT USB232 0x0210 USB-232 Interface
|
||||
product MCT SITECOM_USB232 0x0230 Sitecom USB-232 Products
|
||||
|
||||
/* Meizu Electronics */
|
||||
product MEIZU M6_SL 0x0140 MiniPlayer M6 (SL)
|
||||
|
||||
/* Melco, Inc products */
|
||||
product MELCO LUATX1 0x0001 LUA-TX Ethernet
|
||||
product MELCO LUATX5 0x0005 LUA-TX Ethernet
|
||||
|
@ -50,14 +50,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR at91dcidebug
|
||||
#define usb2_config_td_cc at91dci_config_copy
|
||||
#define usb2_config_td_softc at91dci_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -106,7 +103,6 @@ static void at91dci_standard_done(struct usb2_xfer *);
|
||||
|
||||
static usb2_sw_transfer_func_t at91dci_root_intr_done;
|
||||
static usb2_sw_transfer_func_t at91dci_root_ctrl_done;
|
||||
static usb2_config_td_command_t at91dci_root_ctrl_task;
|
||||
|
||||
/*
|
||||
* NOTE: Some of the bits in the CSR register have inverse meaning so
|
||||
@ -263,13 +259,13 @@ at91dci_pull_down(struct at91dci_softc *sc)
|
||||
static void
|
||||
at91dci_wakeup_peer(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t use_polling;
|
||||
|
||||
if (!(sc->sc_flags.status_suspend)) {
|
||||
return;
|
||||
}
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, AT91_UDP_GSTATE_ESR);
|
||||
|
||||
@ -702,7 +698,7 @@ at91dci_xfer_do_fifo(struct usb2_xfer *xfer)
|
||||
return (1); /* not complete */
|
||||
|
||||
done:
|
||||
sc = xfer->usb2_sc;
|
||||
sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
temp = (xfer->endpoint & UE_ADDR);
|
||||
|
||||
/* update FIFO bank flag and multi buffer */
|
||||
@ -733,11 +729,9 @@ repeat:
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_vbus_interrupt(struct usb2_bus *bus, uint8_t is_on)
|
||||
void
|
||||
at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
|
||||
{
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus);
|
||||
|
||||
DPRINTFN(5, "vbus = %u\n", is_on);
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
@ -764,7 +758,6 @@ at91dci_vbus_interrupt(struct usb2_bus *bus, uint8_t is_on)
|
||||
&at91dci_root_intr_done);
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(&sc->sc_bus);
|
||||
}
|
||||
|
||||
@ -890,7 +883,7 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
|
||||
DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
|
||||
@ -905,7 +898,7 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
|
||||
temp.offset = 0;
|
||||
|
||||
sc = xfer->usb2_sc;
|
||||
sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
ep_no = (xfer->endpoint & UE_ADDR);
|
||||
|
||||
/* check if we should prepend a setup message */
|
||||
@ -1032,7 +1025,7 @@ at91dci_timeout(void *arg)
|
||||
|
||||
DPRINTF("xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
at91dci_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -1046,7 +1039,7 @@ at91dci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
/* poll one time */
|
||||
if (at91dci_xfer_do_fifo(xfer)) {
|
||||
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t ep_no = xfer->endpoint & UE_ADDR;
|
||||
|
||||
/*
|
||||
@ -1059,7 +1052,7 @@ at91dci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
DPRINTFN(15, "enable interrupts on endpoint %d\n", ep_no);
|
||||
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1073,7 +1066,7 @@ static void
|
||||
at91dci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTFN(9, "\n");
|
||||
|
||||
@ -1213,7 +1206,7 @@ done:
|
||||
static void
|
||||
at91dci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t ep_no;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
|
||||
@ -1627,7 +1620,7 @@ at91dci_device_isoc_fs_close(struct usb2_xfer *xfer)
|
||||
static void
|
||||
at91dci_device_isoc_fs_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t temp;
|
||||
uint32_t nframes;
|
||||
|
||||
@ -1709,7 +1702,7 @@ at91dci_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
at91dci_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -1783,7 +1776,7 @@ static const struct usb2_hub_descriptor_min at91dci_hubd = {
|
||||
.wHubCharacteristics[0] =
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
|
||||
.wHubCharacteristics[1] =
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 16,
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
|
||||
.bPwrOn2PwrGood = 50,
|
||||
.bHubContrCurrent = 0,
|
||||
.DeviceRemovable = {0}, /* port is removable */
|
||||
@ -1813,26 +1806,24 @@ at91dci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
at91dci_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command(
|
||||
&sc->sc_config_td, NULL, &at91dci_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_root_ctrl_task(struct at91dci_softc *sc,
|
||||
struct at91dci_config_copy *cc, uint16_t refcount)
|
||||
at91dci_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
at91dci_root_ctrl_poll(sc);
|
||||
at91dci_root_ctrl_poll(AT9100_DCI_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
at91dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint8_t use_polling;
|
||||
@ -1853,7 +1844,7 @@ at91dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
/* demultiplex the control request */
|
||||
|
||||
@ -2258,7 +2249,7 @@ at91dci_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
at91dci_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -2275,7 +2266,7 @@ at91dci_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
at91dci_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct at91dci_softc *sc = xfer->usb2_sc;
|
||||
struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
}
|
||||
@ -2304,11 +2295,6 @@ at91dci_xfer_setup(struct usb2_setup_params *parm)
|
||||
sc = AT9100_DCI_BUS2SC(parm->udev->bus);
|
||||
xfer = parm->curr_xfer;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
/*
|
||||
* NOTE: This driver does not use any of the parameters that
|
||||
* are computed from the following values. Just set some
|
||||
@ -2477,5 +2463,5 @@ struct usb2_bus_methods at91dci_bus_methods =
|
||||
.get_hw_ep_profile = &at91dci_get_hw_ep_profile,
|
||||
.set_stall = &at91dci_set_stall,
|
||||
.clear_stall = &at91dci_clear_stall,
|
||||
.vbus_interrupt = &at91dci_vbus_interrupt,
|
||||
.roothub_exec = &at91dci_root_ctrl_task,
|
||||
};
|
||||
|
@ -34,6 +34,8 @@
|
||||
#ifndef _AT9100_DCI_H_
|
||||
#define _AT9100_DCI_H_
|
||||
|
||||
#define AT91_MAX_DEVICES (USB_MIN_DEVICES + 1)
|
||||
|
||||
#define AT91_UDP_FRM 0x00 /* Frame number register */
|
||||
#define AT91_UDP_FRM_MASK (0x7FF << 0) /* Frame Number as Defined in
|
||||
* the Packet Field Formats */
|
||||
@ -204,8 +206,8 @@ struct at91dci_softc {
|
||||
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
struct usb2_config_td sc_config_td;
|
||||
|
||||
struct usb2_device *sc_devices[AT91_MAX_DEVICES];
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
void *sc_intr_hdl;
|
||||
@ -238,5 +240,6 @@ void at91dci_uninit(struct at91dci_softc *sc);
|
||||
void at91dci_suspend(struct at91dci_softc *sc);
|
||||
void at91dci_resume(struct at91dci_softc *sc);
|
||||
void at91dci_interrupt(struct at91dci_softc *sc);
|
||||
void at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on);
|
||||
|
||||
#endif /* _AT9100_DCI_H_ */
|
||||
|
@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -73,7 +72,7 @@ struct at91_udp_softc {
|
||||
};
|
||||
|
||||
static void
|
||||
at91_vbus_interrupt(struct at91_udp_softc *sc)
|
||||
at91_vbus_poll(struct at91_udp_softc *sc)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint8_t vbus_val;
|
||||
@ -85,8 +84,7 @@ at91_vbus_interrupt(struct at91_udp_softc *sc)
|
||||
/* just forward it */
|
||||
|
||||
vbus_val = at91_pio_gpio_get(VBUS_BASE, VBUS_MASK);
|
||||
(sc->sc_dci.sc_bus.methods->vbus_interrupt)
|
||||
(&sc->sc_dci.sc_bus, vbus_val);
|
||||
at91dci_vbus_interrupt(&sc->sc_dci, vbus_val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -145,9 +143,12 @@ at91_udp_attach(device_t dev)
|
||||
sc->sc_dci.sc_pull_down = &at91_udp_pull_down;
|
||||
sc->sc_dci.sc_pull_arg = sc;
|
||||
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_dci.sc_bus.parent = dev;
|
||||
sc->sc_dci.sc_bus.devices = sc->sc_dci.sc_devices;
|
||||
sc->sc_dci.sc_bus.devices_max = AT91_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_dci.sc_bus,
|
||||
USB_GET_DMA_TAG(dev), NULL)) {
|
||||
return (ENOMEM);
|
||||
@ -205,12 +206,6 @@ at91_udp_attach(device_t dev)
|
||||
}
|
||||
device_set_ivars(sc->sc_dci.sc_bus.bdev, &sc->sc_dci.sc_bus);
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_dci.sc_config_td, sc,
|
||||
&sc->sc_dci.sc_bus.bus_mtx, NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(dev, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
|
||||
@ -224,10 +219,10 @@ at91_udp_attach(device_t dev)
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)at91_vbus_interrupt, sc, &sc->sc_vbus_intr_hdl);
|
||||
NULL, (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
|
||||
#else
|
||||
err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
(void *)at91_vbus_interrupt, sc, &sc->sc_vbus_intr_hdl);
|
||||
(void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
|
||||
#endif
|
||||
if (err) {
|
||||
sc->sc_vbus_intr_hdl = NULL;
|
||||
@ -241,7 +236,7 @@ at91_udp_attach(device_t dev)
|
||||
goto error;
|
||||
} else {
|
||||
/* poll VBUS one time */
|
||||
at91_vbus_interrupt(sc);
|
||||
at91_vbus_poll(sc);
|
||||
}
|
||||
return (0);
|
||||
|
||||
@ -305,8 +300,6 @@ at91_udp_detach(device_t dev)
|
||||
sc->sc_dci.sc_io_res);
|
||||
sc->sc_dci.sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_dci.sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_dci.sc_bus, NULL);
|
||||
|
||||
/* disable clocks */
|
||||
|
2327
sys/dev/usb2/controller/atmegadci.c
Normal file
2327
sys/dev/usb2/controller/atmegadci.c
Normal file
File diff suppressed because it is too large
Load Diff
273
sys/dev/usb2/controller/atmegadci.h
Normal file
273
sys/dev/usb2/controller/atmegadci.h
Normal file
@ -0,0 +1,273 @@
|
||||
/* $FreeBSD$ */
|
||||
/*-
|
||||
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* USB Device Port register definitions, copied from ATMEGA
|
||||
* documentation provided by ATMEL.
|
||||
*/
|
||||
|
||||
#ifndef _ATMEGADCI_H_
|
||||
#define _ATMEGADCI_H_
|
||||
|
||||
#define ATMEGA_MAX_DEVICES (USB_MIN_DEVICES + 1)
|
||||
|
||||
#ifndef ATMEGA_HAVE_BUS_SPACE
|
||||
#define ATMEGA_HAVE_BUS_SPACE 1
|
||||
#endif
|
||||
|
||||
#define ATMEGA_UEINT 0xF4
|
||||
#define ATMEGA_UEINT_MASK(n) (1 << (n)) /* endpoint interrupt mask */
|
||||
|
||||
#define ATMEGA_UEBCHX 0xF3 /* FIFO byte count high */
|
||||
#define ATMEGA_UEBCLX 0xF2 /* FIFO byte count low */
|
||||
#define ATMEGA_UEDATX 0xF1 /* FIFO data */
|
||||
|
||||
#define ATMEGA_UEIENX 0xF0 /* interrupt enable register */
|
||||
#define ATMEGA_UEIENX_TXINE (1 << 0)
|
||||
#define ATMEGA_UEIENX_STALLEDE (1 << 1)
|
||||
#define ATMEGA_UEIENX_RXOUTE (1 << 2)
|
||||
#define ATMEGA_UEIENX_RXSTPE (1 << 3) /* received SETUP packet */
|
||||
#define ATMEGA_UEIENX_NAKOUTE (1 << 4)
|
||||
#define ATMEGA_UEIENX_NAKINE (1 << 6)
|
||||
#define ATMEGA_UEIENX_FLERRE (1 << 7)
|
||||
|
||||
#define ATMEGA_UESTA1X 0xEF
|
||||
#define ATMEGA_UESTA1X_CURRBK (3 << 0) /* current bank */
|
||||
#define ATMEGA_UESTA1X_CTRLDIR (1 << 2) /* control endpoint direction */
|
||||
|
||||
#define ATMEGA_UESTA0X 0xEE
|
||||
#define ATMEGA_UESTA0X_NBUSYBK (3 << 0)
|
||||
#define ATMEGA_UESTA0X_DTSEQ (3 << 2)
|
||||
#define ATMEGA_UESTA0X_UNDERFI (1 << 5) /* underflow */
|
||||
#define ATMEGA_UESTA0X_OVERFI (1 << 6) /* overflow */
|
||||
#define ATMEGA_UESTA0X_CFGOK (1 << 7)
|
||||
|
||||
#define ATMEGA_UECFG1X 0xED /* endpoint config register */
|
||||
#define ATMEGA_UECFG1X_ALLOC (1 << 1)
|
||||
#define ATMEGA_UECFG1X_EPBK0 (0 << 2)
|
||||
#define ATMEGA_UECFG1X_EPBK1 (1 << 2)
|
||||
#define ATMEGA_UECFG1X_EPBK2 (2 << 2)
|
||||
#define ATMEGA_UECFG1X_EPBK3 (3 << 2)
|
||||
#define ATMEGA_UECFG1X_EPSIZE(n) ((n) << 4)
|
||||
|
||||
#define ATMEGA_UECFG0X 0xEC
|
||||
#define ATMEGA_UECFG0X_EPDIR (1 << 0) /* endpoint direction */
|
||||
#define ATMEGA_UECFG0X_EPTYPE0 (0 << 6)
|
||||
#define ATMEGA_UECFG0X_EPTYPE1 (1 << 6)
|
||||
#define ATMEGA_UECFG0X_EPTYPE2 (2 << 6)
|
||||
#define ATMEGA_UECFG0X_EPTYPE3 (3 << 6)
|
||||
|
||||
#define ATMEGA_UECONX 0xEB
|
||||
#define ATMEGA_UECONX_EPEN (1 << 0)
|
||||
#define ATMEGA_UECONX_RSTDT (1 << 3)
|
||||
#define ATMEGA_UECONX_STALLRQC (1 << 4) /* stall request clear */
|
||||
#define ATMEGA_UECONX_STALLRQ (1 << 5) /* stall request set */
|
||||
|
||||
#define ATMEGA_UERST 0xEA /* endpoint reset register */
|
||||
#define ATMEGA_UERST_MASK(n) (1 << (n))
|
||||
|
||||
#define ATMEGA_UENUM 0xE9 /* endpoint number */
|
||||
|
||||
#define ATMEGA_UEINTX 0xE8 /* interrupt register */
|
||||
#define ATMEGA_UEINTX_TXINI (1 << 0)
|
||||
#define ATMEGA_UEINTX_STALLEDI (1 << 1)
|
||||
#define ATMEGA_UEINTX_RXOUTI (1 << 2)
|
||||
#define ATMEGA_UEINTX_RXSTPI (1 << 3) /* received setup packet */
|
||||
#define ATMEGA_UEINTX_NAKOUTI (1 << 4)
|
||||
#define ATMEGA_UEINTX_RWAL (1 << 5)
|
||||
#define ATMEGA_UEINTX_NAKINI (1 << 6)
|
||||
#define ATMEGA_UEINTX_FIFOCON (1 << 7)
|
||||
|
||||
#define ATMEGA_UDMFN 0xE6
|
||||
#define ATMEGA_UDMFN_FNCERR (1 << 4)
|
||||
|
||||
#define ATMEGA_UDFNUMH 0xE5 /* frame number high */
|
||||
#define ATMEGA_UDFNUMH_MASK 7
|
||||
|
||||
#define ATMEGA_UDFNUML 0xE4 /* frame number low */
|
||||
#define ATMEGA_UDFNUML_MASK 0xFF
|
||||
|
||||
#define ATMEGA_FRAME_MASK 0x7FF
|
||||
|
||||
#define ATMEGA_UDADDR 0xE3 /* USB address */
|
||||
#define ATMEGA_UDADDR_MASK 0x7F
|
||||
#define ATMEGA_UDADDR_ADDEN (1 << 7)
|
||||
|
||||
#define ATMEGA_UDIEN 0xE2 /* USB device interrupt enable */
|
||||
#define ATMEGA_UDINT_SUSPE (1 << 0)
|
||||
#define ATMEGA_UDINT_MSOFE (1 << 1)
|
||||
#define ATMEGA_UDINT_SOFE (1 << 2)
|
||||
#define ATMEGA_UDINT_EORSTE (1 << 3)
|
||||
#define ATMEGA_UDINT_WAKEUPE (1 << 4)
|
||||
#define ATMEGA_UDINT_EORSME (1 << 5)
|
||||
#define ATMEGA_UDINT_UPRSME (1 << 6)
|
||||
|
||||
#define ATMEGA_UDINT 0xE1 /* USB device interrupt status */
|
||||
#define ATMEGA_UDINT_SUSPI (1 << 0)
|
||||
#define ATMEGA_UDINT_MSOFI (1 << 1)
|
||||
#define ATMEGA_UDINT_SOFI (1 << 2)
|
||||
#define ATMEGA_UDINT_EORSTI (1 << 3)
|
||||
#define ATMEGA_UDINT_WAKEUPI (1 << 4)
|
||||
#define ATMEGA_UDINT_EORSMI (1 << 5)
|
||||
#define ATMEGA_UDINT_UPRSMI (1 << 6)
|
||||
|
||||
#define ATMEGA_UDCON 0xE0 /* USB device connection register */
|
||||
#define ATMEGA_UDCON_DETACH (1 << 0)
|
||||
#define ATMEGA_UDCON_RMWKUP (1 << 1)
|
||||
#define ATMEGA_UDCON_LSM (1 << 2)
|
||||
#define ATMEGA_UDCON_RSTCPU (1 << 3)
|
||||
|
||||
#define ATMEGA_USBINT 0xDA
|
||||
#define ATMEGA_USBINT_VBUSTI (1 << 0) /* USB VBUS interrupt */
|
||||
|
||||
#define ATMEGA_USBSTA 0xD9
|
||||
#define ATMEGA_USBSTA_VBUS (1 << 0)
|
||||
#define ATMEGA_USBSTA_ID (1 << 1)
|
||||
|
||||
#define ATMEGA_USBCON 0xD8
|
||||
#define ATMEGA_USBCON_VBUSTE (1 << 0)
|
||||
#define ATMEGA_USBCON_OTGPADE (1 << 4)
|
||||
#define ATMEGA_USBCON_FRZCLK (1 << 5)
|
||||
#define ATMEGA_USBCON_USBE (1 << 7)
|
||||
|
||||
#define ATMEGA_UHWCON 0xD7
|
||||
#define ATMEGA_UHWCON_UVREGE (1 << 0)
|
||||
|
||||
#define ATMEGA_READ_1(sc, reg) \
|
||||
bus_space_read_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg)
|
||||
|
||||
#define ATMEGA_WRITE_1(sc, reg, data) \
|
||||
bus_space_write_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, data)
|
||||
|
||||
#define ATMEGA_WRITE_MULTI_1(sc, reg, ptr, len) \
|
||||
bus_space_write_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len)
|
||||
|
||||
#define ATMEGA_READ_MULTI_1(sc, reg, ptr, len) \
|
||||
bus_space_read_multi_1((sc)->sc_io_tag, (sc)->sc_io_hdl, reg, ptr, len)
|
||||
|
||||
/*
|
||||
* Maximum number of endpoints supported:
|
||||
*/
|
||||
#define ATMEGA_EP_MAX 7
|
||||
|
||||
struct atmegadci_td;
|
||||
|
||||
typedef uint8_t (atmegadci_cmd_t)(struct atmegadci_td *td);
|
||||
typedef void (atmegadci_clocks_t)(struct usb2_bus *);
|
||||
|
||||
struct atmegadci_td {
|
||||
struct atmegadci_td *obj_next;
|
||||
atmegadci_cmd_t *func;
|
||||
struct usb2_page_cache *pc;
|
||||
uint32_t offset;
|
||||
uint32_t remainder;
|
||||
uint16_t max_packet_size;
|
||||
uint8_t error:1;
|
||||
uint8_t alt_next:1;
|
||||
uint8_t short_pkt:1;
|
||||
uint8_t support_multi_buffer:1;
|
||||
uint8_t did_stall:1;
|
||||
uint8_t ep_no:3;
|
||||
};
|
||||
|
||||
struct atmegadci_std_temp {
|
||||
atmegadci_cmd_t *func;
|
||||
struct usb2_page_cache *pc;
|
||||
struct atmegadci_td *td;
|
||||
struct atmegadci_td *td_next;
|
||||
uint32_t len;
|
||||
uint32_t offset;
|
||||
uint16_t max_frame_size;
|
||||
uint8_t short_pkt;
|
||||
/*
|
||||
* short_pkt = 0: transfer should be short terminated
|
||||
* short_pkt = 1: transfer should not be short terminated
|
||||
*/
|
||||
uint8_t setup_alt_next;
|
||||
};
|
||||
|
||||
struct atmegadci_config_desc {
|
||||
struct usb2_config_descriptor confd;
|
||||
struct usb2_interface_descriptor ifcd;
|
||||
struct usb2_endpoint_descriptor endpd;
|
||||
} __packed;
|
||||
|
||||
union atmegadci_hub_temp {
|
||||
uWord wValue;
|
||||
struct usb2_port_status ps;
|
||||
};
|
||||
|
||||
struct atmegadci_flags {
|
||||
uint8_t change_connect:1;
|
||||
uint8_t change_suspend:1;
|
||||
uint8_t status_suspend:1; /* set if suspended */
|
||||
uint8_t status_vbus:1; /* set if present */
|
||||
uint8_t status_bus_reset:1; /* set if reset complete */
|
||||
uint8_t remote_wakeup:1;
|
||||
uint8_t self_powered:1;
|
||||
uint8_t clocks_off:1;
|
||||
uint8_t port_powered:1;
|
||||
uint8_t port_enabled:1;
|
||||
uint8_t d_pulled_up:1;
|
||||
};
|
||||
|
||||
struct atmegadci_softc {
|
||||
struct usb2_bus sc_bus;
|
||||
union atmegadci_hub_temp sc_hub_temp;
|
||||
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
|
||||
/* must be set by by the bus interface layer */
|
||||
atmegadci_clocks_t *sc_clocks_on;
|
||||
atmegadci_clocks_t *sc_clocks_off;
|
||||
|
||||
struct usb2_device *sc_devices[ATMEGA_MAX_DEVICES];
|
||||
struct resource *sc_irq_res;
|
||||
void *sc_intr_hdl;
|
||||
#if (ATMEGA_HAVE_BUS_SPACE != 0)
|
||||
struct resource *sc_io_res;
|
||||
bus_space_tag_t sc_io_tag;
|
||||
bus_space_handle_t sc_io_hdl;
|
||||
#endif
|
||||
uint8_t sc_rt_addr; /* root hub address */
|
||||
uint8_t sc_dv_addr; /* device address */
|
||||
uint8_t sc_conf; /* root hub config */
|
||||
|
||||
uint8_t sc_hub_idata[1];
|
||||
|
||||
struct atmegadci_flags sc_flags;
|
||||
};
|
||||
|
||||
/* prototypes */
|
||||
|
||||
usb2_error_t atmegadci_init(struct atmegadci_softc *sc);
|
||||
void atmegadci_uninit(struct atmegadci_softc *sc);
|
||||
void atmegadci_suspend(struct atmegadci_softc *sc);
|
||||
void atmegadci_resume(struct atmegadci_softc *sc);
|
||||
void atmegadci_interrupt(struct atmegadci_softc *sc);
|
||||
|
||||
#endif /* _ATMEGADCI_H_ */
|
27
sys/dev/usb2/controller/atmegadci_atmelarm.c
Normal file
27
sys/dev/usb2/controller/atmegadci_atmelarm.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
@ -52,14 +52,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR ehcidebug
|
||||
#define usb2_config_td_cc ehci_config_copy
|
||||
#define usb2_config_td_softc ehci_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -99,7 +96,6 @@ extern struct usb2_pipe_methods ehci_device_isoc_hs_methods;
|
||||
extern struct usb2_pipe_methods ehci_root_ctrl_methods;
|
||||
extern struct usb2_pipe_methods ehci_root_intr_methods;
|
||||
|
||||
static usb2_config_td_command_t ehci_root_ctrl_task;
|
||||
static void ehci_do_poll(struct usb2_bus *bus);
|
||||
static void ehci_root_ctrl_poll(ehci_softc_t *sc);
|
||||
static void ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
|
||||
@ -975,7 +971,7 @@ ehci_transfer_intr_enqueue(struct usb2_xfer *xfer)
|
||||
return;
|
||||
}
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1139,7 +1135,7 @@ _ehci_remove_qh(ehci_qh_t *sqh, ehci_qh_t *last)
|
||||
static usb2_error_t
|
||||
ehci_non_isoc_done_sub(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
ehci_qtd_t *td;
|
||||
ehci_qtd_t *td_alt_next;
|
||||
uint32_t status;
|
||||
@ -1243,7 +1239,7 @@ ehci_non_isoc_done(struct usb2_xfer *xfer)
|
||||
|
||||
#if USB_DEBUG
|
||||
if (ehcidebug > 10) {
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
ehci_dump_sqtds(sc, xfer->td_transfer_first);
|
||||
}
|
||||
@ -1295,7 +1291,7 @@ static uint8_t
|
||||
ehci_check_transfer(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_pipe_methods *methods = xfer->pipe->methods;
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
uint32_t status;
|
||||
|
||||
@ -1525,7 +1521,7 @@ ehci_timeout(void *arg)
|
||||
|
||||
DPRINTF("xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
ehci_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -1735,11 +1731,11 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
|
||||
DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.average = xfer->max_usb2_frame_size;
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
temp.sc = xfer->usb2_sc;
|
||||
temp.sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* toggle the DMA set we are using */
|
||||
xfer->flags_int.curr_dma_set ^= 1;
|
||||
@ -1767,7 +1763,7 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
temp.auto_data_toggle = 1;
|
||||
}
|
||||
|
||||
if (usb2_get_speed(xfer->udev) != USB_SPEED_HIGH) {
|
||||
if (usb2_get_speed(xfer->xroot->udev) != USB_SPEED_HIGH) {
|
||||
/* max 3 retries */
|
||||
temp.qtd_status |=
|
||||
htoehci32(temp.sc, EHCI_QTD_SET_CERR(3));
|
||||
@ -1898,12 +1894,12 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
EHCI_QH_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
|
||||
EHCI_QH_SET_MPL(xfer->max_packet_size));
|
||||
|
||||
if (usb2_get_speed(xfer->udev) == USB_SPEED_HIGH) {
|
||||
if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
|
||||
qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) |
|
||||
EHCI_QH_DTC | EHCI_QH_SET_NRL(8));
|
||||
} else {
|
||||
|
||||
if (usb2_get_speed(xfer->udev) == USB_SPEED_FULL) {
|
||||
if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_FULL) {
|
||||
qh_endp |= (EHCI_QH_SET_EPS(EHCI_QH_SPEED_FULL) |
|
||||
EHCI_QH_DTC);
|
||||
} else {
|
||||
@ -1926,8 +1922,8 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
(EHCI_QH_SET_MULT(xfer->max_packet_count & 3) |
|
||||
EHCI_QH_SET_CMASK(xfer->usb2_cmask) |
|
||||
EHCI_QH_SET_SMASK(xfer->usb2_smask) |
|
||||
EHCI_QH_SET_HUBA(xfer->udev->hs_hub_addr) |
|
||||
EHCI_QH_SET_PORT(xfer->udev->hs_port_no));
|
||||
EHCI_QH_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
|
||||
EHCI_QH_SET_PORT(xfer->xroot->udev->hs_port_no));
|
||||
|
||||
qh->qh_endphub = htoehci32(temp.sc, qh_endphub);
|
||||
qh->qh_curqtd = htoehci32(temp.sc, 0);
|
||||
@ -1955,7 +1951,7 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
|
||||
|
||||
usb2_pc_cpu_flush(qh->page_cache);
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->xroot->udev->pwr_save.suspended == 0) {
|
||||
EHCI_APPEND_QH(qh, *qh_last);
|
||||
}
|
||||
}
|
||||
@ -1964,7 +1960,7 @@ static void
|
||||
ehci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t i;
|
||||
uint16_t m;
|
||||
|
||||
@ -2121,7 +2117,7 @@ static void
|
||||
ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
struct usb2_pipe_methods *methods = xfer->pipe->methods;
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
|
||||
|
||||
@ -2134,7 +2130,7 @@ ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
if (ehcidebug > 8) {
|
||||
DPRINTF("nexttog=%d; data after transfer:\n",
|
||||
xfer->pipe->toggle_next);
|
||||
ehci_dump_sqtds(xfer->usb2_sc,
|
||||
ehci_dump_sqtds(sc,
|
||||
xfer->td_transfer_first);
|
||||
}
|
||||
#endif
|
||||
@ -2189,7 +2185,7 @@ ehci_device_bulk_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_device_bulk_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
|
||||
@ -2232,7 +2228,7 @@ ehci_device_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_device_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
|
||||
@ -2257,7 +2253,7 @@ struct usb2_pipe_methods ehci_device_ctrl_methods =
|
||||
static void
|
||||
ehci_device_intr_open(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t best;
|
||||
uint16_t bit;
|
||||
uint16_t x;
|
||||
@ -2266,9 +2262,9 @@ ehci_device_intr_open(struct usb2_xfer *xfer)
|
||||
/* Allocate a microframe slot first: */
|
||||
|
||||
slot = usb2_intr_schedule_adjust
|
||||
(xfer->udev, xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX);
|
||||
(xfer->xroot->udev, xfer->max_frame_size, USB_HS_MICRO_FRAMES_MAX);
|
||||
|
||||
if (usb2_get_speed(xfer->udev) == USB_SPEED_HIGH) {
|
||||
if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
|
||||
xfer->usb2_uframe = slot;
|
||||
xfer->usb2_smask = (1 << slot) & 0xFF;
|
||||
xfer->usb2_cmask = 0;
|
||||
@ -2310,11 +2306,11 @@ ehci_device_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_device_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t slot;
|
||||
|
||||
slot = usb2_intr_schedule_adjust
|
||||
(xfer->udev, -(xfer->max_frame_size), xfer->usb2_uframe);
|
||||
(xfer->xroot->udev, -(xfer->max_frame_size), xfer->usb2_uframe);
|
||||
|
||||
sc->sc_intr_stat[xfer->qh_pos]--;
|
||||
|
||||
@ -2330,7 +2326,7 @@ ehci_device_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_device_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ehci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
@ -2355,7 +2351,7 @@ struct usb2_pipe_methods ehci_device_intr_methods =
|
||||
static void
|
||||
ehci_device_isoc_fs_open(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
ehci_sitd_t *td;
|
||||
uint32_t sitd_portaddr;
|
||||
uint8_t ds;
|
||||
@ -2363,8 +2359,8 @@ ehci_device_isoc_fs_open(struct usb2_xfer *xfer)
|
||||
sitd_portaddr =
|
||||
EHCI_SITD_SET_ADDR(xfer->address) |
|
||||
EHCI_SITD_SET_ENDPT(UE_GET_ADDR(xfer->endpoint)) |
|
||||
EHCI_SITD_SET_HUBA(xfer->udev->hs_hub_addr) |
|
||||
EHCI_SITD_SET_PORT(xfer->udev->hs_port_no);
|
||||
EHCI_SITD_SET_HUBA(xfer->xroot->udev->hs_hub_addr) |
|
||||
EHCI_SITD_SET_PORT(xfer->xroot->udev->hs_port_no);
|
||||
|
||||
if (UE_GET_DIR(xfer->endpoint) == UE_DIR_IN) {
|
||||
sitd_portaddr |= EHCI_SITD_SET_DIR_IN;
|
||||
@ -2403,7 +2399,7 @@ static void
|
||||
ehci_device_isoc_fs_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_page_search buf_res;
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
struct usb2_fs_isoc_schedule *fss_start;
|
||||
struct usb2_fs_isoc_schedule *fss_end;
|
||||
struct usb2_fs_isoc_schedule *fss;
|
||||
@ -2464,7 +2460,7 @@ ehci_device_isoc_fs_enter(struct usb2_xfer *xfer)
|
||||
*/
|
||||
xfer->isoc_time_complete =
|
||||
usb2_fs_isoc_schedule_isoc_time_expand
|
||||
(xfer->udev, &fss_start, &fss_end, nframes) + buf_offset +
|
||||
(xfer->xroot->udev, &fss_start, &fss_end, nframes) + buf_offset +
|
||||
xfer->nframes;
|
||||
|
||||
/* get the real number of frames */
|
||||
@ -2640,7 +2636,7 @@ struct usb2_pipe_methods ehci_device_isoc_fs_methods =
|
||||
static void
|
||||
ehci_device_isoc_hs_open(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
ehci_itd_t *td;
|
||||
uint32_t temp;
|
||||
uint8_t ds;
|
||||
@ -2694,7 +2690,7 @@ static void
|
||||
ehci_device_isoc_hs_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_page_search buf_res;
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
ehci_itd_t *td;
|
||||
ehci_itd_t *td_last = NULL;
|
||||
ehci_itd_t **pp_last;
|
||||
@ -2918,7 +2914,7 @@ ehci_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -3025,28 +3021,26 @@ ehci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command
|
||||
(&sc->sc_config_td, NULL, &ehci_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_root_ctrl_task(ehci_softc_t *sc,
|
||||
struct usb2_config_td_cc *cc, uint16_t refcount)
|
||||
ehci_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
ehci_root_ctrl_poll(sc);
|
||||
ehci_root_ctrl_poll(EHCI_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
char *ptr;
|
||||
uint32_t port;
|
||||
uint32_t v;
|
||||
@ -3072,7 +3066,7 @@ ehci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
|
||||
"wValue=0x%04x wIndex=0x%04x\n",
|
||||
@ -3489,7 +3483,7 @@ ehci_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -3506,7 +3500,7 @@ ehci_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ehci_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ehci_softc_t *sc = xfer->usb2_sc;
|
||||
ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
}
|
||||
@ -3543,11 +3537,6 @@ ehci_xfer_setup(struct usb2_setup_params *parm)
|
||||
nsitd = 0;
|
||||
nitd = 0;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
/*
|
||||
* compute maximum number of some structures
|
||||
*/
|
||||
@ -3870,7 +3859,7 @@ ehci_device_resume(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
|
||||
@ -3904,7 +3893,7 @@ ehci_device_suspend(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
|
||||
@ -3969,4 +3958,5 @@ struct usb2_bus_methods ehci_bus_methods =
|
||||
.device_resume = ehci_device_resume,
|
||||
.device_suspend = ehci_device_suspend,
|
||||
.set_hw_power = ehci_set_hw_power,
|
||||
.roothub_exec = ehci_root_ctrl_task,
|
||||
};
|
||||
|
@ -38,6 +38,8 @@
|
||||
#ifndef _EHCI_H_
|
||||
#define _EHCI_H_
|
||||
|
||||
#define EHCI_MAX_DEVICES USB_MAX_DEVICES
|
||||
|
||||
/* PCI config registers */
|
||||
#define PCI_CBMEM 0x10 /* configuration base MEM */
|
||||
#define PCI_INTERFACE_EHCI 0x20
|
||||
@ -453,12 +455,12 @@ union ehci_hub_desc {
|
||||
typedef struct ehci_softc {
|
||||
struct ehci_hw_softc sc_hw;
|
||||
struct usb2_bus sc_bus; /* base device */
|
||||
struct usb2_config_td sc_config_td;
|
||||
struct usb2_callout sc_tmo_pcd;
|
||||
union ehci_hub_desc sc_hub_desc;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
|
||||
struct usb2_device *sc_devices[EHCI_MAX_DEVICES];
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
struct ehci_qh *sc_async_p_last;
|
||||
|
@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -232,12 +231,15 @@ ehci_pci_attach(device_t self)
|
||||
device_printf(self, "Could not allocate sc\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_bus.parent = self;
|
||||
sc->sc_bus.devices = sc->sc_devices;
|
||||
sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_bus,
|
||||
USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
|
||||
return ENOMEM;
|
||||
return (ENOMEM);
|
||||
}
|
||||
sc->sc_dev = self;
|
||||
|
||||
@ -259,8 +261,10 @@ ehci_pci_attach(device_t self)
|
||||
sc->sc_bus.usbrev = USB_REV_2_0;
|
||||
break;
|
||||
default:
|
||||
sc->sc_bus.usbrev = USB_REV_UNKNOWN;
|
||||
break;
|
||||
/* Quirk for Parallels Desktop 4.0 */
|
||||
device_printf(self, "USB revision is unknown. Assuming v2.0.\n");
|
||||
sc->sc_bus.usbrev = USB_REV_2_0;
|
||||
break;
|
||||
}
|
||||
|
||||
rid = PCI_CBMEM;
|
||||
@ -338,12 +342,6 @@ ehci_pci_attach(device_t self)
|
||||
sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
|
||||
}
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_bus.bus_mtx,
|
||||
NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(self, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
|
||||
@ -378,8 +376,6 @@ ehci_pci_detach(device_t self)
|
||||
ehci_softc_t *sc = device_get_softc(self);
|
||||
device_t bdev;
|
||||
|
||||
usb2_config_td_drain(&sc->sc_config_td);
|
||||
|
||||
if (sc->sc_bus.bdev) {
|
||||
bdev = sc->sc_bus.bdev;
|
||||
device_detach(bdev);
|
||||
@ -419,8 +415,6 @@ ehci_pci_detach(device_t self)
|
||||
sc->sc_io_res);
|
||||
sc->sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
|
||||
|
||||
return (0);
|
||||
|
@ -42,14 +42,11 @@
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR musbotgdebug
|
||||
#define usb2_config_td_cc musbotg_config_copy
|
||||
#define usb2_config_td_softc musbotg_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -101,7 +98,6 @@ static void musbotg_interrupt_poll(struct musbotg_softc *);
|
||||
|
||||
static usb2_sw_transfer_func_t musbotg_root_intr_done;
|
||||
static usb2_sw_transfer_func_t musbotg_root_ctrl_done;
|
||||
static usb2_config_td_command_t musbotg_root_ctrl_task;
|
||||
|
||||
/*
|
||||
* Here is a configuration that the chip supports.
|
||||
@ -208,14 +204,14 @@ musbotg_pull_down(struct musbotg_softc *sc)
|
||||
static void
|
||||
musbotg_wakeup_peer(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t temp;
|
||||
uint8_t use_polling;
|
||||
|
||||
if (!(sc->sc_flags.status_suspend)) {
|
||||
return;
|
||||
}
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
temp = MUSB2_READ_1(sc, MUSB2_REG_POWER);
|
||||
temp |= MUSB2_MASK_RESUME;
|
||||
@ -935,7 +931,7 @@ musbotg_xfer_do_fifo(struct usb2_xfer *xfer)
|
||||
return (1); /* not complete */
|
||||
|
||||
done:
|
||||
sc = xfer->usb2_sc;
|
||||
sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* compute all actual lengths */
|
||||
|
||||
@ -958,11 +954,9 @@ repeat:
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_vbus_interrupt(struct usb2_bus *bus, uint8_t is_on)
|
||||
void
|
||||
musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
|
||||
{
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(bus);
|
||||
|
||||
DPRINTFN(4, "vbus = %u\n", is_on);
|
||||
|
||||
USB_BUS_LOCK(&sc->sc_bus);
|
||||
@ -1134,7 +1128,7 @@ musbotg_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
|
||||
DPRINTFN(8, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
|
||||
@ -1149,7 +1143,7 @@ musbotg_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
|
||||
temp.offset = 0;
|
||||
|
||||
sc = xfer->usb2_sc;
|
||||
sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
ep_no = (xfer->endpoint & UE_ADDR);
|
||||
|
||||
/* check if we should prepend a setup message */
|
||||
@ -1249,7 +1243,7 @@ musbotg_timeout(void *arg)
|
||||
|
||||
DPRINTFN(1, "xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
musbotg_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -1258,7 +1252,7 @@ musbotg_timeout(void *arg)
|
||||
static void
|
||||
musbotg_ep_int_set(struct usb2_xfer *xfer, uint8_t on)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t temp;
|
||||
uint8_t ep_no = xfer->endpoint & UE_ADDR;
|
||||
|
||||
@ -1308,7 +1302,7 @@ musbotg_start_standard_chain(struct usb2_xfer *xfer)
|
||||
DPRINTFN(14, "enabled interrupts on endpoint\n");
|
||||
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1322,7 +1316,7 @@ static void
|
||||
musbotg_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTFN(8, "\n");
|
||||
|
||||
@ -1462,7 +1456,7 @@ done:
|
||||
static void
|
||||
musbotg_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
|
||||
xfer, xfer->pipe, error);
|
||||
@ -2025,7 +2019,7 @@ musbotg_device_isoc_close(struct usb2_xfer *xfer)
|
||||
static void
|
||||
musbotg_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t temp;
|
||||
uint32_t nframes;
|
||||
uint32_t fs_frames;
|
||||
@ -2043,7 +2037,7 @@ musbotg_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
*/
|
||||
temp = (nframes - xfer->pipe->isoc_next) & MUSB2_MASK_FRAME;
|
||||
|
||||
if (usb2_get_speed(xfer->udev) == USB_SPEED_HIGH) {
|
||||
if (usb2_get_speed(xfer->xroot->udev) == USB_SPEED_HIGH) {
|
||||
fs_frames = (xfer->nframes + 7) / 8;
|
||||
} else {
|
||||
fs_frames = xfer->nframes;
|
||||
@ -2113,7 +2107,7 @@ musbotg_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
musbotg_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -2218,26 +2212,24 @@ musbotg_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
musbotg_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command(
|
||||
&sc->sc_config_td, NULL, &musbotg_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_root_ctrl_task(struct musbotg_softc *sc,
|
||||
struct musbotg_config_copy *cc, uint16_t refcount)
|
||||
musbotg_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
musbotg_root_ctrl_poll(sc);
|
||||
musbotg_root_ctrl_poll(MUSBOTG_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
musbotg_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint8_t use_polling;
|
||||
@ -2258,7 +2250,7 @@ musbotg_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
/* demultiplex the control request */
|
||||
|
||||
@ -2666,7 +2658,7 @@ musbotg_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
musbotg_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -2683,7 +2675,7 @@ musbotg_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
musbotg_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct musbotg_softc *sc = xfer->usb2_sc;
|
||||
struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
}
|
||||
@ -2712,11 +2704,6 @@ musbotg_xfer_setup(struct usb2_setup_params *parm)
|
||||
sc = MUSBOTG_BUS2SC(parm->udev->bus);
|
||||
xfer = parm->curr_xfer;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
/*
|
||||
* NOTE: This driver does not use any of the parameters that
|
||||
* are computed from the following values. Just set some
|
||||
@ -2884,5 +2871,5 @@ struct usb2_bus_methods musbotg_bus_methods =
|
||||
.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
|
||||
.set_stall = &musbotg_set_stall,
|
||||
.clear_stall = &musbotg_clear_stall,
|
||||
.vbus_interrupt = &musbotg_vbus_interrupt,
|
||||
.roothub_exec = &musbotg_root_ctrl_task,
|
||||
};
|
||||
|
@ -32,6 +32,8 @@
|
||||
#ifndef _MUSB2_OTG_H_
|
||||
#define _MUSB2_OTG_H_
|
||||
|
||||
#define MUSB2_MAX_DEVICES (USB_MIN_DEVICES + 1)
|
||||
|
||||
/* Common registers */
|
||||
|
||||
#define MUSB2_REG_FADDR 0x0000 /* function address register */
|
||||
@ -363,8 +365,9 @@ struct musbotg_softc {
|
||||
union musbotg_hub_temp sc_hub_temp;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
struct usb2_config_td sc_config_td;
|
||||
struct usb2_hw_ep_profile sc_hw_ep_profile[16];
|
||||
|
||||
struct usb2_device *sc_devices[MUSB2_MAX_DEVICES];
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
void *sc_intr_hdl;
|
||||
@ -399,5 +402,6 @@ void musbotg_uninit(struct musbotg_softc *sc);
|
||||
void musbotg_suspend(struct musbotg_softc *sc);
|
||||
void musbotg_resume(struct musbotg_softc *sc);
|
||||
void musbotg_interrupt(struct musbotg_softc *sc);
|
||||
void musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on);
|
||||
|
||||
#endif /* _MUSB2_OTG_H_ */
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -51,14 +50,12 @@ struct musbotg_super_softc {
|
||||
};
|
||||
|
||||
static void
|
||||
musbotg_vbus_interrupt(struct musbotg_super_softc *sc)
|
||||
musbotg_vbus_poll(struct musbotg_super_softc *sc)
|
||||
{
|
||||
uint8_t vbus_val = 1; /* fake VBUS on - TODO */
|
||||
|
||||
/* just forward it */
|
||||
|
||||
(sc->sc_otg.sc_bus.methods->vbus_interrupt)
|
||||
(&sc->sc_otg.sc_bus, vbus_val);
|
||||
musbotg_vbus_interrupt(&sc->sc_otg, vbus_val);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -102,9 +99,12 @@ musbotg_attach(device_t dev)
|
||||
sc->sc_otg.sc_clocks_off = &musbotg_clocks_off;
|
||||
sc->sc_otg.sc_clocks_arg = sc;
|
||||
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_otg.sc_bus.parent = dev;
|
||||
sc->sc_otg.sc_bus.devices = sc->sc_otg.sc_devices;
|
||||
sc->sc_otg.sc_bus.devices_max = MUSB2_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_otg.sc_bus,
|
||||
USB_GET_DMA_TAG(dev), NULL)) {
|
||||
return (ENOMEM);
|
||||
@ -133,12 +133,6 @@ musbotg_attach(device_t dev)
|
||||
}
|
||||
device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_otg.sc_config_td, sc,
|
||||
&sc->sc_otg.sc_bus.bus_mtx, NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(dev, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
|
||||
@ -158,7 +152,7 @@ musbotg_attach(device_t dev)
|
||||
goto error;
|
||||
} else {
|
||||
/* poll VBUS one time */
|
||||
musbotg_vbus_interrupt(sc);
|
||||
musbotg_vbus_poll(sc);
|
||||
}
|
||||
return (0);
|
||||
|
||||
@ -204,8 +198,6 @@ musbotg_detach(device_t dev)
|
||||
sc->sc_otg.sc_io_res);
|
||||
sc->sc_otg.sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_otg.sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_otg.sc_bus, NULL);
|
||||
|
||||
return (0);
|
||||
|
@ -41,14 +41,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR ohcidebug
|
||||
#define usb2_config_td_cc ohci_config_copy
|
||||
#define usb2_config_td_softc ohci_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -99,7 +96,6 @@ extern struct usb2_pipe_methods ohci_device_isoc_methods;
|
||||
extern struct usb2_pipe_methods ohci_root_ctrl_methods;
|
||||
extern struct usb2_pipe_methods ohci_root_intr_methods;
|
||||
|
||||
static usb2_config_td_command_t ohci_root_ctrl_task;
|
||||
static void ohci_root_ctrl_poll(struct ohci_softc *sc);
|
||||
static void ohci_do_poll(struct usb2_bus *bus);
|
||||
static void ohci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
|
||||
@ -673,7 +669,7 @@ ohci_transfer_intr_enqueue(struct usb2_xfer *xfer)
|
||||
return;
|
||||
}
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1237,7 +1233,7 @@ ohci_timeout(void *arg)
|
||||
|
||||
DPRINTF("xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
ohci_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -1408,7 +1404,7 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
|
||||
|
||||
DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.average = xfer->max_usb2_frame_size;
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
@ -1553,27 +1549,26 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
|
||||
|
||||
ed_flags |= (OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD);
|
||||
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
ed_flags |= OHCI_ED_SPEED;
|
||||
}
|
||||
ed->ed_flags = htole32(ed_flags);
|
||||
|
||||
usb2_pc_cpu_flush(ed->page_cache);
|
||||
|
||||
td = xfer->td_transfer_first;
|
||||
|
||||
ed->ed_headp = td->td_self;
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->xroot->udev->pwr_save.suspended == 0) {
|
||||
/* the append function will flush the endpoint descriptor */
|
||||
OHCI_APPEND_QH(ed, *ed_last);
|
||||
|
||||
if (methods == &ohci_device_bulk_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
|
||||
}
|
||||
if (methods == &ohci_device_ctrl_methods) {
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
|
||||
}
|
||||
@ -1586,7 +1581,7 @@ static void
|
||||
ohci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t hstatus;
|
||||
uint16_t i;
|
||||
uint16_t m;
|
||||
@ -1634,7 +1629,7 @@ static void
|
||||
ohci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
struct usb2_pipe_methods *methods = xfer->pipe->methods;
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
ohci_ed_t *ed;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
|
||||
@ -1690,7 +1685,7 @@ ohci_device_bulk_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_device_bulk_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ohci_setup_standard_chain(xfer, &sc->sc_bulk_p_last);
|
||||
@ -1733,7 +1728,7 @@ ohci_device_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_device_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ohci_setup_standard_chain(xfer, &sc->sc_ctrl_p_last);
|
||||
@ -1758,7 +1753,7 @@ struct usb2_pipe_methods ohci_device_ctrl_methods =
|
||||
static void
|
||||
ohci_device_intr_open(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t best;
|
||||
uint16_t bit;
|
||||
uint16_t x;
|
||||
@ -1791,7 +1786,7 @@ ohci_device_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_device_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_intr_stat[xfer->qh_pos]--;
|
||||
|
||||
@ -1807,7 +1802,7 @@ ohci_device_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_device_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
/* setup TD's and QH */
|
||||
ohci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
@ -1846,7 +1841,7 @@ static void
|
||||
ohci_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_page_search buf_res;
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
struct ohci_hcca *hcca;
|
||||
uint32_t buf_offset;
|
||||
uint32_t nframes;
|
||||
@ -2004,18 +1999,17 @@ ohci_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
OHCI_ED_SET_EN(UE_GET_ADDR(xfer->endpoint)) |
|
||||
OHCI_ED_SET_MAXP(xfer->max_frame_size));
|
||||
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
ed_flags |= OHCI_ED_SPEED;
|
||||
}
|
||||
ed->ed_flags = htole32(ed_flags);
|
||||
|
||||
usb2_pc_cpu_flush(ed->page_cache);
|
||||
|
||||
td = xfer->td_transfer_first;
|
||||
|
||||
ed->ed_headp = td->itd_self;
|
||||
|
||||
/* isochronous transfers are not affected by suspend / resume */
|
||||
/* the append function will flush the endpoint descriptor */
|
||||
|
||||
OHCI_APPEND_QH(ed, sc->sc_isoc_p_last);
|
||||
}
|
||||
@ -2053,7 +2047,7 @@ ohci_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -2133,26 +2127,24 @@ ohci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command
|
||||
(&sc->sc_config_td, NULL, &ohci_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_root_ctrl_task(struct ohci_softc *sc,
|
||||
struct ohci_config_copy *cc, uint16_t refcount)
|
||||
ohci_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
ohci_root_ctrl_poll(sc);
|
||||
ohci_root_ctrl_poll(OHCI_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
ohci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
char *ptr;
|
||||
uint32_t port;
|
||||
uint32_t v;
|
||||
@ -2177,7 +2169,7 @@ ohci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
|
||||
"wValue=0x%04x wIndex=0x%04x\n",
|
||||
@ -2478,7 +2470,7 @@ ohci_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -2495,7 +2487,7 @@ ohci_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
ohci_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
ohci_softc_t *sc = xfer->usb2_sc;
|
||||
ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
}
|
||||
@ -2526,11 +2518,6 @@ ohci_xfer_setup(struct usb2_setup_params *parm)
|
||||
sc = OHCI_BUS2SC(parm->udev->bus);
|
||||
xfer = parm->curr_xfer;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
parm->hc_max_packet_size = 0x500;
|
||||
parm->hc_max_packet_count = 1;
|
||||
parm->hc_max_frame_size = OHCI_PAGE_SIZE;
|
||||
@ -2761,7 +2748,7 @@ ohci_device_resume(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
@ -2799,7 +2786,7 @@ ohci_device_suspend(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
@ -2866,4 +2853,5 @@ struct usb2_bus_methods ohci_bus_methods =
|
||||
.device_resume = ohci_device_resume,
|
||||
.device_suspend = ohci_device_suspend,
|
||||
.set_hw_power = ohci_set_hw_power,
|
||||
.roothub_exec = ohci_root_ctrl_task,
|
||||
};
|
||||
|
@ -39,6 +39,8 @@
|
||||
#ifndef _OHCI_H_
|
||||
#define _OHCI_H_
|
||||
|
||||
#define OHCI_MAX_DEVICES USB_MAX_DEVICES
|
||||
|
||||
/* PCI config registers */
|
||||
#define PCI_CBMEM 0x10 /* configuration base memory */
|
||||
#define PCI_INTERFACE_OHCI 0x10
|
||||
@ -318,12 +320,12 @@ union ohci_hub_desc {
|
||||
typedef struct ohci_softc {
|
||||
struct ohci_hw_softc sc_hw;
|
||||
struct usb2_bus sc_bus; /* base device */
|
||||
struct usb2_config_td sc_config_td;
|
||||
struct usb2_callout sc_tmo_rhsc;
|
||||
union ohci_hub_desc sc_hub_desc;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
|
||||
struct usb2_device *sc_devices[OHCI_MAX_DEVICES];
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
struct ohci_hcca *sc_hcca_p;
|
||||
|
@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -73,12 +72,15 @@ ohci_atmelarm_attach(device_t dev)
|
||||
if (sc == NULL) {
|
||||
return (ENXIO);
|
||||
}
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_ohci.sc_bus.parent = dev;
|
||||
sc->sc_ohci.sc_bus.devices = sc->sc_ohci.sc_devices;
|
||||
sc->sc_ohci.sc_bus.devices_max = OHCI_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_ohci.sc_bus,
|
||||
USB_GET_DMA_TAG(dev), &ohci_iterate_hw_softc)) {
|
||||
return ENOMEM;
|
||||
return (ENOMEM);
|
||||
}
|
||||
sc->iclk = at91_pmc_clock_ref("ohci_clk");
|
||||
sc->fclk = at91_pmc_clock_ref("uhpck");
|
||||
@ -111,12 +113,6 @@ ohci_atmelarm_attach(device_t dev)
|
||||
|
||||
strlcpy(sc->sc_ohci.sc_vendor, "Atmel", sizeof(sc->sc_ohci.sc_vendor));
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_ohci.sc_config_td, sc,
|
||||
&sc->sc_ohci.sc_bus.bus_mtx, NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(dev, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
|
||||
@ -200,8 +196,6 @@ ohci_atmelarm_detach(device_t dev)
|
||||
sc->sc_ohci.sc_io_res);
|
||||
sc->sc_ohci.sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_ohci.sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_ohci.sc_bus, &ohci_iterate_hw_softc);
|
||||
|
||||
return (0);
|
||||
|
@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -200,12 +199,15 @@ ohci_pci_attach(device_t self)
|
||||
device_printf(self, "Could not allocate sc\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_bus.parent = self;
|
||||
sc->sc_bus.devices = sc->sc_devices;
|
||||
sc->sc_bus.devices_max = OHCI_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
|
||||
&ohci_iterate_hw_softc)) {
|
||||
return ENOMEM;
|
||||
return (ENOMEM);
|
||||
}
|
||||
sc->sc_dev = self;
|
||||
|
||||
@ -288,12 +290,6 @@ ohci_pci_attach(device_t self)
|
||||
sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
|
||||
}
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_bus.bus_mtx,
|
||||
NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(self, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
/* sc->sc_bus.usbrev; set by ohci_init() */
|
||||
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
@ -329,8 +325,6 @@ ohci_pci_detach(device_t self)
|
||||
ohci_softc_t *sc = device_get_softc(self);
|
||||
device_t bdev;
|
||||
|
||||
usb2_config_td_drain(&sc->sc_config_td);
|
||||
|
||||
if (sc->sc_bus.bdev) {
|
||||
bdev = sc->sc_bus.bdev;
|
||||
device_detach(bdev);
|
||||
@ -365,8 +359,6 @@ ohci_pci_detach(device_t self)
|
||||
sc->sc_io_res);
|
||||
sc->sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_bus, &ohci_iterate_hw_softc);
|
||||
|
||||
return (0);
|
||||
|
@ -44,14 +44,11 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR uhcidebug
|
||||
#define usb2_config_td_cc uhci_config_copy
|
||||
#define usb2_config_td_softc uhci_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -138,7 +135,6 @@ extern struct usb2_pipe_methods uhci_device_isoc_methods;
|
||||
extern struct usb2_pipe_methods uhci_root_ctrl_methods;
|
||||
extern struct usb2_pipe_methods uhci_root_intr_methods;
|
||||
|
||||
static usb2_config_td_command_t uhci_root_ctrl_task;
|
||||
static void uhci_root_ctrl_poll(struct uhci_softc *);
|
||||
static void uhci_do_poll(struct usb2_bus *);
|
||||
static void uhci_device_done(struct usb2_xfer *, usb2_error_t);
|
||||
@ -882,7 +878,7 @@ uhci_transfer_intr_enqueue(struct usb2_xfer *xfer)
|
||||
return;
|
||||
}
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1494,7 +1490,7 @@ uhci_timeout(void *arg)
|
||||
|
||||
DPRINTF("xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
uhci_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -1663,7 +1659,7 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
|
||||
DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.average = xfer->max_frame_size;
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
@ -1687,7 +1683,7 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
htole32(UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) |
|
||||
UHCI_TD_ACTIVE));
|
||||
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
temp.td_status |= htole32(UHCI_TD_LS);
|
||||
}
|
||||
temp.td_token =
|
||||
@ -1820,7 +1816,7 @@ static void
|
||||
uhci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
struct usb2_pipe_methods *methods = xfer->pipe->methods;
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uhci_qh_t *qh;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
|
||||
@ -1840,7 +1836,7 @@ uhci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
UHCI_REMOVE_QH(qh, sc->sc_bulk_p_last);
|
||||
}
|
||||
if (methods == &uhci_device_ctrl_methods) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
@ -1889,7 +1885,7 @@ uhci_device_bulk_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_device_bulk_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uhci_td_t *td;
|
||||
uhci_qh_t *qh;
|
||||
|
||||
@ -1902,7 +1898,7 @@ uhci_device_bulk_start(struct usb2_xfer *xfer)
|
||||
qh->e_next = td;
|
||||
qh->qh_e_next = td->td_self;
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->xroot->udev->pwr_save.suspended == 0) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_bulk_p_last);
|
||||
uhci_add_loop(sc);
|
||||
xfer->flags_int.bandwidth_reclaimed = 1;
|
||||
@ -1948,7 +1944,7 @@ uhci_device_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_device_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uhci_qh_t *qh;
|
||||
uhci_td_t *td;
|
||||
|
||||
@ -1965,8 +1961,8 @@ uhci_device_ctrl_start(struct usb2_xfer *xfer)
|
||||
* NOTE: some devices choke on bandwidth- reclamation for control
|
||||
* transfers
|
||||
*/
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
@ -1994,7 +1990,7 @@ struct usb2_pipe_methods uhci_device_ctrl_methods =
|
||||
static void
|
||||
uhci_device_intr_open(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t best;
|
||||
uint16_t bit;
|
||||
uint16_t x;
|
||||
@ -2027,7 +2023,7 @@ uhci_device_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_device_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_intr_stat[xfer->qh_pos]--;
|
||||
|
||||
@ -2043,7 +2039,7 @@ uhci_device_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_device_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uhci_qh_t *qh;
|
||||
uhci_td_t *td;
|
||||
|
||||
@ -2056,7 +2052,7 @@ uhci_device_intr_start(struct usb2_xfer *xfer)
|
||||
qh->e_next = td;
|
||||
qh->qh_e_next = td->td_self;
|
||||
|
||||
if (xfer->udev->pwr_save.suspended == 0) {
|
||||
if (xfer->xroot->udev->pwr_save.suspended == 0) {
|
||||
|
||||
/* enter QHs into the controller data structures */
|
||||
UHCI_APPEND_QH(qh, sc->sc_intr_p_last[xfer->qh_pos]);
|
||||
@ -2121,7 +2117,7 @@ static void
|
||||
uhci_device_isoc_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uhci_mem_layout ml;
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t nframes;
|
||||
uint32_t temp;
|
||||
uint32_t *plen;
|
||||
@ -2305,7 +2301,7 @@ uhci_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -2496,28 +2492,26 @@ uhci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command
|
||||
(&sc->sc_config_td, NULL, &uhci_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_root_ctrl_task(struct uhci_softc *sc,
|
||||
struct uhci_config_copy *cc, uint16_t refcount)
|
||||
uhci_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
uhci_root_ctrl_poll(sc);
|
||||
uhci_root_ctrl_poll(UHCI_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
char *ptr;
|
||||
uint16_t x;
|
||||
uint16_t port;
|
||||
@ -2543,7 +2537,7 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
DPRINTFN(3, "type=0x%02x request=0x%02x wLen=0x%04x "
|
||||
"wValue=0x%04x wIndex=0x%04x\n",
|
||||
@ -2872,7 +2866,7 @@ uhci_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -2889,7 +2883,7 @@ uhci_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uhci_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
|
||||
@ -2901,7 +2895,7 @@ static void
|
||||
uhci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
|
||||
|
||||
@ -2927,7 +2921,7 @@ static void
|
||||
uhci_root_intr_check(void *arg)
|
||||
{
|
||||
struct usb2_xfer *xfer = arg;
|
||||
uhci_softc_t *sc = xfer->usb2_sc;
|
||||
uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTFN(21, "\n");
|
||||
|
||||
@ -2981,11 +2975,6 @@ uhci_xfer_setup(struct usb2_setup_params *parm)
|
||||
sc = UHCI_BUS2SC(parm->udev->bus);
|
||||
xfer = parm->curr_xfer;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
parm->hc_max_packet_size = 0x500;
|
||||
parm->hc_max_packet_count = 1;
|
||||
parm->hc_max_frame_size = 0x500;
|
||||
@ -3247,7 +3236,7 @@ uhci_device_resume(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
@ -3258,7 +3247,7 @@ uhci_device_resume(struct usb2_device *udev)
|
||||
xfer->flags_int.bandwidth_reclaimed = 1;
|
||||
}
|
||||
if (methods == &uhci_device_ctrl_methods) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_APPEND_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_APPEND_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
@ -3289,7 +3278,7 @@ uhci_device_suspend(struct usb2_device *udev)
|
||||
|
||||
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
|
||||
|
||||
if (xfer->udev == udev) {
|
||||
if (xfer->xroot->udev == udev) {
|
||||
|
||||
methods = xfer->pipe->methods;
|
||||
qh = xfer->qh_start[xfer->flags_int.curr_dma_set];
|
||||
@ -3302,7 +3291,7 @@ uhci_device_suspend(struct usb2_device *udev)
|
||||
UHCI_REMOVE_QH(qh, sc->sc_bulk_p_last);
|
||||
}
|
||||
if (methods == &uhci_device_ctrl_methods) {
|
||||
if (xfer->udev->speed == USB_SPEED_LOW) {
|
||||
if (xfer->xroot->udev->speed == USB_SPEED_LOW) {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_ls_ctl_p_last);
|
||||
} else {
|
||||
UHCI_REMOVE_QH(qh, sc->sc_fs_ctl_p_last);
|
||||
@ -3361,4 +3350,5 @@ struct usb2_bus_methods uhci_bus_methods =
|
||||
.device_resume = uhci_device_resume,
|
||||
.device_suspend = uhci_device_suspend,
|
||||
.set_hw_power = uhci_set_hw_power,
|
||||
.roothub_exec = uhci_root_ctrl_task,
|
||||
};
|
||||
|
@ -39,6 +39,8 @@
|
||||
#ifndef _UHCI_H_
|
||||
#define _UHCI_H_
|
||||
|
||||
#define UHCI_MAX_DEVICES USB_MAX_DEVICES
|
||||
|
||||
/* PCI config registers */
|
||||
#define PCI_USBREV 0x60 /* USB protocol revision */
|
||||
#define PCI_USB_REV_MASK 0xff
|
||||
@ -268,11 +270,11 @@ struct uhci_hw_softc {
|
||||
typedef struct uhci_softc {
|
||||
struct uhci_hw_softc sc_hw;
|
||||
struct usb2_bus sc_bus; /* base device */
|
||||
struct usb2_config_td sc_config_td;
|
||||
union uhci_hub_desc sc_hub_desc;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
|
||||
struct usb2_device *sc_devices[UHCI_MAX_DEVICES];
|
||||
struct uhci_td *sc_isoc_p_last[UHCI_VFRAMELIST_COUNT]; /* pointer to last TD
|
||||
* for isochronous */
|
||||
struct uhci_qh *sc_intr_p_last[UHCI_IFRAMELIST_COUNT]; /* pointer to last QH
|
||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
@ -251,9 +250,12 @@ uhci_pci_attach(device_t self)
|
||||
device_printf(self, "Could not allocate sc\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_bus.parent = self;
|
||||
sc->sc_bus.devices = sc->sc_devices;
|
||||
sc->sc_bus.devices_max = UHCI_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_bus, USB_GET_DMA_TAG(self),
|
||||
&uhci_iterate_hw_softc)) {
|
||||
return ENOMEM;
|
||||
@ -318,16 +320,12 @@ uhci_pci_attach(device_t self)
|
||||
sc->sc_bus.usbrev = USB_REV_1_0;
|
||||
break;
|
||||
default:
|
||||
sc->sc_bus.usbrev = USB_REV_UNKNOWN;
|
||||
/* Quirk for Parallels Desktop 4.0 */
|
||||
device_printf(self, "USB revision is unknown. Assuming v1.1.\n");
|
||||
sc->sc_bus.usbrev = USB_REV_1_1;
|
||||
break;
|
||||
}
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_config_td, sc, &sc->sc_bus.bus_mtx,
|
||||
NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(self, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl);
|
||||
@ -376,8 +374,6 @@ uhci_pci_detach(device_t self)
|
||||
uhci_softc_t *sc = device_get_softc(self);
|
||||
device_t bdev;
|
||||
|
||||
usb2_config_td_drain(&sc->sc_config_td);
|
||||
|
||||
if (sc->sc_bus.bdev) {
|
||||
bdev = sc->sc_bus.bdev;
|
||||
device_detach(bdev);
|
||||
@ -419,8 +415,6 @@ uhci_pci_detach(device_t self)
|
||||
sc->sc_io_res);
|
||||
sc->sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_bus, &uhci_iterate_hw_softc);
|
||||
|
||||
return (0);
|
||||
|
@ -52,9 +52,18 @@ struct usb2_bus {
|
||||
struct usb2_bus_stat stats_err;
|
||||
struct usb2_bus_stat stats_ok;
|
||||
struct usb2_process explore_proc;
|
||||
struct usb2_process roothub_proc;
|
||||
/*
|
||||
* There are two callback processes. One for Giant locked
|
||||
* callbacks. One for non-Giant locked callbacks. This should
|
||||
* avoid congestion and reduce response time in most cases.
|
||||
*/
|
||||
struct usb2_process giant_callback_proc;
|
||||
struct usb2_process non_giant_callback_proc;
|
||||
struct usb2_bus_msg explore_msg[2];
|
||||
struct usb2_bus_msg detach_msg[2];
|
||||
struct usb2_bus_msg attach_msg[2];
|
||||
struct usb2_bus_msg roothub_msg[2];
|
||||
/*
|
||||
* This mutex protects the USB hardware:
|
||||
*/
|
||||
@ -70,7 +79,7 @@ struct usb2_bus {
|
||||
struct usb2_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX];
|
||||
|
||||
struct usb2_bus_methods *methods; /* filled by HC driver */
|
||||
struct usb2_device *devices[USB_MAX_DEVICES];
|
||||
struct usb2_device **devices;
|
||||
|
||||
uint32_t hw_power_state; /* see USB_HW_POWER_XXX */
|
||||
uint32_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
|
||||
|
@ -59,6 +59,7 @@ static void usb2_bus_mem_alloc_all_cb(struct usb2_bus *,
|
||||
static void usb2_bus_mem_free_all_cb(struct usb2_bus *,
|
||||
struct usb2_page_cache *, struct usb2_page *, uint32_t,
|
||||
uint32_t);
|
||||
static void usb2_bus_roothub(struct usb2_proc_msg *pm);
|
||||
|
||||
/* static variables */
|
||||
|
||||
@ -165,6 +166,15 @@ usb2_detach(device_t dev)
|
||||
|
||||
USB_BUS_UNLOCK(bus);
|
||||
|
||||
/* Get rid of USB callback processes */
|
||||
|
||||
usb2_proc_unsetup(&bus->giant_callback_proc);
|
||||
usb2_proc_unsetup(&bus->non_giant_callback_proc);
|
||||
|
||||
/* Get rid of USB roothub process */
|
||||
|
||||
usb2_proc_unsetup(&bus->roothub_proc);
|
||||
|
||||
/* Get rid of USB explore process */
|
||||
|
||||
usb2_proc_unsetup(&bus->explore_proc);
|
||||
@ -381,10 +391,29 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
|
||||
bus->attach_msg[1].hdr.pm_callback = &usb2_bus_attach;
|
||||
bus->attach_msg[1].bus = bus;
|
||||
|
||||
/* Create a new USB process */
|
||||
if (usb2_proc_setup(&bus->explore_proc,
|
||||
bus->roothub_msg[0].hdr.pm_callback = &usb2_bus_roothub;
|
||||
bus->roothub_msg[0].bus = bus;
|
||||
bus->roothub_msg[1].hdr.pm_callback = &usb2_bus_roothub;
|
||||
bus->roothub_msg[1].bus = bus;
|
||||
|
||||
/* Create USB explore, roothub and callback processes */
|
||||
|
||||
if (usb2_proc_setup(&bus->giant_callback_proc,
|
||||
&bus->bus_mtx, USB_PRI_MED)) {
|
||||
printf("WARNING: Creation of USB explore process failed.\n");
|
||||
printf("WARNING: Creation of USB Giant "
|
||||
"callback process failed.\n");
|
||||
} else if (usb2_proc_setup(&bus->non_giant_callback_proc,
|
||||
&bus->bus_mtx, USB_PRI_HIGH)) {
|
||||
printf("WARNING: Creation of USB non-Giant "
|
||||
"callback process failed.\n");
|
||||
} else if (usb2_proc_setup(&bus->roothub_proc,
|
||||
&bus->bus_mtx, USB_PRI_HIGH)) {
|
||||
printf("WARNING: Creation of USB roothub "
|
||||
"process failed.\n");
|
||||
} else if (usb2_proc_setup(&bus->explore_proc,
|
||||
&bus->bus_mtx, USB_PRI_MED)) {
|
||||
printf("WARNING: Creation of USB explore "
|
||||
"process failed.\n");
|
||||
} else {
|
||||
/* Get final attach going */
|
||||
USB_BUS_LOCK(bus);
|
||||
@ -493,8 +522,6 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
|
||||
{
|
||||
bus->alloc_failed = 0;
|
||||
|
||||
bus->devices_max = USB_MAX_DEVICES;
|
||||
|
||||
mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent),
|
||||
NULL, MTX_DEF | MTX_RECURSE);
|
||||
|
||||
@ -506,6 +533,13 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
|
||||
usb2_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
|
||||
dmat, &bus->bus_mtx, NULL, NULL, 32, USB_BUS_DMA_TAG_MAX);
|
||||
|
||||
if ((bus->devices_max > USB_MAX_DEVICES) ||
|
||||
(bus->devices_max < USB_MIN_DEVICES) ||
|
||||
(bus->devices == NULL)) {
|
||||
DPRINTFN(0, "Devices field has not been "
|
||||
"initialised properly!\n");
|
||||
bus->alloc_failed = 1; /* failure */
|
||||
}
|
||||
if (cb) {
|
||||
cb(bus, &usb2_bus_mem_alloc_all_cb);
|
||||
}
|
||||
@ -538,3 +572,38 @@ usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
|
||||
|
||||
mtx_destroy(&bus->bus_mtx);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_bus_roothub
|
||||
*
|
||||
* This function is used to execute roothub control requests on the
|
||||
* roothub and is called from the roothub process.
|
||||
*------------------------------------------------------------------------*/
|
||||
static void
|
||||
usb2_bus_roothub(struct usb2_proc_msg *pm)
|
||||
{
|
||||
struct usb2_bus *bus;
|
||||
|
||||
bus = ((struct usb2_bus_msg *)pm)->bus;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
(bus->methods->roothub_exec) (bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb2_bus_roothub_exec
|
||||
*
|
||||
* This function is used to schedule the "roothub_done" bus callback
|
||||
* method. The bus lock must be locked when calling this function.
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb2_bus_roothub_exec(struct usb2_bus *bus)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
if (usb2_proc_msignal(&bus->roothub_proc,
|
||||
&bus->roothub_msg[0], &bus->roothub_msg[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +91,9 @@ struct usb2_bus_methods {
|
||||
void (*set_stall) (struct usb2_device *udev, struct usb2_xfer *xfer, struct usb2_pipe *pipe);
|
||||
void (*clear_stall) (struct usb2_device *udev, struct usb2_pipe *pipe);
|
||||
|
||||
/* USB Device mode only - Optional */
|
||||
/* USB Device and Host mode - Optional */
|
||||
|
||||
void (*vbus_interrupt) (struct usb2_bus *, uint8_t is_on);
|
||||
void (*roothub_exec) (struct usb2_bus *);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -186,6 +186,7 @@ struct usb2_temp_setup {
|
||||
void usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
|
||||
uint8_t usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat, usb2_bus_mem_cb_t *cb);
|
||||
void usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
|
||||
void usb2_bus_roothub_exec(struct usb2_bus *bus);
|
||||
uint16_t usb2_isoc_time_expand(struct usb2_bus *bus, uint16_t isoc_time_curr);
|
||||
uint16_t usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev, struct usb2_fs_isoc_schedule **pp_start, struct usb2_fs_isoc_schedule **pp_end, uint16_t isoc_time);
|
||||
uint8_t usb2_fs_isoc_schedule_alloc(struct usb2_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
|
||||
|
@ -39,14 +39,11 @@
|
||||
#include <dev/usb2/include/usb2_defs.h>
|
||||
|
||||
#define USB_DEBUG_VAR uss820dcidebug
|
||||
#define usb2_config_td_cc uss820dci_config_copy
|
||||
#define usb2_config_td_softc uss820dci_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
@ -98,7 +95,6 @@ static void uss820dci_update_shared_1(struct uss820dci_softc *, uint8_t,
|
||||
|
||||
static usb2_sw_transfer_func_t uss820dci_root_intr_done;
|
||||
static usb2_sw_transfer_func_t uss820dci_root_ctrl_done;
|
||||
static usb2_config_td_command_t uss820dci_root_ctrl_task;
|
||||
|
||||
/*
|
||||
* Here is a list of what the USS820D chip can support. The main
|
||||
@ -829,7 +825,7 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
|
||||
DPRINTFN(9, "addr=%d endpt=%d sumlen=%d speed=%d\n",
|
||||
xfer->address, UE_GET_ADDR(xfer->endpoint),
|
||||
xfer->sumlen, usb2_get_speed(xfer->udev));
|
||||
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
|
||||
|
||||
temp.max_frame_size = xfer->max_frame_size;
|
||||
|
||||
@ -844,7 +840,7 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
|
||||
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
|
||||
temp.offset = 0;
|
||||
|
||||
sc = xfer->usb2_sc;
|
||||
sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
ep_no = (xfer->endpoint & UE_ADDR);
|
||||
|
||||
/* check if we should prepend a setup message */
|
||||
@ -953,7 +949,7 @@ uss820dci_timeout(void *arg)
|
||||
|
||||
DPRINTF("xfer=%p\n", xfer);
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* transfer is transferred */
|
||||
uss820dci_device_done(xfer, USB_ERR_TIMEOUT);
|
||||
@ -962,7 +958,7 @@ uss820dci_timeout(void *arg)
|
||||
static void
|
||||
uss820dci_intr_set(struct usb2_xfer *xfer, uint8_t set)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint8_t ep_no = (xfer->endpoint & UE_ADDR);
|
||||
uint8_t ep_reg;
|
||||
uint8_t temp;
|
||||
@ -1014,7 +1010,7 @@ uss820dci_start_standard_chain(struct usb2_xfer *xfer)
|
||||
uss820dci_intr_set(xfer, 1);
|
||||
|
||||
/* put transfer on interrupt queue */
|
||||
usb2_transfer_enqueue(&xfer->udev->bus->intr_q, xfer);
|
||||
usb2_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
|
||||
|
||||
/* start timeout, if any */
|
||||
if (xfer->timeout != 0) {
|
||||
@ -1028,7 +1024,7 @@ static void
|
||||
uss820dci_root_intr_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
DPRINTFN(9, "\n");
|
||||
|
||||
@ -1168,7 +1164,7 @@ done:
|
||||
static void
|
||||
uss820dci_device_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
DPRINTFN(2, "xfer=%p, pipe=%p, error=%d\n",
|
||||
xfer, xfer->pipe, error);
|
||||
@ -1642,7 +1638,7 @@ uss820dci_device_isoc_fs_close(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uss820dci_device_isoc_fs_enter(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint32_t temp;
|
||||
uint32_t nframes;
|
||||
|
||||
@ -1724,7 +1720,7 @@ uss820dci_root_ctrl_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uss820dci_root_ctrl_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_ctrl.xfer == xfer) {
|
||||
sc->sc_root_ctrl.xfer = NULL;
|
||||
@ -1798,7 +1794,7 @@ static const struct usb2_hub_descriptor_min uss820dci_hubd = {
|
||||
.wHubCharacteristics[0] =
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) & 0xFF,
|
||||
.wHubCharacteristics[1] =
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 16,
|
||||
(UHD_PWR_NO_SWITCH | UHD_OC_INDIVIDUAL) >> 8,
|
||||
.bPwrOn2PwrGood = 50,
|
||||
.bHubContrCurrent = 0,
|
||||
.DeviceRemovable = {0}, /* port is removable */
|
||||
@ -1828,26 +1824,24 @@ uss820dci_root_ctrl_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uss820dci_root_ctrl_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_ctrl.xfer = xfer;
|
||||
|
||||
usb2_config_td_queue_command(
|
||||
&sc->sc_config_td, NULL, &uss820dci_root_ctrl_task, 0, 0);
|
||||
usb2_bus_roothub_exec(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
static void
|
||||
uss820dci_root_ctrl_task(struct uss820dci_softc *sc,
|
||||
struct uss820dci_config_copy *cc, uint16_t refcount)
|
||||
uss820dci_root_ctrl_task(struct usb2_bus *bus)
|
||||
{
|
||||
uss820dci_root_ctrl_poll(sc);
|
||||
uss820dci_root_ctrl_poll(USS820_DCI_BUS2SC(bus));
|
||||
}
|
||||
|
||||
static void
|
||||
uss820dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
struct usb2_sw_transfer *std)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
uint16_t value;
|
||||
uint16_t index;
|
||||
uint8_t use_polling;
|
||||
@ -1868,7 +1862,7 @@ uss820dci_root_ctrl_done(struct usb2_xfer *xfer,
|
||||
value = UGETW(std->req.wValue);
|
||||
index = UGETW(std->req.wIndex);
|
||||
|
||||
use_polling = mtx_owned(xfer->xfer_mtx) ? 1 : 0;
|
||||
use_polling = mtx_owned(xfer->xroot->xfer_mtx) ? 1 : 0;
|
||||
|
||||
/* demultiplex the control request */
|
||||
|
||||
@ -2264,7 +2258,7 @@ uss820dci_root_intr_open(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uss820dci_root_intr_close(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
if (sc->sc_root_intr.xfer == xfer) {
|
||||
sc->sc_root_intr.xfer = NULL;
|
||||
@ -2281,7 +2275,7 @@ uss820dci_root_intr_enter(struct usb2_xfer *xfer)
|
||||
static void
|
||||
uss820dci_root_intr_start(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uss820dci_softc *sc = xfer->usb2_sc;
|
||||
struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
|
||||
|
||||
sc->sc_root_intr.xfer = xfer;
|
||||
}
|
||||
@ -2310,11 +2304,6 @@ uss820dci_xfer_setup(struct usb2_setup_params *parm)
|
||||
sc = USS820_DCI_BUS2SC(parm->udev->bus);
|
||||
xfer = parm->curr_xfer;
|
||||
|
||||
/*
|
||||
* setup xfer
|
||||
*/
|
||||
xfer->usb2_sc = sc;
|
||||
|
||||
/*
|
||||
* NOTE: This driver does not use any of the parameters that
|
||||
* are computed from the following values. Just set some
|
||||
@ -2496,4 +2485,5 @@ struct usb2_bus_methods uss820dci_bus_methods =
|
||||
.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
|
||||
.set_stall = &uss820dci_set_stall,
|
||||
.clear_stall = &uss820dci_clear_stall,
|
||||
.roothub_exec = &uss820dci_root_ctrl_task,
|
||||
};
|
||||
|
@ -28,6 +28,8 @@
|
||||
#ifndef _USS820_DCI_H_
|
||||
#define _USS820_DCI_H_
|
||||
|
||||
#define USS820_MAX_DEVICES (USB_MIN_DEVICES + 1)
|
||||
|
||||
#define USS820_EP_MAX 8 /* maximum number of endpoints */
|
||||
|
||||
#define USS820_TXDAT 0x00 /* Transmit FIFO data */
|
||||
@ -345,8 +347,8 @@ struct uss820dci_softc {
|
||||
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
|
||||
struct usb2_sw_transfer sc_root_ctrl;
|
||||
struct usb2_sw_transfer sc_root_intr;
|
||||
struct usb2_config_td sc_config_td;
|
||||
|
||||
struct usb2_device *sc_devices[USS820_MAX_DEVICES];
|
||||
struct resource *sc_io_res;
|
||||
struct resource *sc_irq_res;
|
||||
void *sc_intr_hdl;
|
||||
|
@ -34,7 +34,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_sw_transfer.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
||||
@ -138,9 +137,13 @@ uss820_atmelarm_attach(device_t dev)
|
||||
if (sc == NULL) {
|
||||
return (ENXIO);
|
||||
}
|
||||
/* get all DMA memory */
|
||||
|
||||
/* initialise some bus fields */
|
||||
sc->sc_bus.parent = dev;
|
||||
sc->sc_bus.devices = sc->sc_devices;
|
||||
sc->sc_bus.devices_max = USS820_MAX_DEVICES;
|
||||
|
||||
/* get all DMA memory */
|
||||
if (usb2_bus_mem_alloc_all(&sc->sc_bus,
|
||||
USB_GET_DMA_TAG(dev), NULL)) {
|
||||
return (ENOMEM);
|
||||
@ -171,12 +174,6 @@ uss820_atmelarm_attach(device_t dev)
|
||||
}
|
||||
device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
|
||||
|
||||
err = usb2_config_td_setup(&sc->sc_config_td, sc,
|
||||
&sc->sc_bus.bus_mtx, NULL, 0, 4);
|
||||
if (err) {
|
||||
device_printf(dev, "could not setup config thread!\n");
|
||||
goto error;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700031)
|
||||
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
|
||||
NULL, (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
|
||||
@ -240,8 +237,6 @@ uss820_atmelarm_detach(device_t dev)
|
||||
sc->sc_io_res);
|
||||
sc->sc_io_res = NULL;
|
||||
}
|
||||
usb2_config_td_unsetup(&sc->sc_config_td);
|
||||
|
||||
usb2_bus_mem_free_all(&sc->sc_bus, NULL);
|
||||
|
||||
return (0);
|
||||
|
@ -1226,15 +1226,15 @@ usb2_bdma_work_loop(struct usb2_xfer_queue *pq)
|
||||
uint32_t nframes;
|
||||
|
||||
xfer = pq->curr;
|
||||
info = xfer->usb2_root;
|
||||
info = xfer->xroot;
|
||||
|
||||
mtx_assert(info->priv_mtx, MA_OWNED);
|
||||
mtx_assert(info->xfer_mtx, MA_OWNED);
|
||||
|
||||
if (xfer->error) {
|
||||
/* some error happened */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(info->bus);
|
||||
usb2_transfer_done(xfer, 0);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(info->bus);
|
||||
return;
|
||||
}
|
||||
if (!xfer->flags_int.bdma_setup) {
|
||||
@ -1306,9 +1306,9 @@ usb2_bdma_work_loop(struct usb2_xfer_queue *pq)
|
||||
|
||||
}
|
||||
if (info->dma_error) {
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(info->bus);
|
||||
usb2_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(info->bus);
|
||||
return;
|
||||
}
|
||||
if (info->dma_currframe != info->dma_nframes) {
|
||||
@ -1352,7 +1352,7 @@ usb2_bdma_done_event(struct usb2_dma_parent_tag *udpt)
|
||||
|
||||
info = udpt->info;
|
||||
|
||||
mtx_assert(info->priv_mtx, MA_OWNED);
|
||||
mtx_assert(info->xfer_mtx, MA_OWNED);
|
||||
|
||||
/* copy error */
|
||||
info->dma_error = udpt->dma_error;
|
||||
|
@ -393,8 +393,14 @@ usb_linux_shutdown(device_t dev)
|
||||
static uint16_t
|
||||
usb_max_isoc_frames(struct usb_device *dev)
|
||||
{
|
||||
return ((usb2_get_speed(dev->bsd_udev) == USB_SPEED_HIGH) ?
|
||||
USB_MAX_HIGH_SPEED_ISOC_FRAMES : USB_MAX_FULL_SPEED_ISOC_FRAMES);
|
||||
; /* indent fix */
|
||||
switch (usb2_get_speed(dev->bsd_udev)) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
return (USB_MAX_FULL_SPEED_ISOC_FRAMES);
|
||||
default:
|
||||
return (USB_MAX_HIGH_SPEED_ISOC_FRAMES);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
|
@ -101,8 +101,6 @@
|
||||
|
||||
#define USB_HOST_ALIGN 8 /* bytes, must be power of two */
|
||||
|
||||
#define USB_ROOT_HUB_ADDR 1 /* value */
|
||||
|
||||
#define USB_ISOC_TIME_MAX 128 /* ms */
|
||||
#define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */
|
||||
|
||||
@ -162,9 +160,9 @@
|
||||
#define USB_BUS_LOCK(_b) mtx_lock(&(_b)->bus_mtx)
|
||||
#define USB_BUS_UNLOCK(_b) mtx_unlock(&(_b)->bus_mtx)
|
||||
#define USB_BUS_LOCK_ASSERT(_b, _t) mtx_assert(&(_b)->bus_mtx, _t)
|
||||
#define USB_XFER_LOCK(_x) mtx_lock((_x)->xfer_mtx)
|
||||
#define USB_XFER_UNLOCK(_x) mtx_unlock((_x)->xfer_mtx)
|
||||
#define USB_XFER_LOCK_ASSERT(_x, _t) mtx_assert((_x)->xfer_mtx, _t)
|
||||
#define USB_XFER_LOCK(_x) mtx_lock((_x)->xroot->xfer_mtx)
|
||||
#define USB_XFER_UNLOCK(_x) mtx_unlock((_x)->xroot->xfer_mtx)
|
||||
#define USB_XFER_LOCK_ASSERT(_x, _t) mtx_assert((_x)->xroot->xfer_mtx, _t)
|
||||
/* structure prototypes */
|
||||
|
||||
struct file;
|
||||
@ -309,10 +307,7 @@ struct usb2_xfer {
|
||||
* are waiting on */
|
||||
struct usb2_page *dma_page_ptr;
|
||||
struct usb2_pipe *pipe; /* our USB pipe */
|
||||
struct usb2_device *udev;
|
||||
struct mtx *xfer_mtx; /* cannot be changed during operation */
|
||||
struct usb2_xfer_root *usb2_root; /* used by HC driver */
|
||||
void *usb2_sc; /* used by HC driver */
|
||||
struct usb2_xfer_root *xroot; /* used by HC driver */
|
||||
void *qh_start[2]; /* used by HC driver */
|
||||
void *td_start[2]; /* used by HC driver */
|
||||
void *td_transfer_first; /* used by HC driver */
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_device.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_transfer.h>
|
||||
|
||||
/*
|
||||
* Define this unconditionally in case a kernel module is loaded that
|
||||
@ -128,6 +130,7 @@ usb2_dump_pipe(struct usb2_pipe *pipe)
|
||||
void
|
||||
usb2_dump_xfer(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_device *udev;
|
||||
printf("usb2_dump_xfer: xfer=%p\n", xfer);
|
||||
if (xfer == NULL) {
|
||||
return;
|
||||
@ -137,12 +140,13 @@ usb2_dump_xfer(struct usb2_xfer *xfer)
|
||||
xfer);
|
||||
return;
|
||||
}
|
||||
udev = xfer->xroot->udev;
|
||||
printf("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d "
|
||||
"pipe=%p ep=0x%02x attr=0x%02x\n",
|
||||
xfer, xfer->udev,
|
||||
UGETW(xfer->udev->ddesc.idVendor),
|
||||
UGETW(xfer->udev->ddesc.idProduct),
|
||||
xfer->udev->address, xfer->pipe,
|
||||
xfer, udev,
|
||||
UGETW(udev->ddesc.idVendor),
|
||||
UGETW(udev->ddesc.idProduct),
|
||||
udev->address, xfer->pipe,
|
||||
xfer->pipe->edesc->bEndpointAddress,
|
||||
xfer->pipe->edesc->bmAttributes);
|
||||
}
|
||||
|
@ -75,18 +75,6 @@ static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t,
|
||||
static void usb2_notify_addq(const char *type, struct usb2_device *);
|
||||
static void usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t);
|
||||
|
||||
/* static structures */
|
||||
|
||||
static const uint8_t usb2_hub_speed_combs[USB_SPEED_MAX][USB_SPEED_MAX] = {
|
||||
/* HUB *//* subdevice */
|
||||
[USB_SPEED_HIGH][USB_SPEED_HIGH] = 1,
|
||||
[USB_SPEED_HIGH][USB_SPEED_FULL] = 1,
|
||||
[USB_SPEED_HIGH][USB_SPEED_LOW] = 1,
|
||||
[USB_SPEED_FULL][USB_SPEED_FULL] = 1,
|
||||
[USB_SPEED_FULL][USB_SPEED_LOW] = 1,
|
||||
[USB_SPEED_LOW][USB_SPEED_LOW] = 1,
|
||||
};
|
||||
|
||||
/* This variable is global to allow easy access to it: */
|
||||
|
||||
int usb2_template = 0;
|
||||
@ -1290,19 +1278,20 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
|
||||
* Find an unused device index. In USB Host mode this is the
|
||||
* same as the device address.
|
||||
*
|
||||
* NOTE: Index 1 is reserved for the Root HUB.
|
||||
* Device index zero is not used and device index 1 should
|
||||
* always be the root hub.
|
||||
*/
|
||||
for (device_index = USB_ROOT_HUB_ADDR; device_index !=
|
||||
USB_MAX_DEVICES; device_index++) {
|
||||
if (bus->devices[device_index] == NULL)
|
||||
break;
|
||||
}
|
||||
for (device_index = USB_ROOT_HUB_ADDR;
|
||||
(device_index != bus->devices_max) &&
|
||||
(bus->devices[device_index] != NULL);
|
||||
device_index++) /* nop */;
|
||||
|
||||
if (device_index == USB_MAX_DEVICES) {
|
||||
if (device_index == bus->devices_max) {
|
||||
device_printf(bus->bdev,
|
||||
"No free USB device index for new device!\n");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (depth > 0x10) {
|
||||
device_printf(bus->bdev,
|
||||
"Invalid device depth!\n");
|
||||
@ -1363,21 +1352,10 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
|
||||
udev->speed = speed;
|
||||
udev->flags.usb2_mode = usb2_mode;
|
||||
|
||||
/* check speed combination */
|
||||
/* speed combination should be checked by the parent HUB */
|
||||
|
||||
hub = udev->parent_hub;
|
||||
if (hub) {
|
||||
if (usb2_hub_speed_combs[hub->speed][speed] == 0) {
|
||||
#if USB_DEBUG
|
||||
printf("%s: the selected subdevice and HUB speed "
|
||||
"combination is not supported %d/%d.\n",
|
||||
__FUNCTION__, speed, hub->speed);
|
||||
#endif
|
||||
/* reject this combination */
|
||||
err = USB_ERR_INVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* search for our High Speed USB HUB, if any */
|
||||
|
||||
adev = udev;
|
||||
@ -1741,8 +1719,18 @@ usb2_free_device(struct usb2_device *udev)
|
||||
/* unsetup any leftover default USB transfers */
|
||||
usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX);
|
||||
|
||||
/* template unsetup, if any */
|
||||
(usb2_temp_unsetup_p) (udev);
|
||||
|
||||
/*
|
||||
* Make sure that our clear-stall messages are not queued
|
||||
* anywhere:
|
||||
*/
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
usb2_proc_mwait(&udev->bus->non_giant_callback_proc,
|
||||
&udev->cs_msg[0], &udev->cs_msg[1]);
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
sx_destroy(udev->default_sx);
|
||||
sx_destroy(udev->default_sx + 1);
|
||||
|
||||
|
@ -157,12 +157,16 @@ ugen_open(struct usb2_fifo *f, int fflags, struct thread *td)
|
||||
DPRINTFN(6, "flag=0x%x\n", fflags);
|
||||
|
||||
mtx_lock(f->priv_mtx);
|
||||
if (usb2_get_speed(f->udev) == USB_SPEED_HIGH) {
|
||||
f->nframes = UGEN_HW_FRAMES * 8;
|
||||
f->bufsize = UGEN_BULK_HS_BUFFER_SIZE;
|
||||
} else {
|
||||
switch (usb2_get_speed(f->udev)) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
f->nframes = UGEN_HW_FRAMES;
|
||||
f->bufsize = UGEN_BULK_FS_BUFFER_SIZE;
|
||||
break;
|
||||
default:
|
||||
f->nframes = UGEN_HW_FRAMES * 8;
|
||||
f->bufsize = UGEN_BULK_HS_BUFFER_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
type = ed->bmAttributes & UE_XFERTYPE;
|
||||
@ -1688,22 +1692,31 @@ ugen_set_power_mode(struct usb2_fifo *f, int mode)
|
||||
{
|
||||
struct usb2_device *udev = f->udev;
|
||||
int err;
|
||||
uint8_t old_mode;
|
||||
|
||||
if ((udev == NULL) ||
|
||||
(udev->parent_hub == NULL)) {
|
||||
return (EINVAL);
|
||||
}
|
||||
err = priv_check(curthread, PRIV_ROOT);
|
||||
if (err) {
|
||||
if (err)
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* get old power mode */
|
||||
old_mode = udev->power_mode;
|
||||
|
||||
/* if no change, then just return */
|
||||
if (old_mode == mode)
|
||||
return (0);
|
||||
|
||||
switch (mode) {
|
||||
case USB_POWER_MODE_OFF:
|
||||
/* clear suspend */
|
||||
err = usb2_req_clear_port_feature(udev->parent_hub,
|
||||
NULL, udev->port_no, UHF_PORT_SUSPEND);
|
||||
if (err)
|
||||
break;
|
||||
/* get the device unconfigured */
|
||||
err = ugen_set_config(f, USB_UNCONFIG_INDEX);
|
||||
if (err) {
|
||||
DPRINTFN(0, "Could not unconfigure "
|
||||
"device (ignored)\n");
|
||||
}
|
||||
|
||||
/* clear port enable */
|
||||
err = usb2_req_clear_port_feature(udev->parent_hub,
|
||||
@ -1733,6 +1746,13 @@ ugen_set_power_mode(struct usb2_fifo *f, int mode)
|
||||
if (err)
|
||||
return (ENXIO); /* I/O failure */
|
||||
|
||||
/* if we are powered off we need to re-enumerate first */
|
||||
if (old_mode == USB_POWER_MODE_OFF) {
|
||||
err = ugen_re_enumerate(f);
|
||||
if (err)
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* set new power mode */
|
||||
usb2_set_power_mode(udev, mode);
|
||||
|
||||
|
@ -86,7 +86,7 @@ usb2_handle_request_callback(struct usb2_xfer *xfer)
|
||||
|
||||
if (err == USB_ERR_BAD_CONTEXT) {
|
||||
/* we need to re-setup the control transfer */
|
||||
usb2_needs_explore(xfer->udev->bus, 0);
|
||||
usb2_needs_explore(xfer->xroot->bus, 0);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
@ -126,6 +126,7 @@ tr_restart:
|
||||
static usb2_error_t
|
||||
usb2_handle_set_config(struct usb2_xfer *xfer, uint8_t conf_no)
|
||||
{
|
||||
struct usb2_device *udev = xfer->xroot->udev;
|
||||
usb2_error_t err = 0;
|
||||
|
||||
/*
|
||||
@ -134,7 +135,7 @@ usb2_handle_set_config(struct usb2_xfer *xfer, uint8_t conf_no)
|
||||
*/
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
mtx_lock(&Giant); /* XXX */
|
||||
sx_xlock(xfer->udev->default_sx + 1);
|
||||
sx_xlock(udev->default_sx + 1);
|
||||
|
||||
if (conf_no == USB_UNCONFIG_NO) {
|
||||
conf_no = USB_UNCONFIG_INDEX;
|
||||
@ -146,19 +147,19 @@ usb2_handle_set_config(struct usb2_xfer *xfer, uint8_t conf_no)
|
||||
conf_no--;
|
||||
}
|
||||
|
||||
if (usb2_set_config_index(xfer->udev, conf_no)) {
|
||||
if (usb2_set_config_index(udev, conf_no)) {
|
||||
DPRINTF("set config %d failed\n", conf_no);
|
||||
err = USB_ERR_STALLED;
|
||||
goto done;
|
||||
}
|
||||
if (usb2_probe_and_attach(xfer->udev, USB_IFACE_INDEX_ANY)) {
|
||||
if (usb2_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) {
|
||||
DPRINTF("probe and attach failed\n");
|
||||
err = USB_ERR_STALLED;
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
mtx_unlock(&Giant); /* XXX */
|
||||
sx_unlock(xfer->udev->default_sx + 1);
|
||||
sx_unlock(udev->default_sx + 1);
|
||||
USB_XFER_LOCK(xfer);
|
||||
return (err);
|
||||
}
|
||||
@ -177,7 +178,7 @@ usb2_handle_iface_request(struct usb2_xfer *xfer,
|
||||
{
|
||||
struct usb2_interface *iface;
|
||||
struct usb2_interface *iface_parent; /* parent interface */
|
||||
struct usb2_device *udev = xfer->udev;
|
||||
struct usb2_device *udev = xfer->xroot->udev;
|
||||
int error;
|
||||
uint8_t iface_index;
|
||||
|
||||
@ -332,11 +333,12 @@ tr_stalled:
|
||||
static usb2_error_t
|
||||
usb2_handle_set_stall(struct usb2_xfer *xfer, uint8_t ep, uint8_t do_stall)
|
||||
{
|
||||
struct usb2_device *udev = xfer->xroot->udev;
|
||||
usb2_error_t err;
|
||||
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
err = usb2_set_endpoint_stall(xfer->udev,
|
||||
usb2_get_pipe_by_addr(xfer->udev, ep), do_stall);
|
||||
err = usb2_set_endpoint_stall(udev,
|
||||
usb2_get_pipe_by_addr(udev, ep), do_stall);
|
||||
USB_XFER_LOCK(xfer);
|
||||
return (err);
|
||||
}
|
||||
@ -379,7 +381,7 @@ usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on)
|
||||
struct usb2_device *udev;
|
||||
struct usb2_bus *bus;
|
||||
|
||||
udev = xfer->udev;
|
||||
udev = xfer->xroot->udev;
|
||||
bus = udev->bus;
|
||||
|
||||
USB_BUS_LOCK(bus);
|
||||
@ -479,7 +481,7 @@ usb2_handle_request(struct usb2_xfer *xfer)
|
||||
max_len = 0;
|
||||
src_zcopy = NULL;
|
||||
src_mcopy = NULL;
|
||||
udev = xfer->udev;
|
||||
udev = xfer->xroot->udev;
|
||||
|
||||
/* get some request fields decoded */
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <dev/usb2/controller/usb2_bus.h>
|
||||
|
||||
#define UHUB_INTR_INTERVAL 250 /* ms */
|
||||
#define UHUB_N_TRANSFER 1
|
||||
|
||||
#if USB_DEBUG
|
||||
static int uhub_debug = 0;
|
||||
@ -76,10 +77,9 @@ struct uhub_softc {
|
||||
struct uhub_current_state sc_st;/* current state */
|
||||
device_t sc_dev; /* base device */
|
||||
struct usb2_device *sc_udev; /* USB device */
|
||||
struct usb2_xfer *sc_xfer[2]; /* interrupt xfer */
|
||||
struct usb2_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
|
||||
uint8_t sc_flags;
|
||||
#define UHUB_FLAG_DID_EXPLORE 0x01
|
||||
#define UHUB_FLAG_INTR_STALL 0x02
|
||||
char sc_name[32];
|
||||
};
|
||||
|
||||
@ -100,12 +100,11 @@ static bus_child_location_str_t uhub_child_location_string;
|
||||
static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
|
||||
|
||||
static usb2_callback_t uhub_intr_callback;
|
||||
static usb2_callback_t uhub_intr_clear_stall_callback;
|
||||
|
||||
static void usb2_dev_resume_peer(struct usb2_device *udev);
|
||||
static void usb2_dev_suspend_peer(struct usb2_device *udev);
|
||||
|
||||
static const struct usb2_config uhub_config[2] = {
|
||||
static const struct usb2_config uhub_config[UHUB_N_TRANSFER] = {
|
||||
|
||||
[0] = {
|
||||
.type = UE_INTERRUPT,
|
||||
@ -117,17 +116,6 @@ static const struct usb2_config uhub_config[2] = {
|
||||
.mh.callback = &uhub_intr_callback,
|
||||
.mh.interval = UHUB_INTR_INTERVAL,
|
||||
},
|
||||
|
||||
[1] = {
|
||||
.type = UE_CONTROL,
|
||||
.endpoint = 0,
|
||||
.direction = UE_DIR_ANY,
|
||||
.mh.timeout = 1000, /* 1 second */
|
||||
.mh.interval = 50, /* 50ms */
|
||||
.mh.flags = {},
|
||||
.mh.bufsize = sizeof(struct usb2_device_request),
|
||||
.mh.callback = &uhub_intr_clear_stall_callback,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
@ -159,19 +147,6 @@ static driver_t uhub_driver =
|
||||
DRIVER_MODULE(ushub, usbus, uhub_driver, uhub_devclass, 0, 0);
|
||||
DRIVER_MODULE(ushub, ushub, uhub_driver, uhub_devclass, NULL, 0);
|
||||
|
||||
static void
|
||||
uhub_intr_clear_stall_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct uhub_softc *sc = xfer->priv_sc;
|
||||
struct usb2_xfer *xfer_other = sc->sc_xfer[0];
|
||||
|
||||
if (usb2_clear_stall_callback(xfer, xfer_other)) {
|
||||
DPRINTF("stall cleared\n");
|
||||
sc->sc_flags &= ~UHUB_FLAG_INTR_STALL;
|
||||
usb2_transfer_start(xfer_other);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
uhub_intr_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
@ -189,21 +164,22 @@ uhub_intr_callback(struct usb2_xfer *xfer)
|
||||
usb2_needs_explore(sc->sc_udev->bus, 0);
|
||||
|
||||
case USB_ST_SETUP:
|
||||
if (sc->sc_flags & UHUB_FLAG_INTR_STALL) {
|
||||
usb2_transfer_start(sc->sc_xfer[1]);
|
||||
} else {
|
||||
xfer->frlengths[0] = xfer->max_data_length;
|
||||
usb2_start_hardware(xfer);
|
||||
}
|
||||
return;
|
||||
xfer->frlengths[0] = xfer->max_data_length;
|
||||
usb2_start_hardware(xfer);
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
if (xfer->error != USB_ERR_CANCELLED) {
|
||||
/* start clear stall */
|
||||
sc->sc_flags |= UHUB_FLAG_INTR_STALL;
|
||||
usb2_transfer_start(sc->sc_xfer[1]);
|
||||
/*
|
||||
* Do a clear-stall. The "stall_pipe" flag
|
||||
* will get cleared before next callback by
|
||||
* the USB stack.
|
||||
*/
|
||||
xfer->flags.stall_pipe = 1;
|
||||
xfer->frlengths[0] = xfer->max_data_length;
|
||||
usb2_start_hardware(xfer);
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,18 +372,38 @@ repeat:
|
||||
/*
|
||||
* Figure out the device speed
|
||||
*/
|
||||
speed =
|
||||
(sc->sc_st.port_status & UPS_HIGH_SPEED) ? USB_SPEED_HIGH :
|
||||
(sc->sc_st.port_status & UPS_LOW_SPEED) ? USB_SPEED_LOW : USB_SPEED_FULL;
|
||||
|
||||
switch (udev->speed) {
|
||||
case USB_SPEED_HIGH:
|
||||
if (sc->sc_st.port_status & UPS_HIGH_SPEED)
|
||||
speed = USB_SPEED_HIGH;
|
||||
else if (sc->sc_st.port_status & UPS_LOW_SPEED)
|
||||
speed = USB_SPEED_LOW;
|
||||
else
|
||||
speed = USB_SPEED_FULL;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
if (sc->sc_st.port_status & UPS_LOW_SPEED)
|
||||
speed = USB_SPEED_LOW;
|
||||
else
|
||||
speed = USB_SPEED_FULL;
|
||||
break;
|
||||
case USB_SPEED_LOW:
|
||||
speed = USB_SPEED_LOW;
|
||||
break;
|
||||
default:
|
||||
/* same speed like parent */
|
||||
speed = udev->speed;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Figure out the device mode
|
||||
*
|
||||
* NOTE: This part is currently FreeBSD specific.
|
||||
*/
|
||||
usb2_mode =
|
||||
(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE) ?
|
||||
USB_MODE_DEVICE : USB_MODE_HOST;
|
||||
if (sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)
|
||||
usb2_mode = USB_MODE_DEVICE;
|
||||
else
|
||||
usb2_mode = USB_MODE_HOST;
|
||||
|
||||
/* need to create a new child */
|
||||
|
||||
@ -736,7 +732,7 @@ uhub_attach(device_t dev)
|
||||
/* set up interrupt pipe */
|
||||
iface_index = 0;
|
||||
err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
|
||||
uhub_config, 2, sc, &Giant);
|
||||
uhub_config, UHUB_N_TRANSFER, sc, &Giant);
|
||||
if (err) {
|
||||
DPRINTFN(0, "cannot setup interrupt transfer, "
|
||||
"errstr=%s!\n", usb2_errstr(err));
|
||||
@ -821,7 +817,7 @@ uhub_attach(device_t dev)
|
||||
return (0);
|
||||
|
||||
error:
|
||||
usb2_transfer_unsetup(sc->sc_xfer, 2);
|
||||
usb2_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
|
||||
|
||||
if (udev->hub) {
|
||||
free(udev->hub, M_USBDEV);
|
||||
@ -864,7 +860,7 @@ uhub_detach(device_t dev)
|
||||
child = NULL;
|
||||
}
|
||||
|
||||
usb2_transfer_unsetup(sc->sc_xfer, 2);
|
||||
usb2_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
|
||||
|
||||
free(hub, M_USBDEV);
|
||||
sc->sc_udev->hub = NULL;
|
||||
@ -1073,17 +1069,16 @@ usb2_intr_schedule_adjust(struct usb2_device *udev, int16_t len, uint8_t slot)
|
||||
{
|
||||
struct usb2_bus *bus = udev->bus;
|
||||
struct usb2_hub *hub;
|
||||
uint8_t speed;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
|
||||
|
||||
if (usb2_get_speed(udev) == USB_SPEED_HIGH) {
|
||||
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
|
||||
slot = usb2_intr_find_best_slot(bus->uframe_usage, 0,
|
||||
USB_HS_MICRO_FRAMES_MAX);
|
||||
}
|
||||
bus->uframe_usage[slot] += len;
|
||||
} else {
|
||||
if (usb2_get_speed(udev) == USB_SPEED_LOW) {
|
||||
speed = usb2_get_speed(udev);
|
||||
|
||||
switch (speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
if (speed == USB_SPEED_LOW) {
|
||||
len *= 8;
|
||||
}
|
||||
/*
|
||||
@ -1100,6 +1095,14 @@ usb2_intr_schedule_adjust(struct usb2_device *udev, int16_t len, uint8_t slot)
|
||||
}
|
||||
hub->uframe_usage[slot] += len;
|
||||
bus->uframe_usage[slot] += len;
|
||||
break;
|
||||
default:
|
||||
if (slot >= USB_HS_MICRO_FRAMES_MAX) {
|
||||
slot = usb2_intr_find_best_slot(bus->uframe_usage, 0,
|
||||
USB_HS_MICRO_FRAMES_MAX);
|
||||
}
|
||||
bus->uframe_usage[slot] += len;
|
||||
break;
|
||||
}
|
||||
return (slot);
|
||||
}
|
||||
@ -1429,7 +1432,7 @@ usb2_transfer_power_ref(struct usb2_xfer *xfer, int val)
|
||||
uint8_t needs_hw_power;
|
||||
uint8_t xfer_type;
|
||||
|
||||
udev = xfer->udev;
|
||||
udev = xfer->xroot->udev;
|
||||
|
||||
if (udev->device_index == USB_ROOT_HUB_ADDR) {
|
||||
/* no power save for root HUB */
|
||||
@ -1521,7 +1524,7 @@ usb2_bus_powerd(struct usb2_bus *bus)
|
||||
* and we simply skip it.
|
||||
*/
|
||||
for (x = USB_ROOT_HUB_ADDR + 1;
|
||||
x != USB_MAX_DEVICES; x++) {
|
||||
x != bus->devices_max; x++) {
|
||||
|
||||
udev = bus->devices[x];
|
||||
if (udev == NULL)
|
||||
@ -1565,7 +1568,7 @@ usb2_bus_powerd(struct usb2_bus *bus)
|
||||
/* Re-loop all the devices to get the actual state */
|
||||
|
||||
for (x = USB_ROOT_HUB_ADDR + 1;
|
||||
x != USB_MAX_DEVICES; x++) {
|
||||
x != bus->devices_max; x++) {
|
||||
|
||||
udev = bus->devices[x];
|
||||
if (udev == NULL)
|
||||
@ -1823,7 +1826,8 @@ void
|
||||
usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode)
|
||||
{
|
||||
/* filter input argument */
|
||||
if (power_mode != USB_POWER_MODE_ON) {
|
||||
if ((power_mode != USB_POWER_MODE_ON) &&
|
||||
(power_mode != USB_POWER_MODE_OFF)) {
|
||||
power_mode = USB_POWER_MODE_SAVE;
|
||||
}
|
||||
udev->power_mode = power_mode; /* update copy of power mode */
|
||||
|
@ -38,8 +38,9 @@ struct usb2_mbuf {
|
||||
struct usb2_mbuf *usb2_next;
|
||||
|
||||
uint32_t cur_data_len;
|
||||
uint32_t max_data_len:31;
|
||||
uint32_t last_packet:1;
|
||||
uint32_t max_data_len;
|
||||
uint8_t last_packet:1;
|
||||
uint8_t unused:7;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -43,25 +43,44 @@
|
||||
* Else: Next descriptor after "desc"
|
||||
*------------------------------------------------------------------------*/
|
||||
struct usb2_descriptor *
|
||||
usb2_desc_foreach(struct usb2_config_descriptor *cd, struct usb2_descriptor *desc)
|
||||
usb2_desc_foreach(struct usb2_config_descriptor *cd,
|
||||
struct usb2_descriptor *_desc)
|
||||
{
|
||||
void *end;
|
||||
uint8_t *desc_next;
|
||||
uint8_t *start;
|
||||
uint8_t *end;
|
||||
uint8_t *desc;
|
||||
|
||||
if (cd == NULL) {
|
||||
/* be NULL safe */
|
||||
if (cd == NULL)
|
||||
return (NULL);
|
||||
}
|
||||
end = USB_ADD_BYTES(cd, UGETW(cd->wTotalLength));
|
||||
|
||||
if (desc == NULL) {
|
||||
desc = USB_ADD_BYTES(cd, 0);
|
||||
} else {
|
||||
desc = USB_ADD_BYTES(desc, desc->bLength);
|
||||
}
|
||||
return (((((void *)desc) >= ((void *)cd)) &&
|
||||
(((void *)desc) < end) &&
|
||||
(USB_ADD_BYTES(desc, desc->bLength) >= ((void *)cd)) &&
|
||||
(USB_ADD_BYTES(desc, desc->bLength) <= end) &&
|
||||
(desc->bLength >= sizeof(*desc))) ? desc : NULL);
|
||||
/* We assume that the "wTotalLength" has been checked. */
|
||||
start = (uint8_t *)cd;
|
||||
end = start + UGETW(cd->wTotalLength);
|
||||
desc = (uint8_t *)_desc;
|
||||
|
||||
/* Get start of next USB descriptor. */
|
||||
if (desc == NULL)
|
||||
desc = start;
|
||||
else
|
||||
desc = desc + desc[0];
|
||||
|
||||
/* Check that the next USB descriptor is within the range. */
|
||||
if ((desc < start) || (desc >= end))
|
||||
return (NULL); /* out of range, or EOD */
|
||||
|
||||
/* Check that the second next USB descriptor is within range. */
|
||||
desc_next = desc + desc[0];
|
||||
if ((desc_next < start) || (desc_next > end))
|
||||
return (NULL); /* out of range */
|
||||
|
||||
/* Check minimum descriptor length. */
|
||||
if (desc[0] < 3)
|
||||
return (NULL); /* too short descriptor */
|
||||
|
||||
/* Return start of next descriptor. */
|
||||
return ((struct usb2_descriptor *)desc);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -140,7 +159,6 @@ usb2_find_edesc(struct usb2_config_descriptor *cd,
|
||||
desc = ((void *)d);
|
||||
|
||||
while ((desc = usb2_desc_foreach(cd, desc))) {
|
||||
|
||||
if (desc->bDescriptorType == UDESC_INTERFACE) {
|
||||
break;
|
||||
}
|
||||
@ -195,7 +213,6 @@ usb2_get_no_alts(struct usb2_config_descriptor *cd, uint8_t ifaceno)
|
||||
uint16_t n = 0;
|
||||
|
||||
while ((desc = usb2_desc_foreach(cd, desc))) {
|
||||
|
||||
if ((desc->bDescriptorType == UDESC_INTERFACE) &&
|
||||
(desc->bLength >= sizeof(*id))) {
|
||||
id = (void *)desc;
|
||||
|
@ -80,7 +80,7 @@ usb2_do_request_callback(struct usb2_xfer *xfer)
|
||||
usb2_start_hardware(xfer);
|
||||
break;
|
||||
default:
|
||||
usb2_cv_signal(xfer->udev->default_cv);
|
||||
usb2_cv_signal(xfer->xroot->udev->default_cv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -94,18 +94,21 @@ void
|
||||
usb2_do_clear_stall_callback(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_device_request req;
|
||||
struct usb2_device *udev;
|
||||
struct usb2_pipe *pipe;
|
||||
struct usb2_pipe *pipe_end;
|
||||
struct usb2_pipe *pipe_first;
|
||||
uint8_t to = USB_EP_MAX;
|
||||
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
udev = xfer->xroot->udev;
|
||||
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
|
||||
/* round robin pipe clear stall */
|
||||
|
||||
pipe = xfer->udev->pipe_curr;
|
||||
pipe_end = xfer->udev->pipes + USB_EP_MAX;
|
||||
pipe_first = xfer->udev->pipes;
|
||||
pipe = udev->pipe_curr;
|
||||
pipe_end = udev->pipes + USB_EP_MAX;
|
||||
pipe_first = udev->pipes;
|
||||
if (pipe == NULL) {
|
||||
pipe = pipe_first;
|
||||
}
|
||||
@ -145,11 +148,11 @@ tr_setup:
|
||||
/* set length */
|
||||
xfer->frlengths[0] = sizeof(req);
|
||||
xfer->nframes = 1;
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
|
||||
usb2_start_hardware(xfer);
|
||||
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(udev->bus);
|
||||
break;
|
||||
}
|
||||
pipe++;
|
||||
@ -165,8 +168,8 @@ tr_setup:
|
||||
}
|
||||
|
||||
/* store current pipe */
|
||||
xfer->udev->pipe_curr = pipe;
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
udev->pipe_curr = pipe;
|
||||
USB_BUS_UNLOCK(udev->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -367,7 +370,8 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
|
||||
}
|
||||
if (temp > 0) {
|
||||
usb2_pause_mtx(
|
||||
xfer->xfer_mtx, temp);
|
||||
xfer->xroot->xfer_mtx,
|
||||
temp);
|
||||
}
|
||||
#endif
|
||||
xfer->flags.manual_status = 0;
|
||||
@ -384,8 +388,8 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
|
||||
if ((flags & USB_USE_POLLING) || cold) {
|
||||
usb2_do_poll(udev->default_xfer, USB_DEFAULT_XFER_MAX);
|
||||
} else {
|
||||
usb2_cv_wait(xfer->udev->default_cv,
|
||||
xfer->xfer_mtx);
|
||||
usb2_cv_wait(udev->default_cv,
|
||||
xfer->xroot->xfer_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ usb2_sw_transfer(struct usb2_sw_transfer *std,
|
||||
DPRINTF("xfer gone\n");
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
std->xfer = NULL;
|
||||
|
||||
|
@ -63,6 +63,7 @@ static const struct usb2_std_packet_size
|
||||
[USB_SPEED_FULL] = {.range = {0, 64}},
|
||||
[USB_SPEED_HIGH] = {.range = {0, 1024}},
|
||||
[USB_SPEED_VARIABLE] = {.range = {0, 1024}},
|
||||
[USB_SPEED_SUPER] = {.range = {0, 1024}},
|
||||
},
|
||||
|
||||
[UE_CONTROL] = {
|
||||
@ -70,6 +71,7 @@ static const struct usb2_std_packet_size
|
||||
[USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
|
||||
[USB_SPEED_HIGH] = {.fixed = {64, 64, 64, 64}},
|
||||
[USB_SPEED_VARIABLE] = {.fixed = {512, 512, 512, 512}},
|
||||
[USB_SPEED_SUPER] = {.fixed = {512, 512, 512, 512}},
|
||||
},
|
||||
|
||||
[UE_BULK] = {
|
||||
@ -77,6 +79,7 @@ static const struct usb2_std_packet_size
|
||||
[USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
|
||||
[USB_SPEED_HIGH] = {.fixed = {512, 512, 512, 512}},
|
||||
[USB_SPEED_VARIABLE] = {.fixed = {512, 512, 1024, 1536}},
|
||||
[USB_SPEED_SUPER] = {.fixed = {1024, 1024, 1024, 1024}},
|
||||
},
|
||||
|
||||
[UE_ISOCHRONOUS] = {
|
||||
@ -84,6 +87,7 @@ static const struct usb2_std_packet_size
|
||||
[USB_SPEED_FULL] = {.range = {0, 1023}},
|
||||
[USB_SPEED_HIGH] = {.range = {0, 1024}},
|
||||
[USB_SPEED_VARIABLE] = {.range = {0, 3584}},
|
||||
[USB_SPEED_SUPER] = {.range = {0, 1024}},
|
||||
},
|
||||
};
|
||||
|
||||
@ -243,12 +247,12 @@ usb2_transfer_setup_sub_malloc(struct usb2_setup_params *parm,
|
||||
for (x = 0; x != n_dma_pc; x++) {
|
||||
/* need to initialize the page cache */
|
||||
parm->dma_page_cache_ptr[x].tag_parent =
|
||||
&parm->curr_xfer->usb2_root->dma_parent_tag;
|
||||
&parm->curr_xfer->xroot->dma_parent_tag;
|
||||
}
|
||||
for (x = 0; x != count; x++) {
|
||||
/* need to initialize the page cache */
|
||||
parm->xfer_page_cache_ptr[x].tag_parent =
|
||||
&parm->curr_xfer->usb2_root->dma_parent_tag;
|
||||
&parm->curr_xfer->xroot->dma_parent_tag;
|
||||
}
|
||||
|
||||
if (ppc) {
|
||||
@ -413,10 +417,14 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
|
||||
*/
|
||||
xfer->timeout = 1000 / 4;
|
||||
}
|
||||
if (parm->speed == USB_SPEED_HIGH) {
|
||||
frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
|
||||
} else {
|
||||
switch (parm->speed) {
|
||||
case USB_SPEED_LOW:
|
||||
case USB_SPEED_FULL:
|
||||
frame_limit = USB_MAX_FS_ISOC_FRAMES_PER_XFER;
|
||||
break;
|
||||
default:
|
||||
frame_limit = USB_MAX_HS_ISOC_FRAMES_PER_XFER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (xfer->nframes > frame_limit) {
|
||||
@ -446,13 +454,29 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
|
||||
|
||||
xfer->interval = edesc->bInterval;
|
||||
|
||||
if (parm->speed == USB_SPEED_HIGH) {
|
||||
xfer->interval /= 8; /* 125us -> 1ms */
|
||||
switch (parm->speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
case USB_SPEED_VARIABLE:
|
||||
/* 125us -> 1ms */
|
||||
if (xfer->interval < 4)
|
||||
xfer->interval = 1;
|
||||
else if (xfer->interval > 16)
|
||||
xfer->interval = (1<<(16-4));
|
||||
else
|
||||
xfer->interval =
|
||||
(1 << (xfer->interval-4));
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
/* 125us -> 1ms */
|
||||
xfer->interval /= 8;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (xfer->interval == 0) {
|
||||
/*
|
||||
* one millisecond is the smallest
|
||||
* interval
|
||||
* One millisecond is the smallest
|
||||
* interval we support:
|
||||
*/
|
||||
xfer->interval = 1;
|
||||
}
|
||||
@ -670,7 +694,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
|
||||
if (parm->buf) {
|
||||
for (x = 0; x != n_frbuffers; x++) {
|
||||
xfer->frbuffers[x].tag_parent =
|
||||
&xfer->usb2_root->dma_parent_tag;
|
||||
&xfer->xroot->dma_parent_tag;
|
||||
|
||||
if (xfer->flags_int.bdma_enable &&
|
||||
(parm->bufsize_max > 0)) {
|
||||
@ -715,7 +739,7 @@ usb2_error_t
|
||||
usb2_transfer_setup(struct usb2_device *udev,
|
||||
const uint8_t *ifaces, struct usb2_xfer **ppxfer,
|
||||
const struct usb2_config *setup_start, uint16_t n_setup,
|
||||
void *priv_sc, struct mtx *priv_mtx)
|
||||
void *priv_sc, struct mtx *xfer_mtx)
|
||||
{
|
||||
struct usb2_xfer dummy;
|
||||
struct usb2_setup_params parm;
|
||||
@ -745,9 +769,9 @@ usb2_transfer_setup(struct usb2_device *udev,
|
||||
DPRINTFN(6, "ifaces array is NULL!\n");
|
||||
return (USB_ERR_INVAL);
|
||||
}
|
||||
if (priv_mtx == NULL) {
|
||||
if (xfer_mtx == NULL) {
|
||||
DPRINTFN(6, "using global lock\n");
|
||||
priv_mtx = &Giant;
|
||||
xfer_mtx = &Giant;
|
||||
}
|
||||
/* sanity checks */
|
||||
for (setup = setup_start, n = 0;
|
||||
@ -799,13 +823,14 @@ usb2_transfer_setup(struct usb2_device *udev,
|
||||
|
||||
usb2_cv_init(&info->cv_drain, "WDRAIN");
|
||||
|
||||
info->priv_mtx = priv_mtx;
|
||||
info->xfer_mtx = xfer_mtx;
|
||||
|
||||
usb2_dma_tag_setup(&info->dma_parent_tag,
|
||||
parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
|
||||
priv_mtx, &usb2_bdma_done_event, info, 32, parm.dma_tag_max);
|
||||
xfer_mtx, &usb2_bdma_done_event, info, 32, parm.dma_tag_max);
|
||||
|
||||
info->bus = udev->bus;
|
||||
info->udev = udev;
|
||||
|
||||
TAILQ_INIT(&info->done_q.head);
|
||||
info->done_q.command = &usb2_callback_wrapper;
|
||||
@ -814,17 +839,16 @@ usb2_transfer_setup(struct usb2_device *udev,
|
||||
info->dma_q.command = &usb2_bdma_work_loop;
|
||||
|
||||
info->done_m[0].hdr.pm_callback = &usb2_callback_proc;
|
||||
info->done_m[0].usb2_root = info;
|
||||
info->done_m[0].xroot = info;
|
||||
info->done_m[1].hdr.pm_callback = &usb2_callback_proc;
|
||||
info->done_m[1].usb2_root = info;
|
||||
info->done_m[1].xroot = info;
|
||||
|
||||
/* create a callback thread */
|
||||
|
||||
if (usb2_proc_setup(&info->done_p,
|
||||
&udev->bus->bus_mtx, USB_PRI_HIGH)) {
|
||||
parm.err = USB_ERR_NO_INTR_THREAD;
|
||||
goto done;
|
||||
}
|
||||
if (xfer_mtx == &Giant)
|
||||
info->done_p =
|
||||
&udev->bus->giant_callback_proc;
|
||||
else
|
||||
info->done_p =
|
||||
&udev->bus->non_giant_callback_proc;
|
||||
}
|
||||
/* reset sizes */
|
||||
|
||||
@ -871,11 +895,9 @@ usb2_transfer_setup(struct usb2_device *udev,
|
||||
xfer = USB_ADD_BYTES(buf, parm.size[0]);
|
||||
|
||||
ppxfer[n] = xfer;
|
||||
xfer->udev = udev;
|
||||
xfer->address = udev->address;
|
||||
xfer->priv_sc = priv_sc;
|
||||
xfer->xfer_mtx = priv_mtx;
|
||||
xfer->usb2_root = info;
|
||||
xfer->xroot = info;
|
||||
info->setup_refcount++;
|
||||
|
||||
usb2_callout_init_mtx(&xfer->timeout_handle,
|
||||
@ -1046,10 +1068,11 @@ usb2_transfer_unsetup_sub(struct usb2_xfer_root *info, uint8_t needs_delay)
|
||||
temp = usb2_get_dma_delay(info->bus);
|
||||
usb2_pause_mtx(&info->bus->bus_mtx, temp);
|
||||
}
|
||||
USB_BUS_UNLOCK(info->bus);
|
||||
|
||||
/* wait for interrupt thread to exit */
|
||||
usb2_proc_unsetup(&info->done_p);
|
||||
/* make sure that our done messages are not queued anywhere */
|
||||
usb2_proc_mwait(info->done_p, &info->done_m[0], &info->done_m[1]);
|
||||
|
||||
USB_BUS_UNLOCK(info->bus);
|
||||
|
||||
/* free DMA'able memory, if any */
|
||||
pc = info->dma_page_cache_start;
|
||||
@ -1100,7 +1123,7 @@ usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup)
|
||||
if (xfer) {
|
||||
if (xfer->pipe) {
|
||||
USB_XFER_LOCK(xfer);
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
/*
|
||||
* HINT: when you start/stop a transfer, it
|
||||
@ -1112,7 +1135,7 @@ usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup)
|
||||
*
|
||||
* That way, if your code has many parts that
|
||||
* will not stop running under the same
|
||||
* lock, in other words "priv_mtx", the
|
||||
* lock, in other words "xfer_mtx", the
|
||||
* usb2_transfer_start and
|
||||
* usb2_transfer_stop functions will simply
|
||||
* return when they detect a NULL pointer
|
||||
@ -1124,7 +1147,7 @@ usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup)
|
||||
*/
|
||||
pxfer[n_setup] = NULL;
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
|
||||
usb2_transfer_drain(xfer);
|
||||
@ -1145,8 +1168,8 @@ usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup)
|
||||
|
||||
usb2_callout_drain(&xfer->timeout_handle);
|
||||
|
||||
if (xfer->usb2_root) {
|
||||
info = xfer->usb2_root;
|
||||
if (xfer->xroot) {
|
||||
info = xfer->xroot;
|
||||
|
||||
USB_BUS_LOCK(info->bus);
|
||||
|
||||
@ -1349,16 +1372,16 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
|
||||
#if USB_DEBUG
|
||||
if (USB_DEBUG_VAR > 0) {
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
usb2_dump_pipe(xfer->pipe);
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
#endif
|
||||
|
||||
USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_NOTOWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_NOTOWNED);
|
||||
|
||||
/* Only open the USB transfer once! */
|
||||
if (!xfer->flags_int.open) {
|
||||
@ -1366,9 +1389,9 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
|
||||
DPRINTF("open\n");
|
||||
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
(xfer->pipe->methods->open) (xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
/* set "transferring" flag */
|
||||
xfer->flags_int.transferring = 1;
|
||||
@ -1381,9 +1404,9 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
* frequently the "done_q":
|
||||
*/
|
||||
if (xfer->wait_queue) {
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
usb2_transfer_dequeue(xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
/* clear "did_dma_delay" flag */
|
||||
xfer->flags_int.did_dma_delay = 0;
|
||||
@ -1415,16 +1438,16 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
*/
|
||||
DPRINTF("xfer=%p nframes=0: stall "
|
||||
"or clear stall!\n", xfer);
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
xfer->flags_int.can_cancel_immed = 1;
|
||||
/* start the transfer */
|
||||
usb2_command_wrapper(&xfer->pipe->pipe_q, xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
usb2_transfer_done(xfer, USB_ERR_INVAL);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return;
|
||||
}
|
||||
/* compute total transfer length */
|
||||
@ -1433,9 +1456,9 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
xfer->sumlen += xfer->frlengths[x];
|
||||
if (xfer->sumlen < xfer->frlengths[x]) {
|
||||
/* length wrapped around */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
usb2_transfer_done(xfer, USB_ERR_INVAL);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1450,9 +1473,9 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
if (xfer->flags_int.control_xfr) {
|
||||
|
||||
if (usb2_start_hardware_sub(xfer)) {
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
usb2_transfer_done(xfer, USB_ERR_STALLED);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1488,7 +1511,7 @@ usb2_start_hardware(struct usb2_xfer *xfer)
|
||||
*/
|
||||
if (xfer->flags_int.bdma_enable) {
|
||||
/* insert the USB transfer last in the BUS-DMA queue */
|
||||
usb2_command_wrapper(&xfer->usb2_root->dma_q, xfer);
|
||||
usb2_command_wrapper(&xfer->xroot->dma_q, xfer);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@ -1508,7 +1531,7 @@ usb2_pipe_enter(struct usb2_xfer *xfer)
|
||||
|
||||
USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
|
||||
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
pipe = xfer->pipe;
|
||||
|
||||
@ -1524,7 +1547,7 @@ usb2_pipe_enter(struct usb2_xfer *xfer)
|
||||
if (xfer->error) {
|
||||
/* some error has happened */
|
||||
usb2_transfer_done(xfer, 0);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -1533,7 +1556,7 @@ usb2_pipe_enter(struct usb2_xfer *xfer)
|
||||
|
||||
/* start the transfer */
|
||||
usb2_command_wrapper(&pipe->pipe_q, xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -1562,10 +1585,10 @@ usb2_transfer_start(struct usb2_xfer *xfer)
|
||||
if (xfer->flags_int.transferring) {
|
||||
return;
|
||||
}
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
/* call the USB transfer callback */
|
||||
usb2_callback_ss_done_defer(xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -1596,7 +1619,7 @@ usb2_transfer_stop(struct usb2_xfer *xfer)
|
||||
}
|
||||
/* try to stop the current USB transfer */
|
||||
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
xfer->error = USB_ERR_CANCELLED;/* override any previous error */
|
||||
/*
|
||||
* Clear "open" and "started" when both private and USB lock
|
||||
@ -1648,7 +1671,7 @@ usb2_transfer_stop(struct usb2_xfer *xfer)
|
||||
}
|
||||
}
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -1672,22 +1695,22 @@ usb2_transfer_pending(struct usb2_xfer *xfer)
|
||||
/* trivial case */
|
||||
return (1);
|
||||
}
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
if (xfer->wait_queue) {
|
||||
/* we are waiting on a queue somewhere */
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return (1);
|
||||
}
|
||||
info = xfer->usb2_root;
|
||||
info = xfer->xroot;
|
||||
pq = &info->done_q;
|
||||
|
||||
if (pq->curr == xfer) {
|
||||
/* we are currently scheduled for callback */
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return (1);
|
||||
}
|
||||
/* we are not pending */
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1709,7 +1732,7 @@ usb2_transfer_drain(struct usb2_xfer *xfer)
|
||||
/* transfer is gone */
|
||||
return;
|
||||
}
|
||||
if (xfer->xfer_mtx != &Giant) {
|
||||
if (xfer->xroot->xfer_mtx != &Giant) {
|
||||
USB_XFER_LOCK_ASSERT(xfer, MA_NOTOWNED);
|
||||
}
|
||||
USB_XFER_LOCK(xfer);
|
||||
@ -1722,7 +1745,7 @@ usb2_transfer_drain(struct usb2_xfer *xfer)
|
||||
* Wait until the current outstanding USB
|
||||
* transfer is complete !
|
||||
*/
|
||||
usb2_cv_wait(&xfer->usb2_root->cv_drain, xfer->xfer_mtx);
|
||||
usb2_cv_wait(&xfer->xroot->cv_drain, xfer->xroot->xfer_mtx);
|
||||
}
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
}
|
||||
@ -1769,7 +1792,7 @@ static void
|
||||
usb2_callback_proc(struct usb2_proc_msg *_pm)
|
||||
{
|
||||
struct usb2_done_msg *pm = (void *)_pm;
|
||||
struct usb2_xfer_root *info = pm->usb2_root;
|
||||
struct usb2_xfer_root *info = pm->xroot;
|
||||
|
||||
/* Change locking order */
|
||||
USB_BUS_UNLOCK(info->bus);
|
||||
@ -1778,14 +1801,14 @@ usb2_callback_proc(struct usb2_proc_msg *_pm)
|
||||
* We exploit the fact that the mutex is the same for all
|
||||
* callbacks that will be called from this thread:
|
||||
*/
|
||||
mtx_lock(info->priv_mtx);
|
||||
mtx_lock(info->xfer_mtx);
|
||||
USB_BUS_LOCK(info->bus);
|
||||
|
||||
/* Continue where we lost track */
|
||||
usb2_command_wrapper(&info->done_q,
|
||||
info->done_q.curr);
|
||||
|
||||
mtx_unlock(info->priv_mtx);
|
||||
mtx_unlock(info->xfer_mtx);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -1797,10 +1820,10 @@ usb2_callback_proc(struct usb2_proc_msg *_pm)
|
||||
static void
|
||||
usb2_callback_ss_done_defer(struct usb2_xfer *xfer)
|
||||
{
|
||||
struct usb2_xfer_root *info = xfer->usb2_root;
|
||||
struct usb2_xfer_root *info = xfer->xroot;
|
||||
struct usb2_xfer_queue *pq = &info->done_q;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
if (pq->curr != xfer) {
|
||||
usb2_transfer_enqueue(pq, xfer);
|
||||
@ -1812,7 +1835,7 @@ usb2_callback_ss_done_defer(struct usb2_xfer *xfer)
|
||||
* will have a Lock Order Reversal, LOR, if we try to
|
||||
* proceed !
|
||||
*/
|
||||
if (usb2_proc_msignal(&info->done_p,
|
||||
if (usb2_proc_msignal(info->done_p,
|
||||
&info->done_m[0], &info->done_m[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
@ -1836,10 +1859,10 @@ static void
|
||||
usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
{
|
||||
struct usb2_xfer *xfer = pq->curr;
|
||||
struct usb2_xfer_root *info = xfer->usb2_root;
|
||||
struct usb2_xfer_root *info = xfer->xroot;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
if (!mtx_owned(xfer->xfer_mtx)) {
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
if (!mtx_owned(xfer->xroot->xfer_mtx)) {
|
||||
/*
|
||||
* Cases that end up here:
|
||||
*
|
||||
@ -1852,7 +1875,7 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
* will have a Lock Order Reversal, LOR, if we try to
|
||||
* proceed !
|
||||
*/
|
||||
if (usb2_proc_msignal(&info->done_p,
|
||||
if (usb2_proc_msignal(info->done_p,
|
||||
&info->done_m[0], &info->done_m[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
@ -1870,22 +1893,22 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
/* get next USB transfer in the queue */
|
||||
info->done_q.curr = NULL;
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_NOTOWNED);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_NOTOWNED);
|
||||
|
||||
/* set correct USB state for callback */
|
||||
if (!xfer->flags_int.transferring) {
|
||||
xfer->usb2_state = USB_ST_SETUP;
|
||||
if (!xfer->flags_int.started) {
|
||||
/* we got stopped before we even got started */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (usb2_callback_wrapper_sub(xfer)) {
|
||||
/* the callback has been deferred */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
goto done;
|
||||
}
|
||||
/* decrement power reference */
|
||||
@ -1911,12 +1934,11 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
(xfer->callback) (xfer);
|
||||
|
||||
/* pickup the USB mutex again */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
/*
|
||||
* Check if we got started after that we got cancelled, but
|
||||
* before we managed to do the callback. Check if we are
|
||||
* draining.
|
||||
* before we managed to do the callback.
|
||||
*/
|
||||
if ((!xfer->flags_int.open) &&
|
||||
(xfer->flags_int.started) &&
|
||||
@ -1924,13 +1946,19 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
|
||||
/* try to loop, but not recursivly */
|
||||
usb2_command_wrapper(&info->done_q, xfer);
|
||||
return;
|
||||
} else if (xfer->flags_int.draining &&
|
||||
}
|
||||
|
||||
done:
|
||||
/*
|
||||
* Check if we are draining.
|
||||
*/
|
||||
if (xfer->flags_int.draining &&
|
||||
(!xfer->flags_int.transferring)) {
|
||||
/* "usb2_transfer_drain()" is waiting for end of transfer */
|
||||
xfer->flags_int.draining = 0;
|
||||
usb2_cv_broadcast(&xfer->usb2_root->cv_drain);
|
||||
usb2_cv_broadcast(&xfer->xroot->cv_drain);
|
||||
}
|
||||
done:
|
||||
|
||||
/* do the next callback, if any */
|
||||
usb2_command_wrapper(&info->done_q,
|
||||
info->done_q.curr);
|
||||
@ -1949,7 +1977,7 @@ usb2_dma_delay_done_cb(void *arg)
|
||||
{
|
||||
struct usb2_xfer *xfer = arg;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
DPRINTFN(3, "Completed %p\n", xfer);
|
||||
|
||||
@ -2014,7 +2042,7 @@ usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
{
|
||||
struct usb2_xfer_queue *pq;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
DPRINTF("err=%s\n", usb2_errstr(error));
|
||||
|
||||
@ -2040,12 +2068,12 @@ usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
*/
|
||||
usb2_transfer_dequeue(xfer);
|
||||
|
||||
if (mtx_owned(xfer->xfer_mtx)) {
|
||||
if (mtx_owned(xfer->xroot->xfer_mtx)) {
|
||||
/*
|
||||
* If the private USB lock is not locked, then we assume
|
||||
* that the BUS-DMA load stage has been passed:
|
||||
*/
|
||||
pq = &xfer->usb2_root->dma_q;
|
||||
pq = &xfer->xroot->dma_q;
|
||||
|
||||
if (pq->curr == xfer) {
|
||||
/* start the next BUS-DMA load, if any */
|
||||
@ -2054,10 +2082,10 @@ usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
|
||||
}
|
||||
/* keep some statistics */
|
||||
if (xfer->error) {
|
||||
xfer->udev->bus->stats_err.uds_requests
|
||||
xfer->xroot->bus->stats_err.uds_requests
|
||||
[xfer->pipe->edesc->bmAttributes & UE_XFERTYPE]++;
|
||||
} else {
|
||||
xfer->udev->bus->stats_ok.uds_requests
|
||||
xfer->xroot->bus->stats_ok.uds_requests
|
||||
[xfer->pipe->edesc->bmAttributes & UE_XFERTYPE]++;
|
||||
}
|
||||
|
||||
@ -2078,7 +2106,7 @@ usb2_transfer_start_cb(void *arg)
|
||||
struct usb2_xfer *xfer = arg;
|
||||
struct usb2_pipe *pipe = xfer->pipe;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
DPRINTF("start\n");
|
||||
|
||||
@ -2113,11 +2141,11 @@ usb2_transfer_set_stall(struct usb2_xfer *xfer)
|
||||
USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
|
||||
|
||||
/* avoid any races by locking the USB mutex */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
xfer->flags.stall_pipe = 1;
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -2136,11 +2164,11 @@ usb2_transfer_clear_stall(struct usb2_xfer *xfer)
|
||||
USB_XFER_LOCK_ASSERT(xfer, MA_OWNED);
|
||||
|
||||
/* avoid any races by locking the USB mutex */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
|
||||
xfer->flags.stall_pipe = 0;
|
||||
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
@ -2158,7 +2186,7 @@ usb2_pipe_start(struct usb2_xfer_queue *pq)
|
||||
xfer = pq->curr;
|
||||
pipe = xfer->pipe;
|
||||
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/*
|
||||
* If the pipe is already stalled we do nothing !
|
||||
@ -2182,15 +2210,17 @@ usb2_pipe_start(struct usb2_xfer_queue *pq)
|
||||
struct usb2_device *udev;
|
||||
struct usb2_xfer_root *info;
|
||||
|
||||
udev = xfer->udev;
|
||||
info = xfer->xroot;
|
||||
udev = info->udev;
|
||||
pipe->is_stalled = 1;
|
||||
|
||||
if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
|
||||
(udev->bus->methods->set_stall) (
|
||||
udev, NULL, pipe);
|
||||
} else if (udev->default_xfer[1]) {
|
||||
info = udev->default_xfer[1]->usb2_root;
|
||||
if (usb2_proc_msignal(&info->done_p,
|
||||
info = udev->default_xfer[1]->xroot;
|
||||
if (usb2_proc_msignal(
|
||||
&info->bus->non_giant_callback_proc,
|
||||
&udev->cs_msg[0], &udev->cs_msg[1])) {
|
||||
/* ignore */
|
||||
}
|
||||
@ -2260,7 +2290,7 @@ void
|
||||
usb2_transfer_timeout_ms(struct usb2_xfer *xfer,
|
||||
void (*cb) (void *arg), uint32_t ms)
|
||||
{
|
||||
USB_BUS_LOCK_ASSERT(xfer->udev->bus, MA_OWNED);
|
||||
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
|
||||
|
||||
/* defer delay */
|
||||
usb2_callout_reset(&xfer->timeout_handle,
|
||||
@ -2293,9 +2323,9 @@ usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
|
||||
if ((!xfer->flags_int.open) &&
|
||||
(!xfer->flags_int.did_close)) {
|
||||
DPRINTF("close\n");
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
(xfer->pipe->methods->close) (xfer);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
/* only close once */
|
||||
xfer->flags_int.did_close = 1;
|
||||
return (1); /* wait for new callback */
|
||||
@ -2316,16 +2346,16 @@ usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
|
||||
/* we can not cancel this delay */
|
||||
xfer->flags_int.can_cancel_immed = 0;
|
||||
|
||||
temp = usb2_get_dma_delay(xfer->udev->bus);
|
||||
temp = usb2_get_dma_delay(xfer->xroot->bus);
|
||||
|
||||
DPRINTFN(3, "DMA delay, %u ms, "
|
||||
"on %p\n", temp, xfer);
|
||||
|
||||
if (temp != 0) {
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
usb2_transfer_timeout_ms(xfer,
|
||||
&usb2_dma_delay_done_cb, temp);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
return (1); /* wait for new callback */
|
||||
}
|
||||
}
|
||||
@ -2417,7 +2447,7 @@ usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
|
||||
* If the current USB transfer is completing we need to start the
|
||||
* next one:
|
||||
*/
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
if (pipe->pipe_q.curr == xfer) {
|
||||
usb2_command_wrapper(&pipe->pipe_q, NULL);
|
||||
|
||||
@ -2429,7 +2459,7 @@ usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
|
||||
xfer->pipe->is_synced = 0;
|
||||
}
|
||||
}
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
done:
|
||||
return (0);
|
||||
}
|
||||
@ -2632,7 +2662,7 @@ usb2_clear_stall_callback(struct usb2_xfer *xfer1,
|
||||
* "ata-usb.c" depends on this)
|
||||
*/
|
||||
|
||||
usb2_clear_data_toggle(xfer2->udev, xfer2->pipe);
|
||||
usb2_clear_data_toggle(xfer2->xroot->udev, xfer2->pipe);
|
||||
|
||||
/* setup a clear-stall packet */
|
||||
|
||||
@ -2725,7 +2755,7 @@ void
|
||||
usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
|
||||
{
|
||||
struct usb2_xfer *xfer;
|
||||
struct usb2_xfer_root *usb2_root;
|
||||
struct usb2_xfer_root *xroot;
|
||||
struct usb2_device *udev;
|
||||
struct usb2_proc_msg *pm;
|
||||
uint32_t to;
|
||||
@ -2739,8 +2769,8 @@ usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
|
||||
for (n = 0; n != max; n++) {
|
||||
xfer = ppxfer[n];
|
||||
if (xfer) {
|
||||
usb2_root = xfer->usb2_root;
|
||||
udev = xfer->udev;
|
||||
xroot = xfer->xroot;
|
||||
udev = xroot->udev;
|
||||
|
||||
/*
|
||||
* Poll hardware - signal that we are polling by
|
||||
@ -2751,10 +2781,10 @@ usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
|
||||
/* poll clear stall start */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
pm = &udev->cs_msg[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
|
||||
if (udev->default_xfer[1]) {
|
||||
|
||||
@ -2762,20 +2792,20 @@ usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
|
||||
usb2_callout_poll(udev->default_xfer[1]);
|
||||
|
||||
/* poll clear stall done thread */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
pm = &udev->default_xfer[1]->
|
||||
usb2_root->done_m[0].hdr;
|
||||
xroot->done_m[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
/* poll timeout */
|
||||
usb2_callout_poll(xfer);
|
||||
|
||||
/* poll done thread */
|
||||
USB_BUS_LOCK(xfer->udev->bus);
|
||||
pm = &usb2_root->done_m[0].hdr;
|
||||
USB_BUS_LOCK(xfer->xroot->bus);
|
||||
pm = &xroot->done_m[0].hdr;
|
||||
(pm->pm_callback) (pm);
|
||||
USB_BUS_UNLOCK(xfer->udev->bus);
|
||||
USB_BUS_UNLOCK(xfer->xroot->bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
*/
|
||||
struct usb2_done_msg {
|
||||
struct usb2_proc_msg hdr;
|
||||
struct usb2_xfer_root *usb2_root;
|
||||
struct usb2_xfer_root *xroot;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -46,17 +46,17 @@ struct usb2_xfer_root {
|
||||
struct usb2_xfer_queue done_q;
|
||||
struct usb2_done_msg done_m[2];
|
||||
struct cv cv_drain;
|
||||
|
||||
struct usb2_dma_parent_tag dma_parent_tag;
|
||||
|
||||
struct usb2_process done_p;
|
||||
struct usb2_process *done_p; /* pointer to callback process */
|
||||
void *memory_base;
|
||||
struct mtx *priv_mtx;
|
||||
struct mtx *xfer_mtx; /* cannot be changed during operation */
|
||||
struct usb2_page_cache *dma_page_cache_start;
|
||||
struct usb2_page_cache *dma_page_cache_end;
|
||||
struct usb2_page_cache *xfer_page_cache_start;
|
||||
struct usb2_page_cache *xfer_page_cache_end;
|
||||
struct usb2_bus *bus;
|
||||
struct usb2_bus *bus; /* pointer to USB bus (cached) */
|
||||
struct usb2_device *udev; /* pointer to USB device */
|
||||
|
||||
uint32_t memory_size;
|
||||
uint32_t setup_refcount;
|
||||
|
@ -35,6 +35,10 @@
|
||||
#define USB_EP_MAX (2*16) /* hardcoded */
|
||||
#define USB_FIFO_MAX (4 * USB_EP_MAX)
|
||||
|
||||
#define USB_ROOT_HUB_ADDR 1 /* index */
|
||||
|
||||
#define USB_MIN_DEVICES 2 /* unused + root HUB */
|
||||
|
||||
#define USB_MAX_DEVICES USB_DEV_MAX /* including virtual root HUB and
|
||||
* address zero */
|
||||
#define USB_MAX_ENDPOINTS USB_EP_MAX /* 2 directions on 16 endpoints */
|
||||
@ -56,13 +60,18 @@
|
||||
/* sanity checks */
|
||||
|
||||
#if (USB_FIFO_MAX < USB_EP_MAX)
|
||||
#error "Misconfigured limits #1"
|
||||
#error "There cannot be less FIFOs than USB endpoints."
|
||||
#endif
|
||||
#if (USB_FIFO_MAX & 1)
|
||||
#error "Misconfigured limits #2"
|
||||
#error "Number of FIFOs must be odd."
|
||||
#endif
|
||||
#if (USB_EP_MAX < (2*16))
|
||||
#error "Misconfigured limits #3"
|
||||
#error "Number of hardware USB endpoints cannot be less than 32."
|
||||
#endif
|
||||
#if (USB_MAX_DEVICES < USB_MIN_DEVICES)
|
||||
#error "Minimum number of devices is greater than maximum number of devices."
|
||||
#endif
|
||||
#if (USB_ROOT_HUB_ADDR >= USB_MIN_DEVICES)
|
||||
#error "The root hub address must be less than USB_MIN_DEVICES."
|
||||
#endif
|
||||
|
||||
#endif /* _USB2_DEFS_H_ */
|
||||
|
@ -4,7 +4,7 @@
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*
|
||||
* generated from:
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 186651 2008-12-31 14:25:14Z luigi
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 187163 2009-01-13 19:01:25Z thompsa
|
||||
*/
|
||||
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
|
||||
|
||||
@ -158,6 +158,7 @@
|
||||
#define USB_VENDOR_KYOCERA 0x0482 /* Kyocera Wireless Corp. */
|
||||
#define USB_VENDOR_STMICRO 0x0483 /* STMicroelectronics */
|
||||
#define USB_VENDOR_FOXCONN 0x0489 /* Foxconn */
|
||||
#define USB_VENDOR_MEIZU 0x0492 /* Meizu Electronics */
|
||||
#define USB_VENDOR_YAMAHA 0x0499 /* YAMAHA */
|
||||
#define USB_VENDOR_COMPAQ 0x049f /* Compaq */
|
||||
#define USB_VENDOR_HITACHI 0x04a4 /* Hitachi */
|
||||
@ -1664,6 +1665,9 @@
|
||||
#define USB_PRODUCT_MCT_USB232 0x0210 /* USB-232 Interface */
|
||||
#define USB_PRODUCT_MCT_SITECOM_USB232 0x0230 /* Sitecom USB-232 Products */
|
||||
|
||||
/* Meizu Electronics */
|
||||
#define USB_PRODUCT_MEIZU_M6_SL 0x0140 /* MiniPlayer M6 (SL) */
|
||||
|
||||
/* Melco, Inc products */
|
||||
#define USB_PRODUCT_MELCO_LUATX1 0x0001 /* LUA-TX Ethernet */
|
||||
#define USB_PRODUCT_MELCO_LUATX5 0x0005 /* LUA-TX Ethernet */
|
||||
|
@ -4,7 +4,7 @@
|
||||
* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
|
||||
*
|
||||
* generated from:
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 186651 2008-12-31 14:25:14Z luigi
|
||||
* FreeBSD: head/sys/dev/usb/usbdevs 187163 2009-01-13 19:01:25Z thompsa
|
||||
*/
|
||||
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
|
||||
|
||||
@ -4030,6 +4030,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"MCT",
|
||||
"Sitecom USB-232 Products",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL,
|
||||
0,
|
||||
"Meizu Electronics",
|
||||
"MiniPlayer M6 (SL)",
|
||||
},
|
||||
{
|
||||
USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX1,
|
||||
0,
|
||||
@ -7870,6 +7876,12 @@ const struct usb_knowndev usb_knowndevs[] = {
|
||||
"Foxconn",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
USB_VENDOR_MEIZU, 0,
|
||||
USB_KNOWNDEV_NOPROD,
|
||||
"Meizu Electronics",
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
USB_VENDOR_YAMAHA, 0,
|
||||
USB_KNOWNDEV_NOPROD,
|
||||
|
@ -602,12 +602,12 @@ struct usb2_port_status {
|
||||
#define UPS_SUSPEND 0x0004
|
||||
#define UPS_OVERCURRENT_INDICATOR 0x0008
|
||||
#define UPS_RESET 0x0010
|
||||
#define UPS_PORT_MODE_DEVICE 0x0020 /* currently FreeBSD specific */
|
||||
#define UPS_PORT_POWER 0x0100
|
||||
#define UPS_LOW_SPEED 0x0200
|
||||
#define UPS_HIGH_SPEED 0x0400
|
||||
#define UPS_PORT_TEST 0x0800
|
||||
#define UPS_PORT_INDICATOR 0x1000
|
||||
#define UPS_PORT_MODE_DEVICE 0x8000 /* currently FreeBSD specific */
|
||||
uWord wPortChange;
|
||||
#define UPS_C_CONNECT_STATUS 0x0001
|
||||
#define UPS_C_PORT_ENABLED 0x0002
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
@ -92,7 +91,7 @@ SYSCTL_INT(_hw_usb2_ubsa, OID_AUTO, debug, CTLFLAG_RW,
|
||||
#define UBSA_N_TRANSFER 6 /* units */
|
||||
#define UBSA_BSIZE 1024 /* bytes */
|
||||
|
||||
#define UBSA_CONFIG_INDEX 1
|
||||
#define UBSA_CONFIG_INDEX 0
|
||||
#define UBSA_IFACE_INDEX 0
|
||||
|
||||
#define UBSA_REG_BAUDRATE 0x00
|
||||
|
@ -87,7 +87,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -81,7 +81,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -93,7 +93,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -59,7 +59,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
@ -178,9 +177,6 @@ static const struct usb2_device_id ugensa_devs[] = {
|
||||
{USB_VPI(USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1, 0)},
|
||||
{USB_VPI(USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K, 0)},
|
||||
{USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS, 0)},
|
||||
/* {USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E270, 0)}, */
|
||||
{USB_VPI(USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE, 0)},
|
||||
{USB_VPI(USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620, 0)},
|
||||
{USB_VPI(USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS, 0)},
|
||||
};
|
||||
|
||||
|
@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -92,7 +92,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -95,7 +95,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -78,13 +78,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/include/usb2_cdc.h>
|
||||
|
||||
#define USB_DEBUG_VAR usb2_com_debug
|
||||
#define usb2_config_td_cc usb2_com_config_copy
|
||||
#define usb2_config_td_softc usb2_com_softc
|
||||
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_busdma.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
@ -99,30 +96,26 @@ SYSCTL_INT(_hw_usb2_ucom, OID_AUTO, debug, CTLFLAG_RW,
|
||||
&usb2_com_debug, 0, "ucom debug level");
|
||||
#endif
|
||||
|
||||
struct usb2_com_config_copy {
|
||||
struct usb2_com_softc *cc_softc;
|
||||
uint8_t cc_flag0;
|
||||
uint8_t cc_flag1;
|
||||
uint8_t cc_flag2;
|
||||
uint8_t cc_flag3;
|
||||
};
|
||||
|
||||
static usb2_config_td_command_t usb2_com_config_copy;
|
||||
static usb2_config_td_command_t usb2_com_cfg_start_transfers;
|
||||
static usb2_config_td_command_t usb2_com_cfg_open;
|
||||
static usb2_config_td_command_t usb2_com_cfg_close;
|
||||
static usb2_config_td_command_t usb2_com_cfg_break;
|
||||
static usb2_config_td_command_t usb2_com_cfg_dtr;
|
||||
static usb2_config_td_command_t usb2_com_cfg_rts;
|
||||
static usb2_config_td_command_t usb2_com_cfg_status_change;
|
||||
static usb2_config_td_command_t usb2_com_cfg_param;
|
||||
static usb2_proc_callback_t usb2_com_cfg_start_transfers;
|
||||
static usb2_proc_callback_t usb2_com_cfg_open;
|
||||
static usb2_proc_callback_t usb2_com_cfg_close;
|
||||
static usb2_proc_callback_t usb2_com_cfg_break_on;
|
||||
static usb2_proc_callback_t usb2_com_cfg_break_off;
|
||||
static usb2_proc_callback_t usb2_com_cfg_dtr_on;
|
||||
static usb2_proc_callback_t usb2_com_cfg_dtr_off;
|
||||
static usb2_proc_callback_t usb2_com_cfg_rts_on;
|
||||
static usb2_proc_callback_t usb2_com_cfg_rts_off;
|
||||
static usb2_proc_callback_t usb2_com_cfg_status_change;
|
||||
static usb2_proc_callback_t usb2_com_cfg_param;
|
||||
|
||||
static uint8_t usb2_com_units_alloc(uint32_t, uint32_t *);
|
||||
static void usb2_com_units_free(uint32_t, uint32_t);
|
||||
static int usb2_com_attach_sub(struct usb2_com_softc *);
|
||||
static void usb2_com_detach_sub(struct usb2_com_softc *);
|
||||
static void usb2_com_queue_command(struct usb2_com_softc *,
|
||||
usb2_config_td_command_t *, int);
|
||||
static void usb2_com_queue_command(struct usb2_com_softc *sc,
|
||||
uint8_t cmd);
|
||||
static void usb2_com_wait_command(struct usb2_com_softc *sc,
|
||||
uint8_t cmd);
|
||||
static void usb2_com_shutdown(struct usb2_com_softc *);
|
||||
static void usb2_com_start_transfers(struct usb2_com_softc *);
|
||||
static void usb2_com_break(struct usb2_com_softc *, uint8_t);
|
||||
@ -251,9 +244,7 @@ usb2_com_attach(struct usb2_com_super_softc *ssc, struct usb2_com_softc *sc,
|
||||
if (usb2_com_units_alloc(sub_units, &root_unit)) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
if (usb2_config_td_setup
|
||||
(&ssc->sc_config_td, sc, p_mtx, NULL,
|
||||
sizeof(struct usb2_com_config_copy), 24 * sub_units)) {
|
||||
if (usb2_proc_setup(&ssc->sc_config_td, p_mtx, USB_PRI_MED)) {
|
||||
usb2_com_units_free(root_unit, sub_units);
|
||||
return (ENOMEM);
|
||||
}
|
||||
@ -285,7 +276,7 @@ usb2_com_detach(struct usb2_com_super_softc *ssc, struct usb2_com_softc *sc,
|
||||
{
|
||||
uint32_t n;
|
||||
|
||||
usb2_config_td_drain(&ssc->sc_config_td);
|
||||
usb2_proc_drain(&ssc->sc_config_td);
|
||||
|
||||
for (n = 0; n < sub_units; n++, sc++) {
|
||||
if (sc->sc_flag & UCOM_FLAG_ATTACHED) {
|
||||
@ -298,8 +289,7 @@ usb2_com_detach(struct usb2_com_super_softc *ssc, struct usb2_com_softc *sc,
|
||||
sc->sc_flag &= ~UCOM_FLAG_ATTACHED;
|
||||
}
|
||||
}
|
||||
|
||||
usb2_config_td_unsetup(&ssc->sc_config_td);
|
||||
usb2_proc_unsetup(&ssc->sc_config_td);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -307,6 +297,7 @@ usb2_com_attach_sub(struct usb2_com_softc *sc)
|
||||
{
|
||||
struct tty *tp;
|
||||
int error = 0;
|
||||
uint8_t n;
|
||||
char buf[32]; /* temporary TTY device name buffer */
|
||||
|
||||
tp = tty_alloc(&usb2_com_class, sc, sc->sc_parent_mtx);
|
||||
@ -336,6 +327,39 @@ usb2_com_attach_sub(struct usb2_com_softc *sc)
|
||||
DPRINTF("ttycreate: %s\n", buf);
|
||||
usb2_cv_init(&sc->sc_cv, "usb2_com");
|
||||
|
||||
/*
|
||||
* Set all function callback pointers for deferred COM
|
||||
* operations:
|
||||
*/
|
||||
for (n = 0; n != 2; n++) {
|
||||
sc->sc_cmds[(2*USB_COM_CFG_START_TRANSFERS) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_start_transfers;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_OPEN) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_open;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_CLOSE) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_close;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_BREAK_ON) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_break_on;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_BREAK_OFF) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_break_off;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_DTR_ON) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_dtr_on;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_DTR_OFF) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_dtr_off;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_RTS_ON) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_rts_on;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_RTS_OFF) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_rts_off;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_STATUS_CHANGE) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_status_change;
|
||||
sc->sc_cmds[(2*USB_COM_CFG_PARAM) + n].hdr.pm_callback =
|
||||
&usb2_com_cfg_param;
|
||||
}
|
||||
|
||||
/* initialise all callback pointer arguments */
|
||||
for (n = 0; n != (2*USB_COM_CFG_MAX); n++) {
|
||||
sc->sc_cmds[n].cc_softc = sc;
|
||||
}
|
||||
done:
|
||||
return (error);
|
||||
}
|
||||
@ -379,27 +403,41 @@ usb2_com_detach_sub(struct usb2_com_softc *sc)
|
||||
usb2_cv_destroy(&sc->sc_cv);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function queues a command for deferred execution.
|
||||
* The following function must be called locked.
|
||||
*/
|
||||
static void
|
||||
usb2_com_config_copy(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
{
|
||||
cc->cc_softc = sc + (refcount % UCOM_SUB_UNIT_MAX);
|
||||
cc->cc_flag0 = (refcount / (1 * UCOM_SUB_UNIT_MAX)) % 2;
|
||||
cc->cc_flag1 = (refcount / (2 * UCOM_SUB_UNIT_MAX)) % 2;
|
||||
cc->cc_flag2 = (refcount / (4 * UCOM_SUB_UNIT_MAX)) % 2;
|
||||
cc->cc_flag3 = (refcount / (8 * UCOM_SUB_UNIT_MAX)) % 2;
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_queue_command(struct usb2_com_softc *sc, usb2_config_td_command_t *cmd, int flag)
|
||||
usb2_com_queue_command(struct usb2_com_softc *sc, uint8_t cmd)
|
||||
{
|
||||
struct usb2_com_super_softc *ssc = sc->sc_super;
|
||||
|
||||
usb2_config_td_queue_command
|
||||
(&ssc->sc_config_td, &usb2_com_config_copy,
|
||||
cmd, (cmd == &usb2_com_cfg_status_change) ? 1 : 0,
|
||||
((sc->sc_local_unit % UCOM_SUB_UNIT_MAX) +
|
||||
(flag ? UCOM_SUB_UNIT_MAX : 0)));
|
||||
if (usb2_proc_is_gone(&ssc->sc_config_td)) {
|
||||
DPRINTF("proc is gone\n");
|
||||
return; /* nothing to do */
|
||||
}
|
||||
|
||||
if (usb2_proc_msignal(&ssc->sc_config_td,
|
||||
&sc->sc_cmds[2*cmd], &sc->sc_cmds[(2*cmd)+1])) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function waits until a command has been executed.
|
||||
* The following function must be called locked.
|
||||
*/
|
||||
static void
|
||||
usb2_com_wait_command(struct usb2_com_softc *sc, uint8_t cmd)
|
||||
{
|
||||
struct usb2_com_super_softc *ssc = sc->sc_super;
|
||||
|
||||
if (usb2_proc_is_gone(&ssc->sc_config_td)) {
|
||||
DPRINTF("proc is gone\n");
|
||||
return; /* nothing to do */
|
||||
}
|
||||
usb2_proc_mwait(&ssc->sc_config_td,
|
||||
&sc->sc_cmds[2*cmd], &sc->sc_cmds[(2*cmd)+1]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -420,6 +458,8 @@ usb2_com_shutdown(struct usb2_com_softc *sc)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will sleep "timeout" system ticks.
|
||||
*
|
||||
* Return values:
|
||||
* 0: normal delay
|
||||
* else: config thread is gone
|
||||
@ -428,8 +468,26 @@ uint8_t
|
||||
usb2_com_cfg_sleep(struct usb2_com_softc *sc, uint32_t timeout)
|
||||
{
|
||||
struct usb2_com_super_softc *ssc = sc->sc_super;
|
||||
uint8_t is_gone;
|
||||
|
||||
return (usb2_config_td_sleep(&ssc->sc_config_td, timeout));
|
||||
is_gone = usb2_proc_is_gone(&ssc->sc_config_td);
|
||||
if (is_gone)
|
||||
goto done; /* we are detaching */
|
||||
if (timeout == 0)
|
||||
timeout = 1; /* one tick is the least timeout */
|
||||
|
||||
mtx_unlock(sc->sc_parent_mtx);
|
||||
|
||||
if (pause("UCOMWAIT", timeout)) {
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
mtx_lock(sc->sc_parent_mtx);
|
||||
|
||||
/* refresh gone status */
|
||||
is_gone = usb2_proc_is_gone(&ssc->sc_config_td);
|
||||
done:
|
||||
return (is_gone);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -442,13 +500,15 @@ usb2_com_cfg_is_gone(struct usb2_com_softc *sc)
|
||||
{
|
||||
struct usb2_com_super_softc *ssc = sc->sc_super;
|
||||
|
||||
return (usb2_config_td_is_gone(&ssc->sc_config_td));
|
||||
return (usb2_proc_is_gone(&ssc->sc_config_td));
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_start_transfers(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_start_transfers(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
struct usb2_com_command_msg *cc = (void *)_cc;
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
|
||||
@ -485,14 +545,16 @@ usb2_com_start_transfers(struct usb2_com_softc *sc)
|
||||
(sc->sc_callback->usb2_com_start_write) (sc);
|
||||
}
|
||||
if (!(sc->sc_flag & UCOM_FLAG_GP_DATA)) {
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_start_transfers, 0);
|
||||
usb2_com_queue_command(sc, USB_COM_CFG_START_TRANSFERS);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_open(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_open(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
struct usb2_com_command_msg *cc = (void *)_cc;
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
DPRINTF("\n");
|
||||
@ -550,7 +612,7 @@ usb2_com_open(struct tty *tp)
|
||||
sc->sc_msr = 0;
|
||||
sc->sc_mcr = 0;
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_open, 0);
|
||||
usb2_com_queue_command(sc, USB_COM_CFG_OPEN);
|
||||
|
||||
usb2_com_start_transfers(sc);
|
||||
|
||||
@ -564,9 +626,11 @@ usb2_com_open(struct tty *tp)
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_close(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_close(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
struct usb2_com_command_msg *cc = (void *)_cc;
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
DPRINTF("\n");
|
||||
@ -588,7 +652,6 @@ static void
|
||||
usb2_com_close(struct tty *tp)
|
||||
{
|
||||
struct usb2_com_softc *sc = tty_softc(tp);
|
||||
struct usb2_com_super_softc *ssc = sc->sc_super;
|
||||
|
||||
mtx_assert(sc->sc_parent_mtx, MA_OWNED);
|
||||
|
||||
@ -600,8 +663,9 @@ usb2_com_close(struct tty *tp)
|
||||
}
|
||||
usb2_com_shutdown(sc);
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_close, 0);
|
||||
usb2_config_td_sync(&ssc->sc_config_td);
|
||||
/* Queue and wait for close command to complete */
|
||||
usb2_com_queue_command(sc, USB_COM_CFG_CLOSE);
|
||||
usb2_com_wait_command(sc, USB_COM_CFG_CLOSE);
|
||||
|
||||
sc->sc_flag &= ~(UCOM_FLAG_HL_READY |
|
||||
UCOM_FLAG_WR_START |
|
||||
@ -704,21 +768,34 @@ usb2_com_modem(struct tty *tp, int sigon, int sigoff)
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_break(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_break(struct usb2_com_command_msg *cc, uint8_t onoff)
|
||||
{
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
|
||||
return;
|
||||
}
|
||||
DPRINTF("onoff=%d\n", cc->cc_flag0);
|
||||
DPRINTF("onoff=%d\n", onoff);
|
||||
|
||||
if (sc->sc_callback->usb2_com_cfg_set_break) {
|
||||
(sc->sc_callback->usb2_com_cfg_set_break) (sc, cc->cc_flag0);
|
||||
(sc->sc_callback->usb2_com_cfg_set_break) (sc, onoff);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_break_on(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_break((void *)_cc, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_break_off(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_break((void *)_cc, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_break(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
{
|
||||
@ -729,25 +806,39 @@ usb2_com_break(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
}
|
||||
DPRINTF("onoff = %d\n", onoff);
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_break, onoff);
|
||||
usb2_com_queue_command(sc, onoff ?
|
||||
USB_COM_CFG_BREAK_ON : USB_COM_CFG_BREAK_OFF);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_dtr(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_dtr(struct usb2_com_command_msg *cc, uint8_t onoff)
|
||||
{
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
|
||||
return;
|
||||
}
|
||||
DPRINTF("onoff=%d\n", cc->cc_flag0);
|
||||
DPRINTF("onoff=%d\n", onoff);
|
||||
|
||||
if (sc->sc_callback->usb2_com_cfg_set_dtr) {
|
||||
(sc->sc_callback->usb2_com_cfg_set_dtr) (sc, cc->cc_flag0);
|
||||
(sc->sc_callback->usb2_com_cfg_set_dtr) (sc, onoff);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_dtr_on(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_dtr((void *)_cc, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_dtr_off(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_dtr((void *)_cc, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_dtr(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
{
|
||||
@ -758,25 +849,39 @@ usb2_com_dtr(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
}
|
||||
DPRINTF("onoff = %d\n", onoff);
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_dtr, onoff);
|
||||
usb2_com_queue_command(sc, onoff ?
|
||||
USB_COM_CFG_DTR_ON : USB_COM_CFG_DTR_OFF);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_rts(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_rts(struct usb2_com_command_msg *cc, uint8_t onoff)
|
||||
{
|
||||
struct usb2_com_softc *sc;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
|
||||
DPRINTF("onoff=%d\n", cc->cc_flag0);
|
||||
DPRINTF("onoff=%d\n", onoff);
|
||||
|
||||
if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
|
||||
return;
|
||||
}
|
||||
if (sc->sc_callback->usb2_com_cfg_set_rts) {
|
||||
(sc->sc_callback->usb2_com_cfg_set_rts) (sc, cc->cc_flag0);
|
||||
(sc->sc_callback->usb2_com_cfg_set_rts) (sc, onoff);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_rts_on(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_rts((void *)_cc, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_rts_off(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
usb2_com_cfg_rts((void *)_cc, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_rts(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
{
|
||||
@ -787,13 +892,15 @@ usb2_com_rts(struct usb2_com_softc *sc, uint8_t onoff)
|
||||
}
|
||||
DPRINTF("onoff = %d\n", onoff);
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_rts, onoff);
|
||||
usb2_com_queue_command(sc, onoff ?
|
||||
USB_COM_CFG_RTS_ON : USB_COM_CFG_RTS_OFF);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_status_change(struct usb2_com_softc *sc,
|
||||
struct usb2_com_config_copy *cc, uint16_t refcount)
|
||||
usb2_com_cfg_status_change(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
struct usb2_com_command_msg *cc = (void *)_cc;
|
||||
struct usb2_com_softc *sc;
|
||||
struct tty *tp;
|
||||
|
||||
uint8_t new_msr;
|
||||
@ -847,13 +954,14 @@ usb2_com_status_change(struct usb2_com_softc *sc)
|
||||
}
|
||||
DPRINTF("\n");
|
||||
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_status_change, 0);
|
||||
usb2_com_queue_command(sc, USB_COM_CFG_STATUS_CHANGE);
|
||||
}
|
||||
|
||||
static void
|
||||
usb2_com_cfg_param(struct usb2_com_softc *sc, struct usb2_com_config_copy *cc,
|
||||
uint16_t refcount)
|
||||
usb2_com_cfg_param(struct usb2_proc_msg *_cc)
|
||||
{
|
||||
struct usb2_com_command_msg *cc = (void *)_cc;
|
||||
struct usb2_com_softc *sc;
|
||||
struct termios t_copy;
|
||||
|
||||
sc = cc->cc_softc;
|
||||
@ -924,7 +1032,7 @@ usb2_com_param(struct tty *tp, struct termios *t)
|
||||
sc->sc_flag &= ~UCOM_FLAG_GP_DATA;
|
||||
|
||||
/* Queue baud rate programming command first */
|
||||
usb2_com_queue_command(sc, &usb2_com_cfg_param, 0);
|
||||
usb2_com_queue_command(sc, USB_COM_CFG_PARAM);
|
||||
|
||||
/* Queue transfer enable command last */
|
||||
usb2_com_start_transfers(sc);
|
||||
|
@ -119,11 +119,35 @@ struct usb2_com_callback {
|
||||
#define ULSR_RXRDY 0x01 /* Byte ready in Receive Buffer */
|
||||
#define ULSR_RCV_MASK 0x1f /* Mask for incoming data or error */
|
||||
|
||||
/*
|
||||
* List of serial adapter commands or deferred function calls:
|
||||
*/
|
||||
enum {
|
||||
USB_COM_CFG_START_TRANSFERS,
|
||||
USB_COM_CFG_OPEN,
|
||||
USB_COM_CFG_CLOSE,
|
||||
USB_COM_CFG_BREAK_ON,
|
||||
USB_COM_CFG_BREAK_OFF,
|
||||
USB_COM_CFG_DTR_ON,
|
||||
USB_COM_CFG_DTR_OFF,
|
||||
USB_COM_CFG_RTS_ON,
|
||||
USB_COM_CFG_RTS_OFF,
|
||||
USB_COM_CFG_STATUS_CHANGE,
|
||||
USB_COM_CFG_PARAM,
|
||||
USB_COM_CFG_MAX,
|
||||
};
|
||||
|
||||
struct usb2_com_command_msg {
|
||||
struct usb2_proc_msg hdr; /* must be first */
|
||||
struct usb2_com_softc *cc_softc;
|
||||
};
|
||||
|
||||
struct usb2_com_super_softc {
|
||||
struct usb2_config_td sc_config_td;
|
||||
struct usb2_process sc_config_td;
|
||||
};
|
||||
|
||||
struct usb2_com_softc {
|
||||
struct usb2_com_command_msg sc_cmds[2*USB_COM_CFG_MAX];
|
||||
struct termios sc_termios_copy;
|
||||
struct cv sc_cv;
|
||||
const struct usb2_com_callback *sc_callback;
|
||||
@ -146,6 +170,7 @@ struct usb2_com_softc {
|
||||
uint8_t sc_msr;
|
||||
uint8_t sc_mcr;
|
||||
uint8_t sc_ttyfreed; /* set when TTY has been freed */
|
||||
uint8_t sc_last_cmd_flag[USB_COM_CFG_MAX];
|
||||
};
|
||||
|
||||
int usb2_com_attach(struct usb2_com_super_softc *ssc,
|
||||
|
@ -66,7 +66,6 @@
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
|
@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/usb2/core/usb2_core.h>
|
||||
#include <dev/usb2/core/usb2_debug.h>
|
||||
#include <dev/usb2/core/usb2_process.h>
|
||||
#include <dev/usb2/core/usb2_config_td.h>
|
||||
#include <dev/usb2/core/usb2_request.h>
|
||||
#include <dev/usb2/core/usb2_lookup.h>
|
||||
#include <dev/usb2/core/usb2_util.h>
|
||||
@ -339,9 +338,9 @@ uvscom_attach(device_t dev)
|
||||
goto detach;
|
||||
}
|
||||
/* start interrupt pipe */
|
||||
USB_XFER_LOCK(sc->sc_xfer[4]);
|
||||
mtx_lock(&Giant);
|
||||
usb2_transfer_start(sc->sc_xfer[4]);
|
||||
USB_XFER_UNLOCK(sc->sc_xfer[4]);
|
||||
mtx_unlock(&Giant);
|
||||
|
||||
return (0);
|
||||
|
||||
|
@ -2921,6 +2921,8 @@ uaudio_mixer_write_cfg_callback(struct usb2_xfer *xfer)
|
||||
uint8_t chan;
|
||||
uint8_t buf[2];
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
tr_transferred:
|
||||
@ -2980,11 +2982,14 @@ tr_setup:
|
||||
if (repeat) {
|
||||
goto tr_setup;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
|
||||
default: /* Error */
|
||||
DPRINTF("error=%s\n", usb2_errstr(xfer->error));
|
||||
|
||||
if (xfer->error == USB_ERR_CANCELLED) {
|
||||
/* do nothing - we are detaching */
|
||||
break;
|
||||
}
|
||||
goto tr_transferred;
|
||||
}
|
||||
}
|
||||
|
@ -773,11 +773,12 @@ atausb2_t_bbb_status_callback(struct usb2_xfer *xfer)
|
||||
|
||||
sc->ata_request = NULL;
|
||||
|
||||
USB_XFER_UNLOCK(xfer);
|
||||
/* drop the USB transfer lock while doing the ATA interrupt */
|
||||
mtx_unlock(&sc->locked_mtx);
|
||||
|
||||
ata_interrupt(device_get_softc(request->parent));
|
||||
|
||||
USB_XFER_LOCK(xfer);
|
||||
mtx_lock(&sc->locked_mtx);
|
||||
return;
|
||||
|
||||
case USB_ST_SETUP:
|
||||
|
@ -916,6 +916,10 @@ static const struct umass_devdescr umass_devdescr[] = {
|
||||
UMASS_PROTO_ATAPI | UMASS_PROTO_CBI,
|
||||
NO_QUIRKS
|
||||
},
|
||||
{USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL, RID_WILDCARD,
|
||||
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
|
||||
NO_INQUIRY | NO_SYNCHRONIZE_CACHE
|
||||
},
|
||||
{VID_EOT, PID_EOT, RID_EOT, 0, 0}
|
||||
};
|
||||
|
||||
@ -2410,6 +2414,9 @@ umass_t_cbi_data_read_callback(struct usb2_xfer *xfer)
|
||||
}
|
||||
xfer->timeout = sc->sc_transfer.data_timeout;
|
||||
|
||||
if (xfer->flags.ext_buffer) {
|
||||
usb2_set_frame_data(xfer, sc->sc_transfer.data_ptr, 0);
|
||||
}
|
||||
xfer->frlengths[0] = max_bulk;
|
||||
usb2_start_hardware(xfer);
|
||||
return;
|
||||
|
@ -1,8 +1,8 @@
|
||||
#
|
||||
# GENERIC -- Generic kernel configuration file for FreeBSD/i386
|
||||
#
|
||||
# For more information on this file, please read the handbook section on
|
||||
# Kernel Configuration Files:
|
||||
# For more information on this file, please read the config(5) manual page,
|
||||
# and/or the handbook section on Kernel Configuration Files:
|
||||
#
|
||||
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
|
||||
#
|
||||
@ -28,9 +28,9 @@ ident GENERIC
|
||||
|
||||
# Use the following to compile in values accessible to the kernel
|
||||
# through getenv() (or kenv(1) in userland). The format of the file
|
||||
# is 'variable=value' , same as for hints files.
|
||||
# is 'variable=value', see kenv(1)
|
||||
#
|
||||
# env "my_kenv_variables"
|
||||
# env "GENERIC.env"
|
||||
|
||||
makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
|
||||
|
||||
|
@ -108,3 +108,7 @@ device usb2_input_ms
|
||||
|
||||
# USB sound and MIDI device support
|
||||
#device usb2_sound
|
||||
|
||||
# USB scanner support
|
||||
device usb2_image
|
||||
device usb2_scanner
|
||||
|
@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/frame.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/apicvar.h>
|
||||
#include <machine/specialreg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
/* Fields in address for Intel MSI messages. */
|
||||
@ -212,9 +213,18 @@ msi_init(void)
|
||||
{
|
||||
|
||||
/* Check if we have a supported CPU. */
|
||||
if (!(cpu_vendor_id == CPU_VENDOR_INTEL ||
|
||||
cpu_vendor_id == CPU_VENDOR_AMD))
|
||||
switch (cpu_vendor_id) {
|
||||
case CPU_VENDOR_INTEL:
|
||||
case CPU_VENDOR_AMD:
|
||||
break;
|
||||
case CPU_VENDOR_CENTAUR:
|
||||
if (I386_CPU_FAMILY(cpu_id) == 0x6 &&
|
||||
I386_CPU_MODEL(cpu_id) >= 0xf)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
msi_enabled = 1;
|
||||
intr_register_pic(&msi_pic);
|
||||
|
@ -414,6 +414,7 @@ softclock(void *arg)
|
||||
lastfunc = c_func;
|
||||
}
|
||||
#endif
|
||||
CTR1(KTR_CALLOUT, "callout %p finished", c);
|
||||
if ((c_flags & CALLOUT_RETURNUNLOCKED) == 0)
|
||||
class->lc_unlock(c_lock);
|
||||
skip:
|
||||
|
41
sys/modules/usb2/controller_atmegadci/Makefile
Normal file
41
sys/modules/usb2/controller_atmegadci/Makefile
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
#
|
||||
|
||||
S=${.CURDIR}/../../..
|
||||
|
||||
.PATH: $S/dev/usb2/controller
|
||||
|
||||
KMOD=usb2_controller_atmegadci
|
||||
SRCS=
|
||||
SRCS+= bus_if.h usb2_if.h device_if.h vnode_if.h
|
||||
SRCS+= opt_usb.h pci_if.h opt_bus.h card_if.h
|
||||
SRCS+= atmegadci.c
|
||||
.if defined(HAS_ATMELARM)
|
||||
SRCS+= atmegadci_atmelarm.c
|
||||
.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -399,6 +399,87 @@ ivor_setup:
|
||||
mtspr SPR_IVOR15, %r3
|
||||
blr
|
||||
|
||||
/*
|
||||
* void tid_flush(tlbtid_t tid);
|
||||
*
|
||||
* Invalidate all TLB0 entries which match the given TID. Note this is
|
||||
* dedicated for cases when invalidation(s) should NOT be propagated to other
|
||||
* CPUs.
|
||||
*
|
||||
* Global vars tlb0_ways, tlb0_entries_per_way are assumed to have been set up
|
||||
* correctly (by tlb0_get_tlbconf()).
|
||||
*
|
||||
*/
|
||||
ENTRY(tid_flush)
|
||||
cmpwi %r3, TID_KERNEL
|
||||
beq tid_flush_end /* don't evict kernel translations */
|
||||
|
||||
/* Number of TLB0 ways */
|
||||
lis %r4, tlb0_ways@h
|
||||
ori %r4, %r4, tlb0_ways@l
|
||||
lwz %r4, 0(%r4)
|
||||
|
||||
/* Number of entries / way */
|
||||
lis %r5, tlb0_entries_per_way@h
|
||||
ori %r5, %r5, tlb0_entries_per_way@l
|
||||
lwz %r5, 0(%r5)
|
||||
|
||||
/* Disable interrupts */
|
||||
mfmsr %r10
|
||||
wrteei 0
|
||||
|
||||
li %r6, 0 /* ways counter */
|
||||
loop_ways:
|
||||
li %r7, 0 /* entries [per way] counter */
|
||||
loop_entries:
|
||||
/* Select TLB0 and ESEL (way) */
|
||||
lis %r8, MAS0_TLBSEL0@h
|
||||
rlwimi %r8, %r6, 16, 14, 15
|
||||
mtspr SPR_MAS0, %r8
|
||||
isync
|
||||
|
||||
/* Select EPN (entry within the way) */
|
||||
rlwinm %r8, %r7, 12, 13, 19
|
||||
mtspr SPR_MAS2, %r8
|
||||
isync
|
||||
tlbre
|
||||
|
||||
/* Check if valid entry */
|
||||
mfspr %r8, SPR_MAS1
|
||||
andis. %r9, %r8, MAS1_VALID@h
|
||||
beq next_entry /* invalid entry */
|
||||
|
||||
/* Check if this is our TID */
|
||||
rlwinm %r9, %r8, 16, 24, 31
|
||||
|
||||
cmplw %r9, %r3
|
||||
bne next_entry /* not our TID */
|
||||
|
||||
/* Clear VALID bit */
|
||||
rlwinm %r8, %r8, 0, 1, 31
|
||||
mtspr SPR_MAS1, %r8
|
||||
isync
|
||||
tlbwe
|
||||
isync
|
||||
msync
|
||||
|
||||
next_entry:
|
||||
addi %r7, %r7, 1
|
||||
cmpw %r7, %r5
|
||||
bne loop_entries
|
||||
|
||||
/* Next way */
|
||||
addi %r6, %r6, 1
|
||||
cmpw %r6, %r4
|
||||
bne loop_ways
|
||||
|
||||
/* Restore MSR (possibly re-enable interrupts) */
|
||||
mtmsr %r10
|
||||
isync
|
||||
|
||||
tid_flush_end:
|
||||
blr
|
||||
|
||||
/*
|
||||
* Cache disable/enable/inval sequences according
|
||||
* to section 2.16 of E500CORE RM.
|
||||
|
@ -490,6 +490,7 @@ void
|
||||
cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz)
|
||||
{
|
||||
|
||||
pcpu->pc_tid_next = TID_MIN;
|
||||
}
|
||||
|
||||
/* Set set up registers on exec. */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,106 +0,0 @@
|
||||
/*-
|
||||
* Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "assym.s"
|
||||
|
||||
#include <machine/param.h>
|
||||
#include <machine/asm.h>
|
||||
#include <machine/spr.h>
|
||||
#include <machine/psl.h>
|
||||
#include <machine/pte.h>
|
||||
#include <machine/trap.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <machine/tlb.h>
|
||||
|
||||
.text
|
||||
/*
|
||||
* void remap_ccsrbar(vm_offset_t old_ccsrbar_va, vm_offset_t new_ccsrbar_va,
|
||||
* vm_offset_t new_ccsrbar_pa)
|
||||
*
|
||||
* r3 - old_ccsrbar_va
|
||||
* r4 - new_ccsrbar_va
|
||||
* r5 - new_ccsrbar_pa
|
||||
*/
|
||||
ENTRY(remap_ccsrbar)
|
||||
/*
|
||||
* CCSRBAR updating sequence according
|
||||
* to section 4.3.1.1.1 of MPC8555E RM.
|
||||
*/
|
||||
|
||||
/* Read current value of CCSRBAR */
|
||||
lwz %r6, 0(%r3)
|
||||
isync
|
||||
|
||||
/* Write new value */
|
||||
rlwinm %r6, %r5, 20, 12, 23
|
||||
stw %r6, 0(%r3)
|
||||
|
||||
/*
|
||||
* Read from address that is outside of CCSRBAR space.
|
||||
* We have RAM locations available at KERNBASE.
|
||||
*/
|
||||
lis %r7, KERNBASE@ha
|
||||
addi %r7, %r7, KERNBASE@l
|
||||
lwz %r6, 0(%r7)
|
||||
isync
|
||||
|
||||
/* Read value of CCSRBAR from new location */
|
||||
lwz %r6, 0(%r4)
|
||||
isync
|
||||
blr
|
||||
|
||||
/*
|
||||
* void switch_to_as0(void)
|
||||
*/
|
||||
ENTRY(switch_to_as0)
|
||||
mflr %r5 /* Save LR */
|
||||
|
||||
mfmsr %r3
|
||||
lis %r6, (PSL_IS | PSL_DS)@ha
|
||||
ori %r6, %r6, (PSL_IS | PSL_DS)@l
|
||||
not %r6, %r6
|
||||
and %r3, %r3, %r6 /* Clear IS/DS bits */
|
||||
|
||||
bl 1f
|
||||
1: mflr %r4 /* Use current address */
|
||||
addi %r4, %r4, 20 /* Increment to instruction after rfi */
|
||||
mtspr SPR_SRR0, %r4
|
||||
mtspr SPR_SRR1, %r3
|
||||
rfi
|
||||
|
||||
mtlr %r5 /* Restore LR */
|
||||
blr
|
||||
|
||||
/*
|
||||
* void load_pid0(tlbtid_t)
|
||||
*/
|
||||
ENTRY(load_pid0)
|
||||
mtspr SPR_PID0, %r3
|
||||
isync
|
||||
blr
|
@ -1,6 +1,6 @@
|
||||
/*-
|
||||
* Copyright (C) 2006-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
|
||||
* Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
|
||||
* Copyright (C) 2006 Semihalf, Rafal Jaworowski <raj@semihalf.com>
|
||||
* Copyright (C) 2006 Juniper Networks, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -127,7 +127,7 @@
|
||||
bf 17, 1f; \
|
||||
GET_CPUINFO(%r1); /* Per-cpu structure */ \
|
||||
lwz %r1, PC_CURPCB(%r1); /* Per-thread kernel stack */ \
|
||||
1:
|
||||
1:
|
||||
|
||||
#define STANDARD_CRIT_PROLOG(sprg_sp, savearea, isrr0, isrr1) \
|
||||
mtspr sprg_sp, %r1; /* Save SP */ \
|
||||
@ -213,7 +213,6 @@
|
||||
stw %r30, FRAME_SRR0+8(1); \
|
||||
stw %r31, FRAME_SRR1+8(1)
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* isrr0-1 - save restore registers to restore CPU state to (may be
|
||||
@ -250,7 +249,7 @@
|
||||
*
|
||||
* Notes:
|
||||
* - potential TLB miss: NO. It is crucial that we do not generate a TLB
|
||||
* miss withing the TLB prolog itself!
|
||||
* miss within the TLB prolog itself!
|
||||
* - TLBSAVE is always translated
|
||||
*/
|
||||
#define TLB_PROLOG \
|
||||
@ -334,9 +333,9 @@
|
||||
.align 5
|
||||
interrupt_vector_base:
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Critical input interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_critical_input)
|
||||
STANDARD_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
|
||||
FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_CRIT)
|
||||
@ -346,9 +345,9 @@ INTERRUPT(int_critical_input)
|
||||
rfci
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Machine check interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_machine_check)
|
||||
STANDARD_PROLOG(SPR_SPRG3, PC_BOOKE_MCHKSAVE, SPR_MCSRR0, SPR_MCSRR1)
|
||||
FRAME_SETUP(SPR_SPRG3, PC_BOOKE_MCHKSAVE, EXC_MCHK)
|
||||
@ -358,27 +357,27 @@ INTERRUPT(int_machine_check)
|
||||
rfmci
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Data storage interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_data_storage)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_DISISAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_DISISAVE, EXC_DSI)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Instruction storage interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_instr_storage)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_ISI)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* External input interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_external_input)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_EXI)
|
||||
@ -398,18 +397,18 @@ INTERRUPT(int_program)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* System call
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_syscall)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_SC)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Decrementer interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_decrementer)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_DECR)
|
||||
@ -418,36 +417,34 @@ INTERRUPT(int_decrementer)
|
||||
b trapexit
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Fixed interval timer
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_fixed_interval_timer)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_FIT)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Watchdog interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_watchdog)
|
||||
STANDARD_PROLOG(SPR_SPRG1, PC_TEMPSAVE, SPR_SRR0, SPR_SRR1)
|
||||
FRAME_SETUP(SPR_SPRG1, PC_TEMPSAVE, EXC_WDOG)
|
||||
b trap_common
|
||||
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Data TLB miss interrupt
|
||||
*
|
||||
* There can be nested TLB misses - while
|
||||
* handling a TLB miss we dereference data
|
||||
* structures that may be not covered by
|
||||
* translations. We support up to
|
||||
* There can be nested TLB misses - while handling a TLB miss we reference
|
||||
* data structures that may be not covered by translations. We support up to
|
||||
* TLB_NESTED_MAX-1 nested misses.
|
||||
*
|
||||
* Registers use:
|
||||
* r31 - dear
|
||||
* r30 - tlb0 entry address
|
||||
* r30 - unused
|
||||
* r29 - saved mas0
|
||||
* r28 - saved mas1
|
||||
* r27 - saved mas2
|
||||
@ -455,23 +452,20 @@ INTERRUPT(int_watchdog)
|
||||
* r25 - pte address
|
||||
*
|
||||
* r20:r23 - scratch registers
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_data_tlb_error)
|
||||
TLB_PROLOG
|
||||
|
||||
mfdear %r31
|
||||
|
||||
/*
|
||||
* Save MAS0-MAS2 registers. There might be another tlb miss during pte
|
||||
* lookup overwriting current contents (which was hw filled).
|
||||
* Save MAS0-MAS2 registers. There might be another tlb miss during
|
||||
* pte lookup overwriting current contents (which was hw filled).
|
||||
*/
|
||||
mfspr %r29, SPR_MAS0
|
||||
mfspr %r28, SPR_MAS1
|
||||
mfspr %r27, SPR_MAS2
|
||||
|
||||
/* return tlb0 entry address in r30 */
|
||||
bl get_tlb0table_entry
|
||||
|
||||
/* Check faulting address. */
|
||||
lis %r21, VM_MAXUSER_ADDRESS@h
|
||||
ori %r21, %r21, VM_MAXUSER_ADDRESS@l
|
||||
@ -521,11 +515,6 @@ search_failed:
|
||||
*/
|
||||
lis %r23, 0xffff0000@h /* revoke all permissions */
|
||||
|
||||
/* Save MAS registers to tlb0[] table. */
|
||||
stw %r28, TLB0TABLE_MAS1(%r30) /* write tlb0[idx].mas1 */
|
||||
stw %r27, TLB0TABLE_MAS2(%r30) /* write tlb0[idx].mas2 */
|
||||
stw %r23, TLB0TABLE_MAS3(%r30) /* write tlb0[idx].mas3 */
|
||||
|
||||
/* Load MAS registers. */
|
||||
mtspr SPR_MAS0, %r29
|
||||
isync
|
||||
@ -541,61 +530,18 @@ search_failed:
|
||||
isync
|
||||
b tlb_miss_return
|
||||
|
||||
/******************************************************/
|
||||
/*
|
||||
* Calculate address of tlb0[tlb0table_idx], save it in r30
|
||||
/*****************************************************************************
|
||||
*
|
||||
* tlb0table_idx = (way * entries_per_way) + entry_number
|
||||
* entries_per_way = 128
|
||||
* entry_number is defined by EPN[45:51]
|
||||
*
|
||||
* input: r31 - faulting address
|
||||
* input: r29 - MAS0
|
||||
* output: r30 - address of corresponding tlb0[] entry
|
||||
*
|
||||
* scratch regs used: r21-r23
|
||||
*/
|
||||
/******************************************************/
|
||||
get_tlb0table_entry:
|
||||
lis %r21, 0 /* keeps tlb0table_idx */
|
||||
|
||||
/* Add entry number, use DEAR from r31 (faulting va) */
|
||||
rlwinm %r22, %r31, 20, 25, 31 /* get EPN[45:51] */
|
||||
add %r21, %r21, %r22
|
||||
|
||||
/* Select way */
|
||||
rlwinm %r22, %r29, 16, 30, 31 /* get way# = ESEL[0:1] */
|
||||
|
||||
/* Get number of entries per tlb0 way. */
|
||||
lis %r23, tlb0_nentries_per_way@h
|
||||
ori %r23, %r23, tlb0_nentries_per_way@l
|
||||
lwz %r23, 0(%r23)
|
||||
|
||||
mullw %r22, %r22, %r23 /* multiply by #entries per way */
|
||||
add %r21, %r21, %r22
|
||||
|
||||
mulli %r21, %r21, TLB0_ENTRY_SIZE /* multipy by tlb0 entry size */
|
||||
|
||||
/* Get tlb0[tlb0tble_idx] address, save it in r30 */
|
||||
lis %r30, tlb0@h
|
||||
ori %r30, %r30, tlb0@l
|
||||
lwz %r30, 0(%r30)
|
||||
add %r30, %r30, %r21
|
||||
blr
|
||||
|
||||
|
||||
/******************************************************/
|
||||
/*
|
||||
* Return pte address that corresponds to given pmap/va.
|
||||
* If there is no valid entry return 0.
|
||||
* Return pte address that corresponds to given pmap/va. If there is no valid
|
||||
* entry return 0.
|
||||
*
|
||||
* input: r26 - pmap
|
||||
* input: r31 - dear
|
||||
* output: r25 - pte address
|
||||
*
|
||||
* scratch regs used: r21
|
||||
*/
|
||||
/******************************************************/
|
||||
*
|
||||
****************************************************************************/
|
||||
pte_lookup:
|
||||
cmpwi %r26, 0
|
||||
beq 1f /* fail quickly if pmap is invalid */
|
||||
@ -605,8 +551,11 @@ pte_lookup:
|
||||
|
||||
addi %r25, %r26, PM_PDIR /* pmap pm_dir[] address */
|
||||
add %r25, %r25, %r21 /* offset within pm_pdir[] table */
|
||||
lwz %r25, 0(%r25) /* get ptbl address, i.e. pmap->pm_pdir[pdir_idx] */
|
||||
|
||||
/*
|
||||
* Get ptbl address, i.e. pmap->pm_pdir[pdir_idx]
|
||||
* This load may cause a Data TLB miss for non-kernel pmap!
|
||||
*/
|
||||
lwz %r25, 0(%r25)
|
||||
cmpwi %r25, 0
|
||||
beq 2f
|
||||
|
||||
@ -618,7 +567,11 @@ pte_lookup:
|
||||
srwi %r21, %r21, (PTBL_SHIFT - PTBL_ENTRY_SHIFT)
|
||||
|
||||
add %r25, %r25, %r21 /* address of pte entry */
|
||||
lwz %r21, PTE_FLAGS(%r25) /* get pte->flags */
|
||||
/*
|
||||
* Get pte->flags
|
||||
* This load may cause a Data TLB miss for non-kernel pmap!
|
||||
*/
|
||||
lwz %r21, PTE_FLAGS(%r25)
|
||||
andis. %r21, %r21, PTE_VALID@h
|
||||
bne 2f
|
||||
1:
|
||||
@ -626,32 +579,38 @@ pte_lookup:
|
||||
2:
|
||||
blr
|
||||
|
||||
/******************************************************/
|
||||
/*
|
||||
* Save MAS1-MAS3 registers to tlb0[] table, write TLB entry
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Load MAS1-MAS3 registers with data, write TLB entry
|
||||
*
|
||||
* input:
|
||||
* r29 - mas0
|
||||
* r28 - mas1
|
||||
* r27 - mas2
|
||||
* r25 - pte
|
||||
* r30 - tlb0 entry address
|
||||
*
|
||||
* output: none
|
||||
*
|
||||
* scratch regs: r21-r23
|
||||
*/
|
||||
/******************************************************/
|
||||
*
|
||||
****************************************************************************/
|
||||
tlb_fill_entry:
|
||||
/* Handle pte flags. */
|
||||
lwz %r21, PTE_FLAGS(%r25) /* get pte->flags */
|
||||
/*
|
||||
* Update PTE flags: we have to do it atomically, as pmap_protect()
|
||||
* running on other CPUs could attempt to update the flags at the same
|
||||
* time.
|
||||
*/
|
||||
li %r23, PTE_FLAGS
|
||||
1:
|
||||
lwarx %r21, %r23, %r25 /* get pte->flags */
|
||||
oris %r21, %r21, PTE_REFERENCED@h /* set referenced bit */
|
||||
|
||||
andi. %r22, %r21, (PTE_UW | PTE_UW)@l /* check if writable */
|
||||
beq 1f
|
||||
beq 2f
|
||||
oris %r21, %r21, PTE_MODIFIED@h /* set modified bit */
|
||||
1:
|
||||
stw %r21, PTE_FLAGS(%r25) /* write it back */
|
||||
2:
|
||||
stwcx. %r21, %r23, %r25 /* write it back */
|
||||
bne- 1b
|
||||
|
||||
/* Update MAS2. */
|
||||
rlwimi %r27, %r21, 0, 27, 30 /* insert WIMG bits from pte */
|
||||
@ -661,11 +620,6 @@ tlb_fill_entry:
|
||||
|
||||
rlwimi %r23, %r21, 24, 26, 31 /* insert protection bits from pte */
|
||||
|
||||
/* Save MAS registers to tlb0[] table. */
|
||||
stw %r28, TLB0TABLE_MAS1(%r30) /* write tlb0[idx].mas1 */
|
||||
stw %r27, TLB0TABLE_MAS2(%r30) /* write tlb0[idx].mas2 */
|
||||
stw %r23, TLB0TABLE_MAS3(%r30) /* write tlb0[idx].mas3 */
|
||||
|
||||
/* Load MAS registers. */
|
||||
mtspr SPR_MAS0, %r29
|
||||
isync
|
||||
@ -681,12 +635,11 @@ tlb_fill_entry:
|
||||
msync
|
||||
blr
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Instruction TLB miss interrupt
|
||||
*
|
||||
* Same notes as for the Data TLB miss
|
||||
*
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_inst_tlb_error)
|
||||
TLB_PROLOG
|
||||
|
||||
@ -700,9 +653,6 @@ INTERRUPT(int_inst_tlb_error)
|
||||
mfspr %r28, SPR_MAS1
|
||||
mfspr %r27, SPR_MAS2
|
||||
|
||||
/* return tlb0 entry address in r30 */
|
||||
bl get_tlb0table_entry
|
||||
|
||||
mfsrr1 %r21
|
||||
mtcr %r21
|
||||
|
||||
@ -714,9 +664,9 @@ INTERRUPT(int_inst_tlb_error)
|
||||
.globl interrupt_vector_top
|
||||
interrupt_vector_top:
|
||||
|
||||
/****************************************
|
||||
/*****************************************************************************
|
||||
* Debug interrupt
|
||||
****************************************/
|
||||
****************************************************************************/
|
||||
INTERRUPT(int_debug)
|
||||
STANDARD_CRIT_PROLOG(SPR_SPRG2, PC_BOOKE_CRITSAVE, SPR_CSRR0, SPR_CSRR1)
|
||||
FRAME_SETUP(SPR_SPRG2, PC_BOOKE_CRITSAVE, EXC_DEBUG)
|
||||
@ -731,7 +681,7 @@ INTERRUPT(int_debug)
|
||||
bge 1f
|
||||
/* Disable single-stepping for the interrupt handlers. */
|
||||
lwz %r3, FRAME_SRR1+8(%r1);
|
||||
rlwinm %r3,%r3,0,23,21
|
||||
rlwinm %r3, %r3, 0, 23, 21
|
||||
stw %r3, FRAME_SRR1+8(%r1);
|
||||
/* Restore srr0 and srr1 as they could have been clobbered. */
|
||||
lwz %r3, (PC_BOOKE_CRITSAVE+CPUSAVE_SRR0+8)(%r2);
|
||||
@ -752,9 +702,9 @@ INTERRUPT(int_debug)
|
||||
rfci
|
||||
|
||||
|
||||
/********************************
|
||||
/*****************************************************************************
|
||||
* Common trap code
|
||||
********************************/
|
||||
****************************************************************************/
|
||||
trap_common:
|
||||
/* Call C trap dispatcher */
|
||||
addi %r3, %r1, 8
|
||||
@ -773,8 +723,8 @@ CNAME(trapexit):
|
||||
GET_CPUINFO(%r3)
|
||||
lwz %r4, PC_CURTHREAD(%r3)
|
||||
lwz %r4, TD_FLAGS(%r4)
|
||||
lis %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@h
|
||||
ori %r5, %r5, (TDF_ASTPENDING|TDF_NEEDRESCHED)@l
|
||||
lis %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@h
|
||||
ori %r5, %r5, (TDF_ASTPENDING | TDF_NEEDRESCHED)@l
|
||||
and. %r4, %r4, %r5
|
||||
beq 1f
|
||||
|
||||
@ -800,12 +750,12 @@ CNAME(breakpoint):
|
||||
mtsprg1 %r1
|
||||
mfmsr %r3
|
||||
mtsrr1 %r3
|
||||
andi. %r3,%r3,~(PSL_EE|PSL_ME)@l
|
||||
andi. %r3, %r3, ~(PSL_EE | PSL_ME)@l
|
||||
mtmsr %r3 /* disable interrupts */
|
||||
isync
|
||||
GET_CPUINFO(%r3)
|
||||
stw %r30,(PC_DBSAVE+CPUSAVE_R30)(%r3)
|
||||
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r3)
|
||||
stw %r30, (PC_DBSAVE+CPUSAVE_R30)(%r3)
|
||||
stw %r31, (PC_DBSAVE+CPUSAVE_R31)(%r3)
|
||||
|
||||
mflr %r31
|
||||
mtsrr0 %r31
|
||||
@ -829,9 +779,9 @@ CNAME(breakpoint):
|
||||
dbtrap:
|
||||
FRAME_SETUP(SPR_SPRG1, PC_DBSAVE, EXC_DEBUG)
|
||||
/* Call C trap code: */
|
||||
addi %r3,%r1,8
|
||||
addi %r3, %r1, 8
|
||||
bl CNAME(db_trap_glue)
|
||||
or. %r3,%r3,%r3
|
||||
or. %r3, %r3, %r3
|
||||
bne dbleave
|
||||
/* This wasn't for KDB, so switch to real trap: */
|
||||
b trap_common
|
||||
|
@ -59,7 +59,8 @@ struct pmap;
|
||||
register_t pc_booke_critsave[BOOKE_CRITSAVE_LEN]; \
|
||||
register_t pc_booke_mchksave[CPUSAVE_LEN]; \
|
||||
register_t pc_booke_tlbsave[BOOKE_TLBSAVE_LEN]; \
|
||||
register_t pc_booke_tlb_level;
|
||||
register_t pc_booke_tlb_level; \
|
||||
int pc_tid_next;
|
||||
|
||||
/* Definitions for register offsets within the exception tmp save areas */
|
||||
#define CPUSAVE_R28 0 /* where r28 gets saved */
|
||||
|
@ -111,17 +111,17 @@ struct md_page {
|
||||
#else
|
||||
|
||||
struct pmap {
|
||||
struct mtx pm_mtx; /* pmap mutex */
|
||||
tlbtid_t pm_tid; /* TID to identify this pmap entries in TLB */
|
||||
u_int pm_active; /* active on cpus */
|
||||
int pm_refs; /* ref count */
|
||||
struct pmap_statistics pm_stats;/* pmap statistics */
|
||||
struct mtx pm_mtx; /* pmap mutex */
|
||||
tlbtid_t pm_tid[MAXCPU]; /* TID to identify this pmap entries in TLB */
|
||||
u_int pm_active; /* active on cpus */
|
||||
int pm_refs; /* ref count */
|
||||
struct pmap_statistics pm_stats; /* pmap statistics */
|
||||
|
||||
/* Page table directory, array of pointers to page tables. */
|
||||
pte_t *pm_pdir[PDIR_NENTRIES];
|
||||
pte_t *pm_pdir[PDIR_NENTRIES];
|
||||
|
||||
/* List of allocated ptbl bufs (ptbl kva regions). */
|
||||
TAILQ_HEAD(, ptbl_buf) ptbl_list;
|
||||
TAILQ_HEAD(, ptbl_buf) pm_ptbl_list;
|
||||
};
|
||||
typedef struct pmap *pmap_t;
|
||||
|
||||
|
@ -211,11 +211,11 @@ extern u_int dsisr(void);
|
||||
* Page Table Entry definitions and macros.
|
||||
*/
|
||||
#ifndef LOCORE
|
||||
struct pte_entry {
|
||||
struct pte {
|
||||
vm_offset_t rpn;
|
||||
u_int32_t flags;
|
||||
uint32_t flags;
|
||||
};
|
||||
typedef struct pte_entry pte_t;
|
||||
typedef struct pte pte_t;
|
||||
#endif
|
||||
|
||||
/* RPN mask, TLB0 4K pages */
|
||||
|
@ -46,7 +46,8 @@
|
||||
#define MAS1_IPROT 0x40000000
|
||||
#define MAS1_TID_MASK 0x00FF0000
|
||||
#define MAS1_TID_SHIFT 16
|
||||
#define MAS1_TS 0x00001000
|
||||
#define MAS1_TS_MASK 0x00001000
|
||||
#define MAS1_TS_SHIFT 12
|
||||
#define MAS1_TSIZE_MASK 0x00000F00
|
||||
#define MAS1_TSIZE_SHIFT 8
|
||||
|
||||
@ -62,7 +63,7 @@
|
||||
#define TLB_SIZE_1G 10
|
||||
#define TLB_SIZE_4G 11
|
||||
|
||||
#define MAS2_EPN 0xFFFFF000
|
||||
#define MAS2_EPN_MASK 0xFFFFF000
|
||||
#define MAS2_EPN_SHIFT 12
|
||||
#define MAS2_X0 0x00000040
|
||||
#define MAS2_X1 0x00000020
|
||||
@ -109,31 +110,37 @@
|
||||
#define MAS2_TLB0_ENTRY_IDX_SHIFT 12
|
||||
|
||||
/*
|
||||
* Maximum number of TLB1 entries used for a permanat
|
||||
* mapping of kernel region (kernel image plus statically
|
||||
* allocated data.
|
||||
* Maximum number of TLB1 entries used for a permanent mapping of kernel
|
||||
* region (kernel image plus statically allocated data).
|
||||
*/
|
||||
#define KERNEL_REGION_MAX_TLB_ENTRIES 4
|
||||
|
||||
#define _TLB_ENTRY_IO (MAS2_I | MAS2_G)
|
||||
#ifdef SMP
|
||||
#define _TLB_ENTRY_MEM (MAS2_M)
|
||||
#else
|
||||
#define _TLB_ENTRY_MEM (0)
|
||||
#endif
|
||||
|
||||
#define KERNEL_TID 0 /* TLB TID to use for kernel translations */
|
||||
#define TID_KERNEL 0 /* TLB TID to use for kernel (shared) translations */
|
||||
#define TID_KRESERVED 1 /* Number of TIDs reserved for kernel */
|
||||
#define TID_URESERVED 0 /* Number of TIDs reserve for user */
|
||||
#define TID_URESERVED 0 /* Number of TIDs reserved for user */
|
||||
#define TID_MIN (TID_KRESERVED + TID_URESERVED)
|
||||
#define TID_MAX 255
|
||||
#define TID_NONE -1
|
||||
|
||||
#if !defined(LOCORE)
|
||||
typedef struct tlb_entry {
|
||||
u_int32_t mas1;
|
||||
u_int32_t mas2;
|
||||
u_int32_t mas3;
|
||||
uint32_t mas1;
|
||||
uint32_t mas2;
|
||||
uint32_t mas3;
|
||||
} tlb_entry_t;
|
||||
|
||||
typedef u_int8_t tlbtid_t;
|
||||
typedef int tlbtid_t;
|
||||
struct pmap;
|
||||
|
||||
void tlb0_print_tlbentries(void);
|
||||
|
||||
void tlb1_inval_entry(unsigned int);
|
||||
void tlb1_init(vm_offset_t);
|
||||
void tlb1_print_entries(void);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user