qemu_irq irq;
MemoryRegion mem;
AddressSpace *as;
- int num_ports;
+ uint32_t num_ports;
const char *name;
QEMUTimer *eof_timer;
bool int_req = relative_frame_number == frame_count &&
OHCI_BM(iso_td.flags, TD_DI) == 0;
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ if (dev == NULL) {
+ trace_usb_ohci_td_dev_error();
+ return 1;
+ }
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, false, int_req);
usb_packet_addbuf(&ohci->usb_packet, ohci->usb_buf, len);
return 1;
}
-#ifdef trace_event_get_state
static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
{
- bool print16 = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_SHORT);
- bool printall = !!trace_event_get_state(TRACE_USB_OHCI_TD_PKT_FULL);
+ bool print16;
+ bool printall;
const int width = 16;
int i;
char tmp[3 * width + 1];
char *p = tmp;
+ print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT);
+ printall = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_FULL);
+
if (!printall && !print16) {
return;
}
p += sprintf(p, " %.2x", buf[i]);
}
}
-#else
-static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len)
-{
-}
-#endif
/* Service a transport descriptor.
Returns nonzero to terminate processing of this endpoint. */
return 1;
}
dev = ohci_find_device(ohci, OHCI_BM(ed->flags, ED_FA));
+ if (dev == NULL) {
+ trace_usb_ohci_td_dev_error();
+ return 1;
+ }
ep = usb_ep_get(dev, pid, OHCI_BM(ed->flags, ED_EN));
usb_packet_setup(&ohci->usb_packet, pid, ep, 0, addr, !flag_r,
OHCI_BM(td.flags, TD_DI) == 0);
OHCI_SET_BM(td.flags, TD_EC, 3);
break;
}
+ /* An error occured so we have to clear the interrupt counter. See
+ * spec at 6.4.4 on page 104 */
+ ohci->done_count = 0;
}
ed->head |= OHCI_ED_H;
}
/* set a timer for EOF */
static void ohci_eof_timer(OHCIState *ohci)
{
- ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
timer_mod(ohci->eof_timer, ohci->sof_time + usb_frame_time);
}
/* Set a timer for EOF and generate a SOF event */
static void ohci_sof(OHCIState *ohci)
{
+ ohci->sof_time += usb_frame_time;
ohci_eof_timer(ohci);
ohci_set_interrupt(ohci, OHCI_INTR_SF);
}
* can meet some race conditions
*/
+ ohci->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
ohci_eof_timer(ohci);
return 1;
* set already.
*/
tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ohci->sof_time;
+ if (tks < 0) {
+ tks = 0;
+ }
/* avoid muldiv if possible */
if (tks >= usb_frame_time)
};
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
- int num_ports, dma_addr_t localmem_base,
+ uint32_t num_ports, dma_addr_t localmem_base,
char *masterbus, uint32_t firstport,
AddressSpace *as, Error **errp)
{
ohci->as = as;
if (num_ports > OHCI_MAX_PORTS) {
- error_setg(errp, "OHCI num-ports=%d is too big (limit is %d ports)",
+ error_setg(errp, "OHCI num-ports=%u is too big (limit is %u ports)",
num_ports, OHCI_MAX_PORTS);
return;
}
/*< public >*/
OHCIState ohci;
+ char *masterbus;
uint32_t num_ports;
+ uint32_t firstport;
dma_addr_t dma_offset;
} OHCISysBusState;
{
OHCISysBusState *s = SYSBUS_OHCI(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+ Error *err = NULL;
- /* Cannot fail as we pass NULL for masterbus */
- usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset, NULL, 0,
- &address_space_memory, &error_abort);
+ usb_ohci_init(&s->ohci, dev, s->num_ports, s->dma_offset,
+ s->masterbus, s->firstport,
+ &address_space_memory, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
sysbus_init_irq(sbd, &s->ohci.irq);
sysbus_init_mmio(sbd, &s->ohci.mem);
}
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(OHCIPCIState),
.class_init = ohci_pci_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { },
+ },
};
static Property ohci_sysbus_properties[] = {
+ DEFINE_PROP_STRING("masterbus", OHCISysBusState, masterbus),
DEFINE_PROP_UINT32("num-ports", OHCISysBusState, num_ports, 3),
+ DEFINE_PROP_UINT32("firstport", OHCISysBusState, firstport, 0),
DEFINE_PROP_DMAADDR("dma-offset", OHCISysBusState, dma_offset, 0),
DEFINE_PROP_END_OF_LIST(),
};