if (len >= 4) {
iowrite32_rep(fifo, src, len >> 2);
index = len & ~0x03;
} if (len & 0x02) {
writew(*(u16 *)&src[index], fifo);
index += 2;
} if (len & 0x01)
writeb(src[index], fifo);
}
if (len >= 4) {
ioread32_rep(fifo, dst, len >> 2);
index = len & ~0x03;
} if (len & 0x3) {
value = readl(fifo);
memcpy(&dst[index], &value, len & 0x3);
}
}
staticvoid ep0_load_test_packet(struct mtu3 *mtu)
{ /* * because the length of test packet is less than max packet of HS ep0, * write it into fifo directly.
*/
ep0_write_fifo(mtu->ep0, mtu3_test_packet, sizeof(mtu3_test_packet));
}
/* * A. send STALL for setup transfer without data stage: * set SENDSTALL and SETUPPKTRDY at the same time; * B. send STALL for other cases: * set SENDSTALL only.
*/ staticvoid ep0_stall_set(struct mtu3_ep *mep0, bool set, u32 pktrdy)
{ struct mtu3 *mtu = mep0->mtu; void __iomem *mbase = mtu->mac_base;
u32 csr;
/* * handle all control requests can be handled * returns: * negative errno - error happened * zero - need delegate SETUP to gadget driver * positive - already handled
*/ staticint handle_standard_request(struct mtu3 *mtu, struct usb_ctrlrequest *setup)
{ void __iomem *mbase = mtu->mac_base; enum usb_device_state state = mtu->g.state; int handled = -EINVAL;
u32 dev_conf;
u16 value;
value = le16_to_cpu(setup->wValue);
/* the gadget driver handles everything except what we must handle */ switch (setup->bRequest) { case USB_REQ_SET_ADDRESS: /* change it after the status stage */
mtu->address = (u8) (value & 0x7f);
dev_dbg(mtu->dev, "set address to 0x%x\n", mtu->address);
/* read packet and ack; or stall because of gadget driver bug */ if (req) { void *buf = req->buf + req->actual; unsignedint len = req->length - req->actual;
finish: if (mtu->test_mode) {
; /* nothing to do */
} elseif (handled == USB_GADGET_DELAYED_STATUS) {
mreq = next_ep0_request(mtu); if (mreq) { /* already asked us to continue delayed status */
ep0_do_status_stage(mtu);
ep0_req_giveback(mtu, &mreq->request);
} else { /* do delayed STATUS stage till receive ep0_queue */
mtu->delayed_status = true;
}
} elseif (le16_to_cpu(setup.wLength) == 0) { /* no data stage */
/* we sent a stall.. need to clear it now.. */ if (csr & EP0_SENTSTALL) {
ep0_stall_set(mtu->ep0, false, 0);
csr = mtu3_readl(mbase, U3D_EP0CSR);
ret = IRQ_HANDLED;
}
dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu));
mtu3_dbg_trace(mtu->dev, "ep0_state %s", decode_ep0_state(mtu));
switch (mtu->ep0_state) { case MU3D_EP0_STATE_TX: /* irq on clearing txpktrdy */ if ((csr & EP0_FIFOFULL) == 0) {
ep0_tx_state(mtu);
ret = IRQ_HANDLED;
} break; case MU3D_EP0_STATE_RX: /* irq on set rxpktrdy */ if (csr & EP0_RXPKTRDY) {
ep0_rx_state(mtu);
ret = IRQ_HANDLED;
} break; case MU3D_EP0_STATE_TX_END:
mtu3_writel(mbase, U3D_EP0CSR,
(csr & EP0_W1C_BITS) | EP0_DATAEND);
mreq = next_ep0_request(mtu); if (mreq)
ep0_req_giveback(mtu, &mreq->request);
mtu->ep0_state = MU3D_EP0_STATE_SETUP;
ret = IRQ_HANDLED;
dev_dbg(mtu->dev, "ep0_state: %s\n", decode_ep0_state(mtu)); break; case MU3D_EP0_STATE_SETUP: if (!(csr & EP0_SETUPPKTRDY)) break;
len = mtu3_readl(mbase, U3D_RXCOUNT0); if (len != 8) {
dev_err(mtu->dev, "SETUP packet len %d != 8 ?\n", len); break;
}
switch (mtu->ep0_state) { case MU3D_EP0_STATE_SETUP: case MU3D_EP0_STATE_RX: /* control-OUT data */ case MU3D_EP0_STATE_TX: /* control-IN data */ break; default:
dev_err(mtu->dev, "%s, error in ep0 state %s\n", __func__,
decode_ep0_state(mtu)); return -EINVAL;
}
if (mtu->delayed_status) {
mtu->delayed_status = false;
ep0_do_status_stage(mtu); /* needn't giveback the request for handling delay STATUS */ return 0;
}
if (!list_empty(&mep->req_list)) return -EBUSY;
list_add_tail(&mreq->list, &mep->req_list);
/* sequence #1, IN ... start writing the data */ if (mtu->ep0_state == MU3D_EP0_STATE_TX)
ep0_tx_state(mtu);
staticint mtu3_ep0_dequeue(struct usb_ep *ep, struct usb_request *req)
{ /* we just won't support this */ return -EINVAL;
}
staticint mtu3_ep0_halt(struct usb_ep *ep, int value)
{ struct mtu3_ep *mep; struct mtu3 *mtu; unsignedlong flags; int ret = 0;
if (!ep || !value) return -EINVAL;
mep = to_mtu3_ep(ep);
mtu = mep->mtu;
dev_dbg(mtu->dev, "%s\n", __func__);
spin_lock_irqsave(&mtu->lock, flags);
if (!list_empty(&mep->req_list)) {
ret = -EBUSY; goto cleanup;
}
switch (mtu->ep0_state) { /* * stalls are usually issued after parsing SETUP packet, either * directly in irq context from setup() or else later.
*/ case MU3D_EP0_STATE_TX: case MU3D_EP0_STATE_TX_END: case MU3D_EP0_STATE_RX: case MU3D_EP0_STATE_SETUP:
ep0_stall_set(mtu->ep0, true, 0); break; default:
dev_dbg(mtu->dev, "ep0 can't halt in state %s\n",
decode_ep0_state(mtu));
ret = -EINVAL;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.15Bemerkung:
(vorverarbeitet am 2026-04-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.