mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-08-13 16:53:54 -04:00
Add halt qTD and race-free qTD queuing method
This commit is contained in:
parent
f4d60b7594
commit
897cf23bf3
35
host.h
35
host.h
@ -49,7 +49,6 @@ struct Pipe_struct {
|
|||||||
Device_t *device;
|
Device_t *device;
|
||||||
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
|
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
|
||||||
uint8_t direction; // 0=out, 1=in
|
uint8_t direction; // 0=out, 1=in
|
||||||
//uint8_t endpoint; // 0 to 15
|
|
||||||
//uint8_t data01; // next packet DATA0 or DATA1
|
//uint8_t data01; // next packet DATA0 or DATA1
|
||||||
uint8_t unusedbyte[2];
|
uint8_t unusedbyte[2];
|
||||||
uint32_t unused[2];
|
uint32_t unused[2];
|
||||||
@ -70,40 +69,6 @@ struct Transfer_struct {
|
|||||||
uint32_t unused[5];
|
uint32_t unused[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define EHCI_QH_CAPABILITIES1( \
|
|
||||||
nak_count_reload, \
|
|
||||||
control_endpoint_flag, \
|
|
||||||
max_packet_length, \
|
|
||||||
head_of_list, \
|
|
||||||
data_toggle_control, \
|
|
||||||
speed, \
|
|
||||||
endpoint_number, \
|
|
||||||
inactivate, \
|
|
||||||
address) \
|
|
||||||
( ((nak_count_reload) << 28) | \
|
|
||||||
((control_endpoint_flag) << 27) | \
|
|
||||||
((max_packet_length) << 16) | \
|
|
||||||
((head_of_list) << 15) | \
|
|
||||||
((data_toggle_control) << 14) | \
|
|
||||||
((speed) << 12) | \
|
|
||||||
((endpoint_number) << 8) | \
|
|
||||||
((inactivate) << 7) | \
|
|
||||||
((address) << 0) )
|
|
||||||
|
|
||||||
#define EHCI_QH_CAPABILITIES2( \
|
|
||||||
high_bw_mult, \
|
|
||||||
hub_port_number, \
|
|
||||||
hub_address, \
|
|
||||||
split_completion_mask, \
|
|
||||||
interrupt_schedule_mask) \
|
|
||||||
( ((high_bw_mult) << 30) | \
|
|
||||||
((hub_port_number) << 23) | \
|
|
||||||
((hub_address) << 16) | \
|
|
||||||
((split_completion_mask) << 8) | \
|
|
||||||
((interrupt_schedule_mask) << 0) )
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Device_t * allocate_Device(void);
|
Device_t * allocate_Device(void);
|
||||||
void free_Device(Device_t *q);
|
void free_Device(Device_t *q);
|
||||||
Pipe_t * allocate_Pipe(void);
|
Pipe_t * allocate_Pipe(void);
|
||||||
|
@ -279,9 +279,7 @@ Device_t * new_Device(uint32_t speed, uint32_t hub_addr, uint32_t hub_port)
|
|||||||
dev->setup.wValue = 0x0100;
|
dev->setup.wValue = 0x0100;
|
||||||
dev->setup.wIndex = 0x0000;
|
dev->setup.wIndex = 0x0000;
|
||||||
dev->setup.wLength = 8;
|
dev->setup.wLength = 8;
|
||||||
Transfer_t *transfer = new_Transfer(dev->control_pipe, buffer, 8);
|
new_Transfer(dev->control_pipe, buffer, 8);
|
||||||
//print(dev->control_pipe);
|
|
||||||
if (transfer) queue_Transfer(transfer);
|
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
}
|
}
|
||||||
@ -309,21 +307,24 @@ Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t dire
|
|||||||
uint32_t max_packet_len)
|
uint32_t max_packet_len)
|
||||||
{
|
{
|
||||||
Pipe_t *pipe;
|
Pipe_t *pipe;
|
||||||
|
Transfer_t *halt;
|
||||||
uint32_t c=0, dtc=0;
|
uint32_t c=0, dtc=0;
|
||||||
|
|
||||||
Serial.println("new_Pipe");
|
Serial.println("new_Pipe");
|
||||||
pipe = allocate_Pipe();
|
pipe = allocate_Pipe();
|
||||||
if (!pipe) return NULL;
|
if (!pipe) return NULL;
|
||||||
|
halt = allocate_Transfer();
|
||||||
|
if (!halt) {
|
||||||
|
free_Pipe(pipe);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pipe, 0, sizeof(Pipe_t));
|
||||||
|
memset(halt, 0, sizeof(Transfer_t));
|
||||||
|
halt->qtd.next = 1;
|
||||||
|
halt->qtd.token = 0x40;
|
||||||
pipe->device = dev;
|
pipe->device = dev;
|
||||||
pipe->qh.current = 0;
|
pipe->qh.next = (uint32_t)halt;
|
||||||
pipe->qh.next = 1;
|
|
||||||
pipe->qh.alt_next = 1;
|
pipe->qh.alt_next = 1;
|
||||||
pipe->qh.token = 0;
|
|
||||||
pipe->qh.buffer[0] = 0;
|
|
||||||
pipe->qh.buffer[1] = 0;
|
|
||||||
pipe->qh.buffer[2] = 0;
|
|
||||||
pipe->qh.buffer[3] = 0;
|
|
||||||
pipe->qh.buffer[4] = 0;
|
|
||||||
pipe->direction = direction;
|
pipe->direction = direction;
|
||||||
pipe->type = type;
|
pipe->type = type;
|
||||||
if (type == 0) {
|
if (type == 0) {
|
||||||
@ -339,7 +340,7 @@ Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t dire
|
|||||||
dtc, dev->speed, endpoint, 0, dev->address);
|
dtc, dev->speed, endpoint, 0, dev->address);
|
||||||
pipe->qh.capabilities[1] = QH_capabilities2(1, dev->hub_port,
|
pipe->qh.capabilities[1] = QH_capabilities2(1, dev->hub_port,
|
||||||
dev->hub_address, 0, 0);
|
dev->hub_address, 0, 0);
|
||||||
#if 1
|
|
||||||
if (type == 0 || type == 2) {
|
if (type == 0 || type == 2) {
|
||||||
// control or bulk: add to async queue
|
// control or bulk: add to async queue
|
||||||
Pipe_t *list = (Pipe_t *)USBHS_ASYNCLISTADDR;
|
Pipe_t *list = (Pipe_t *)USBHS_ASYNCLISTADDR;
|
||||||
@ -359,7 +360,6 @@ Pipe_t * new_Pipe(Device_t *dev, uint32_t type, uint32_t endpoint, uint32_t dire
|
|||||||
// interrupt: add to periodic schedule
|
// interrupt: add to periodic schedule
|
||||||
// TODO: link it into the periodic table
|
// TODO: link it into the periodic table
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return pipe;
|
return pipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,13 +388,13 @@ void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len,
|
|||||||
t->qtd.buffer[4] = addr + 0x4000;
|
t->qtd.buffer[4] = addr + 0x4000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a list of Transfers
|
// Create a Transfer and queue it
|
||||||
//
|
//
|
||||||
Transfer_t * new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
bool new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
||||||
{
|
{
|
||||||
Serial.println("new_Transfer");
|
Serial.println("new_Transfer");
|
||||||
Transfer_t *transfer = allocate_Transfer();
|
Transfer_t *transfer = allocate_Transfer();
|
||||||
if (!transfer) return NULL;
|
if (!transfer) return false;
|
||||||
transfer->pipe = pipe;
|
transfer->pipe = pipe;
|
||||||
if (pipe->type == 0) {
|
if (pipe->type == 0) {
|
||||||
// control transfer
|
// control transfer
|
||||||
@ -402,19 +402,19 @@ Transfer_t * new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
|||||||
uint32_t status_direction;
|
uint32_t status_direction;
|
||||||
if (len > 16384) {
|
if (len > 16384) {
|
||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
status = allocate_Transfer();
|
status = allocate_Transfer();
|
||||||
if (!status) {
|
if (!status) {
|
||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
data = allocate_Transfer();
|
data = allocate_Transfer();
|
||||||
if (!data) {
|
if (!data) {
|
||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
free_Transfer(status);
|
free_Transfer(status);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
init_qTD(data, buffer, len, pipe->direction, 1, false);
|
init_qTD(data, buffer, len, pipe->direction, 1, false);
|
||||||
transfer->qtd.next = (uint32_t)data;
|
transfer->qtd.next = (uint32_t)data;
|
||||||
@ -434,26 +434,26 @@ Transfer_t * new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
|||||||
} else {
|
} else {
|
||||||
// bulk, interrupt or isochronous transfer
|
// bulk, interrupt or isochronous transfer
|
||||||
free_Transfer(transfer);
|
free_Transfer(transfer);
|
||||||
return NULL;
|
return false;
|
||||||
}
|
|
||||||
return transfer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void queue_Transfer(Transfer_t *transfer)
|
|
||||||
{
|
|
||||||
Serial.println("queue_Transfer");
|
|
||||||
Pipe_t *pipe = transfer->pipe;
|
|
||||||
Transfer_t *last = (Transfer_t *)(pipe->qh.next);
|
|
||||||
if ((uint32_t)last & 1) {
|
|
||||||
pipe->qh.next = (uint32_t)transfer;
|
|
||||||
Serial.println(" first on QH");
|
|
||||||
} else {
|
|
||||||
while ((last->qtd.next & 1) == 0) last = (Transfer_t *)(last->qtd.next);
|
|
||||||
// TODO: what happens if qTD is completed before we write to it?
|
|
||||||
last->qtd.next = (uint32_t)transfer;
|
|
||||||
Serial.println(" added to qTD list");
|
|
||||||
}
|
}
|
||||||
|
Transfer_t *halt = (Transfer_t *)(pipe->qh.next);
|
||||||
|
while (!(halt->qtd.token & 0x40)) halt = (Transfer_t *)(halt->qtd.next);
|
||||||
|
uint32_t token = transfer->qtd.token;
|
||||||
|
transfer->qtd.token = 0x40; // transfer becomes new halt qTD
|
||||||
|
halt->qtd.next = transfer->qtd.next;
|
||||||
|
halt->qtd.alt_next = transfer->qtd.alt_next;
|
||||||
|
halt->qtd.buffer[0] = transfer->qtd.buffer[0];
|
||||||
|
halt->qtd.buffer[1] = transfer->qtd.buffer[1];
|
||||||
|
halt->qtd.buffer[2] = transfer->qtd.buffer[2];
|
||||||
|
halt->qtd.buffer[3] = transfer->qtd.buffer[3];
|
||||||
|
halt->qtd.buffer[4] = transfer->qtd.buffer[4];
|
||||||
|
halt->pipe = pipe;
|
||||||
|
Transfer_t *last = transfer;
|
||||||
|
while ((uint32_t)(last->qtd.next) != 1) last = (Transfer_t *)(last->qtd.next);
|
||||||
|
last->qtd.next = (uint32_t)transfer;
|
||||||
|
transfer->qtd.next = 1;
|
||||||
|
halt->qtd.token = token; // old halt becomes new transfer
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user