Started rewrite of USB packet handling required for full async packet support.

Step #1: Allocate buffer for data transfers dynamicly with the required size
(done in UHCI, OHCI and EHCI).
This commit is contained in:
Volker Ruppert 2016-11-18 21:27:43 +00:00
parent de6ee1d7eb
commit 0192554c25
7 changed files with 50 additions and 47 deletions

View File

@ -65,22 +65,16 @@ bx_uhci_core_c::bx_uhci_core_c()
{
put("uhci_core", "UHCIC");
memset((void*)&hub, 0, sizeof(bx_uhci_core_t));
device_buffer = NULL;
hub.timer_index = BX_NULL_TIMER_HANDLE;
}
bx_uhci_core_c::~bx_uhci_core_c()
{
if (device_buffer != NULL)
delete [] device_buffer;
BX_DEBUG(("Exit"));
}
void bx_uhci_core_c::init_uhci(Bit8u devfunc, Bit16u devid, Bit8u headt, Bit8u intp)
{
device_buffer = new Bit8u[65536];
// Call our timer routine every 1mS (1,000uS)
// Continuous and active
hub.timer_index =
@ -801,18 +795,17 @@ bx_bool bx_uhci_core_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *
BX_ERROR(("too many pending packets"));
return 0;
}
usb_packet_init(&usb_packet, maxlen);
usb_packet.pid = pid;
usb_packet.devaddr = addr;
usb_packet.devep = endpt;
usb_packet.data = device_buffer;
usb_packet.len = maxlen;
usb_packet.complete_cb = uhci_async_complete_packet;
usb_packet.complete_dev = this;
switch (pid) {
case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
if (maxlen > 0) {
DEV_MEM_READ_PHYSICAL_DMA(td->dword3, maxlen, device_buffer);
DEV_MEM_READ_PHYSICAL_DMA(td->dword3, maxlen, usb_packet.data);
}
ret = broadcast_packet(&usb_packet);
len = maxlen;
@ -839,7 +832,7 @@ bx_bool bx_uhci_core_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *
ret = USB_RET_BABBLE;
}
if (len > 0) {
DEV_MEM_WRITE_PHYSICAL_DMA(td->dword3, len, device_buffer);
DEV_MEM_WRITE_PHYSICAL_DMA(td->dword3, len, usb_packet.data);
}
} else {
len = 0;
@ -850,6 +843,7 @@ bx_bool bx_uhci_core_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *
} else {
set_status(td, 1, 0, 0, 0, 0, 0, 0x007); // stalled
}
usb_packet_cleanup(&usb_packet);
return 1;
}

View File

@ -190,7 +190,6 @@ protected:
bx_uhci_core_t hub;
Bit8u global_reset;
bx_bool busy;
Bit8u *device_buffer;
USBPacket usb_packet;

View File

