mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-21 08:35:03 -05: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;
|
||||
uint8_t type; // 0=control, 1=isochronous, 2=bulk, 3=interrupt
|
||||
uint8_t direction; // 0=out, 1=in
|
||||
//uint8_t endpoint; // 0 to 15
|
||||
//uint8_t data01; // next packet DATA0 or DATA1
|
||||
uint8_t unusedbyte[2];
|
||||
uint32_t unused[2];
|
||||
@ -70,40 +69,6 @@ struct Transfer_struct {
|
||||
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);
|
||||
void free_Device(Device_t *q);
|
||||
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.wIndex = 0x0000;
|
||||
dev->setup.wLength = 8;
|
||||
Transfer_t *transfer = new_Transfer(dev->control_pipe, buffer, 8);
|
||||
//print(dev->control_pipe);
|
||||
if (transfer) queue_Transfer(transfer);
|
||||
new_Transfer(dev->control_pipe, buffer, 8);
|
||||
|
||||
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)
|
||||
{
|
||||
Pipe_t *pipe;
|
||||
Transfer_t *halt;
|
||||
uint32_t c=0, dtc=0;
|
||||
|
||||
Serial.println("new_Pipe");
|
||||
pipe = allocate_Pipe();
|
||||
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->qh.current = 0;
|
||||
pipe->qh.next = 1;
|
||||
pipe->qh.next = (uint32_t)halt;
|
||||
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->type = type;
|
||||
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);
|
||||
pipe->qh.capabilities[1] = QH_capabilities2(1, dev->hub_port,
|
||||
dev->hub_address, 0, 0);
|
||||
#if 1
|
||||
|
||||
if (type == 0 || type == 2) {
|
||||
// control or bulk: add to async queue
|
||||
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
|
||||
// TODO: link it into the periodic table
|
||||
}
|
||||
#endif
|
||||
return pipe;
|
||||
}
|
||||
|
||||
@ -388,13 +388,13 @@ void init_qTD(volatile Transfer_t *t, void *buf, uint32_t len,
|
||||
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");
|
||||
Transfer_t *transfer = allocate_Transfer();
|
||||
if (!transfer) return NULL;
|
||||
if (!transfer) return false;
|
||||
transfer->pipe = pipe;
|
||||
if (pipe->type == 0) {
|
||||
// control transfer
|
||||
@ -402,19 +402,19 @@ Transfer_t * new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
||||
uint32_t status_direction;
|
||||
if (len > 16384) {
|
||||
free_Transfer(transfer);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
status = allocate_Transfer();
|
||||
if (!status) {
|
||||
free_Transfer(transfer);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
if (len > 0) {
|
||||
data = allocate_Transfer();
|
||||
if (!data) {
|
||||
free_Transfer(transfer);
|
||||
free_Transfer(status);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
init_qTD(data, buffer, len, pipe->direction, 1, false);
|
||||
transfer->qtd.next = (uint32_t)data;
|
||||
@ -434,26 +434,26 @@ Transfer_t * new_Transfer(Pipe_t *pipe, void *buffer, uint32_t len)
|
||||
} else {
|
||||
// bulk, interrupt or isochronous transfer
|
||||
free_Transfer(transfer);
|
||||
return NULL;
|
||||
}
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
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