Lines Matching +full:cmd +full:- +full:db
31 #include "hw/usb/uhci-regs.h"
34 #include "hw/qdev-properties.h"
40 #include "qemu/main-loop.h"
43 #include "hcd-uhci.h"
108 if ((td->token & (0xf << 15)) == 0) { in uhci_queue_token()
110 return td->token & 0x7ff00; in uhci_queue_token()
112 /* covers ep, dev, pid -> identifies the endpoint */ in uhci_queue_token()
113 return td->token & 0x7ffff; in uhci_queue_token()
123 queue->uhci = s; in uhci_queue_new()
124 queue->qh_addr = qh_addr; in uhci_queue_new()
125 queue->token = uhci_queue_token(td); in uhci_queue_new()
126 queue->ep = ep; in uhci_queue_new()
127 QTAILQ_INIT(&queue->asyncs); in uhci_queue_new()
128 QTAILQ_INSERT_HEAD(&s->queues, queue, next); in uhci_queue_new()
129 queue->valid = QH_VALID; in uhci_queue_new()
130 trace_usb_uhci_queue_add(queue->token); in uhci_queue_new()
136 UHCIState *s = queue->uhci; in uhci_queue_free()
139 while (!QTAILQ_EMPTY(&queue->asyncs)) { in uhci_queue_free()
140 async = QTAILQ_FIRST(&queue->asyncs); in uhci_queue_free()
143 usb_device_ep_stopped(queue->ep->dev, queue->ep); in uhci_queue_free()
145 trace_usb_uhci_queue_del(queue->token, reason); in uhci_queue_free()
146 QTAILQ_REMOVE(&s->queues, queue, next); in uhci_queue_free()
155 QTAILQ_FOREACH(queue, &s->queues, next) { in uhci_queue_find()
156 if (queue->token == token) { in uhci_queue_find()
166 UHCIAsync *first = QTAILQ_FIRST(&queue->asyncs); in uhci_queue_verify()
167 uint32_t queue_token_addr = (queue->token >> 8) & 0x7f; in uhci_queue_verify()
169 return queue->qh_addr == qh_addr && in uhci_queue_verify()
170 queue->token == uhci_queue_token(td) && in uhci_queue_verify()
171 queue_token_addr == queue->ep->dev->addr && in uhci_queue_verify()
172 (queuing || !(td->ctrl & TD_CTRL_ACTIVE) || first == NULL || in uhci_queue_verify()
173 first->td_addr == td_addr); in uhci_queue_verify()
180 async->queue = queue; in uhci_async_alloc()
181 async->td_addr = td_addr; in uhci_async_alloc()
182 usb_packet_init(&async->packet); in uhci_async_alloc()
183 trace_usb_uhci_packet_add(async->queue->token, async->td_addr); in uhci_async_alloc()
190 trace_usb_uhci_packet_del(async->queue->token, async->td_addr); in uhci_async_free()
191 usb_packet_cleanup(&async->packet); in uhci_async_free()
192 if (async->buf != async->static_buf) { in uhci_async_free()
193 g_free(async->buf); in uhci_async_free()
200 UHCIQueue *queue = async->queue; in uhci_async_link()
201 QTAILQ_INSERT_TAIL(&queue->asyncs, async, next); in uhci_async_link()
202 trace_usb_uhci_packet_link_async(async->queue->token, async->td_addr); in uhci_async_link()
207 UHCIQueue *queue = async->queue; in uhci_async_unlink()
208 QTAILQ_REMOVE(&queue->asyncs, async, next); in uhci_async_unlink()
209 trace_usb_uhci_packet_unlink_async(async->queue->token, async->td_addr); in uhci_async_unlink()
215 trace_usb_uhci_packet_cancel(async->queue->token, async->td_addr, in uhci_async_cancel()
216 async->done); in uhci_async_cancel()
217 if (!async->done) { in uhci_async_cancel()
218 usb_cancel_packet(&async->packet); in uhci_async_cancel()
231 QTAILQ_FOREACH(queue, &s->queues, next) { in uhci_async_validate_begin()
232 queue->valid--; in uhci_async_validate_begin()
243 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) { in uhci_async_validate_end()
244 if (!queue->valid) { in uhci_async_validate_end()
245 uhci_queue_free(queue, "validate-end"); in uhci_async_validate_end()
254 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, n) { in uhci_async_cancel_device()
255 if (queue->ep->dev == dev) { in uhci_async_cancel_device()
256 uhci_queue_free(queue, "cancel-device"); in uhci_async_cancel_device()
265 QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) { in uhci_async_cancel_all()
266 uhci_queue_free(queue, "cancel-all"); in uhci_async_cancel_all()
275 QTAILQ_FOREACH(queue, &s->queues, next) { in uhci_async_find_td()
276 QTAILQ_FOREACH(async, &queue->asyncs, next) { in uhci_async_find_td()
277 if (async->td_addr == td_addr) { in uhci_async_find_td()
288 if (((s->status2 & 1) && (s->intr & (1 << 2))) || in uhci_update_irq()
289 ((s->status2 & 2) && (s->intr & (1 << 3))) || in uhci_update_irq()
290 ((s->status & UHCI_STS_USBERR) && (s->intr & (1 << 0))) || in uhci_update_irq()
291 ((s->status & UHCI_STS_RD) && (s->intr & (1 << 1))) || in uhci_update_irq()
292 (s->status & UHCI_STS_HSERR) || in uhci_update_irq()
293 (s->status & UHCI_STS_HCPERR)) { in uhci_update_irq()
296 qemu_set_irq(s->irq, level); in uhci_update_irq()
306 s->cmd = 0; in uhci_state_reset()
307 s->status = UHCI_STS_HCHALTED; in uhci_state_reset()
308 s->status2 = 0; in uhci_state_reset()
309 s->intr = 0; in uhci_state_reset()
310 s->fl_base_addr = 0; in uhci_state_reset()
311 s->sof_timing = 64; in uhci_state_reset()
314 port = &s->ports[i]; in uhci_state_reset()
315 port->ctrl = 0x0080; in uhci_state_reset()
316 if (port->port.dev && port->port.dev->attached) { in uhci_state_reset()
317 usb_port_reset(&port->port); in uhci_state_reset()
322 qemu_bh_cancel(s->bh); in uhci_state_reset()
328 s->uhci_reset(s); in uhci_reset()
346 s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + in uhci_post_load()
361 VMSTATE_UINT16(cmd, UHCIState),
384 if ((val & UHCI_CMD_RS) && !(s->cmd & UHCI_CMD_RS)) { in uhci_port_write()
387 s->expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + in uhci_port_write()
389 timer_mod(s->frame_timer, s->expire_time); in uhci_port_write()
390 s->status &= ~UHCI_STS_HCHALTED; in uhci_port_write()
392 s->status |= UHCI_STS_HCHALTED; in uhci_port_write()
400 port = &s->ports[i]; in uhci_port_write()
401 usb_device_reset(port->port.dev); in uhci_port_write()
410 s->cmd = val; in uhci_port_write()
412 if ((s->ports[0].ctrl & UHCI_PORT_RD) || in uhci_port_write()
413 (s->ports[1].ctrl & UHCI_PORT_RD)) { in uhci_port_write()
419 s->status &= ~val; in uhci_port_write()
425 s->status2 = 0; in uhci_port_write()
430 s->intr = val; in uhci_port_write()
434 if (s->status & UHCI_STS_HCHALTED) { in uhci_port_write()
435 s->frnum = val & 0x7ff; in uhci_port_write()
439 s->fl_base_addr &= 0xffff0000; in uhci_port_write()
440 s->fl_base_addr |= val & ~0xfff; in uhci_port_write()
443 s->fl_base_addr &= 0x0000ffff; in uhci_port_write()
444 s->fl_base_addr |= (val << 16); in uhci_port_write()
447 s->sof_timing = val & 0xff; in uhci_port_write()
459 port = &s->ports[n]; in uhci_port_write()
460 dev = port->port.dev; in uhci_port_write()
461 if (dev && dev->attached) { in uhci_port_write()
464 !(port->ctrl & UHCI_PORT_RESET)) { in uhci_port_write()
468 port->ctrl &= UHCI_PORT_READ_ONLY; in uhci_port_write()
470 if (!(port->ctrl & UHCI_PORT_CCS)) { in uhci_port_write()
473 port->ctrl |= (val & ~UHCI_PORT_READ_ONLY); in uhci_port_write()
475 port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR); in uhci_port_write()
488 val = s->cmd; in uhci_port_read()
491 val = s->status; in uhci_port_read()
494 val = s->intr; in uhci_port_read()
497 val = s->frnum; in uhci_port_read()
500 val = s->fl_base_addr & 0xffff; in uhci_port_read()
503 val = (s->fl_base_addr >> 16) & 0xffff; in uhci_port_read()
506 val = s->sof_timing; in uhci_port_read()
516 port = &s->ports[n]; in uhci_port_read()
517 val = port->ctrl; in uhci_port_read()
540 if (s->cmd & UHCI_CMD_EGSM) { in uhci_resume()
541 s->cmd |= UHCI_CMD_FGR; in uhci_resume()
542 s->status |= UHCI_STS_RD; in uhci_resume()
549 UHCIState *s = port1->opaque; in uhci_attach()
550 UHCIPort *port = &s->ports[port1->index]; in uhci_attach()
553 port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC; in uhci_attach()
556 if (port->port.dev->speed == USB_SPEED_LOW) { in uhci_attach()
557 port->ctrl |= UHCI_PORT_LSDA; in uhci_attach()
559 port->ctrl &= ~UHCI_PORT_LSDA; in uhci_attach()
567 UHCIState *s = port1->opaque; in uhci_detach()
568 UHCIPort *port = &s->ports[port1->index]; in uhci_detach()
570 uhci_async_cancel_device(s, port1->dev); in uhci_detach()
573 if (port->ctrl & UHCI_PORT_CCS) { in uhci_detach()
574 port->ctrl &= ~UHCI_PORT_CCS; in uhci_detach()
575 port->ctrl |= UHCI_PORT_CSC; in uhci_detach()
578 if (port->ctrl & UHCI_PORT_EN) { in uhci_detach()
579 port->ctrl &= ~UHCI_PORT_EN; in uhci_detach()
580 port->ctrl |= UHCI_PORT_ENC; in uhci_detach()
588 UHCIState *s = port1->opaque; in uhci_child_detach()
595 UHCIState *s = port1->opaque; in uhci_wakeup()
596 UHCIPort *port = &s->ports[port1->index]; in uhci_wakeup()
598 if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) { in uhci_wakeup()
599 port->ctrl |= UHCI_PORT_RD; in uhci_wakeup()
610 UHCIPort *port = &s->ports[i]; in uhci_find_device()
611 if (!(port->ctrl & UHCI_PORT_EN)) { in uhci_find_device()
614 dev = usb_find_device(&port->port, addr); in uhci_find_device()
625 dma_memory_read(s->as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); in uhci_dma_read()
631 dma_memory_write(s->as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); in uhci_dma_write()
637 le32_to_cpus(&td->link); in uhci_read_td()
638 le32_to_cpus(&td->ctrl); in uhci_read_td()
639 le32_to_cpus(&td->token); in uhci_read_td()
640 le32_to_cpus(&td->buffer); in uhci_read_td()
651 td->ctrl |= TD_CTRL_NAK; in uhci_handle_td_error()
655 td->ctrl |= TD_CTRL_STALL; in uhci_handle_td_error()
661 td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; in uhci_handle_td_error()
670 td->ctrl |= TD_CTRL_TIMEOUT; in uhci_handle_td_error()
671 td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); in uhci_handle_td_error()
677 td->ctrl &= ~TD_CTRL_ACTIVE; in uhci_handle_td_error()
678 s->status |= UHCI_STS_USBERR; in uhci_handle_td_error()
679 if (td->ctrl & TD_CTRL_IOC) { in uhci_handle_td_error()
692 max_len = ((td->token >> 21) + 1) & 0x7ff; in uhci_complete_td()
693 pid = td->token & 0xff; in uhci_complete_td()
695 if (td->ctrl & TD_CTRL_IOS) { in uhci_complete_td()
696 td->ctrl &= ~TD_CTRL_ACTIVE; in uhci_complete_td()
699 if (async->packet.status != USB_RET_SUCCESS) { in uhci_complete_td()
700 return uhci_handle_td_error(s, td, async->td_addr, in uhci_complete_td()
701 async->packet.status, int_mask); in uhci_complete_td()
704 len = async->packet.actual_length; in uhci_complete_td()
705 td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff); in uhci_complete_td()
712 td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK); in uhci_complete_td()
713 if (td->ctrl & TD_CTRL_IOC) { in uhci_complete_td()
718 uhci_dma_write(s, td->buffer, async->buf, len); in uhci_complete_td()
719 if ((td->ctrl & TD_CTRL_SPD) && len < max_len) { in uhci_complete_td()
722 trace_usb_uhci_packet_complete_shortxfer(async->queue->token, in uhci_complete_td()
723 async->td_addr); in uhci_complete_td()
729 trace_usb_uhci_packet_complete_success(async->queue->token, in uhci_complete_td()
730 async->td_addr); in uhci_complete_td()
740 uint8_t pid = td->token & 0xff; in uhci_handle_td()
745 if (uhci_queue_verify(async->queue, qh_addr, td, td_addr, queuing)) { in uhci_handle_td()
746 assert(q == NULL || q == async->queue); in uhci_handle_td()
747 q = async->queue; in uhci_handle_td()
749 uhci_queue_free(async->queue, "guest re-used pending td"); in uhci_handle_td()
757 uhci_queue_free(q, "guest re-used qh"); in uhci_handle_td()
763 q->valid = QH_VALID; in uhci_handle_td()
767 if (!(td->ctrl & TD_CTRL_ACTIVE)) { in uhci_handle_td()
769 /* Guest marked a pending td non-active, cancel the queue */ in uhci_handle_td()
770 uhci_queue_free(async->queue, "pending td non-active"); in uhci_handle_td()
776 if (td->ctrl & TD_CTRL_IOC) { in uhci_handle_td()
789 s->status |= UHCI_STS_HCPERR; in uhci_handle_td()
790 s->cmd &= ~UHCI_CMD_RS; in uhci_handle_td()
804 if (!async->done) { in uhci_handle_td()
806 UHCIAsync *last = QTAILQ_LAST(&async->queue->asyncs); in uhci_handle_td()
809 * may have added more tds to the queue. Note we re-read the td in uhci_handle_td()
812 uhci_read_td(s, &last_td, last->td_addr); in uhci_handle_td()
813 uhci_queue_fill(async->queue, &last_td); in uhci_handle_td()
821 if (s->completions_only) { in uhci_handle_td()
830 dev = uhci_find_device(s, (td->token >> 8) & 0x7f); in uhci_handle_td()
835 ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf); in uhci_handle_td()
840 max_len = ((td->token >> 21) + 1) & 0x7ff; in uhci_handle_td()
841 spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0); in uhci_handle_td()
842 usb_packet_setup(&async->packet, pid, q->ep, 0, td_addr, spd, in uhci_handle_td()
843 (td->ctrl & TD_CTRL_IOC) != 0); in uhci_handle_td()
844 if (max_len <= sizeof(async->static_buf)) { in uhci_handle_td()
845 async->buf = async->static_buf; in uhci_handle_td()
847 async->buf = g_malloc(max_len); in uhci_handle_td()
849 usb_packet_addbuf(&async->packet, async->buf, max_len); in uhci_handle_td()
854 uhci_dma_read(s, td->buffer, async->buf, max_len); in uhci_handle_td()
855 usb_handle_packet(q->ep->dev, &async->packet); in uhci_handle_td()
856 if (async->packet.status == USB_RET_SUCCESS) { in uhci_handle_td()
857 async->packet.actual_length = max_len; in uhci_handle_td()
862 usb_handle_packet(q->ep->dev, &async->packet); in uhci_handle_td()
869 if (async->packet.status == USB_RET_ASYNC) { in uhci_handle_td()
886 UHCIState *s = async->queue->uhci; in uhci_async_complete()
888 if (packet->status == USB_RET_REMOVE_FROM_QUEUE) { in uhci_async_complete()
893 async->done = 1; in uhci_async_complete()
895 s->completions_only = true; in uhci_async_complete()
896 qemu_bh_schedule(s->bh); in uhci_async_complete()
914 /* QH DB used for detecting QH loops */
921 static void qhdb_reset(QhDb *db) in qhdb_reset() argument
923 db->count = 0; in qhdb_reset()
926 /* Add QH to DB. Returns 1 if already present or DB is full. */
927 static int qhdb_insert(QhDb *db, uint32_t addr) in qhdb_insert() argument
930 for (i = 0; i < db->count; i++) { in qhdb_insert()
931 if (db->addr[i] == addr) { in qhdb_insert()
936 if (db->count >= UHCI_MAX_QUEUES) { in qhdb_insert()
940 db->addr[db->count++] = addr; in qhdb_insert()
947 uint32_t plink = td->link; in uhci_queue_fill()
952 uhci_read_td(q->uhci, &ptd, plink); in uhci_queue_fill()
956 if (uhci_queue_token(&ptd) != q->token) { in uhci_queue_fill()
960 ret = uhci_handle_td(q->uhci, q, q->qh_addr, &ptd, plink, &int_mask); in uhci_queue_fill()
968 usb_device_flush_ep_queue(q->ep->dev, q->ep); in uhci_queue_fill()
980 frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2); in uhci_process_frame()
990 for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) { in uhci_process_frame()
991 if (!s->completions_only && s->frame_bytes >= s->frame_bandwidth) { in uhci_process_frame()
1069 s->frame_bytes += (td.ctrl & 0x7ff) + 1; in uhci_process_frame()
1093 s->pending_int_mask |= int_mask; in uhci_process_frame()
1109 s->completions_only = false; in uhci_frame_timer()
1110 qemu_bh_cancel(s->bh); in uhci_frame_timer()
1112 if (!(s->cmd & UHCI_CMD_RS)) { in uhci_frame_timer()
1115 timer_del(s->frame_timer); in uhci_frame_timer()
1117 /* set hchalted bit in status - UHCI11D 2.1.2 */ in uhci_frame_timer()
1118 s->status |= UHCI_STS_HCHALTED; in uhci_frame_timer()
1123 t_last_run = s->expire_time - frame_t; in uhci_frame_timer()
1127 frames = (t_now - t_last_run) / frame_t; in uhci_frame_timer()
1128 if (frames > s->maxframes) { in uhci_frame_timer()
1129 int skipped = frames - s->maxframes; in uhci_frame_timer()
1130 s->expire_time += skipped * frame_t; in uhci_frame_timer()
1131 s->frnum = (s->frnum + skipped) & 0x7ff; in uhci_frame_timer()
1132 frames -= skipped; in uhci_frame_timer()
1139 s->frame_bytes = 0; in uhci_frame_timer()
1140 trace_usb_uhci_frame_start(s->frnum); in uhci_frame_timer()
1146 * the guest must look at frnum - 1 on interrupt, so inc frnum now in uhci_frame_timer()
1148 s->frnum = (s->frnum + 1) & 0x7ff; in uhci_frame_timer()
1149 s->expire_time += frame_t; in uhci_frame_timer()
1153 if (s->pending_int_mask) { in uhci_frame_timer()
1154 s->status2 |= s->pending_int_mask; in uhci_frame_timer()
1155 s->status |= UHCI_STS_USBINT; in uhci_frame_timer()
1158 s->pending_int_mask = 0; in uhci_frame_timer()
1160 timer_mod(s->frame_timer, t_now + frame_t); in uhci_frame_timer()
1189 if (s->masterbus) { in usb_uhci_init()
1192 ports[i] = &s->ports[i].port; in usb_uhci_init()
1194 usb_register_companion(s->masterbus, ports, UHCI_PORTS, in usb_uhci_init()
1195 s->firstport, s, &uhci_port_ops, in usb_uhci_init()
1203 usb_bus_new(&s->bus, sizeof(s->bus), &uhci_bus_ops, DEVICE(dev)); in usb_uhci_init()
1205 usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops, in usb_uhci_init()
1209 s->bh = qemu_bh_new_guarded(uhci_bh, s, &dev->mem_reentrancy_guard); in usb_uhci_init()
1210 s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uhci_frame_timer, s); in usb_uhci_init()
1211 s->num_ports_vmstate = UHCI_PORTS; in usb_uhci_init()
1212 QTAILQ_INIT(&s->queues); in usb_uhci_init()
1214 memory_region_init_io(&s->mem, OBJECT(s), &uhci_ioport_ops, s, in usb_uhci_init()
1222 if (s->frame_timer) { in usb_uhci_exit()
1223 timer_free(s->frame_timer); in usb_uhci_exit()
1224 s->frame_timer = NULL; in usb_uhci_exit()
1227 if (s->bh) { in usb_uhci_exit()
1228 qemu_bh_delete(s->bh); in usb_uhci_exit()
1233 if (!s->masterbus) { in usb_uhci_exit()
1234 usb_bus_release(&s->bus); in usb_uhci_exit()