@ -214,6 +214,26 @@ protected:
int set_usb_string(Bit8u *buf, const char *str);
};
static BX_CPP_INLINE void usb_packet_init(USBPacket *p, int size)
{
memset(p, 0, sizeof(USBPacket));
if (size > 0) {
p->data = new Bit8u[size];
if (!p->data) {
return;
}
}
p->len = size;
}
static BX_CPP_INLINE void usb_packet_cleanup(USBPacket *p)
{
if (p->data) {
delete [] p->data;
p->data = NULL;
}
}
static BX_CPP_INLINE void usb_defer_packet(USBPacket *p, usb_device_c *dev)
{
p->dev = dev;

View File

@ -184,7 +184,6 @@ bx_usb_ehci_c::bx_usb_ehci_c()
{
put("usb_ehci", "EHCI");
memset((void*)&hub, 0, sizeof(bx_usb_ehci_t));
device_buffer = NULL;
rt_conf_id = -1;
hub.frame_timer_index = BX_NULL_TIMER_HANDLE;
}
@ -195,8 +194,6 @@ bx_usb_ehci_c::~bx_usb_ehci_c()
int i;
SIM->unregister_runtime_config_handler(rt_conf_id);
if (BX_EHCI_THIS device_buffer != NULL)
delete [] BX_EHCI_THIS device_buffer;
for (i = 0; i < 3; i++) {
if (BX_EHCI_THIS uhci[i] != NULL)
@ -233,8 +230,6 @@ void bx_usb_ehci_c::init(void)
return;
}
BX_EHCI_THIS device_buffer = new Bit8u[BUFF_SIZE];
// Call our frame timer routine every 1mS (1,024uS)
// Continuous and active
BX_EHCI_THIS hub.frame_timer_index = bx_pc_system.register_timer(this, ehci_frame_handler,
@ -1207,7 +1202,7 @@ int bx_usb_ehci_c::qh_do_overlay(EHCIQueue *q)
return 0;
}
int bx_usb_ehci_c::init_transfer(EHCIPacket *p)
int bx_usb_ehci_c::transfer(EHCIPacket *p)
{
Bit32u cpage, offset, bytes, plen, blen = 0;
Bit64u page;
@ -1233,9 +1228,9 @@ int bx_usb_ehci_c::init_transfer(EHCIPacket *p)
// Bochs specific code (no async and scatter/gather support yet)
if (p->pid == USB_TOKEN_IN) {
DEV_MEM_WRITE_PHYSICAL_DMA(page, plen, device_buffer+blen);
DEV_MEM_WRITE_PHYSICAL_DMA(page, plen, p->packet.data+blen);
} else {
DEV_MEM_READ_PHYSICAL_DMA(page, plen, device_buffer+blen);
DEV_MEM_READ_PHYSICAL_DMA(page, plen, p->packet.data+blen);
}
blen += plen;
bytes -= plen;
@ -1273,7 +1268,7 @@ void bx_usb_ehci_c::async_complete_packet(USBPacket *packet)
BX_INFO(("Experimental async packet completion"));
p = container_of_usb_packet(packet);
if (p->pid == USB_TOKEN_IN) {
BX_EHCI_THIS init_transfer(p);
BX_EHCI_THIS transfer(p);
}
BX_ASSERT(p->async == EHCI_ASYNC_INFLIGHT);
p->async = EHCI_ASYNC_FINISHED;
@ -1379,18 +1374,17 @@ int bx_usb_ehci_c::execute(EHCIPacket *p)
// FIXME: This check makes transfer fail with current Bochs code
// if (p->async == EHCI_ASYNC_NONE) {
usb_packet_init(&p->packet, p->tbytes);
if (p->pid != USB_TOKEN_IN) {
if (BX_EHCI_THIS init_transfer(p) != 0) {
if (BX_EHCI_THIS transfer(p) != 0) {
return USB_RET_PROCERR;
}
}
// Packet setup (could be moved separate function)
// Packet setup
p->packet.pid = p->pid;
p->packet.devaddr = p->queue->dev->get_address();
p->packet.devep = endp;
p->packet.data = BX_EHCI_THIS device_buffer;
p->packet.len = p->tbytes;
p->packet.complete_cb = ehci_async_complete_packet;
p->packet.complete_dev = BX_EHCI_THIS_PTR;
@ -1413,11 +1407,12 @@ int bx_usb_ehci_c::execute(EHCIPacket *p)
// it received, not the amount it anticipates on receiving/sending in the next packet.
ret = 8;
} else if (p->pid == USB_TOKEN_IN) {
if (BX_EHCI_THIS init_transfer(p) != 0) {
if (BX_EHCI_THIS transfer(p) != 0) {
return USB_RET_PROCERR;
}
}
}
usb_packet_cleanup(&p->packet);
return ret;
}

View File

@ -4,7 +4,7 @@
//
// Experimental USB EHCI adapter (partly ported from Qemu)
//
// Copyright (C) 2015 The Bochs Project
// Copyright (C) 2015-2016 The Bochs Project
//
// Copyright(c) 2008 Emutex Ltd. (address@hidden)
// Copyright(c) 2011-2012 Red Hat, Inc.
@ -344,7 +344,6 @@ private:
Bit8u devfunc;
Bit8u device_change;
int rt_conf_id;
Bit8u *device_buffer;
Bit32u maxframes;
void reset_hc(void);
@ -383,7 +382,7 @@ private:
int put_dwords(Bit32u addr, Bit32u *buf, int num);
void flush_qh(EHCIQueue *q);
int qh_do_overlay(EHCIQueue *q);
int init_transfer(EHCIPacket *p);
int transfer(EHCIPacket *p);
void finish_transfer(EHCIQueue *q, int status);
void execute_complete(EHCIQueue *q);
int execute(EHCIPacket *p);

View File

@ -132,7 +132,6 @@ bx_usb_ohci_c::bx_usb_ohci_c()
{
put("usb_ohci", "OHCI");
memset((void*)&hub, 0, sizeof(bx_usb_ohci_t));
device_buffer = NULL;
hub.frame_timer_index = BX_NULL_TIMER_HANDLE;
hub.rt_conf_id = -1;
}
@ -142,8 +141,6 @@ bx_usb_ohci_c::~bx_usb_ohci_c()
char pname[16];
SIM->unregister_runtime_config_handler(hub.rt_conf_id);
if (BX_OHCI_THIS device_buffer != NULL)
delete [] BX_OHCI_THIS device_buffer;
for (int i=0; i<USB_OHCI_PORTS; i++) {
sprintf(pname, "port%d.device", i+1);
@ -174,8 +171,6 @@ void bx_usb_ohci_c::init(void)
return;
}
BX_OHCI_THIS device_buffer = new Bit8u[8192];
// Call our frame timer routine every 1mS (1,000uS)
// Continuous and active
BX_OHCI_THIS hub.frame_timer_index =
@ -1213,6 +1208,7 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
unsigned pid = 0, len = 0, len1, len2;
int ilen, ret = 0;
Bit32u addr;
Bit16u maxlen = 0;
bx_bool completion;
addr = ED_GET_HEADP(ed);
@ -1263,21 +1259,21 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
BX_ERROR(("too many pending packets"));
return 0;
}
BX_OHCI_THIS usb_packet.pid = pid;
BX_OHCI_THIS usb_packet.devaddr = ED_GET_FA(ed);
BX_OHCI_THIS usb_packet.devep = ED_GET_EN(ed);
BX_OHCI_THIS usb_packet.data = BX_OHCI_THIS device_buffer;
BX_OHCI_THIS usb_packet.complete_cb = ohci_async_complete_packet;
BX_OHCI_THIS usb_packet.complete_dev = this;
switch (pid) {
case USB_TOKEN_SETUP:
case USB_TOKEN_OUT:
BX_OHCI_THIS usb_packet.len = (len <= ED_GET_MPS(ed)) ? len : ED_GET_MPS(ed);
maxlen = (len <= ED_GET_MPS(ed)) ? len : ED_GET_MPS(ed);
break;
case USB_TOKEN_IN:
BX_OHCI_THIS usb_packet.len = len;
maxlen = len;
break;
}
usb_packet_init(&BX_OHCI_THIS usb_packet, maxlen);
BX_OHCI_THIS usb_packet.pid = pid;
BX_OHCI_THIS usb_packet.devaddr = ED_GET_FA(ed);
BX_OHCI_THIS usb_packet.devep = ED_GET_EN(ed);
BX_OHCI_THIS usb_packet.complete_cb = ohci_async_complete_packet;
BX_OHCI_THIS usb_packet.complete_dev = this;
BX_DEBUG((" pid = %s addr = %i endpnt = %i len = %i mps = %i (td->cbp = 0x%08X, td->be = 0x%08X)",
(pid == USB_TOKEN_IN)? "IN" : (pid == USB_TOKEN_OUT) ? "OUT" : (pid == USB_TOKEN_SETUP) ? "SETUP" : "UNKNOWN",
@ -1287,7 +1283,7 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
switch (pid) {
case USB_TOKEN_SETUP:
if (len > 0)
DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), len, device_buffer);
DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), len, BX_OHCI_THIS usb_packet.data);
// TODO: This is a hack. dev->handle_packet() should return the amount of bytes
// it received, not the amount it anticipates on receiving/sending in the next packet.
if ((ret = BX_OHCI_THIS broadcast_packet(&BX_OHCI_THIS usb_packet)) >= 0)
@ -1295,7 +1291,7 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
break;
case USB_TOKEN_OUT:
if (len > 0)
DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), len, device_buffer);
DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), maxlen, BX_OHCI_THIS usb_packet.data);
ret = BX_OHCI_THIS broadcast_packet(&BX_OHCI_THIS usb_packet);
break;
case USB_TOKEN_IN:
@ -1317,10 +1313,10 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
if (((TD_GET_CBP(td) & 0xfff) + ret) > 0x1000) {
len1 = 0x1000 - (TD_GET_CBP(td) & 0xfff);
len2 = ret - len1;
DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), len1, device_buffer);
DEV_MEM_WRITE_PHYSICAL_DMA((TD_GET_BE(td) & ~0xfff), len2, device_buffer+len1);
DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), len1, BX_OHCI_THIS usb_packet.data);
DEV_MEM_WRITE_PHYSICAL_DMA((TD_GET_BE(td) & ~0xfff), len2, BX_OHCI_THIS usb_packet.data+len1);
} else {
DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), ret, device_buffer);
DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), ret, BX_OHCI_THIS usb_packet.data);
}
}
if ((ret == (int)len) || ((pid == USB_TOKEN_IN) && (ret >= 0) &&
@ -1373,6 +1369,7 @@ bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
BX_DEBUG((" td->cbp = 0x%08X ret = %i len = %i td->cc = %i td->ec = %i ed->h = %i", TD_GET_CBP(td), ret, len, TD_GET_CC(td), TD_GET_EC(td), ED_GET_H(ed)));
BX_DEBUG((" td->t = %i ed->c = %i", TD_GET_T(td), ED_GET_C(ed)));
usb_packet_cleanup(&BX_OHCI_THIS usb_packet);
return 1;
}

View File

@ -263,7 +263,6 @@ public:
private:
bx_usb_ohci_t hub;
Bit8u *device_buffer;
USBPacket usb_packet;