00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00034 #include <errno.h>
00035 #include <usb/debug.h>
00036
00037 #include "transfer_descriptor.h"
00038 #include "../utils/malloc32.h"
00039
00062 void td_init(td_t *instance, int err_count, size_t size, bool toggle, bool iso,
00063 bool low_speed, usb_target_t target, usb_packet_id pid, void *buffer,
00064 td_t *next)
00065 {
00066 assert(instance);
00067 assert(size < 1024);
00068 assert((pid == USB_PID_SETUP) || (pid == USB_PID_IN)
00069 || (pid == USB_PID_OUT));
00070
00071 const uint32_t next_pa = addr_to_phys(next);
00072 assert((next_pa & LINK_POINTER_ADDRESS_MASK) == next_pa);
00073
00074 instance->next = 0
00075 | LINK_POINTER_VERTICAL_FLAG
00076 | (next_pa ? next_pa : LINK_POINTER_TERMINATE_FLAG);
00077
00078 instance->status = 0
00079 | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
00080 << TD_STATUS_ERROR_COUNT_POS)
00081 | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
00082 | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
00083 | TD_STATUS_ERROR_ACTIVE;
00084
00085 if (pid == USB_PID_IN && !iso) {
00086 instance->status |= TD_STATUS_SPD_FLAG;
00087 }
00088
00089 instance->device = 0
00090 | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
00091 | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
00092 | ((target.address & TD_DEVICE_ADDRESS_MASK)
00093 << TD_DEVICE_ADDRESS_POS)
00094 | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK)
00095 << TD_DEVICE_ENDPOINT_POS)
00096 | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
00097
00098 instance->buffer_ptr = addr_to_phys(buffer);
00099
00100 usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
00101 instance, instance->next, instance->status, instance->device,
00102 instance->buffer_ptr, buffer);
00103 td_print_status(instance);
00104 if (pid == USB_PID_SETUP) {
00105 usb_log_debug("SETUP BUFFER: %s\n",
00106 usb_debug_str_buffer(buffer, 8, 8));
00107 }
00108 }
00109
00115 int td_status(td_t *instance)
00116 {
00117 assert(instance);
00118
00119
00120 if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
00121 return EAGAIN;
00122
00123
00124
00125 if ((instance->status & TD_STATUS_ERROR_CRC) != 0)
00126 return EBADCHECKSUM;
00127
00128
00129 if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
00130 return EAGAIN;
00131
00132
00133 if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
00134 return ERANGE;
00135
00136
00137 if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
00138 return EIO;
00139
00140
00141
00142 if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
00143 return ESTALL;
00144
00145 return EOK;
00146 }
00147
00152 void td_print_status(td_t *instance)
00153 {
00154 assert(instance);
00155 const uint32_t s = instance->status;
00156 usb_log_debug2("TD(%p) status(%#" PRIx32 "):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
00157 instance, instance->status,
00158 (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
00159 (s >> TD_STATUS_ERROR_COUNT_POS) & TD_STATUS_ERROR_COUNT_MASK,
00160 (s & TD_STATUS_LOW_SPEED_FLAG) ? " LOW SPEED," : "",
00161 (s & TD_STATUS_ISOCHRONOUS_FLAG) ? " ISOCHRONOUS," : "",
00162 (s & TD_STATUS_IOC_FLAG) ? " IOC," : "",
00163 (s & TD_STATUS_ERROR_ACTIVE) ? " ACTIVE," : "",
00164 (s & TD_STATUS_ERROR_STALLED) ? " STALLED," : "",
00165 (s & TD_STATUS_ERROR_BUFFER) ? " BUFFER," : "",
00166 (s & TD_STATUS_ERROR_BABBLE) ? " BABBLE," : "",
00167 (s & TD_STATUS_ERROR_NAK) ? " NAK," : "",
00168 (s & TD_STATUS_ERROR_CRC) ? " CRC/TIMEOUT," : "",
00169 (s & TD_STATUS_ERROR_BIT_STUFF) ? " BIT_STUFF," : "",
00170 (s & TD_STATUS_ERROR_RESERVED) ? " RESERVED," : "",
00171 td_act_size(instance)
00172 );
00173 }