MFH r187125-187188

This commit is contained in:
thompsa 2009-01-13 20:42:05 +00:00
commit 1bdc6a93e7
107 changed files with 4693 additions and 1825 deletions

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -108,4 +108,4 @@ The
and
.Fn flsll
functions appeared in
.Fx 8.0 .
.Fx 7.1 .

View File

@ -486,6 +486,8 @@ libusb20_dev_close(struct libusb20_device *pdev)
pdev->is_opened = 0;
pdev->claimed_interfaces = 0;
return (error);
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -33,7 +33,7 @@ T[] = {
};
#ifdef INLINE_KERNEL_TANDF
extern inline
extern __gnu89_inline
#endif
float
__kernel_tandf(double x, int iy)

View File

@ -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);

View File

@ -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>.

View File

@ -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

View File

@ -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

View File

@ -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 )

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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" },

View File

@ -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");
);

View File

@ -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

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View 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_ */

View 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.
*/

View File

@ -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,
};

View File

@ -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;

View File

@ -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);

View File

@ -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,
};

View File

@ -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_ */

View File

@ -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);

View File

@ -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,
};

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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,
};

View File

@ -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

View File

@ -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);

View File

@ -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];

View File

@ -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 */
}
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}
/*------------------------------------------------------------------------*

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
};
/*

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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_ */

View File

@ -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 */

View File

@ -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,

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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)},
};

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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,

View File

@ -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>

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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:

View 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>

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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 */

View File

@ -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